Files
thoughtsync/android/app/src
bvandeusenandClaude Opus 5 c8318c323a
Android / Build, or is the channel already serving this? (push) Successful in 3s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Build now, or wait for Android? (push) Successful in 3s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 2s
Desktop (Tauri) / Tauri desktop (Linux) (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Skipped
Desktop (Tauri) / Update manifest (push) Skipped
CI & Build / TypeScript typecheck (push) Successful in 7s
CI & Build / Python tests (push) Successful in 13s
CI & Build / integration (push) Successful in 22s
CI & Build / Build & push image (push) Skipped
Android / Kotlin + Rust (APK) (push) Successful in 6m21s
android: Share → ThoughtSync, and a "New note" entry in the selection toolbar
Capture without opening the app first — the input half of #1899. Two ways in:
the share sheet from anywhere, and the text-selection toolbar in any app's
text field.

## The note is created, not pre-filled

The obvious build is "open the editor on a draft holding the shared text".
That silently loses it. `NoteEditorScreen`'s flush is guarded by
`bodyText != note.body`, so a draft handed the text already has nothing to
save — share a link, press back without typing, and it is gone. Which is
exactly the shape of a share: the common case is walking away.

So `captureShared` makes the row first and opens the editor on the real
note. A share has already said "keep this"; creating it is what honours
that, and back then leaves a saved note rather than a decision.

## launchMode="singleTop"

The reminder notification adds FLAG_ACTIVITY_SINGLE_TOP to its own intent,
which is why `onNewIntent` already worked there. A share intent is built by
the OTHER app and nothing here can add a flag to it, so the activity has to
declare it. Without that, every share while the app was running would stack a
second MainActivity — a second view model, a second board, and a back press
landing on a stale copy of the same app.

## Subject and text, both

A browser sends EXTRA_SUBJECT as the page title and EXTRA_TEXT as the URL.
Keeping both makes the note read as its title, because the core names a note
by its first line — the difference between a board you can scan and a column
of identical links. `distinct` because plenty of senders put the same string
in both.

The extras are removed on read, like the reminder's note id and for the same
reason: the activity keeps its launch intent, so without consuming them a
rotation would replay the share and mint the note again.

## Not included: images

`image/*` is deliberately absent from the filter. Nothing in this app can
create an attachment — the core has `delete_attachment` and no counterpart,
and the FFI exposes neither. Declaring the mime type would put ThoughtSync in
front of people in the share sheet for a job it cannot do, and fail after
they had already chosen it. Adding it needs an attachment-creation path
through the core, the FFI and sync, which is its own piece of work.

The desktop half of #1899 — a global hotkey — is not in this commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K3MMqUtzX1TJgA1oypvm1c
2026-09-01 08:53:38 -04:00
..