Commit Graph

6 Commits

Author SHA1 Message Date
Riley Crane
8e906bef47 fix(desktop): manage viewer panel focus and give the view picker its own row
Review P2 (#6731): in the narrow single-panel layout, opening a
document unmounted the focused attachment card and closing unmounted
the focused panel, dropping keyboard/screen-reader users onto <body>
(then the remounted channel's composer autofocus). The panel now moves
focus to its close control on mount and returns it to the opening card
on unmount, matched by data-doc-url since the original element was
remounted meanwhile; the restore yields to any control that already
claimed focus, overriding only <body> and the composer autofocus. A
narrow-layout e2e covers open-focus and Escape-restore.

Also moves the Preview/Code picker out of the title row onto its own
pinned row below the header (review feedback: the shared row squeezed
the filename out), inside the chrome-padded body since the header band
overlays anything placed after it in the header slot.

Signed-off-by: Riley Crane <rileycrane@squareup.com>
Co-authored-by: Fizz <d4ec90109b43092b0ec94cf136850915a3732a29ab3089a1dec43d2ed43dd6eb@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 13:30:51 -07:00
Riley Crane
34c9f56c0b fix(desktop): enforce the markdown viewer's 2 MiB cap natively during fetch
Routing the viewer through the generic fetch_media_bytes command meant an
attachment with a forged or absent imeta size could occupy up to the 50 MiB
download cap in memory and IPC before the frontend decoder rejected it. Add
a markdown-specific fetch_markdown_doc_bytes command whose 2 MiB cap is
owned by Rust: an oversized Content-Length is refused before the body is
read, and the streamed byte count aborts mid-transfer when the header is
missing or dishonest. The untrusted imeta pre-gate stays UX-only.

The cap checks are extracted into pure helpers (declared_length_refusal_error,
append_chunk_within_cap) so both enforcement points are unit-tested without
a Tauri State; media_download.rs tests move to a sibling file per the repo's
_tests.rs convention to stay under the per-file line cap. The panel maps the
native refusal onto the existing too-large download fallback, and new e2e
coverage proves the forged-size fallback plus the reload/back-forward
contract. The viewer command skips MIME sniffing deliberately: bytes are
strictly UTF-8-decoded and rendered escaped, and a legitimate .md may begin
with bytes that sniff as a blocked type.

Signed-off-by: Riley Crane <rileycrane@squareup.com>
Co-authored-by: Fizz <d4ec90109b43092b0ec94cf136850915a3732a29ab3089a1dec43d2ed43dd6eb@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 13:29:27 -07:00
Riley Crane
520dff6bfc fix(desktop): address markdown-viewer review findings
- Extract pane-open handlers (manage channel + markdown doc) into
  useChannelPaneOpeners, bringing ChannelScreen back under the
  1000-line file-size ratchet (1016 -> 984).
- Include the markdown doc panel in hasAuxiliaryPanel so narrow
  layouts enter single-panel view (and Escape-to-close engages)
  the same way sibling panes do, instead of squeezing the timeline.
- Key MarkdownDocPanel by URL so opening a different document resets
  the Preview/Code toggle.
- Pre-gate the open-in-viewer affordance on the advertised imeta size
  so a >2MiB .md is not fetched twice just to be refused (decoder
  still re-checks — imeta size is untrusted).
- Document the 150-line syntax-highlight cap inherited from
  SyntaxHighlightedCode in the Code view.

Signed-off-by: Riley Crane <rileycrane@squareup.com>
Co-authored-by: Fizz <d4ec90109b43092b0ec94cf136850915a3732a29ab3089a1dec43d2ed43dd6eb@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 13:29:27 -07:00
Riley Crane
332c54ea89 feat(desktop): open markdown attachments in an in-app viewer panel
Shared .md/.markdown/.mdx attachments now open in a right auxiliary
panel with a Preview/Code toggle instead of triggering a download,
mirroring berd's markdown-artifact viewer.

Nostr-specific adaptations vs berd: the relay stores markdown as
application/octet-stream ({sha256}.bin — no magic bytes), so
classification is by imeta filename only; relay media URLs require
Blossom auth (401 in plain browsers), so the panel fetches through the
authenticated fetch_media_bytes Tauri command; content-addressed URLs
allow staleTime: Infinity caching. Panel state is URL-search-param
backed (doc/docName) like the other channel panes. Strict UTF-8 decode
with a 2 MiB cap keeps binary/oversized files on the download path,
and surfaces without a panel host (forum, projects) keep download
behavior via a nullable context.

Signed-off-by: Riley Crane <rileycrane@squareup.com>
Co-authored-by: Fizz <d4ec90109b43092b0ec94cf136850915a3732a29ab3089a1dec43d2ed43dd6eb@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 13:29:27 -07:00
klopez4212
2fc8b9cf5f Apply smooth corners to inline media (#1422) 2026-07-01 07:50:26 -07:00
Wes
c27b4251a9 refactor(desktop): split global styles and markdown renderers (#1361)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
2026-06-29 12:49:36 -07:00