Trust the core when it says a file cannot be opened - #563
Merged
Conversation
A failed CoreLoader load that RawLoader could not pick up ended as
onUnsupported, and DocumentFragment offered to upload the file to
use.opendocument.app. That server runs the same engine that just said no,
so a damaged .odt cost the user a consent dialog, an upload, a progress
dialog and a second failure to learn what the core already knew.
The service already had the distinction it needed: coreLoader.isSupported
is odrcore's own format table, asked until now only to log
load_odf_error_expected. Route on it. A format the core names and still
fails on is the file's fault and the answer is final; onUnsupported is now
reached only for formats the core never claimed - iwork, wordperfect, dxf -
which is what OnlineLoader is actually good for. It also makes
dialog_upload_file ("we don't support its format") true, which it was not
before.
What the user sees instead is a dialog over the landing screen rather than
a snackbar over an empty document view: the file may be damaged or
something went wrong on our side, with the support address as a live
mailto link and a Contact button next to OK. FileNotFoundException and
OutOfMemoryError keep their own snackbars, so "too big" is still its own
message.
The dialog carries its own content view. AppCompat's button bar showed a
grey band that turned out to be the framework's default focus highlight -
drawn from onDrawForeground, so every view in the hierarchy reads
bg=null fg=null while a solid band sits on screen - which appears whenever
a window is out of touch mode. defaultFocusHighlightEnabled is off on
everything focusable in the layout.
corrupt.odt is a valid ODF zip with content.xml cut in half, and
testCorruptODTIsNotOfferedForUpload asserts both halves: no upload dialog,
and the new message on screen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6G6AhhqpUNAsd6iStodKs
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 66455dc0af
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Two findings on the first commit. An upload that does not come back was landing in the catch-all and getting the broken-file dialog, which closes the document. But an ONLINE failure says nothing about the file - the network or the server is what failed, and it is a format the core never claimed in the first place, so the reopen offer is still the useful thing to do with it. Branch on result.loaderType and give it toast_error_upload_failed. The address in the dialog was clickable through autoLink, which uses TextView's own mailto handler and throws where no mail app exists - outside the try/catch the Contact button goes through. It is a ClickableSpan calling the same guarded contactSupport now. A translation that dropped the address leaves the message as plain text rather than mislinking it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q6G6AhhqpUNAsd6iStodKs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
A failed
CoreLoaderload thatRawLoadercould not pick up ended atLoaderService.kt:174asonUnsupported, andDocumentFragmentoffered to upload the file touse.opendocument.app. That server runs the same engine that just said no, so a damaged.odtcost the user a consent dialog, an upload, a progress dialog and a second failure to learn what the core already knew.Route on what the service already knows
coreLoader.isSupportedis odrcore's own format table (SupportedDocumentTypes.isRenderedByCore), asked until now only to logload_odf_error_expected. One new branch:OnlineLoaderstays, narrowed to what it is genuinely good for - iwork, wordperfect, dxf, postscript. A side effect is thatdialog_upload_file("we aren't able to open this document, because we don't support its format") becomes true; it was not before.What the user sees
A dialog over the landing screen rather than a snackbar over an empty document view.
MainActivity.closeDocument()is no longer private so the failed load can drop back to it.mailto:linkACTION_SENDTOFileNotFoundExceptionandOutOfMemoryErrorkeep their own snackbars, so "too big / too many pictures" is still its own message.toast_error_genericis gone; its stale translations stay for Crowdin to prune, sinceExtraTranslationis ignored inapp/lint.xml.The grey bar under the buttons
The dialog carries its own content view rather than AppCompat's button bar, which showed a grey band. That band turned out to be the framework's default focus highlight: drawn from
onDrawForeground, so every view in the hierarchy readsbg=null fg=nullwhile a solid band sits on screen, and it appears whenever a window is out of touch mode.defaultFocusHighlightEnabledis off on everything focusable in the layout.Worth knowing for the next person:
MainThemeis duplicated acrossvalues/,values-v29/andvalues-v35/, so a theme item added to only one of them silently does nothing on a modern device. Left alone here.Test
app/src/androidTest/assets/corrupt.odtis a valid ODF zip withcontent.xmlcut in half - the core detects it as odt and then fails onnot an xml file.testCorruptODTIsNotOfferedForUploadasserts both halves: the upload dialog does not exist, and the new message is on screen.spotlessCheck,lintProDebug,testProDebugUnitTestand all 48 instrumented tests pass on a Pixel 9 Pro emulator (API 36).Not verified on a device
The preserved upload path. It needs a format the core does not claim to reach the app, which requires the
CATCH_ALLalias, andpm enableon that component is blocked for shell. The branch itself is unchanged code andOnlineLoaderTeststill covers the whitelist.🤖 Generated with Claude Code
https://claude.ai/code/session_01Q6G6AhhqpUNAsd6iStodKs