Skip to content

Merge upstream AnkiDroid - #64

Merged
float3 merged 455 commits into
float3:ankiquestfrom
ankidroid:main
Oct 29, 2026
Merged

float3 merged 455 commits into
float3:ankiquestfrom
ankidroid:main

Conversation

@float3

@float3 float3 commented Oct 15, 2026

Copy link
Copy Markdown
Owner

10 new commits from ankidroid/Anki-Android main.

Merge with a merge commit, never squash or rebase, so ankiquest keeps upstream's history.

If this conflicts, merge ankidroid/Anki-Android main into a branch from ankiquest, resolve there, and merge that branch instead; this pull request then shows as merged.

@github-actions

Copy link
Copy Markdown

Snapshot diff report vs ankiquest. Open screenshot-diff for diffs.

  • AddEditReminderDialogScreenshotTest: 1 change
  • ChangeNoteTypeDialogScreenshotTest: 26 changes
  • CollectionTooLargeScreenshotTest: 1 change
  • DeckPickerScreenshotTest: 10 changes
  • DeckPickerTabletScreenshotTest: 2 changes
  • LocaleSelectionDialogScreenshotTest: 2 changes
  • MultimediaScreenshotTest: 5 changes
  • NavigationDrawerScreenshotTest: 2 changes
  • NoteEditorScreenshotTest: 2 changes
  • PreferencesScreenshotTest: 2 changes
  • PreviewerScreenshotTest: 1 change
  • ReviewRemindersScreenshotTest: 5 changes
  • SortOrderBottomSheetFragmentScreenshotTest: 3 changes
  • StudyScreenScreenshotTest: 6 changes
  • TagsDialogScreenshotTest: 1 change
  • TemplatePreviewerScreenshotTest: 1 change
All 70 changed screenshots

AddEditReminderDialogScreenshotTest

  • delete_confirmation_dialog_compare.png

ChangeNoteTypeDialogScreenshotTest

  • desktop_fields_fit_viewport_compare.png
  • desktop_gesture_navigation_compare.png
  • desktop_landscape_compare.png
  • desktop_long_note_type_names_large_text_landscape_compare.png
  • desktop_long_note_type_names_large_text_narrow_portrait_compare.png
  • desktop_many_fields_large_text_landscape_compare.png
  • desktop_many_fields_scrolled_to_bottom_compare.png
  • desktop_many_templates_large_text_landscape_compare.png
  • desktop_many_templates_scrolled_to_bottom_compare.png
  • desktop_portrait_compare.png
  • desktop_portrait_cutout_compare.png
  • desktop_templates_fit_viewport_compare.png
  • desktop_templates_tab_large_text_compare.png
  • fields_fit_viewport_compare.png
  • gesture_navigation_compare.png
  • landscape_compare.png
  • long_note_type_names_large_text_landscape_compare.png
  • long_note_type_names_large_text_narrow_portrait_compare.png
  • many_fields_large_text_landscape_compare.png
  • many_fields_scrolled_to_bottom_compare.png
  • many_templates_large_text_landscape_compare.png
  • many_templates_scrolled_to_bottom_compare.png
  • portrait_compare.png
  • portrait_cutout_compare.png
  • templates_fit_viewport_compare.png
  • templates_tab_large_text_compare.png

CollectionTooLargeScreenshotTest

  • collection_too_large_dialog_compare.png

DeckPickerScreenshotTest

  • deck_list_after_dismissing_create_deck_dialog_compare.png
  • edgeToEdge_30_decks_compare.png
  • hierarchy_lines_collapsed_compare.png
  • hierarchy_lines_compare.png
  • hierarchy_lines_deep_nesting_compare.png
  • hierarchy_lines_many_siblings_compare.png
  • keyboard_open_scrolled_to_bottom_compare.png
  • keyboard_studied_line_overlaying_deck_name_compare.png
  • snackbar_keyboard_closed_compare.png
  • snackbar_keyboard_open_compare.png

DeckPickerTabletScreenshotTest

  • 30_decks_tablet_compare.png
  • keyboard_open_compare.png

LocaleSelectionDialogScreenshotTest

  • landscape_compare.png
  • portrait_compare.png

