Repository navigation
Conversation
… charter Adds scripts/home-phone-layout-smoke.mjs: loads the real Home host and GUI against a fixture host in Playwright Chromium and WebKit at iPhone 14 portrait, landscape and an 820 px tablet, measures targets under 44 px, text under 12 px and horizontal overflow on every shell surface and one window per first-party app, writes report.json plus screenshots, and asserts a per-profile baseline that later PRs may only lower. Records the source truths the phone layer will change (viewport-fit, bare 100vh, backdrop-filter count). Wires the smoke into just product-ui-browser, adds docs/HOME_MOBILE.md (size classes, rubric, gesture-surface rule, baseline, real-device checks, capsule guidance) linked from ROADMAP.md, and pins the ratchet in home-entropy-check. No UI change.
- viewport-fit=cover and interactive-widget=resizes-visual on the Home host and GUI index files, so env(safe-area-inset-*) is real on iOS and the soft keyboard shrinks only the visual viewport on Android like it does on iOS - shell-form-factor.js: single reader of the 640/1100 size classes and the media-feature pointer class; mirrors body[data-form-factor] and body[data-pointer]; writes --keyboard-inset from visualViewport on coarse-pointer hosts (a phone held sideways stays a phone; desktop pinch-zoom is never a keyboard); shouldOpenMaximizedByDefault() delegates - style.css: --stage-bottom adds --keyboard-inset; overscroll-behavior none on the shell; touch-action manipulation and no tap highlight on controls; touch-callout off on shell chrome only; 100dvh twin for the last bare 100vh; side safe-area insets on the bar and the phone window - home-form-factor.test.mjs in verify; entropy contracts for every truth above, mutation-tested; phone smoke reports fallback vs bare 100vh Co-authored-by: Cursor <cursoragent@cursor.com>
Phone size class in CSS is one media list mirroring classifyFormFactor (width <= 640, or coarse/hover-less pointer with height <= 640), so a landscape phone keeps the phone shell. home-entropy-check derives the list from PHONE_MAX_WIDTH. Bar: --toolbar-h 44px, every control a 44x44 hit box around the 22px glyph, 16px badge with 12px numerals. Wallet and Overview leave the phone bar; Control Centre keeps both (Quick open / Overview). Dock: thumb scroll (taskbar-item touch-action pan-x instead of none), scroll-snap, scroll-driven edge fades, 14x4 running indicator, safe-area sides in landscape. With a window open the Dock tucks (body.phone-dock-tucked) and --stage-bottom shrinks to a 24px handle; tap/swipe the handle peeks the Dock over the app (phone-dock-peek + scrim); scrim, Escape or picking a window tucks it. New shell-phone-dock.js, synced from updateTaskbarState. Smoke: opens Mission Control via Control Centre, probes tuck/peek/tuck on both phone profiles, lowers phone baselines, records one boot retry for the WebKit first-profile flake. node:test coverage for the Dock decisions. Co-authored-by: Cursor <cursoragent@cursor.com>
The phone block set gap: 8px on .taskbar-inner. The hidden launcher and Assistant face stay in flow (display: flex, collapsed to 0 for the face animation), so the column gap added 16px of dead space above the icon row: the pill was 88px with icons low. Drop the gap; the launcher popover already carries its own spacing inside the clipped region. The phone smoke now pins the idle pill at --taskbar-h (72px). Co-authored-by: Cursor <cursoragent@cursor.com>
The plate-free glyphs are drawn at 58.6% of their square for the pointer desktop; beside 48px app plates on a phone they read small. Launcher via background-size (its .taskbar-icon transform is reserved for magnification); Assistant via its inner icon node so the mark's layer animation is untouched. Co-authored-by: Cursor <cursoragent@cursor.com>
One 44px presentation of .window-head for every chrome mode: leading Close, centred capsule icon + title, trailing Minimise drawn as a chevron (go home; the capsule keeps running). Fullscreen hidden. The traffic-light group is display: contents so the same buttons land in a three-column grid; chrome modes in shell-core.js are untouched. The head is in flow above the body in all modes, including unified sidebar/toolbar: a phone-width capsule has content at the top of its main column, so the desktop overlay would cover it. A 2px accent hairline runs under the title until .window-frame.is-ready (static under reduced motion) so the bar reads as alive while the capsule boots. shell-window-geometry.js guards drag/resize on phone. Smoke window baseline 5 -> 2 (only the 24px Dock handle remains). Co-authored-by: Cursor <cursoragent@cursor.com>
Mission Control is the phone's app switcher: title-bar swipe-down opens it (pointer capture across the capsule frame, the ending click swallowed), cards carry the capsule icon + name and a 44 px Close on coarse pointers, portrait Space thumbs are sized by height, copy loses mouse language. Windows rise from the Dock in 200 ms (none under reduced motion). Stage history keeps one entry of the shell's own, decided from history.state and never more than one back() per close cycle; popstate closes the top layer then goes home. Off on WebKit (buttons only): one back() after pushState took the shell frame to about:blank there — recorded in docs/HOME_MOBILE.md. Pure model unit-tested (scripts/home-phone-stage.test.mjs, in verify); the phone smoke probes swipe, back, rotation and the Home frame staying alive; entropy contract pins it all (21 mutations caught). Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ut fixtures Library imports /apps/home/home-navigation-client.js and the Browser imports /apps/home/home-clipboard-client.js; neither fixture served them, so both product layout smokes failed before measuring anything (500 / stuck on "Loading Library..."). Co-authored-by: Cursor <cursoragent@cursor.com>
The launcher and Assistant sit outside the scrolling app row, so when the pill reached its width limit flex shrank them to 45 px and their glyphs drew a third smaller than the app plates. They now keep full tiles and the scrolling row gives way. The 1.5x glyph scale applies only to plate-free art (the launcher, and the Assistant when it wears its plate-free mark); a plate raster already fills its square. Control Centre and Notifications span the phone stage with even margins instead of hugging the trailing edge. Co-authored-by: Cursor <cursoragent@cursor.com>
…push drawer
A capsule cannot tell a phone stage from a narrow desktop window by its own
width, so on phone every capsule kept the desktop traffic-light insets and
opened with dead space above and beside its content. The shell now posts
elastos:shell-layout {formFactor, pointer} to each frame on load and on a
size-class change (shell-capsule-layout.js). The shared theme runtime takes
it only from the opaque parent and only allowlisted values and sets
html[data-el-form-factor] and [data-el-pointer]; the shared sheet zeroes
--window-chrome-safe-top/-leading on phone and adds --el-touch-target and
the drawer tokens.
elastos-drawer.js is the Assistant's saved-chats pattern for any capsule
sidebar, bound by markup alone: content first, a 44 px toggle slides the
sidebar in and pushes the view aside, tapping the view (swallowed), Escape
or picking an item closes it; inert while closed. Vendored only to the
capsules whose sidebar uses it.
Unit-tested in verify; the phone smoke checks the size class reaches every
shared-theme frame on both engines; scripts/lib/phone-drawer-assert.mjs is
the shared smoke assertion for capsule drawers.
Co-authored-by: Cursor <cursoragent@cursor.com>
On phone the store opens on its content; the Discover title leads with a 44 px sidebar toggle that slides the categories in and pushes the store aside. Nav items are 44 px at 16 px and search is 16 px so iOS does not zoom. The layout smoke asserts the closed, open and picked states. Co-authored-by: Cursor <cursoragent@cursor.com>
The 220 px list column squeezed the editor to half the phone. On phone the editor takes the full width, the title row leads with the list toggle, actions are one row of 44 px buttons, and the editor and fields are 16 px. Split has no room on a phone and reads as Write; the desktop Hide list control gives way to the drawer. The layout smoke asserts the editor size, the hidden controls and the drawer. Co-authored-by: Cursor <cursoragent@cursor.com>
Favorites, path and search took 225 px above the first file. On phone the navigation row carries Back, Up, the current folder as its title, Search, view and More at 44 px, and Favorites sit under it as one sliding chip row; opening Search gives the field the whole row. Rows are 48 px at 16 px, the Name/Modified header is gone (only names show), and status floats above the footer as a pill. The list now starts at 104 px. Co-authored-by: Cursor <cursoragent@cursor.com>
The menu button sat 72 px in, clearing traffic lights that do not exist on phone. It now takes the leading edge as a 44 px target, vertically centred on the page title, which is indented to share its line; the open sidebar starts below it. Phone landscape keeps the desktop sidebar. The UI/UX smoke gains a phone step and joins the browser lane. Co-authored-by: Cursor <cursoragent@cursor.com>
At 640 px and below the list took a fixed 42% band, so with one or two requests the detail started mid-screen. The list is now as tall as its requests (capped at 40 dvh, then it scrolls) and the detail follows directly. The layout smoke fails on the old rule. Co-authored-by: Cursor <cursoragent@cursor.com>
The toolbar kept a 96 px traffic-light inset on phone. The navigation row now spans the stage with 40-44 px controls and a 44 px, 16 px address field. The layout smoke gains a phone step and joins the browser lane. Co-authored-by: Cursor <cursoragent@cursor.com>
Records the shell-to-capsule size class, the shared push drawer and the per-capsule phone layouts; the touch token is --el-touch-target. Co-authored-by: Cursor <cursoragent@cursor.com>
At 1.5x on full tiles the launcher and the Assistant mark matched the plates' height exactly and read too heavy beside them; 1.3x sits them just inside the plates. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Write/Read and Save stay in one unscrolled row; Save as, Publish, Unpublish, Copy Published Link and Delete open from a More button as labelled 44 px rows. The menu reuses the real buttons, so their handlers and enabled state are unchanged; desktop keeps them inline. Co-authored-by: Cursor <cursoragent@cursor.com>
The Write/Read tabs become full 44 px targets with the pill painted inside their padding, and the title field is 44 px tall. Documents' phone ratchet drops from 3 to 0 on both profiles. Co-authored-by: Cursor <cursoragent@cursor.com>
…lity # Conflicts: # elastos/CHANGELOG.md
Verification: node --check scripts/chat-room-configured-layout-smoke.mjs; git diff --check; independent source review. Real-WASM execution awaits matching generated assets and the shared lease.
|
@andersalm Is this intended? Chat disables Send whenever Community is "unreachable", which
|
|
@irzhywau agreed, thanks. Decision (Anders, 12 Oct): Send stays enabled whenever joined, also when nobody else is online; the Home keeps the message and delivers it when any participant or the Community node is reachable, and later joiners catch up. Messages show Sending, Sent, or Waiting, and do not expire while joined. Disabled only when Left or Not joined. Recorded in #86. |
|
Cross-family review of 31cc051: FAIL with 1 P1 (unchecked Chat payloads can fill the incoming slots) and 3 P2 (receive-limit race, delivery outcome lost after pruning, poll cursor skips a peer message). Sent to the Chat lane; merge after the fixes and a re-review. |
|
Cross-family review r2 on 04c6c69: FAIL (P1 49-character names pass admission but fail display; P2 stale poll overwrites Accepted; P2 shipped WASM lacked the cursor fix). r3 on 913568c: FAIL (P1 malformed Presence fills the 32 slots; P2 recovery with Chat closed loses the outcome; P2 retry restore exceeds caps). |
|
Note, non-blocking (known issue): a Home left alone while the Community node is down stays "Community unreachable" after the node returns, until its Runtime restarts. Reproduced locally with debug logs. |
- Composer: after a send, a draft restore or an emoji insert, Chat sets the text itself, which raises no input event, so the composer kept its multiline height. set_composer_text now refits it through the Chat chrome's elastosChatSyncComposer. - Message from People: Chat's hybrid window policy reused a window only for a launch without a query, so each conversation request opened a new Chat window. Home now sends elastos.chat.navigate/v1 to the open Chat window; Chat checks the sender, token and shape, then opens the conversation through open_direct_conversation. - Open Inbox from People: People posts a home:open-target message for inbox, but the Home shell only let People open Chat and System, so it dropped the request. The People smoke now checks every target People opens against the shell's source policy. - Troubleshooting: a Home that is the network's bootstrap shows Community Live but exchanges no Chat messages; how to confirm it and move the bootstrap to a separate Runtime. - Troubleshooting: a Home left alone while the Community node was down stays unreachable after the node returns, until its Runtime restarts. Known iroh-gossip 0.101.0 issue (upstream #161 merged, unreleased); not worked around here.
|
Visual review of Chat on Visual review checklistBasics
Profile card
Community status
While unreachable
Delivery and retry
Spam limits
Notes
|

Chat shows the Community state supplied by Runtime and renders a received Shared row and clears an accepted draft before optional metadata completes. Runtime keeps Community and Direct delivery work independent, preserves signed Profile and message authority, and keeps contacts and local history readable through Leave and Rejoin.
The Linux Carrier change disables UDP segmentation offload for the observed Jetson Wi-Fi batching fault. Managed Runtimes inherit Carrier's single mDNS default and preserve an explicit operator choice through launch and restart. CPU repairs reuse bounded verified data and signature work while each request still checks current authority, expiry and revocation. Release and update fixtures now follow the merged packaging contract.
The published candidate is
31cc05131e5b040f6445a88c185d4e5f92e40f74, tree76e2954d3dc77b7b8336b5e57361cc25e0be0946, with developaa3d61e4merged normally. It passes the full Linux slot-3 check (gate 35m34s, workspace 8m39s, capsules 4m36s), prescribed Python 3.12 Mac behavior and source gates, all 25 bundled-Chromium real-WASM scenarios, the CI precheck, formatting and diff checks. CI on 31cc051 is green (run 38284192556).Status, proof and acceptance: #86. Installed and hardware qualification runs once on the alpha.16 train release. The Linux three-user restart/Recovery regression uses a separate bootstrap Runtime and follows publication. The latest node-switchboard Send/Sent/Waiting decision is a separate Community follow-up dependent on this PR.
Anders owns Chat. OMP owns integration, relay work in #354, and release. Selected human risk review covers account/session authority, signed delivery, provider availability and update/release boundaries on one exact candidate. #334 retains the separate Community signing and release-pin admission work; Sasha owns #116.