Skip to content

Take core 7.1.0, and edit with the editor the page now carries - #662

Merged
andiwand merged 7 commits into
mainfrom
core-7-editing
Sep 20, 2026
Merged

andiwand merged 7 commits into
mainfrom
core-7-editing

Conversation

@andiwand

@andiwand andiwand commented Sep 18, 2026

Copy link
Copy Markdown
Member

In core 7, editing is part of the rendered page. The page owns the edit mode, the operation log, undo and the refusals. A pdf page also gets an annotator. This PR drives that page from the app, and it takes core 7.1.0, which has the fixes and additions this PR needs (see below).

What changes

  • The core bump. CoreLoader follows the API breaks: DecodeOptions, Html.translate without a cache path, Document.edit, and csv and markdown files that hold a text file rather than being one.

  • What can be changed is one answer from the core. CoreLoader.editingOf returns an EditingKind: DOCUMENT (odt, docx, pptx), SHEET (ods, xlsx), TEXT (txt), ANNOTATION (pdf), or NONE. The file answers for itself, so a decrypted document or a repaired pdf says no.

  • No second render for the edit mode. A document that can be written back is rendered with its editor. The edit button calls odr.editing.enable(), so the reader stays where they were.

  • The page decides, and the app only listens. PageView injects editing-bridge.js on each page load. The script points the page's callbacks (onEditChange, onEditRefused, onSelectionChange, onCellsStale, onAnnotationChange) at PageView, and turns on markOnSelection. It holds no logic. A pdf tool button calls odr.annotation.press or recolor, and the page decides what the press does to a selection.

  • No document stays open between the render and the save. CoreLoader.writeEdits opens the cached copy again and applies the payload with the call for its kind: Document.edit and save, TextFile.edit and save, or PdfFile.annotate.

  • The UI follows the website's viewer, and matches OpenDocument.ios 3.10.0 #195. The bar of the edit mode holds save. Under the bar, a row holds the tools, with undo and redo at its end:

    • a document: bold, italic, underline, strikethrough, text color (opens the colors), highlight (toggles; its arrow picks the color) and text size, which shows the size of the selection;
    • a pdf: highlight, underline, strike out, squiggly and draw. Each tool has its own color and an arrow to pick it. A tool tapped with text selected marks the selection once and arms nothing. A pdf has undo only;
    • a sheet or a plain text file: undo and redo.

    The color bars follow the selection. Both apps offer the same colors. iOS adds "Other color…" from the system picker, which Android does not have. A save stays in the edit mode.

  • Leaving the edit mode with unsaved edits asks to save or discard them. Before, closing the bar dropped the edits without a question.

  • A refusal from the page (a formula cell, a range over a picture, and so on) shows as a snackbar in our own words. When an edit leaves formula cells out of date, a snackbar shows their count each time the count grows.

Pro and lite

The same line as OpenDocument.ios #195. Features.advancedEditing comes from ADVANCED_EDITING, next to LINKS_ADS in Linked.kt. It is false in lite, and true in pro and foss (which share noAds). Features.offersEditing is the one list of what each edition edits.

lite pro, foss
text inside one paragraph (odt, odp, odg, docx, pptx) yes yes
sheet cells (ods, xlsx) yes yes
plain text (txt) yes yes
split or merge a paragraph, formatting tools shown behind a "Pro" badge; offers Pro, once per edit yes
mark up a pdf the button offers Pro yes

The Edit button depends on the core's answer in every edition. The offer is a dialog with "Get Pro" and "Not now". It is reported as pro_gate_shown / pro_gate_tapped with the feature, as on iOS. Lite renders a text document with HtmlEditingScope.PARAGRAPH, so the page itself refuses an edit that reaches past one paragraph (outOfScope).

This is different from OpenDocument.core/offline/feature-gate-plan.md, which put sheet cells and plain text on the Pro side. We decided to make them free in both apps.

What core 7.1.0 brings to this PR

Checked

On core 7.1.0, on an API 31 emulator with Gboard:

  • spotlessCheck, assembleDebug (three flavors), lintProDebug, lintLiteDebug, lintFossDebug and testProDebugUnitTest pass.
  • CoreTest: 21 of 21 pass, with save round trips for odt, docx, pptx, pdf annotation and txt.
  • MainActivityTests: 16 of 16 pass in pro and in lite. They check each edition's side of the gate: a sheet edits in both, a pdf offers Pro in lite, and the scope is paragraph in lite.
  • By hand in pro: text typed with Gboard into an odt is in getOperations() as setText, and Enter is splitParagraph. Leaving the edit mode asks about the unsaved edits, and Discard leaves a clean page.
  • By hand in lite: typed text is recorded. Enter is refused (no splitParagraph) and offers Pro.
  • By hand on a pdf: a tool tapped over a selection marks it once and arms nothing. A tool tapped without a selection arms, and a second tap disarms. Undo removes the mark and disables the Undo button.
  • On core 7.0.0, before the bump: 94 instrumented tests, and a pdf and a sheet saved through the picker and opened again.

New strings are translated into all 19 locales. ga, hi, ko and et have no iOS text to follow, so they need a review by a native speaker.

Not in this PR

  • Store screenshots per flavor. The UI now differs between lite and pro, so the screenshot set has to split. That is the next step.
  • The Play listing and the house ad do not yet say what Pro edits (step 3 of the plan).

Core 7.0.0 moves editing into the rendered page: the page owns the edit
mode, the operation log, undo and the refusals, and a pdf page gets an
annotator. The app now drives that page instead of reloading it.

- CoreLoader follows the API breaks: DecodeOptions, translate without a
  cache path, Document.edit, and csv and markdown files that hold a text
  file rather than being one.
- CoreLoader asks the opened file what the user can change and returns
  an EditingKind: a document, a sheet, a plain text file, or a pdf to
  mark up. A document that can be written back is rendered with its
  editor, so the edit button only turns the page's mode on.
- No document stays open between the render and the save. writeEdits
  opens the cached copy again and applies the page's payload through
  Document.edit, TextFile.writeEdited or PdfFile.annotate.
- The edit mode's bar gets undo and redo, and a strip of tools under it:
  bold, italic, underline, strikethrough, text colour, highlight and size
  for a document, and five marking tools for a pdf. This is the layout of
  the viewer on the website.
- Features.withAdvancedEditing is false in lite. Lite renders with the
  editing scope "paragraph", so the page refuses an edit that splits or
  merges a paragraph. Lite also shows the formatting tools locked, and
  the pdf button. Each of them offers Pro instead of acting.
- Leaving the edit mode with unsaved edits asks to save or discard them.
  Before, the edits were dropped without a question.

Known gap, in core: document.js drops text that an Android keyboard
types, because the keyboard keeps a composition open. See the pull
request.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F6AQY2k86AaPq12nxBfN7A
andiwand and others added 3 commits September 18, 2026 21:15
The plan (OpenDocument.core offline/feature-gate-plan.md) keeps free
what the free app shipped: an edit inside one paragraph of a text
document or a presentation. Sheet cells, plain text files and pdf marks
are Pro's, with paragraphs and formatting.

- The flag is ADVANCED_EDITING in Linked.kt, beside LINKS_ADS, as
  OpenDocument.ios has it. It is no longer a buildConfigField.
  Features.offersEditing is the one list of what an edition edits.
- In lite, the Edit button over a sheet, a plain text file or a pdf
  offers Pro. Such a document is rendered without the editor.
- The offer is a dialog with "Get Pro" and "Not now". A refused edit
  that reaches past one paragraph raises it once per edit.
- The new strings are translated into the 19 locales.
- The instrumented tests check each edition's side of the gate, and the
  README says why the F-Droid build has what free lacks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F6AQY2k86AaPq12nxBfN7A
Lite now gates only what goes past typing inside a paragraph: new and
joined paragraphs, formatting, and marks on a pdf. A sheet cell and a
plain text file are edited in every build, so a sheet is rendered with
its editor in lite too.

The Pro offer is named by feature, formatting or pdf, and is reported
as pro_gate_shown and pro_gate_tapped, the events iOS reports for the
same gate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F6AQY2k86AaPq12nxBfN7A
- Undo and redo leave the bar and end the tool row, for every kind of
  document: a sheet and a plain text file now get a row with only these
  two. The bar keeps save.
- Text color is one control that opens the colors. Its bar and the
  highlight's bar follow the selection, as the website's do.
- The colors are the set both apps offer. The first of each set is the
  website's default.
- The notice about formula cells shows when their count grows, and not
  when an undo brings it down.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F6AQY2k86AaPq12nxBfN7A
Core 7.1.0 records what an Android keyboard types into a document
(OpenDocument.core#905). Before, a save lost it. The release also adds
odr.onAnnotationChange and odr.annotation.press and recolor
(OpenDocument.core#906).

- editing-bridge.js only points the page's callbacks at PageView, and
  sets markOnSelection. The count of marks now comes from
  onAnnotationChange, so the bridge no longer counts after each pointer
  event.
- PageView calls odr.annotation.press, recolor, undo and setTool
  directly.
- CoreLoader writes a plain text file with TextFile.edit and save,
  because writeEdited is deprecated. It also hands an empty envelope to
  Document.edit. Neither 7.0.0 nor 7.1.0 refuses one, so the guard and
  its comment were wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H3sFjPT7zd8fvmpqhznzEP
@andiwand andiwand changed the title Take core 7.0.0, and edit with the editor the page now carries Take core 7.1.0, and edit with the editor the page now carries Sep 19, 2026
andiwand and others added 2 commits September 19, 2026 10:46
- DocumentSaver passes LoadedDocument.editing to CoreLoader.writeEdits,
  so a save no longer opens the document a second time only to ask what
  kind it is.
- The page callbacks that show a snackbar or a dialog return if the
  fragment is detached.
- The comment in fragment_document.xml said that the tools are gone for
  a sheet and a plain text file. Both show undo and redo.
- writeEdits no longer logs the payload, which holds the user's text.
- The comments are shorter. The reasons are in the PR and in CLAUDE.md.
- CHANGELOG.md has entries for the edit mode, pro and the core 7
  rendering fixes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H3sFjPT7zd8fvmpqhznzEP
In lite, the banner sat between the edit mode's bar and its tools,
because the banner is in the activity layout and the tools were in the
fragment. The tool row is now in main.xml, above the banner.
DocumentFragment still drives it, and hides it when its view goes away.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H3sFjPT7zd8fvmpqhznzEP
@andiwand
andiwand marked this pull request as ready for review September 19, 2026 09:52
@andiwand
andiwand merged commit c475621 into main Sep 20, 2026
6 of 7 checks passed
@andiwand
andiwand deleted the core-7-editing branch September 20, 2026 07:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant