Repository navigation
Conversation
Store normalized shared tags in existing session metadata and apply permission-checked Add/Remove patches atomically without changing recency. Add personal match-all filters and native single/batch tag editors while preserving existing search, views and mobile hold actions. Cover validation, authorization, concurrency, persistence and responsive UI regressions; document the feature and storage model.
Reclaim idle title space without moving the opening target, paint the complete session item, and separate tags from the title. Preserve Lantern styling and use a text-only batch Edit tags action. Add real-browser regressions for layout, hit testing, themes, and action consistency.
# Conflicts: # docs/features.md # docs/map.md
…actions Adds four experimental pocket members, and WebRequest.sessions on the server: - pocket.sessionChips: chips under a row's title; a chip with run is a button. - pocket.sessionSearch: words that the list's search and the launcher match. - pocket.sessionFilter: a button in the search field; while match is set, the list shows only what every filter that is on keeps. - pocket.sessionAction: an action in a held row's sheet and the selection bar. - request.sessions(): the sessions the person can see, so routes check ids with core's own rule. A function that throws stops its module, and the list draws without it. Theme parts: session-chips, session-chip, session-filter. From the review of #118 by Jeroen Dee (@jeroendee): the mechanism goes to core as extension points (C7), and tags become an extension.
Shared tags on sessions, built only on host, web, and the session list's extension points: chips on rows, a tag filter beside the search (a tap on a chip filters too), tags in the search and the launcher, and Edit tags for a held row, selected rows, or the open session. Tags are lowercase, 32 characters, 10 a session at most; a change is all or nothing. Routes check ids with request.sessions(), and each person gets only the tags of sessions they see. Viewers read and filter; people invited to one session do not load it. Based on #118 by Jeroen Dee (@jeroendee), which first put tags in core. Thanks to Jeroen Dee for the feature, its design, and its limits. Tested: test/session-tags.test.ts, test/session-list-extensions-ui.test.ts, npm run check, lint, format, docs-site check, and the full npm test.
Splits #118 by Jeroen Dee (@jeroendee): the session list gets experimental extension points, and tags become a built-in extension, off by default. Thanks to Jeroen Dee for the feature and its design.
- sessionAction takes icon or iconPath: the first such action is also a button on rows, beside archive, pin, and mark unread. Session tags' Edit tags is one. - sessionFilter takes started(id): New in the Sessions head, while the filter is on, gives the new session to it. Session tags tags it with the chosen tags, so it stays in the filtered list. - Session tags shows what a save answered at once, and looks again when the tab comes back: an event sent while the tab reconnects is lost. - On a server older than 0.20.0 the module adds nothing. Such a server loads the file when its checkout moves, and would turn it on without the core it needs. A server that runs 0.20.0 turns it on and off with no restart. Both are from #118 by Jeroen Dee (@jeroendee). Tested: npm run check, lint, the new and changed tests, and the full npm test (395 of 397; the 2 timing tests that failed under load pass alone).
|
Thank you, @jeroendee! This is a great feature, and your PR made the case for it clearly. Tags ship in 0.20.0, in a different shape from this PR, so I'm closing it. Why the change: under our core-or-extension policy, tags are a way to organize work that only some people want (C6). The session list's mechanism goes into core instead, and the tags workflow becomes an extension on top of it (C7). Other extensions can then use the same hooks for status labels, priorities, and similar. What is on
Tags are stored in the extension's own document, not on You're credited in the commits (668c65b, e191b32, d8b14c4, 0aa7195) and in the policy doc's example section. If you try the release branch and something from your design is missing or feels off, please open an issue. Thanks again! |
Summary
Proof
Original feature evidence:
a5774cc(current PR head:7a264a3). Real isolated app on Linux/Chromium; 19 synthetic sessions seeded with 133 tags and a scripted model. No mocked HTTP responses or production data.X-Pocket→ 403Original validation (
a5774cc):npm run check,npm run lint,npm test→ 422/422 pass, zero failures/skips. Format, syntax and whitespace checks pass. The committed files match the validated tree.20-second end-to-end demo:
end-to-end-20s.mp4
API contract and actual response
Authenticated
POST /api/sessions/tags: positive-integerids[]; optionaladd[]/remove[]names. Names are trimmed/lowercased, 1–32 characters; at most 10 tags per session. Success is{ok:true}; errors are{error:string}.Actual browser request and response:
Subsequent
GET /api/sessionsconfirms both gainedreviewed, only session 3 lostshipping, and other labels/updatedAtsurvived. A batch exceeding 10 tags returned409 {"error":"A selected session would have more than 10 tags. Nothing was saved."}; before/after metadata matched. WithoutX-Pocket:403 {"error":"Missing X-Pocket header"}, no mutation.Screenshots of changed screens and resulting state
All at
a5774cc; phone captures use the identical precommit tree.16-second phone journey:
filter-phone-16s.mp4
Before → after regressions
List title space:

38979b5→a32e21f(254px list).Search wording:

a92cd21→6beba9d(unchanged sidebar width).Filter inventory:

6beba9d→a5774cc(390×844, same synthetic vocabulary).New sessions inherit active tags
At
7a264a3, select tags → Done → Sessions New → folder picker Open creates a session with all selected tags, saved in the initial creation transaction. In the actual native journey,POST /api/sessionswithtags: ["polish", "review"]returned HTTP 200 and opened session 29; its stored metadata and matching list row contained both tags. No follow-up tag patch was needed.Creation regressions pass at desktop, 390×844 and 320×500, including reload persistence, unchanged no-filter behavior, and rejection of 11 tags without partial creation. Backend tests also verify restart persistence. The complete current candidate passed 439/439 tests, zero failures/skips; exact-revision type/lint and regression checks pass.
session-tags-polish-22s.mp4
Local isolated app, real routes/assets and synthetic data; phone sizes use Chromium emulation. Other text/view constraints can still hide a new session.
Limits: local/emulated Chromium, not production, physical-device or screen-reader acceptance. At 320×500, ~3px of the results' lower border initially clips; ~7px outer scrolling reveals it, with all actions reachable. Capture setup needed selector/timing corrections and one aborted-reload retry; the final recorded journey passes.