webui: one design system across the app - #129
zelfroster wants to merge 22 commits into
Conversation
This carries the whole revamp, which had been sitting uncommitted: design tokens, the Phosphor icon sprite replacing FontAwesome, one dropdown and one field treatment, one emoji picker, the mail table (tri-state sort, date & time, drafts) and the composer. Roboto and the FontAwesome webfont are gone; Archivo and DM Mono ship as woff2. It also settles the pull of RetroShare#33/RetroShare#34, which revamped the same screens in parallel. The two approaches collided in the library sections, so the reconciliation was done by hand rather than by the merge. Ported from their commits, restyled on our tokens where they carried CSS: 6f37dd1 channel posts newest-first, by mPublishTs 47fb3dc keyed channel cards and keyed recipient <li>s -- both needed: unkeyed, the newest-first sort makes mithril reuse DOM by position, so one post's onerror display:none sticks to whatever post shifts into that slot 788ffbc avatars and full GXS ids in the To/Cc/Bcc autocomplete, with the avatar fetch deferred to IntersectionObserver, and the identity tooltip anchored below the id instead of over the row 5f35ca1 board post images on a media stage: object-fit contain, click or Enter opens the PhotoViewModal we already had. Their dark #0b0f19 stage, blurred ambient backdrop and drop shadows are not ported -- chrome here is a well and a hairline c45fc1e the Debug mobile action row only: minmax(0, 1fr) so three buttons share the width, and a .debug-btn__suffix that leaves just the verb Not ported, with reasons: c45fc1e library_layout.js and _library.scss. 183 lines of #f1f5f9 / #cbd5e1 / #3ba4d7, box shadows and 700 weights, @use'd last so it overrode the token layer at every breakpoint. The nav-rail and list-pane mixins already do this job. c45fc1e rails pinned to a flat 280px. Ours flex 250/230/280. c45fc1e 'New email' -> 'New mail' and 'Select an email' -> 'Select an mail', which reintroduced the typo b332299 had just fixed. 731cceb .chat-create-room-btn hard-coded to #3ba4d7. It is already btn-base + btn-strong, which renders the same thing. b332299 "All means all". There is no All tab on this branch -- the sections are My / Subscribed / Popular / Other -- so the Popular u Other merge it fixes does not exist here. c223473 library_layout props and icon swaps for that shell. Its Forums comments -> bullhorn is also a downgrade.
Mail
Drafts had two definitions of "draft": the folder listed anything with
the DRAFT bit, the reading pane asked for the exact DRAFTBOX value
(OUTGOING|DRAFT). A draft the core had not also marked OUTGOING was
listed and then opened with the Reply / Forward / Spam toolbar of a
received mail. One predicate now, read by both.
A draft is written by us, so an empty `from` means the core recorded no
identity, not that the sender is a stranger -- it falls back to our
first identity, which also fixes the "Sender is not known" sheet that
Edit draft opened. Star and spam are judgements about mail someone sent
you, so they are gone from draft rows and the Drafts folder drops both
columns rather than heading blank cells.
rs.userList.username() returns the id itself while its fetch is in
flight and forever for an identity this node has never seen, so the To:
chips and the From column were 32-character hex strings; identityLabel()
shortens what it cannot name. Subjects: one subjectOf(), so the table
says (No Subject) like the cards and the reading pane already did, and
whitespace-only titles count as empty.
Tags get a column of their own after Date, with the named badge the
cards use -- lifted out of .mail-card-item so one badge serves all three.
Files
My Files and Friends' Files are one tree treatment instead of the base
table's centred 18px black headings. The twist moved into the name cell
and the indent became padding: it was `position: relative; left:`, which
moves the text and leaves every level's chevron in the same column.
My Files tested `children !== undefined` for a folder, true for a file
too, so every shared file wore a folder icon; a non-zero hash is the
test. A friend's file in progress rendered the whole File card inside a
table cell -- it is a percentage and an info tooltip now.
Transfers: the chunk select used one `chunkTag` id on every row, the
chunk bar was 32px to hold a centred percentage, and the stat icons were
styled through `span > i`, which has matched nothing since Phosphor.
Search: `.search-form { width: 40% }` on a shrink-to-fit flex item
collapsed the field to a white square; the page header sizes it now, and
the page has empty states instead of a bare "Results".
Tooltips
Three implementations became one component. The hint was
white-on-near-black with `margin-left: -120px` standing in for centring,
undone again in two responsive blocks; the identity card was 53
`!important` declarations on --warn-bg, the warning colour, for
something that is not a warning. Both sit on one tip-surface mixin with
a new --lift-sm. The !importants were beating UserAvatar's inline
sizing, so the callers pass `size: 48` instead.
Also
Statistics uses the shared rail like every other section, which needed
Sidebar to work from local state as well as from the route; its refresh
button had `.icon { display: none }`. Forum search was offset by a 250px
margin left over from the old two-row header. Hovering the selected rail
item repainted it: `.sidebar a:hover` is (0,2,1) and the selected rule
was (0,2,0). Debug KPI cards no longer lift on hover -- they are
readouts, not controls. Chat room info: the lobby id fits a column, the
topic is a sentence, so they swap.
|
@defnax @jolavillette I was working on this, and still will be pushing fixes to this. Please try it out and let me know what more things need fix/improvement. |
|
not works on windows, howto install it
|
894178a to
d21dc9e
Compare
|
@defnax i was experimenting with it, removed it and its back to original way. you have to once run |
|
the new buttons looks lots of better then the old one only phone ui is broken, i did lots of fixes for phone :) |
|
the new icons and new buttons realy nice like a new fresh webui :) |
One back button everywhere a detail view can be left, replacing four separate implementations across Forums, Boards, Channels and Mail. It is part of the page header row now instead of taking a row of its own, so PageHead gains a `back` attribute. Forums and Channels listed the same thing with two copies of the same table, so both now use one `.group-table` component. formatTimestamp and getTimestampValue lived only in forums_util; moved to rswebui so other sections use them instead of their own copies. userList.username() printed the raw id for an unsigned post, whose author id is all zeros. There is no identity to fetch, so it returns [Unknown]. Selection colours raised: the previous band measured 1.14:1 against the surface behind it, which is below where a tint is reliably visible.
The thread list was read out of Data.Threads, a flat index of every post, so every reply appeared as a thread of its own. It now starts from Data.ParentThreads and walks each struct's replies, giving the tree the hierarchy call already returned. Columns are Threads, Unread, Date and Author, with replies indented and collapsible. Unread was tested as `mMsgStatus === 3`. It is a bit, not a value (GXS_MSG_STATUS_GUI_UNREAD = 0x02), so the column was permanently empty. Selecting a thread fills a reading pane below the list instead of loading a page, with previous, next and next-unread arrows. A post reached by link opens its parent threads so its row is on screen. On a phone the reader replaces the list, since two panes do not fit. Forum details moved into a dropdown off the header: description, subscribers, posts, last post, sync and storage windows, distribution, owner and anti-spam, matching what the desktop client reports. Each forum list row used to mount a component that fetched that forum's info and its whole post hierarchy. All Forums with 98 forums meant 196 requests before the list could draw. The summaries already carry the name, post count and last post, so the list makes none, and descriptions come from one batched getForumsInfo. All Forums was empty for two reasons: other_forums.js was a placeholder returning "No forums to show", and getForums had no key for the tab. Creating a forum or a thread left the modal open.
Channels uses the shared group table: icon, name, description, posts and last post. Like Forums, each row used to fetch its own channel info, so the list now renders from the summaries and takes descriptions from one batched getChannelsInfo. The channel header showed "Invalid Date" and "No Description" because readChannel ran before the fetch resolved and nothing re-read it after. A post card rendered the image and its fallback together, relying on the hidden attribute to suppress the fallback; the placeholder's display rule outranks it, so both drew. The card renders one or the other, with failed thumbnails tracked in a set rather than by writing display:none onto the DOM node. Cards also get an explicit column direction, a covering image and a single-line title so a row of them ends level. Boards and Channels detail headers use the shared page header, which drops the row that held only a back arrow and lets the phone overflow menus sit in the flow instead of being positioned against the panel.
Chat header buttons held 44px of content in a 32px box, so the labels ran outside them; the labels are in spans the stylesheet can hide. The participants sheet takes the full width on a phone rather than half the viewport. Overflow menus in Forums, Boards and Channels sized themselves from their widest button, which btn-base keeps on one line, so a long label pushed the panel off the side of the screen. Mail date column and its header are left aligned like the subject beside them, and the sender row can wrap. Debug panels and tables can shrink below their content width, and the KPI grid collapses to one column instead of overflowing at 320px. Page headers wrap on the space they have rather than at a viewport breakpoint, since each sits to the right of a 250px rail.
|
what i like without the phone issues>
on master what i changed seems not so usefull on phone when it has more then 3 entries |
|
Thanks for the ping. Full disclosure before anything else: this is an AI-assisted audit (Claude, driven by me) — several independent review passes over the diff, then each claim re-verified against the sources before it made the list. Take it for what it is worth: the line references and the reasoning are checked, but do double-check anything before acting on it, and feel free to push back on any point — some "findings" may be deliberate choices on your side. With that said: I read the whole diff (JS and SCSS) against master, rebuilt it (sass reproduces Blocks a merge
Regressions against #121
defnax's phone list, located
Emoji table
Build, a11y, misc
I checked that the #121 follow-ups not listed above are intact (channel batching, split-retry, |
|
@jolavillette feel free to send PRs for improvements, would be very helpful |
On master every create/post/add form ended its success path with popupMessage([h3 'Success' ...]), and popupMessage re-mounts #modal-container, so the form was replaced by the notice and the modal was effectively closed. The design-system branch swaps those notices for toast.success(), which does not touch the modal: the form stays open with its fields filled and its button live, and a second click creates the channel / forum / board / post / thread / identity again, re-adds the shared directory or the file, or re-sends the friend certificate. Every success branch now calls widget.closePopupMessage() before the toast. Failure branches keep the form open so the user can correct and retry, as before. The forum reply toast also says "Reply" rather than "Thread" when it was a reply. Sites: channel create/post, forum create/thread/reply, board create/post, add-friend Finish (both certificate kinds), identity create (signed and pseudonymous), identity edit (signed and pseudonymous), add shared directory, add file by link. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Seven regressions against master, each with the master behaviour as
the reference:
- The All section is back for channels, boards and forums, fed by the
full list sorted by popularity (all_*.js). Popular and Other are the
two halves of the NON-subscribed list, so the section labelled "All
Channels" hid every subscribed channel and the five most popular
ones; Other is labelled Other again. /channels/All, /boards/All and
/forums/All -- the phone default tab on master, so in bookmarks --
resolve again instead of rendering m(undefined). Forums have no
popularity split, so their empty "Other" page is gone.
- [hidden] { display: none !important } in the base sheet. The UA
sheet hides the attribute, but an author display rule on the same
element wins regardless of specificity, and the channel post
placeholder sets display: flex on itself: the "No image" box showed
under every real thumbnail. The image error fallback now clears the
attribute instead of writing an inline display.
- Distant chat: removing an attached picture clears the session's
copy too, or selectChatContact restores it and it goes out with the
next message after a contact switch.
- Ctrl/Cmd+Enter inserts a newline again in the shared composer
(execCommand first, keeps the undo stack, splice fallback), and the
field carries enterkeyhint=send again for phone keyboards.
- The in-channel post search is rendered at every width: the page
head, which hosts the channels search, is not rendered inside a
channel, so there was no post search on a desktop.
- The forum thread search shows on phones again: the <= 700px block
lost its display: flex.
- The channel and forum list filters live in module state, like the
isSearched flags they set: the field is unmounted inside a group and
recreated on the way back, and came back empty while every
non-matching group stayed hidden. Clearing the field resets the
flags instead of calling the per-forum loader with no id (which
POSTed getForumsInfo with forumIds [null]); a group reloaded while a
filter is active is filtered too. The channels and posts fields gain
a clear button.
- Modal close buttons get the 44px touch box under the touch mixin;
the 26px pointer target is what master's phone padding rule used to
correct.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
defnax's list, each located and fixed at its cause: - Phone header status pill: the header went from dark to --chrome but the pill kept near-white text over a white tint (1.2:1). Now --ink-dim on --sunken with a --line border, the dot outlined in --surface. - Composer: the <= 700px File / Picture menu came back inside the shared ChatComposer -- one paperclip opening the menu (the shared .mobile-chat-attachment rules), the two wide tools hidden there -- and the send button is a round glyph on phones, as on master. The three copies of the old menu's click-outside guard, which watched an element nothing rendered any more, are removed with it. - Emoji picker: no media rule touched .emoji-picker any more, so the 320px box anchored on the emoji tool ran past the panes' overflow: hidden. It now opens at the strip's left padding, capped to the viewport width and to the visible height. - Boards on a phone: the detail widget is a three-row grid with only two children placed, so the board's name and Subscribe button auto-placed under the post list; the heading is placed in row 2 and the body in row 3. The view toggle keeps its glyphs only, since toggle plus pagination outgrew a 360px toolbar by ~50px. - The overflow menu's Subscribe was painted as a destructive action (is-danger on both states); only Unsubscribe is. - Two blank icons: external-link-alt (Web Help "Open link") had no sprite symbol -- mapped to arrow-square-out -- and the Friends' Files friend row asked for user-friends in duotone, which does not exist; it uses users, the same glyph, which does. Not touched, as they are design calls: the --ink-dim contrast token, the contacts select sharing the tabs' row, the forum composer's picker inside its modal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Deleting a draft. The core's MessageDelete searches the received, sent, trash and outgoing boxes and never the draft box (p3msgservice.cc), so the deletes that saveDraft and the send path issued for the previous draft id always failed: every re-save of a reopened draft left a copy, and a sent draft stayed in Drafts. The new mail_api.deleteMessage() goes through the trash -- MessageToTrash does move drafts -- and chains the two calls, since fired together the delete could land first. The reading pane's Discard uses it too; it fired both at once. A draft the core keeps flagged DRAFT after a move to Trash is no longer listed in both folders. A failed draft save keeps the composer open instead of discarding the text. - identityDetails() re-fired /rsIdentity/getIdDetails on every redraw after a failed answer: the in-flight marker was cleared before the check and nothing was cached on failure, and the request's own redraw called it again from the view -- one request per unresolved address for as long as the core stayed unreachable (the RetroShare#15 class of loop). A miss is now remembered for a minute. identityLabel() asks the bulk identity list first, so a name it already knows costs no request, and the row and card fetches go through the same shared fetch instead of their own, so a first paint is one request per identity rather than two. - loadTagTypes() read res.body in the callback form, which is handed the body itself: the cache stayed empty and every tag rendered as "Tag <id>" in grey. Pre-existing; one line. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Four PRs against |
…or-129 Close the modal when its form has succeeded
Restore what the RetroShare#121 follow-ups had fixed
The phone layout items from the RetroShare#129 thread
Mail: drafts that can be deleted, identity lookups that stop
…gn-system # Conflicts: # webui-src/app/forums/other_forums.js
|
here PR for turtle page: |





















Follow-up to #121. Makes the whole web UI look like one app.
Design
Mail
Chat
Files
People, Network, Config, Boards, Channels, Forums, Statistics
Bugs fixed along the way
Other
Also includes the work from #33 and #34. Details in the commit message.