MultimediaScreenshotTest

  • image_editor_camera_compare.png
  • image_editor_compare.png
  • image_editor_drawing_compare.png
  • image_editor_error_compare.png
  • landscape_compare.png

NavigationDrawerScreenshotTest

  • navigationDrawer_compare.png
  • sideNavigationBar_compare.png

NoteEditorScreenshotTest

  • tablet_compare.png
  • tablet_keyboard_compare.png

PreferencesScreenshotTest

  • AnkiquestStudySettingsFragment_compare.png
  • SwitchProfilesFragment_compare.png

PreviewerScreenshotTest

  • base_compare.png

ReviewRemindersScreenshotTest

  • studyOptionsFragmentHost_scheduleReminders_compare.png
  • studyOptionsFragmentHost_systemBars_compare.png
  • studyOptionsFragmentHost_systemBars_scrolledToEnd_compare.png
  • studyOptionsFragmentHost_troubleshooting_compare.png
  • studyOptionsFragmentHost_troubleshooting_systemBars_compare.png

SortOrderBottomSheetFragmentScreenshotTest

  • landscape_compare.png
  • landscape_scrolled_to_bottom_compare.png
  • landscape_scrollshot_compare.png

StudyScreenScreenshotTest

  • bar=BOTTOM_frame=CARDbttns=false_compare.png
  • bar=BOTTOM_frame=CARDbttns=true_compare.png
  • bar=NONE_frame=CARDbttns=false_compare.png
  • bar=NONE_frame=CARDbttns=true_compare.png
  • bar=TOP_frame=CARDbttns=false_compare.png
  • bar=TOP_frame=CARDbttns=true_compare.png

TagsDialogScreenshotTest

  • empty_tags_compare.png

TemplatePreviewerScreenshotTest

  • base_compare.png

criticalAY and others added 28 commits October 24, 2026 01:56
The snackbar helpers only need two view ids and a debug flag, so
they move down with them for other modules to use. Packages are
unchanged, so callers are too.

Assisted-by: Claude Opus 5.5
A trailing '+' was treated as a modifier separator.

Now start the search before the last character so we
can serialize/deserialize '+'.

Fixes 22648

Assisted-by: GPT-6.1-Sol xhigh
`otherActionTitleForBinding` is added, returning the
binding title.

Warnings now use this result, rather than being set
directly in this method.

Split from PR 18303: 31e41d1

Assisted-by: GPT-6-Astra xhigh
Assisted-by: GPT-6.1-Sol xhigh
Co-authored-by: David Allison <62114487+david-allison@users.noreply.github.com>
[from profiling]
~7% improvement; 3.5% less CPU

Tested on my M1 Max under a variable load

Assisted-by: GPT-6 high
Preparation for these to be used in a JaCoCo fix/refactor.

Assisted-by: GPT-6.1-Sol xhigh
Separate the class/source inputs from execution data.

Non-functional. This is to make a future commit easy to reason about.

Prep for 13277

Assisted-by: GPT-6.1-Sol xhigh
`playDebug` or `debug`

Reproduction: with release emulator tests selected, the app unit report
previously selected release classes.

Assisted-by: GPT-6.1-Sol xhigh
Fixes loading java classes from JVM modules.

Part of 13277

Assisted-by: GPT-6.1-Sol xhigh
coverage now uses declarative compiler outputs, allowing Gradle to infer
task dependencies.

----

Previously, the report constructed a path:

`build/intermediates/built_in_kotlinc/playDebug/compilePlayDebugKotlin/classes`

which:
* omitted Java files
* had no information about the producing task

`JacocoCoverage` now uses AGP's artifact API
`AndroidCoverageInputs` converts the results into a file tree which
JaCoCo can handle

Part of 13277

Assisted-by: GPT-6.1-Sol xhigh
Fixes `.exec` and `.ec` files read by the coverage report, using the
producers outputs directly.
Previously a `playDebug` report could pick up coverage from other flavors.

* create a live collection selecting the test task (handles late registration)
* Use the declared outputs filtered to `.exec` and `.ec`

Fixes 13277

Assisted-by: GPT-6.1-Sol xhigh
Prep for 22403

Assisted-by: GPT-6-Astra xhigh
Report:
* System locale
* Selected language
* Selected backend languages

