uploadFailure attaches what the client observed (unreadable, offline, hidden tab, aborted,
progressed, stopped) and keeps a homeserver errcode; uploadReason turns that into a cause and an
action. The upload cards and the share panel's refusal list use it.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A file larger than m.upload.size is named in the note and dropped from the pick before any
upload or album root; a pick of only such files sends nothing. No stated cap or no file size
refuses nothing.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The coverage guard now scans every script file under src, resolves aliased and
namespace-member IconButton tags, and fails loudly on any other mention
(as={IconButton}, rebinding, re-export, destructuring, element access). A
PhoneHit that an inner scope rebinds, or that is imported as a type, no longer
counts. drawnPx/sizeProp read the parsed tag, not its text. The emoji Sidebar
column's 4 px gap is pinned.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The navigator's 'Desk · N open' counted cards the desk withdraws on an
options_hash mismatch. buildDesk now owns the count (open_count less the
withdrawn open cards) and the navigator reads it through the same
useUnverified check the page uses; before the check lands it shows no count.
A row's fold is derived from the screen size and a tap, so rotation cannot
leave it stale. Adds guest and settled-while-answered fixtures and tests.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The provisional media[<mind>] key was never written by anything; gamecult-ops #111 records ids under @rooms. The old key is no longer read.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Stop aborts the running upload (onPromise + mx.cancelUpload) and leaves it and the rest picked as 'stopped'. foldVersions shows files caught in a replaces loop with no head instead of hiding them. An add reads the room timeline at send time for the newest event in the thread.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
sendShareSet takes a title or an existing album (no new root; the first file threads after the album's newest event). Failed files carry the refusal for M_TOO_LARGE, M_FORBIDDEN and M_LIMIT_EXCEEDED in the result note. AlbumView mounts an Add files panel inside an open album.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A file event naming org.gamecult.publish.replaces supersedes the event it names. foldVersions reads the chain from the events alone; buildAlbums lists heads (count too) and AlbumView unfolds 'N earlier versions'. Both events stay ordinary files for other clients.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
useAlbums followed no next_batch, so a zone past 100 albums or 100 files per album was silently cut. readPages follows the token up to 20 pages per endpoint and says when the cap stopped it; AlbumView shows a dim note then.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Albums titled a/b/c group into folders in AlbumView; ShareSet prefixes the
current folder onto the album title it sends. No wire change.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
wipeLocalData moves to its own module with injectable ports: per-database failures are contained and localStorage clears in a finally. A soft logout with no session to remember is treated as hard. Login/PasswordLoginForm/ResetPassword MAS behavior is now tested by rendering. Login and register completion settle once per response.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
First SessionLoggedOut decides; later events are ignored so a second soft event cannot fall into the wipe. Under MAS a configured registrationEntry (with its training notice) is kept; the MAS notice replaces only the in-client form and bare link. Registration goes through the same keep-or-wipe settle as login. Soft record drops its unused baseUrl. One shared https-or-localhost predicate.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Soft (soft_logout === true) drops only the access token and records the device; sign-in is fixed to that user and sends device_id; same user and device keeps the stores, anything else wipes via the one wipeLocalData. Hard logout still wipes. When discovery advertises an msc2965 account or issuer, the register and forgot-password entries give way to a notice pointing at the account page.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
folds draws a glyph at 16-24 px; on a phone the 16/18/20 px ones read small in their buttons. One global
rule per folds Icon size scales the glyph (22/24/24/26/28 px) at paint time inside an IconButton, so no
button, PhoneHit area or row changes size and desktop is untouched. phoneGlyph.test.ts pins the folds
class names, the px range and that the rule is a phone-only scale.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>