You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Receive a shared file on Android, and share a chat URL on iOS #253
#249 Deepen the installed PWA. Sibling of #247, #248, #250, #251, and #252. Not blocked by them.
What to build
On an installed Android Chrome PWA, accept a shared Word or Markdown file and open it as a new pad.
iOS has no Share Target. Do not claim it does. On iOS, Chat Share must open the OS share sheet for the chat URL, the same way Document Share already shares a pad URL.
Acceptance criteria
/receive is a Next page (same shape as /new and /privacy). It is not a pad named receive. Add /receive to UTILITY_PATHS and receive to RESERVED_SLUGS.
/share is unchanged. It still opens a pad named share if someone visits it.
Manifest share_target action is same-origin /receive. Scope stays /. Do not change manifest id (docs-plus-pwa).
Installed Android Chrome: Share to docs.plus with a .docx or .md file lands on /receive, then a new pad, then the existing import convert and apply flow.
The custom service worker intercepts POST /receive, keeps one file that existing Import would accept (same types, 10 MB cap), and replies with a redirect to GET /receive. Any other POST is ignored.
/receive then location.replace('/new'). That leaves the pad that was already open. Never setContent on that prior document id.
After /new lands, the new pad is the only reader of that stash. It waits until the slug has a DocumentMetadata row the same way a normal first open does, and until a session JWT exists. Then it calls existing importDocument and the Settings apply path, then deletes the stash. One consumer. /receive does not import after the replace.
Signed-out: show Sign in on /receive and drop the stash. Do not keep the file across sign-in. The user shares again after they sign in.
A tab that is not the installed Android app does not have to show the target.
iOS Safari and the iOS Home Screen app: docs.plus does not appear as a receive target. No fake target.
iOS inbound file stays the existing Import picker. That click stays sync. No capture.
iOS and other browsers with Web Share: Chat Share opens navigator.share with the chat URL. Copy stays the fallback.
Private pad: Document Share still blocks a public post. Chat Share of a URL may use the sheet or copy. It must not add social posts.
No new Next pages/api route. No rest-api share endpoint. Health, Validate, and Status stay as they are.
file_handlers is not added.
Agent Brief
Category: enhancement Summary: Android Share Target into a new pad. iOS can share a chat URL out. iOS cannot receive.
Current behavior: UTILITY_PATHS is /privacy and /terms only. /new is a real page that redirects to a random slug. /share is not reserved. [...slugs] would treat it as a pad.
The manifest has no share_target and no file_handlers. launch_handler is navigate-existing.
Document Share uses navigator.share with title, text, and URL when the pad is not Private. Chat Share only copies the chat URL. Gallery Save on iOS shares a file.
Next pages/api keeps only Health. A share action cannot live on rest-api if that host is outside the PWA scope.
Import already converts .docx and .md on a live pad. Media insert needs a live editor. A share must not land on Home with no editor. Import needs a DocumentMetadata row and a signed-in token. /new only redirects; it does not stamp ownerId.
Desired behavior:
Add /receive as a utility page. Register share_target for files only, accept Word and Markdown, same as Import.
The worker holds the file from the Android share POST, then the page goes through /new so navigate-existing leaves the current room. The new pad is the only consumer of that stash. Then run existing Import on that new slug. Do not insert into the open document. Do not import on /receive after the replace.
Signed-out users sign in, then share the file again. Do not keep the blob across an auth change.
iOS: leave receive unimplemented. The honest inbound path is Import. Cover iOS on the way out: Chat Share uses the OS sheet when navigator.share exists, and copy when it does not. Document Share already does this for the pad URL. Do not route Chat Share through gallery file helpers.
Key interfaces:
/receive — utility page for Share Target. Not a pad. Redirects; does not import.
Share Target — Android Chromium installed PWA only
Stash — one-shot file in the worker; the new pad reads it once and deletes it
Import — existing Word and Markdown convert and apply
/new — leave the open room, then land on a new slug
Document Share — pad URL out; already uses the OS sheet
Chat Share — chat URL out; must use the OS sheet on iOS
Editing lock — import still needs a writable pad on the new document
Out of scope
iOS Share Target (the OS does not offer it)
file_handlers
Sharing into the already-open pad
Images, plain text, or a URL as the first receive payload
Spec review: concrete receive path — worker POST stash, GET /receive, replace /new, then existing Import. Signed-out drops the file. Do not change manifest id.
Parent
#249 Deepen the installed PWA. Sibling of #247, #248, #250, #251, and #252. Not blocked by them.
What to build
On an installed Android Chrome PWA, accept a shared Word or Markdown file and open it as a new pad.
iOS has no Share Target. Do not claim it does. On iOS, Chat Share must open the OS share sheet for the chat URL, the same way Document Share already shares a pad URL.
Acceptance criteria
/receiveis a Next page (same shape as/newand/privacy). It is not a pad namedreceive. Add/receivetoUTILITY_PATHSandreceivetoRESERVED_SLUGS./shareis unchanged. It still opens a pad namedshareif someone visits it.share_targetaction is same-origin/receive. Scope stays/. Do not change manifestid(docs-plus-pwa)..docxor.mdfile lands on/receive, then a new pad, then the existing import convert and apply flow./receive, keeps one file that existing Import would accept (same types, 10 MB cap), and replies with a redirect to GET/receive. Any other POST is ignored./receivethenlocation.replace('/new'). That leaves the pad that was already open. NeversetContenton that prior document id./newlands, the new pad is the only reader of that stash. It waits until the slug has a DocumentMetadata row the same way a normal first open does, and until a session JWT exists. Then it calls existingimportDocumentand the Settings apply path, then deletes the stash. One consumer./receivedoes not import after the replace./receiveand drop the stash. Do not keep the file across sign-in. The user shares again after they sign in.capture.navigator.sharewith the chat URL. Copy stays the fallback.pages/apiroute. No rest-api share endpoint. Health, Validate, and Status stay as they are.file_handlersis not added.Agent Brief
Category: enhancement
Summary: Android Share Target into a new pad. iOS can share a chat URL out. iOS cannot receive.
Current behavior:
UTILITY_PATHSis/privacyand/termsonly./newis a real page that redirects to a random slug./shareis not reserved.[...slugs]would treat it as a pad.The manifest has no
share_targetand nofile_handlers.launch_handlerisnavigate-existing.Document Share uses
navigator.sharewith title, text, and URL when the pad is not Private. Chat Share only copies the chat URL. Gallery Save on iOS shares a file.Next
pages/apikeeps only Health. A share action cannot live on rest-api if that host is outside the PWA scope.Import already converts
.docxand.mdon a live pad. Media insert needs a live editor. A share must not land on Home with no editor. Import needs a DocumentMetadata row and a signed-in token./newonly redirects; it does not stampownerId.Desired behavior:
Add
/receiveas a utility page. Registershare_targetfor files only, accept Word and Markdown, same as Import.The worker holds the file from the Android share POST, then the page goes through
/newsonavigate-existingleaves the current room. The new pad is the only consumer of that stash. Then run existing Import on that new slug. Do not insert into the open document. Do not import on/receiveafter the replace.Signed-out users sign in, then share the file again. Do not keep the blob across an auth change.
iOS: leave receive unimplemented. The honest inbound path is Import. Cover iOS on the way out: Chat Share uses the OS sheet when
navigator.shareexists, and copy when it does not. Document Share already does this for the pad URL. Do not route Chat Share through gallery file helpers.Key interfaces:
/receive— utility page for Share Target. Not a pad. Redirects; does not import./new— leave the open room, then land on a new slugOut of scope
file_handlersid