For the test issues: the backend can now be initialized before the
conflict override. The cached backend is discarded after installing
the override to be sure this didn't happen.

Fixes 22403

Assisted-by: GPT-6-Astra xhigh
Co-authored-by: David Allison <62114487+david-allison@users.noreply.github.com>
Assisted-by: GPT-6.1-Sol xhigh
After the screen was recreated, for example by switching to dark mode,
picking tags in "Study by card state or tag" did nothing: the restored
menu in the back stack took over the tags result it never used. Only the
sub-dialogs listen for it now.

Assisted-by: Claude Opus 5.5
The congrats screen opened Custom Study in its own fragment manager, so
the menu stayed open under the "Increase today's limit" dialog. When the
screen was recreated, for example by switching to dark mode, the menu
restarted loading the defaults and the input dialog crashed on them. It
now opens the same way as from the deck list.

Fixes 22631

Assisted-by: Claude Opus 5.5
After Android killed the app with the tag picker open, the restored
"Study by card state or tag" dialog fell back to the menu without
building its view, so picking tags crashed. Only the dialogs that need
the loaded defaults fall back to the menu now. The test is from David's
review.

Assisted-by: Claude Opus 5.5
Reuses saveState(), closes each activity with use {}, and presses OK
the same way on both dialogs instead of looking up the tags dialog.

Assisted-by: Claude Opus 5.5
On tablets, dragging the Note Editor's divider also moved the split
Card Browser's divider, and the other way round, because both saved
a pane weight under noteEditorPaneWeight. The Card Browser now saves
its editor pane under its own key.

Assisted-by: Claude Opus 5.5
Allow SafeWebViewLayout to resolve OnWebViewRecreatedListener from a
hosting Activity when not attached to a Fragment. Adds canGoBack()
convenience method.

Assisted-by: Claude sonnet 4.6
Replace raw WebView with SafeWebViewLayout in activity_info.xml, implement
OnWebViewRecreatedListener in Info, and add InfoTest covering WebView
recovery and lifecycle teardown.

Part of #22091

Assisted-by: Claude sonnet 4.6
EditTextUtils, rawHitTest and DialogTitleView only depend on Android,
and the AlertDialog helpers need them.

Assisted-by: Claude Opus 5.5
The helpers move with their layouts, help icon and margins, so any
module can build dialogs with them. They now focus the input and show
the keyboard themselves, as AndroidUiUtils needs :compat and stays in
the app. Packages are unchanged.

Assisted-by: Claude Opus 5.5
It only needs TR and the AlertDialog helpers, which are now available
below the app.

Assisted-by: Claude Opus 5.5
InvalidStringFormatDetector listed only <string> and <plurals> in
getApplicableElements(), so <string-array> items were never visited
and invalid format specifiers in them went unreported.

Visit <string-array> and check each <item> the same way as plurals.

Fixes 22441
In:
`a::b::c`, searching for `b` no longer expands `a::b::c`
But if `a` was collapsed, it would be expanded

Part of 10397

Assisted-by: GPT-6-Astra xhigh
* flip `collapsed` and update the visible rows before backend access
* This means taps may be queued, use `previousSave` to enqueue backend updates
* All other operations wait for the save

The UI is not reverted on failure

Part of 10397

Assisted-by: GPT-6-Astra xhigh
When `Science::Biology::Cells` is collapsed. Searching for `Cells` automatically opens the tree

When tapping `Science`:
* Before, it used the saved state, rather than the visible state, so appeared as a no-op.
* Now, it toggles the displayed state and remembers that the tag was explicitly collapsed.

Part of 10397

Assisted-by: GPT-6-Astra xhigh
Limit saved search names & queries to 500 characters, to prevent ANRs.

Fixes 22820

Assisted-by: GPT-6.1-Sol xhigh
Assisted-by: GPT-6.1-Sol xhigh
Report `UnusedTagNotMoved` when the backend fails to move a tag
subtree as it is unused.

Part of 10397
Workaround for https://redirect.github.com/ankitects/anki/issues/5870

Assisted-by: GPT-6.1-Sol xhigh
Assisted-by: GPT-6-Astra xhigh
david-allison and others added 3 commits October 28, 2026 18:08
Fixes 22827

Assisted-by: GPT-6.1-Sol xhigh
Typing an existing tag in the add tag dialog shows an error. This adds a
test that typing a new tag afterwards clears it and enables OK again.
The dialog setup moves into a helper shared with the existing test.
DeckSelectionDialog's layouts and menu use keyline_1,
deck_picker_right_padding, ActionBarStyle, ActionBar.Popup and
ic_search_white, so these move first. The dimens keep their sw600dp
values. Layouts that use them are unchanged, and DeckAdapter,
DeckHierarchyLinesDecoration and DeckSelectionDialog read the dimens
through CommonR.

Assisted-by: Claude Opus 5.5
criticalAY and others added 16 commits October 28, 2026 21:37
Saving a note now reports progress from InstantEditorViewModel, so back
is ignored until the save finishes instead of closing the editor
halfway through.

Assisted-by: Claude Opus 5.5
The editor is a dialog, so Save could still be tapped while a note was
saving. The second tap added the same note again, which failed in the
backend and broke the collection until the app restarted.

Save is now ignored while a note is saving or the editor is closing,
both in the editor and in the no-cloze warning. The check runs before
the fields are read, so an ignored Save can't change the note being
saved, and confirming the warning saves the fields that were checked.

Assisted-by: Claude Opus 5.5
For the reminders to fire, there needs to be at least one card
due.

But: this allowed two states for when our test
on review history filtering could suppress the notification:

* 0 cards due
* cards reviewed

by adding a second card, we ensure that the notifications are suppressed
because a review occurred.

Part of 22814

Assisted-by: GPT-6.1-Sol xhigh
Fixes 22814

Assisted-by: GPT-6.1-Sol xhigh
AnkiDroidApp sets it on startup, so VersionUtils no longer looks it
up or falls back to AnkiDroidApp.TAG.

Assisted-by: Claude Opus 5.5
It needs :compat.

Assisted-by: Claude Opus 5.5
AndroidUtils and ClipboardUtil no longer need anything from the app.

Assisted-by: Claude Opus 5.5
* launches CSV importer for text
* enqueues a message for *pkg

Assisted-by: GPT-6
Assisted-by: GPT-6-Astra xhigh
apkg/csv now take the same route:
`TEXT_IMPORT` => `FILE_IMPORT`

This is prep for better import handling, we have been misidentifying
`apkg` files as text based on a faulty MIME type, having a single place
to accept a file, and determine its actual contents will resolve this.

A `prepareImport` => `openImport` call chain is used for handling.

Also allows us to move it to a background thread in a later commit.

Prep for 21430

Assisted-by: GPT-6
Assisted-by: GPT-6-Astra xhigh
Rather then a separate CSV import.

Assisted-by: GPT-6
Assisted-by: GPT-6-Astra xhigh
Assisted-by: GPT-6
Assisted-by: GPT-6-Astra xhigh
Assisted-by: GPT-6.1-Sol xhigh
Assisted-by: GPT-6
Assisted-by: GPT-6-Astra xhigh
We have cases where `apkg` is `text/plain`, which was previously
imported as a failed CSV ('stream did not contain valid UTF-8').

Now, we check to see if a file has an apkg extension before falling
back to UTF-8

Fixes 21430

Assisted-by: GPT-6
Assisted-by: GPT-6-Astra xhigh
Assisted-by: GPT-6.1-Sol xhigh
A [a/col]pkg MIME type is a signal, whereas `text/plain` is more ambiguous.
So treat *pkg MIME types as a stronger signal than filenames/MIME hints.

Filenames are still used for deck vs collection detection.

Part of 21430

Assisted-by: GPT-6-Astra xhigh
When the release smoke build failed while packaging, the log hid the
cause. Pass --stacktrace to both smoke steps so it shows. The run step
needs it too: lint takes the flag as an input, so leaving it off makes
that step redo lint.

Part of 22741

Assisted-by: Claude Opus 5.5
The release smoke build sometimes ran out of heap while packaging the
APKs. Raise the emulator job's Gradle heap from 3 GB to 4 GB. All the
job's Gradle steps share one daemon, so they all get it.

Fixes 22741

Assisted-by: Claude Opus 5.5
@float3
float3 merged commit a1b9fee into float3:ankiquest Oct 29, 2026
4 checks passed
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.