Skip to content

Merge upstream AnkiDroid (Oct 5) - #60

Merged
float3 merged 151 commits into
ankiquestfrom
merge/upstream-oct05
Oct 5, 2026
Merged

float3 merged 151 commits into
ankiquestfrom
merge/upstream-oct05

Conversation

@float3

@float3 float3 commented Oct 4, 2026

Copy link
Copy Markdown
Owner

150 upstream commits, resolving #57's conflicts:

  • bottom navigation: upstream added DeckPicker.bottomNavigationEnabled (dev option && !fragmented); AnkiQuest navigation is added next to it at each check (drawer, key shortcuts and their labels, setupBottomNavigation, showRestoredBottomNavTab), same behaviour as before
  • DeckPicker: deck list stays ConcatAdapter(decks, heatmap); hierarchy lines use upstream's condition
  • DeckPickerTest: keeps the fork's id-based longPressDeck, which handles the ConcatAdapter
  • screenshot_compare.yml: keeps the fork's earlier, strict baseline download; takes upstream's action bump to v27
  • libs.versions.toml: upstream androidxCoreKtx 1.19.1, keeps androidxCoreRemoteViews
  • versionCode 22600102 merged without a conflict now that the AnkiQuest block sits elsewhere

Built and tested only in CI: the new Gradle wrapper can't download locally.

Merge with a merge commit; #57 then shows as merged.

david-allison and others added 30 commits September 30, 2026 10:56
Ensure `requestCollection` suspends before the opening error is raised.

Part of 22197

Assisted-by: GPT-6
This ensures the collection queue dispatcher is unchanged.

I will unit test this later.

Part of 22197

Assisted-by: GPT-6
Part of 22197

Assisted-by: GPT-6
Regression test for 22197

Assisted-by: GPT-6
portrait & landscape:
* normal
* scrolled to bottom
* scrollshot
* tablet

Part of 22080
Keep the top inset inside the toolbar so the collapsing scrim covers the
status bar. Increase both toolbar heights to preserve the scroll range
and touch targets.

Adjust the scrim visibility threshold by the same inset. Otherwise, a
48dp cutout prevents the scrim from appearing even when fully collapsed.
Reproduced this in settingsPanelSystemBarsChange's fullscreen cutout
screenshot.

Validated eight screenshot cases on phones and tablets in light and dark
themes, plus Kotlin formatting and Android lint.

GPT-6 assisted with implementation, screenshot tests, and self-review.

Fixes 22087

Assisted-by: GPT-6
Part of 21915

Assisted-by: GPT-6
Load FSRS in `viewModelScope` so the dialog can load asynchronously

Part of 21915

Assisted-by: GPT-6
Part of 21915

Assisted-by: GPT-6
Part of 18424

Assisted-by: GPT-6
Use `sortWith` so the set used for case-insensitive uniqueness
inside UniqueArrayList is retained.

Part of 18424

Assisted-by: GPT-6
Extract the tag hierarchy comparison into an overload for tag parts.

Allows future reuse of parsed tag parts.

Part of 18424

Assisted-by: GPT-6
Precompute splitting tags on '::' so this work is not performed
 repeatedly in a sort operation.

Keys are recomputed on each sort to ensure selection changes update
the list.

Part of 18424

Assisted-by: GPT-6
... and skip re-sorting if elements are unchanged

Invalidated when:
* adding tags
* changing any checked states

Part of 18424

Assisted-by: GPT-6
Add `:AnkiDroid:writeReleaseMetadata`:

A file is used as Gradle can also write to stdout/stderr:

`outputs/release-metadata.json`

```json
{
    "versionName": "2.26.0alpha1",
    "versionCode": 22600101,
    "releaseType": "alpha"
}
```

Part of 20166

Assisted-by: GPT-6
Scheduled for every Monday at 04:30 UTC

Skipped if:
* A publish occurred fewer than 7 UTC calendar days ago.
* The app is not in alpha.
* There were no commits since the last release.

This uses the release metadata published by gradle (`build/outputs/release-metadata.json`)
 and `.github/check_alpha_release.js` to keep the yaml lean.

Fixes 20166

Assisted-by: GPT-6
Add:
* `DEFAULT_COLUMNS`
* `getDefaultColumns()` (Java)

Mutating these arrays no longer impacts the API

Part of 12346

Assisted-by: GPT-6
`DEFAULT_PROJECTION` mutability affected the API,
`DEFAULT_COLUMNS` fixes this

Part of 12346

Assisted-by: GPT-6
We want to add functionality improving test coverage extraction

Part of 22147

Assisted-by: GPT-6
This allows coverage to be recovered without rerunning the tests.

Part of 22147

Assisted-by: GPT-6
Coverage could be truncated.
Copy coverage and verify it via SHA-256, retrying up to 5 times.

Fixes Issue 22147

Assisted-by: GPT-6
* Cancel returns to the deck list
* Recovery options are preserved if we restore from a DB error

Fixes 22186

Assisted-by: GPT-6
mikehardy and others added 25 commits October 4, 2026 12:49
build(deps): bump actions/setup-java from 6.0.0 to 6.0.1

Bumps [actions/setup-java](https://github.com/actions/setup-java) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](actions/setup-java@v6...de7274f)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

build(deps): bump com.google.testparameterinjector:test-parameter-injector

Bumps com.google.testparameterinjector:test-parameter-injector from 1.23 to 1.24.

---
updated-dependencies:
- dependency-name: com.google.testparameterinjector:test-parameter-injector
  dependency-version: '1.24'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

build(deps): bump the non-breaking group

Bumps the non-breaking group in /tools/localization with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [dotenv](https://github.com/motdotla/dotenv) | `18.0.2` | `18.0.4` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.6.2` | `26.6.3` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.70.1` | `8.71.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.70.1` | `8.71.0` |
| [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n) | `18.3.0` | `18.4.0` |
| [prettier](https://github.com/prettier/prettier) | `3.9.8` | `3.9.9` |
| [ts-jest](https://github.com/kulshekhar/ts-jest) | `29.4.12` | `29.4.14` |

Updates `dotenv` from 18.0.2 to 18.0.4
- [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md)
- [Commits](motdotla/dotenv@v18.0.2...v18.0.4)

Updates `@types/node` from 26.6.2 to 26.6.3
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@typescript-eslint/eslint-plugin` from 8.70.1 to 8.71.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.71.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.70.1 to 8.71.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.71.0/packages/parser)

Updates `eslint-plugin-n` from 18.3.0 to 18.4.0
- [Release notes](https://github.com/eslint-community/eslint-plugin-n/releases)
- [Changelog](https://github.com/eslint-community/eslint-plugin-n/blob/master/CHANGELOG.md)
- [Commits](eslint-community/eslint-plugin-n@v18.3.0...v18.4.0)

Updates `prettier` from 3.9.8 to 3.9.9
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](prettier/prettier@3.9.8...3.9.9)

Updates `ts-jest` from 29.4.12 to 29.4.14
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](kulshekhar/ts-jest@v29.4.12...v29.4.14)

---
updated-dependencies:
- dependency-name: dotenv
  dependency-version: 18.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: non-breaking
- dependency-name: "@types/node"
  dependency-version: 26.6.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.71.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.71.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking
- dependency-name: eslint-plugin-n
  dependency-version: 18.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: non-breaking
- dependency-name: prettier
  dependency-version: 3.9.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking
- dependency-name: ts-jest
  dependency-version: 29.4.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: non-breaking
...

Signed-off-by: dependabot[bot] <support@github.com>

build(deps): bump dawidd6/action-download-artifact from 25 to 26

Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 25 to 26.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](dawidd6/action-download-artifact@634d83b...27e4ae6)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-version: '26'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

build(deps): bump gradle/actions/setup-gradle from 6.3.0 to 6.4.0

Bumps [gradle/actions/setup-gradle](https://github.com/gradle/actions) from 6.3.0 to 6.4.0.
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](gradle/actions@9c97196...3f5f9ad)

---
updated-dependencies:
- dependency-name: gradle/actions/setup-gradle
  dependency-version: 6.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

build(deps): bump dawidd6/action-download-artifact from 26 to 27

Fixes a bug in GitHub which meant the latest workflow was not returned, breaking
our screenshot baselines.

dawidd6/action-download-artifact@eab87c9

Fixes 21888
See https://redirect.github.com/dawidd6/action-download-artifact/pull/432

Assisted-by: GPT-6
My own copyright lines were not added to the licenses header.
A concurrent scroll and call to `clearCardsList` could cause an inconsistent state:

* The adapter thinks it has rows
* but the rows were cleared

To fix this, use and update a snapshot of the rows
in the adapter, to ensure they're consistent.

Fixes 17759

Assisted-by: GPT-6
Using 'Edit Tags' so there are intermediate states:

With BOTH tags `B` and `B`::child` selected on a note.

* Deselect `B`
* B appears partially checked, as the child remained selected
* Submit
* `B` remains selected.

The user's intention was to remove `B`, but this didn't occur, as we used the
visible state of the tag rather than our concept of 'preserved tags'.

This fix separates out the display state, so we don't over-select tags

Assisted-by: GPT-6
`TMPDIR` can be unwritable (`/data/local/tmp`).

In this case, set the 'overwrite' flag to true, and overwrite the
envvar with `context.cacheDir.path` when we start up.

Fixes 19545

Assisted-by: GPT-6
* different heights
* 200% font sizes

Prep for 18524

Assisted-by: GPT-6
Handle the padding and deck name

Part of 18524

Assisted-by: GPT-6
Names and card counts are centered within each row

Part of 18524

Assisted-by: GPT-6
* Measure the rows so only complete rows are shown
* Center the list
* Refresh the list if widget is resized

Part of 18524

Assisted-by: GPT-6
If there's not enough space for the first row, shrink its text
so it is visible.

Fixes 18524

Assisted-by: GPT-6
As the API uses a content provider, a query could theoretically hit
the backend before `Application.onCreate`'s init routine.

Assisted-by: GPT-6
The exception is user-facing and non-actionable by us.
Filters `BackendSchedulerUpgradeRequiredException`.

Fixes 17385

Assisted-by: GPT-6
When an in-flight request to the API failed, it could
be picked up by the media handler, showing an unexpected
`.bin` file failing to load.

Fixes 16510

Assisted-by: GPT-6
Hardening for 16510

Assisted-by: GPT-6
Mostly for media throttling

Part of 16510

Assisted-by: GPT-6
Assisted-by: Claude Sonnet 5 [tests]
This is very heavily documented as there are subtle issues, such as
`ViewModel.onCleared` not necessarily being a permanent dismissal.

As part of our IdsFile changes, where we want to keep a file on disk
and reference this in our activity state, but also allow multiple
concurrent files on disk in case an activity exists twice in the task
graph.

Part of 19572

Assisted-by: GPT-6
* Delete only after the replacement is written
* Delete the final snapshot via `onPermanentDismissal`

Part of 19572

Assisted-by: Claude Fable 5.1
Assisted-by: GPT-6
Buggy if the build logic classloaders are reused between builds,
potentially using outdated data from the cache.

Caused a 0.004 ms saving (warmed-lookup estimate) - not worth keeping

Assisted-by: GPT-6
Previously, if our `alert` implementation failed, we returned `false`,
which had the WebView show the default.

Now, we cancel the alert, confirming the request without a fallback.

This could fail for the same reason - for example, I suspect this was caused
by our Congrats page continuing to refresh (and failing), when the app is backgrounded
and can no longer show alerts.

**Bug Reporting**
If we hit a window-limit failure, ensure we're only reporting it if silent mode is enabled
otherwise, this shows a dialog itself.

This is defensive handling for a legacy bug, it has likely already been resolved
by Anki updates the congrats screen and our lifecycle fixes.

Part of 15658

Assisted-by: GPT-6
Restore the expanded add menu views and Back behavior when DeckPicker is recreated.

GPT-5.6 added the recreation handling and regression test.

Fixes ankidroid#22241

Assisted-by: GPT-5.6
The sort chip is icon only, so TalkBack announced it as an unlabelled
button, and the flipped icon was the only hint of the sort direction.

Give it a content description with the same text as the sort snackbar,
such as "Sort by Created · Newest first" or "No sorting". The ViewModel
now keeps the current sort as state, so the label is right as soon as
the browser opens, and it is rebuilt after a language change.

Assisted-by: Claude Opus 5.5
Cards and notes mode keep separate sort settings, but switching modes
didn't reload them. The sort chip kept showing the old mode's direction,
and its TalkBack label still named the old mode's sort.

Assisted-by: Claude Opus 5.5
# Conflicts:
#	.github/workflows/screenshot_compare.yml
#	AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt
#	AnkiDroid/src/main/java/com/ichi2/anki/HomeScreenNavigation.kt
#	AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.kt
#	gradle/libs.versions.toml
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown

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

  • AnkiquestHomeScreenshotTest: 1 change
  • DeckPickerScreenshotTest: 5 changes
  • DeckPickerTabletScreenshotTest: 1 change
  • DeckPickerWidgetScreenshotTest: 6 changes
  • FilteredDeckOptionsScreenshotTest: 6 changes
  • NavigationDrawerScreenshotTest: 1 change
  • NoteTypeFieldEditorScreenshotTest: 1 change
  • PreferencesScreenshotTest: 14 changes
  • ReviewRemindersScreenshotTest: 5 changes
  • SharedDecksScreenshotTest: 1 change
  • SortOrderBottomSheetFragmentScreenshotTest: 8 changes
  • StudyOptionsScreenshotTest: 1 change
All 50 changed screenshots

AnkiquestHomeScreenshotTest

  • today_320dp_compare.png

DeckPickerScreenshotTest

  • deck_list_after_dismissing_create_deck_dialog_compare.png
  • hierarchy_lines_collapsed_compare.png
  • hierarchy_lines_many_siblings_compare.png
  • keyboard_open_scrolled_to_bottom_compare.png
  • keyboard_studied_line_overlaying_deck_name_compare.png

DeckPickerTabletScreenshotTest

  • keyboard_open_compare.png

DeckPickerWidgetScreenshotTest

  • compact_compare.png
  • compact_large_font_compare.png
  • full_height_compare.png
  • full_height_large_font_compare.png
  • minimum_height_compare.png
  • minimum_height_large_font_compare.png

FilteredDeckOptionsScreenshotTest

  • existingDeck_systemBars_compare.png
  • landscapeCutout_compare.png
  • landscapeCutout_scrolledToEnd_compare.png
  • newDeck_compare.png
  • previewDelays_systemBars_scrolledToEnd_compare.png
  • secondFilter_systemBars_compare.png

NavigationDrawerScreenshotTest

  • navigationDrawer_compare.png

NoteTypeFieldEditorScreenshotTest

  • keyboard_open_compare.png

PreferencesScreenshotTest

  • AboutFragment_compare.png
  • AppearanceSettingsFragment_compare.png
  • BackupLimitsSettingsFragment_compare.png
  • GeneralSettingsFragment_sdk36_collapsed_compare.png
  • GeneralSettingsFragment_sdk36_fullscreen_collapsed_compare.png
  • GeneralSettingsFragment_sdk36_fullscreen_cutout_collapsed_compare.png
  • GeneralSettingsFragment_sdk36_fullscreen_cutout_compare.png
  • GeneralSettingsFragment_sdk36_fullscreen_expanded_compare.png
  • GeneralSettingsFragment_sdk36_system_bars_restored_compare.png
  • HeaderFragment_gesture_bar_hidden_scrolled_to_bottom_compare.png
  • HeaderFragment_gesture_bar_scrolled_to_bottom_compare.png
  • HeaderFragment_toolbar_collapsed_compare.png
  • HeaderFragment_toolbar_expanded_compare.png
  • ReviewerOptionsFragment_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

SharedDecksScreenshotTest

  • download_compare.png

SortOrderBottomSheetFragmentScreenshotTest

  • landscape_compare.png
  • landscape_scrolled_to_bottom_compare.png
  • landscape_scrollshot_compare.png
  • portrait_compare.png
  • portrait_scrolled_to_bottom_compare.png
  • portrait_scrollshot_compare.png
  • tablet_landscape_compare.png
  • tablet_portrait_compare.png

StudyOptionsScreenshotTest

  • keyboard_open_compare.png

@float3
float3 merged commit 8da6896 into ankiquest Oct 5, 2026
29 checks passed
@float3
float3 deleted the merge/upstream-oct05 branch October 5, 2026 07:36
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.