Skip to content

Save export with a Chromium picker and iOS Files #252

Description

@HMarzban

Parent

#249 Deepen the installed PWA. Sibling of #247, #248, #250, and #251. Not blocked by them.

What to build

Keep the current export pipeline. On Chromium desktop, let the user pick a save location. On iOS, offer the share sheet so they can Save to Files.

Safari, Firefox, and Android stay on the current download. Do not add a format.

Acceptance criteria

  • Word, Markdown, and OpenDocument still export the last saved snapshot through the same REST route.
  • Chromium desktop with showSaveFilePicker: the click opens that picker with a suggested name, then writes the blob.
  • The suggested name is the same string today’s download uses (Content-Disposition, or the existing slugify fallback).
  • Write once, then drop the file handle. Do not keep it for a later write.
  • If the picker is missing, throws, or the user cancels, the current download still runs. Cancel is not an error toast.
  • The picker opens in the same click. Do not open it after await fetch with no gesture.
  • iOS: if navigator.canShare accepts the file, export opens the share sheet. Copy says Save to Files, matching gallery Save.
  • iOS: AbortError from that sheet is not an error toast. If share is unavailable, keep the current download.
  • Safari on a Mac, Firefox, and Android Chrome: no picker. The current <a download> path still works.
  • A signed-in viewer under Read-only can still export. Editing lock still blocks Replace only.
  • History still has no Import and export.
  • Import still uses a hidden file input. Do not add showOpenFilePicker. Do not add capture.

Agent Brief

Category: enhancement
Summary: Chromium save location, iOS Save to Files, download everywhere else.

Current behavior:
Export fetches a blob and clicks an <a download>. Safari needs a delayed revoke. iOS often ignores download on a blob URL.

Gallery Save on iOS already uses navigator.share({ files }) and tells the user to choose Save to Files. Document Share shares a URL, not a file. Export never calls navigator.share.

File System Access is unused. Import is a hidden file input. That click stays sync so iOS will open it.

REST export needs a signed-in token. Read-only does not block export. The server names the file from Title, then slug, then id. Pad title is the client fallback.

Desired behavior:
Reuse exportDocument and the Import and export rows. Do not add pdf or EPUB. Do not change who may export.

On Chromium desktop, if showSaveFilePicker exists, open it on the click with the suggested name and the format accept type. Write the fetched blob into that handle. If anything fails, use today’s download.

On iOS, after the blob is ready, share the file when the OS allows it. Follow the gallery Save pattern. Do not send export through gallery helpers or through Document Share.

Do not use showOpenFilePicker for import. iOS has no File System Access. Do not put capture on the Word or Markdown picker. That would open the camera.

Key interfaces:

  • Export — last saved snapshot as Word, Markdown, or OpenDocument
  • Chromium save picker — optional location pick on desktop Chrome and Edge
  • iOS Files share — navigator.share of the export file
  • Download — the product path when the picker or share sheet is missing
  • Title — server filename source
  • Pad title — client fallback name only
  • Editing lock — blocks Replace, not export

Out of scope

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions