Repository navigation
Conversation
* Fix scrolling spacing so bottom rows are reachable * Wrapped field/template don't overlap vertically * Truncate note-type names * Tabs handle large text Fixes 21008 Assisted-by: GPT-6
The design of 'To' already indicates it's clickable and we could do with the space to render the note type name From a review comment on 21008 Assisted-by: GPT-6
Prepare the Kotlin DSL conversion while preserving git blame. Break the build to maintain git history across the migrated files Issue 20910
Part of Issue 20910 Assisted-by: GPT-6
`SyncAuth` was not constructed correctly, dropping ioTimeoutSecs We now handle this via `toProto().toByteArray()` Fixes 22293 Assisted-by: GPT-6
* Tags * Locale Selection Prep for 7110 Assisted-by: GPT-6
The dialog should not be responsible for the parent. Code was unnecessary. Part of 7110 Code added in 409455e (2014); ADJUST_RESIZE was set so controls were usable when the keyboard was open, but this also applied it to the calling window. Assisted-by: GPT-6
and document it Part of 7110 Assisted-by: GPT-6
Prep for 7110 Assisted-by: GPT-6
Replaces `SOFT_INPUT_ADJUST_RESIZE` (Android 11+ and later) On resize, we now fit the IME insets. On pan (compact screens), we remove the insets and apply `SOFT_INPUT_ADJUST_PAN` Part of 7110 Assisted-by: GPT-6
List the CardIds and return the current row of the cursor, rather than pre-fetching all rows. Reduces memory usage Part of 20253 Assisted-by: GPT-6
Part of 20253 Assisted-by: GPT-6
Only load when a column is read, so restoring the cursor position does not fetch an unused row. Part of 20253 Assisted-by: GPT-6
Defers rendering questions/answers/card names until they're requested. Part of 20253 Assisted-by: GPT-6
Part of 20253 Assisted-by: GPT-6
When loading a row, check if the card is deleted. If it is, all columns except the ID will return `null` Part of 20253 Assisted-by: GPT-6
No longer exists. Part of 21487 Assisted-by: GPT-6
Part of 21487 Assisted-by: GPT-6
This takes up a runner, 2.5GB of cache space, and has only once picked up a runner-specific bug, which was a fixed bug in the framework. We're getting more runner contention these days, so only test it weekly. Part of 21487 Assisted-by: GPT-6
Frees up 2.5 GB of cache (1/4 of our total) Part of 21487 Assisted-by: GPT-6
ProcessPhoenix will do the restart. It relaunches the app from a separate process once this one has been killed, so the relaunch is never handed to a process that is still dying. It is Apache 2.0 and has no dependencies of its own.
PhoenixActivity runs in its own :phoenix process, and Android creates the Application in every process of the app. AnkiDroidApp would start the backend and the rest of the app there, in a process that only lives long enough to kill the old one and launch the new one. It now returns straight away there. Assisted-by: Claude Opus 5 (multiple iterations over original code)
A profile switch restarts the process, so it has to wait for work that outlives the collection queue, and keep new work from starting. A backup keeps writing after the backend releases the collection, and syncs run in workers. Each now holds a lock while it runs, for the restart to take. A worker that finds its lock taken drops its work rather than rescheduling it, since the work carries the AnkiWeb key of the profile being left. The backend cannot be asked to wait for a backup from elsewhere: it hands its running backup to the first caller that asks, and createBackup asks as soon as the backup starts. Assisted-by: Claude Opus 5 (multiple iterations over original code)
A profile switch cannot be applied in place: the backend, WebView and SharedPreferences all cache paths from the profile that was active when the process started, so the process has to die and come back. The restart takes the sync lock first, waiting for a sync that is already running, since that sync queues a media sync before it lets go of its lock. Sync work is then cancelled, since it carries this profile's AnkiWeb key, which also stops a running media sync rather than waiting it out. The media sync and backup locks come next. All three are kept until ProcessPhoenix kills the process, so nothing can start in the meantime, and released if the handover fails. The collection is then closed: the backend holds it open, and killing the process mid-write risks corrupting it. ensureClosed runs on the collection queue, so it also waits for an operation that is already running. Assisted-by: Claude Opus 5 (multiple iterations over original code)
A switch is followed by a process restart, and SharedPreferences.apply() writes to disk asynchronously. Android does not flush pending apply() writes when the process is killed, so the new profile id could be lost and the app would come back on the old profile. Commit the switch write. Startup keeps the asynchronous write, since nothing kills the process after it.
A few Card Browser, Previewer and Custom Study tests only passed because a leftover test dispatcher made background loads finish instantly. They now wait for the load, or run under runTest like the tests around them. Assisted-by: Claude Opus 5.5
runTest swapped ioDispatcher for a test dispatcher and never put it back, so later tests in the same fork ran background work on the main thread. That hid races like 22271 until a test happened to run first. Reset it in tearDown, next to resetMain(). Assisted-by: Claude Opus 5.5
The recording screen now goes through the shared recorder and player instead of AudioRecordingController. The layout is the same, but leaving the app or recreating the screen no longer loses the recording, Done works after the reviewer's recorder was used (#19438), and a failed recording shows an error and can't be added. Discarded recordings are deleted, the screen only stays on while recording or playing, the long press buzz isn't recorded, playback takes audio focus, and landscape hides the waveform. Assisted-by: Claude Opus 5.5
Alpha and beta builds kept an old changelog, because it was only rendered for public releases. Render it for every release, and add a note to test builds saying their changelog comes with the stable release. The docs repo is now cloned for test releases too. Fixes 18707 Assisted-by: Claude Opus 5.5
Every observer dismissed the one shared dialog on `Idle`, so with two observers in an activity, one could close the other's dialog. Assisted-by: Claude Opus 5 (implementation iteration and tests)
The loading dialog only shows after 600 ms, and until then the screen still took taps. On the deck list a tap could change the selected deck while an operation was using it. Block touches straight away, like the legacy withProgress does. The legacy withProgress now uses the same count, so neither one unblocks touches while the other is still running. Assisted-by: Claude Opus 5.5
The application keeps the manager to route storage, but only privately, so the switch profiles screen had no way to read the profile registry.
The list was a hardcoded empty flow. It now maps ProfileManager.getAllProfiles() into the UI model, so the screen shows the real profiles. The registry is backed by SharedPreferences, which has no defined iteration order, so profiles are sorted by name, ignoring case, to keep the list stable across launches. If the profile environment failed to load at startup, the screen shows an error and goes back instead of crashing. Assisted-by: Claude Opus 5.5
Fixes 22497 Assisted-by: GPT-6-Astra default
Assisted-by: GPT-6-Astra default
`"false"` is truthy in JS Fixes 22483 Introduced in 44a1977 Related 15576 Related 15569 Assisted-by: GPT-6-Astra default
Ensure we select the correct dialog via a fragment lookup ``` com.ichi2.anki.ForegroundMediaNetworkTest.conflict resolution preserves one-time metered confirmation java.lang.ClassCastException: class android.app.ProgressDialog cannot be cast to class androidx.appcompat.app.AlertDialog ``` Fixes 22489 Assisted-by: GPT-6-Astra default
Assisted-by: gpt-5.6-terra
Assisted-by: Opus 5.5
…ownload Assisted-by: Opus 5.5
Assisted-by: Opus 5.5
…loadOutcome Assisted-by: Opus 5.5
…ownload Assisted-by: Opus 5.5
The screenshot-diff artifact held every file Roborazzi left in each diffs folder. Reviewers only use the _compare images, so stage just those. The comment workflow already reads only them. Fixes 22297 Assisted-by: Claude Opus 5.5
On a fresh install where Android can't provide a storage location, the storage permission check throws. Treat that as no access, as the widget provider and BootService already do. Assisted-by: Claude Opus 5.5
A widget added before storage permission was granted kept a dead button, because the broadcast meant to refresh it named a component that does not exist. Send it to WidgetPermissionReceiver directly. Assisted-by: Claude Opus 5.5
On a phone in landscape, the "Choose display order" sheet sat in the middle of the screen like a dialog, because bottom sheets stop at 640dp wide. It now uses the full width on phones, as in portrait. Tablets keep the narrower sheet. Fixes 22080 Assisted-by: Claude Opus 5.5
Opening the study screen in a dark theme briefly showed a white card area, because the WebView had no background until the card loaded. It now starts with the theme's background, which the card uses too. The previewers share this code and get the same fix. Fixes 19657 Assisted-by: Claude Opus 5.5
Use `getAppWidgetManager` Fixes 22515 Related to 16581 Assisted-by: GPT-6-Astra default
`AppWidgetManager.getInstance` returns null on a Supernote A5 X Part of 22515 Related to 16581 Assisted-by: GPT-6-Astra default
Deleting unused media, backups or the collection now reports progress from ManageSpaceViewModel instead of the fragment. Assisted-by: Claude Opus 5.5
Android clears an app's cache when storage runs low, which could delete a recording while it was still being made. Recordings now go to noBackupFilesDir, which isn't cleared or backed up. Assisted-by: Claude Opus 5.5
The system no longer clears recordings left behind when the app is killed, so recordings older than 7 days are deleted at startup, like the multimedia argument files. Assisted-by: Claude Opus 5.5
|
Merged into Twenty-nine files conflicted. Eighteen were the ankiquest string files, which upstream's move of every translation into Four things then failed in CI that no conflict could show, because upstream changed APIs this fork calls on lines it never touched: four Code quality, emulator tests, the conflict scan and the regression tests are green. Unit tests are red, as they were on |
22 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.