Skip to content

Land share-email links in the Dashboard's Shared view - #3634

Merged
Salazareo merged 3 commits into
mainfrom
share-links-land-on-dashboard-shared
Aug 25, 2026
Merged

Land share-email links in the Dashboard's Shared view#3634
Salazareo merged 3 commits into
mainfrom
share-links-land-on-dashboard-shared

Conversation

@jelveh

@jelveh jelveh commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

What

When files are shared, the recipient's email carries links to each file and an "Open Puter" button. All of them now take the recipient to the Dashboard's Files tab, with Shared selected in the sidebar and the newly shared files highlighted. Previously the file links opened the item on the desktop and "Open Puter" went to the bare origin (Home).

Backend

  • shareDeepLink.ts: sharedViewLink(origin, paths) builds /?shared=a&shared=b (deduped, capped at 20 items so mail clients don't truncate; with no items it is /?shared=, which still lands on Shared). shareDeepLink delegates to it, so per-file links are unchanged.
  • ShareNotificationService / shareNotifyTitle.ts: digest items keep their masked path; the "Open Puter" button links to Shared with every item in the mail highlighted. Older KV digest records without path degrade to a plain Shared link.
  • templates.ts: the button href is triple-braced like the item links (=/& stay literal in html and text); the unsubscribe link is built from a separate origin value.

GUI

  • initgui.js: /?shared= boots the dashboard (route { tab: 'files', shared: [...] }) instead of the desktop; /desktop?shared= keeps opening the item in place. A share link never mints a temp user (same rule as app landings).
  • UIDashboard.js: consumes the route → Files tab on window.shared_path, strips the param (replaceState/#files). An existing temp session gets the login cover first, mirroring the desktop handler.
  • TabFiles.js: after the Shared listing renders, rows are selected by uid (rename-proof). selectUploadedRows is refactored onto a shared selectRowsWhere.
  • clear_shared_param moves into helpers/parse_shared_path.js so both shells share it; shared_uids_from_paths added to share_paths.js.

Verification

  • Backend share/email suites 202/202, GUI vitest 344/344, npm run typecheck clean. New tests: multi-item link (order, dedupe, cap, empty), digestItemPaths, template rendering of the button, and the button in the real send path (shareEmail.test.ts).
  • Live, against a local server with a real captured digest email: per-file links and a two-item "Open Puter" href. Single link → Files / Shared / one row selected; button → both rows selected; URL cleaned to /#files. Signed out → sign-in cover with ?shared= intact, lands correctly after sign-in. /desktop?shared= still opens the file in the editor.

Notes

  • Highlighting covers the items the email names (DIGEST_NAMES_PER_SENDER, 5 per sender per batch); "+N more" items aren't highlighted.
  • Not browser-tested: the temp-session prompt path in UIDashboard (no temp session at hand; the code mirrors the desktop's).
  • Pre-existing duplication left alone: helpers/parse_shared_path.js and helpers/share_paths.js both parse the same path shape — worth folding together separately.

A share email's links opened the item on the desktop, and "Open Puter"
went to the bare origin — the recipient arrived on Home with nothing to
say what had just been shared. Every link now lands in the Dashboard's
Files tab, on Shared, with the shared items selected.

Each named file still links to itself. "Open Puter" carries every item
in the mail (?shared=a&shared=b), so the whole batch lands highlighted;
the digest records now keep each item's masked path for that. The
button's href is rendered raw like the item links, so `=` and `&` read
the same in the html and text parts, and the unsubscribe link is built
from a separate origin value.

On the GUI side `/?shared=` boots the dashboard rather than the desktop;
`/desktop?shared=` keeps opening the item in place. The Files tab
selects the rows by uid, which survives a rename. A share only reaches a
real account, so a share link never mints a temp user and an existing
temp session is asked to sign in first, as the desktop already did. The
address-bar cleanup both shells need moves into a helper.
@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 93.64%
🟰 ±0%
24453 / 26112
🔵 Statements 91.91%
⬆️ +0.01%
26395 / 28716
🔵 Functions 89.79%
🟰 ±0%
4252 / 4735
🔵 Branches 80.38%
⬆️ +0.02%
17766 / 22102
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/backend/clients/email/templates.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
src/backend/services/share/ShareNotificationService.ts 86.56%
🟰 ±0%
78.69%
🟰 ±0%
93.93%
🟰 ±0%
88.88%
🟰 ±0%
55, 86, 88-90, 99, 112, 126, 180, 249, 252, 315, 341-342, 351-356, 363-364, 388, 399, 453, 471, 492-495, 511-514, 519, 526-530, 593-605, 621, 642-643, 655
src/backend/services/share/shareDeepLink.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
src/backend/services/share/shareNotifyTitle.ts 100%
🟰 ±0%
92.85%
⬆️ +0.55%
100%
🟰 ±0%
100%
🟰 ±0%
Generated in workflow #824 for commit 081cb88 by the Vitest Coverage Report Action

jelveh added 2 commits August 24, 2026 15:59
The "Open Puter" link names every item in the mail, capped at twenty. But
a single item's parameter is ~150 characters once the owner, uuid and an
encoded name are in it, so twenty of them run to several kilobytes — past
the ~2000 characters where older mail clients cut a URL off or stop making
it clickable — and the count alone couldn't do what its comment promised
for the mail's primary button.

Add a length budget beside the count: items go in, in digest order, only
while the whole link stays under it, so the button always works and the
first items are the ones highlighted. A single item always fits.
`shareDeepLink` now builds through `sharedViewLink`, whose length budget
applied to the first item too: a parameter that alone overran it was
dropped, and the link came out as a bare `?shared=`. A name of a few
hundred characters — the GUI allows five hundred, and encoding triples
every non-ASCII one — was enough, so that item's own link in the mail
landed on Shared with nothing picked out, where it used to open the item.

The first item now always goes in; the budget only decides how many more
join it. One long link is still the item the mail is about, and it is no
worse than a bare origin for the clients that truncate it.
@Salazareo
Salazareo merged commit 2c9a5c4 into main Aug 25, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants