Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ release; it refuses a version without one. `scripts/store-copy.py` writes Play's

## Unreleased

- Spreadsheet cells can be formatted: fill, bold, italic, underline, strikethrough,
text color, size and alignment. The fill is in every edition.
- Paragraphs in a document can be aligned left, center, right or justified.
- A space typed into a document or a cell shows, and saving no longer turns spaces
into no-break spaces.
- Spreadsheet fills show their real colors, and keep them in night mode.
- A document no longer loads images from the internet, and only a web link leaves it.

## 4.20.1

- A selection in a PDF covers the spaces between words, and no longer drifts to the
Expand Down
11 changes: 6 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,15 @@ says whether a password is worth asking for.

**The gate is on the tool, not on the mode.** Every edition opens every editable kind, so
`Features.offersEditing` is the core's answer alone. A locked `EditingTools` dims what is
pro and leaves the highlighter working, in documents and in pdfs. Do not put the whole-mode
gate back.
pro and leaves the highlighter working, in documents and in pdfs, and the fill in sheets. Do
not put the whole-mode gate back.

**The editor is in the page.** An editable document is rendered with `HtmlConfig.editable`,
and the edit button only calls `odr.editing.enable()`, with no second render. The page owns
the operation log, undo and the refusals; `editing-bridge.js`, injected by `PageView`,
forwards its callbacks. Lite narrows `HtmlConfig.editingScope` to `PARAGRAPH`, and the page
answers the rest with `outOfScope`, which `DocumentFragment` turns into the offer of pro.
the operation log, undo and the refusals. `HtmlConfig.hostMessageHandler` sends its callbacks
to `PageView.postMessage`; do not inject a script for them. Lite narrows
`HtmlConfig.editingScope` to `PARAGRAPH`, and the page answers the rest with `outOfScope`,
which `DocumentFragment` turns into the offer of pro.

**The bar holds what is done to the document, the strip what is done to the text.** Undo,
redo and save are `menu/edit.xml`, dimmed by `EditActionModeCallback`. `EditingTools` under
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,48 @@ class MainActivityTests {
onView(withText(R.string.pro_offer_title)).check(doesNotExist())
}

/**
* A sheet's strip fills a cell in every edition, the fill being its free tool. The page reports
* the edit through `HtmlConfig.hostMessageHandler`, with no script of the app's in between.
*/
@Test
fun aSheetCellTakesAFill() {
respondToOpenDocumentWith(requireTestFile("spreadsheet-test.ods"))

openDocumentThroughPicker()
waitForDocumentActions()

onView(withContentDescription(R.string.menu_edit)).perform(clickThroughLongPress())

val activity = mainActivityActivityTestRule.activity
val documentFragment = requireNotNull(waitForDocumentFragment(activity, 10000))
val pageView = requireNotNull(documentFragment.pageView)

Assert.assertTrue(
"the sheet should turn editable",
waitFor(EDIT_MODE_TIMEOUT_MS) { pageAnswers(pageView, "odr.editing.isEnabled()") },
)
Assert.assertTrue("the formatting strip should come up", awaitEditingTools())
Assert.assertTrue(
"the first cell should take the pin",
pageAnswers(pageView, "odr.sheet.pin({column: 0, row: 0})"),
)

onView(withContentDescription(R.string.tool_fill)).perform(click())

Assert.assertTrue(
"the cell should be filled",
waitFor(EDIT_MODE_TIMEOUT_MS) {
pageAnswers(pageView, "odr.editing.getOperations().indexOf('setCellStyle') >= 0")
},
)
Assert.assertTrue(
"and the page should say so to the app",
waitFor(EDIT_MODE_TIMEOUT_MS) { documentFragment.hasUnsavedEdits() },
)
onView(withText(R.string.pro_offer_title)).check(doesNotExist())
}

/** Lite edits a text document inside one paragraph, and the page itself holds it to that. */
@Test
fun theEditionDecidesHowFarAnEditReaches() {
Expand Down
41 changes: 0 additions & 41 deletions app/src/main/assets/editing-bridge.js

This file was deleted.

11 changes: 11 additions & 0 deletions app/src/main/java/app/opendocument/droid/background/CoreLoader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import app.opendocument.core.TextEncoding
import app.opendocument.core.TextFile
import app.opendocument.droid.nonfree.CrashManager
import app.opendocument.droid.nonfree.Features
import app.opendocument.droid.ui.widget.PageView
import java.io.File
import java.io.IOException

Expand Down Expand Up @@ -144,6 +145,16 @@ class CoreLoader(private val context: Context) {
htmlConfig.editingScope =
if (Features.advancedEditing) HtmlEditingScope.DOCUMENT else HtmlEditingScope.PARAGRAPH

// every odr.on* callback, as one json string to PageView.postMessage
htmlConfig.hostMessageHandler = PageView.HOST_MESSAGE_HANDLER

// a phone has no double click to spare, and the pointer is not asked: a WebView answers
// that one as a mouse on an emulator
htmlConfig.sheetEditOnClick = true

// an armed tool marks each selection as it is made: a tap elsewhere would lose it
htmlConfig.pdfAnnotationMarkOnSelection = true

// both schemes, each behind prefers-color-scheme, rather than the one it is being read in
// now: this is decided while translating, and darkening is turned on and off over the open
// document. PageView.setDarkeningAllowed picks between them
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,14 +438,17 @@ class DocumentFragment : Fragment(), DocumentLoader.Listener {
}

/**
* The strip under the bar: what the kind of document takes. A sheet or a plain text file takes
* nothing, so there is no strip over it at all - undo, redo and save are the bar's.
* The strip under the bar: what the kind of document takes. A plain text file takes nothing, so
* there is no strip over it at all - undo, redo and save are the bar's.
*/
private fun showEditingTools(document: LoadedDocument, editing: Boolean) {
when {
!editing || !document.editing.isEditable -> editingTools.hide()
document.editing == EditingKind.DOCUMENT ->
editingTools.showFormatting(locked = !Features.advancedEditing)
document.editing == EditingKind.DOCUMENT || document.editing == EditingKind.SHEET ->
editingTools.showFormatting(
sheet = document.editing == EditingKind.SHEET,
locked = !Features.advancedEditing,
)
document.editing == EditingKind.ANNOTATION ->
editingTools.showMarking(locked = !Features.advancedEditing)
else -> editingTools.hide()
Expand Down
Loading
Loading