Links to a post, in the web and the desktop app (#289) #304

Merged
littlefox merged 8 commits from issue-289-links into main 2026-10-23 15:45:17 +00:00
Owner

Closes #289

Links to a post that open in NeoKOM, in the browser and the desktop app (the plan on #289):

  1. kom_client::link: parse and format <server>/<kind>/<N> as a web link (https://…/#server/text/N), lyskom://server/text/N or bare, and <text N: Ämne>; the server is its canonical-name (aux 31; kom.lysator.liu.se sets it, a logged-out probe), else the address logged in to. Unit tests incl. random input.
  2. Copy and open: "Kopiera länk" in a post's ··· menu; opening from Ctrl+K and the channel/post field; a link for another server says so; a missing or unreadable post gets the same message; a link pasted into the composer becomes <text N: Ämne>; the post opens in its thread, briefly highlighted, not read.
  3. Web: the link after # (the server never sees it), kept through the login page, cleared once opened; hashchange opens new ones.
  4. Desktop: neokom.desktop handles x-scheme-handler/lyskom (Exec=neokom %u); one app at a time — a second launch hands its link over a socket in $XDG_RUNTIME_DIR and exits; NeoKOM links inside posts open in the app.

The devserver now sets canonical-name (dev.neokom.test).

Verified: new e2e/tests/share-links.spec.ts (logged out → log in → post shown and highlighted; address change; another server; unreadable post; Ctrl+K; copy; pasted link → reference) in desktop/android/iphone; full e2e suite 377 passed; desktop smoke test with a second neokom lyskom://… handing over (one session, the post shown); lint with CI's three clippy commands; unit tests; screenshots looked at.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XJW2ocwLunyaLiUwCBHEP8

Closes #289 Links to a post that open in NeoKOM, in the browser and the desktop app (the plan on #289): 1. **`kom_client::link`**: parse and format `<server>/<kind>/<N>` as a web link (`https://…/#server/text/N`), `lyskom://server/text/N` or bare, and `<text N: Ämne>`; the server is its `canonical-name` (aux 31; kom.lysator.liu.se sets it, a logged-out probe), else the address logged in to. Unit tests incl. random input. 2. **Copy and open**: "Kopiera länk" in a post's ··· menu; opening from Ctrl+K and the channel/post field; a link for another server says so; a missing or unreadable post gets the same message; a link pasted into the composer becomes `<text N: Ämne>`; the post opens in its thread, briefly highlighted, not read. 3. **Web**: the link after `#` (the server never sees it), kept through the login page, cleared once opened; `hashchange` opens new ones. 4. **Desktop**: `neokom.desktop` handles `x-scheme-handler/lyskom` (`Exec=neokom %u`); one app at a time — a second launch hands its link over a socket in `$XDG_RUNTIME_DIR` and exits; NeoKOM links inside posts open in the app. The devserver now sets canonical-name (`dev.neokom.test`). Verified: new `e2e/tests/share-links.spec.ts` (logged out → log in → post shown and highlighted; address change; another server; unreadable post; Ctrl+K; copy; pasted link → reference) in desktop/android/iphone; full e2e suite 377 passed; desktop smoke test with a second `neokom lyskom://…` handing over (one session, the post shown); lint with CI's three clippy commands; unit tests; screenshots looked at. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01XJW2ocwLunyaLiUwCBHEP8
"Kopiera länk" gives a link that opens the post in NeoKOM for anyone
who can read it: the server's canonical-name and the post's number after
the page's #, so the web server never sees it. Links open from the
address (kept through the login), from Ctrl+K and from the post field;
one for another server says so, and a pasted link becomes <text N: …>
in a post. kom.lysator.liu.se sets canonical-name (a logged-out probe);
the devserver now does too. The desktop lyskom:// handler is step 4.

Refs #289

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJW2ocwLunyaLiUwCBHEP8
neokom.desktop registers x-scheme-handler/lyskom, so the OS runs
neokom with the link. If NeoKOM is already running, the new launch
hands the link over a socket in XDG_RUNTIME_DIR and exits: one login,
not two. A NeoKOM link inside a post opens in the app too, not in a
new browser tab. The desktop smoke test checks the hand-over.

Closes #289

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJW2ocwLunyaLiUwCBHEP8
Roadmap: links done
Some checks failed
ci / check (push) Successful in 10m51s
packaging / arch (pull_request) Successful in 14m57s
ci / desktop (push) Successful in 17m45s
packaging / debian (pull_request) Successful in 18m23s
packaging / fedora (pull_request) Successful in 33m49s
packaging / nix (pull_request) Has started running
ci / e2e (push) Failing after 39m5s
packaging / release (pull_request) Has been cancelled
cac67514d9
Refs #289

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJW2ocwLunyaLiUwCBHEP8
Test: open an ordinary post by link, not a footnote
Some checks failed
ci / check (push) Successful in 10m6s
packaging / arch (pull_request) Successful in 15m52s
ci / desktop (push) Successful in 18m16s
packaging / debian (pull_request) Successful in 21m23s
packaging / fedora (pull_request) Successful in 31m50s
ci / e2e (push) Failing after 36m17s
packaging / nix (pull_request) Failing after 32m49s
packaging / release (pull_request) Has been cancelled
746ab1a597
Post 58 is the footnote to 57, so since #277 it opens as 57 with the
footnote highlighted; whether the head showed 57 or 58 depended on
timing (failed once on CI, iPhone). 59 is a comment.

Refs #289

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJW2ocwLunyaLiUwCBHEP8
Merge main into issue-289-links
Some checks failed
ci / check (push) Successful in 12m27s
packaging / arch (pull_request) Successful in 17m1s
ci / desktop (push) Successful in 18m30s
packaging / debian (pull_request) Successful in 25m6s
packaging / fedora (pull_request) Successful in 35m59s
ci / e2e (push) Failing after 42m10s
packaging / nix (pull_request) Successful in 20m57s
packaging / release (pull_request) Has been skipped
c9e768ff84
Merge remote-tracking branch 'origin/main' into issue-289-links
All checks were successful
ci / check (push) Successful in 10m19s
packaging / arch (pull_request) Successful in 17m18s
ci / desktop (push) Successful in 17m29s
packaging / debian (pull_request) Successful in 24m48s
packaging / fedora (pull_request) Successful in 34m46s
ci / e2e (push) Successful in 43m23s
packaging / nix (pull_request) Successful in 20m50s
packaging / release (pull_request) Has been skipped
85e02a3656
# Conflicts:
#	app/src/i18n.rs
#	app/src/main.rs
#	docs/DESIGN.md
#	docs/ROADMAP.md
Merge remote-tracking branch 'origin/main' into issue-289-links
All checks were successful
ci / check (push) Successful in 8m28s
packaging / arch (pull_request) Successful in 13m57s
ci / desktop (push) Successful in 18m16s
packaging / debian (pull_request) Successful in 23m56s
packaging / fedora (pull_request) Successful in 29m6s
ci / e2e (push) Successful in 36m33s
packaging / nix (pull_request) Successful in 20m55s
packaging / release (pull_request) Has been skipped
44ac09abc3
# Conflicts:
#	app/src/i18n.rs
#	app/src/main.rs
littlefox referenced this pull request from a commit 2026-10-24 13:23:56 +00:00
Sign in to join this conversation.
No description provided.