Reconstruct the strings for the feedback-toast message to Reviewer actions
Basically, use strings on Anki Desktop instead of the current ones. Create new ones as needed.
For Bury and Suspend, I set the style described in the following comment as a goal:
https://github.com/ankidroid/Anki-Android/pull/12446#issuecomment-1279763351
------------------------------
- Replace `<string name="buried_card">Card buried</string>`
with `<string name="card_buried">Card buried.</string>`
- Remove `<string name="buried_note">Note buried</string>`
(Instead of the string, its counterpart on Anki Desktop will work on the toast.)
- Remove `<string name="deleted_note">Note deleted</string>`
(Instead of the string, its counterpart on Anki Desktop will work on the toast.)
- Remove `<string name="suspended_card">Card suspended</string>`
(Instead of the string, its counterpart on Anki Desktop will work on the toast.)
- Replace `<string name="suspended_note">Note suspended</string>`
with the following code:
`<plurals name="note_suspended"
<item quantity="one">%d card suspended.</item>
<item quantity="other">%d cards suspended.</item>
</plurals>`
------------------------------
Change the word order of some of the toast messages
"[Subject] (omission of [be Verb]) [Past participle]" word order is used in Anki Desktop and AnkiDroid, but it isn't on some strings of AnkiDroid
before change --> after change
-------------------------------------------------
"Buried card" --> "Card buried"
"Buried note" --> "Note buried"
"Deleted note" --> "Note deleted"
"Suspended card" --> "Card suspended"
"Suspended note" --> "Note suspended"
"Created deck" --> "Deck created"
"Renamed deck" --> "Deck renamed"
"Copied debug information to clipboard" --> "Debug information was copied to clipboard" (no omission of be Verb)
-------------------------------------------------
If a user has uninstalled the app, one of the options should
be to restore from a .colpkg
Use `ankiDroidDirectoryOverride` as code uses the location in
CollectionHelper rather than `col.path`. Defining a temporary
collection in `CollectionManager` was deemed to be too challenging
Tested with 'Don't keep activities' and failures in the import copy
Issue 5304
If a user uninstalls AnkiDroid, `preserveLegacyStorage` no longer
works
This means they have a deckPath of `/storage/emulated/0/AnkiDroid`
which can no longer be accessed.
Their data exists, but cannot be accessed unless:
* They restore from AnkiWeb
* They have a colpkg
* They manually copy the folder over
* They install a non-Google-Play copy
Options:
* Restore from AnkiWeb
* Restore folder access
(https://github.com/ankidroid/Anki-Android/wiki/Full-Storage-Access)
* Restore backup (Hidden - Not Implemented)
* Get Help (Link to: Google Group)
* Delete collection and create a new one
Issue 5304
If a migration requires a sync, and a sync completes when the app is
paused, a notification occurs prompting the user to migrate.
This is handled by `DialogHandler`, which runs in AnkiActivity.onResume
BEFORE `loadDeckCounts`.
This races with closing the collection for a storage migration.
Instead, start the task and allow it to be stopped.
Issue 5304
We need a media sync before a storage migration.
If this has been disabled, it is the user's responsibility
to perform a sync before this migration occurs
There are currently two reasons:
Fetch media on Sync is set to:
* 'Only if unmetered' & connection is metered
* Never
Issue 5304
We need to move the user's data to /Android/ to handle scoped storage
changes. Before we perform this migration, we should ensure that users
data is safe. To do this, we enforce a sync.
A user should have completed a full media sync before the migration
occurs.
This ensures that their data is up to date and can be restored if
anything goes awry with the migration
Dialog wording as discussed on the Figma, with the exception of
changing 'sync' to 'media sync'
Issue 5304
Checkbox to disable permanently if `timesStorageMigrationPostponed > 1`
+ Warning that uninstalling the app will delete/make storage inaccessible
Issue 5304
If a user doesn't migrate:
* Storage is slow
* They permanently lose access to their collection on uninstall
If the user does migrate:
* Storage is fast
* Data is deleted on uninstall (unless a user opts out)
We have a subset of users who are safe to migrate (syncing)
and want them to migrate ASAP so they get the speed benefits
while syncing
Display the dialog from showDialogThatOffersToMigrateStorage
Issue 5304
/AnkiDroid can be re-enabled via the following on a `play` build:
```
adb shell am compat disable FORCE_ENABLE_SCOPED_STORAGE com.ichi2.anki.debug
adb shell am compat disable DEFAULT_SCOPED_STORAGE com.ichi2.anki.debug
adb shell pm grant com.ichi2.anki.debug android.permission.READ_EXTERNAL_STORAGE
adb shell pm grant com.ichi2.anki.debug android.permission.WRITE_EXTERNAL_STORAGE
```
In one case `hasStorageAccessPermission` wasn't executed due to faulty assumptions.
Fix this and document the issue
Issue 5304
MANAGE_EXTERNAL_STORAGE is for non-Google Play builds.
Google won't let us have the permission, but there's no reason
other stores + users have to suffer this decision.
This allows a Google Play user to restore their data if they uninstall
(uninstall, then download the APK and data is available again)
* Remove MANAGE_EXTERNAL_STORAGE from the manifest if targeting `play`
Version Codes & Outcomes:
1 < Q - force storage permissions as done previously (incl. Play Store)
2 Q - Users are unsafe and need a storage migration
* MANAGE_EXTERNAL_STORAGE is unavailable
* READ/WRITE_EXTERNAL_STORAGE is unavailable
3 > Q - Non-Play-Store users need MANAGE_EXTERNAL_STORAGE (*)
4 > Q - Play Store users are unsafe and need a storage migration
If a user is starting out and may request 'safe' permissions (1) (3)
Then we keep `deckPath` as a legacy path.
1) & 3) We do not allow access to the app until they give permission
----
Storage can be re-enabled after this change via:
```
adb shell am compat disable DEFAULT_SCOPED_STORAGE com.ichi2.anki.debug
adb shell am compat disable FORCE_ENABLE_SCOPED_STORAGE com.ichi2.anki.debug
adb shell pm grant com.ichi2.anki.debug android.permission.READ_EXTERNAL_STORAGE
adb shell pm grant com.ichi2.anki.debug android.permission.WRITE_EXTERNAL_STORAGE
```
on an API 30 emulator (or a non-AOSP emulator)
Related: Issue 5304
Fixes 13051 - targetSdkVersion 30 fixes this
This logic will get more complex after scoped storage.
This makes it more testable
This hides complexity as permissions dialogs:
* May not be necessary (permissions already granted)
* Return permission granted/denied in an async fashion
Android provides no native way to know if permissions have been denied
permanently.
To work around this, we define a PermissionsManager which encapsulates
both concerns: `.requestDialog` returns the dialog state and accepts a
callback if the method is async.
* Fixes a TODO where a permissions dialog is not shown
In order to use `registerForActivityResult`, registration needs to
occur on activity startup.
Uses `shouldShowRequestPermissionRationale` to determine if a
permission denial is temporary or permanent
Fixes a DeckPicker TODO on checking media
Summary: splits out sound playing + sound lists
* Remove logic for only creating a list containing `QUESTION_AND_ANSWER` if requested
* Instead, concat the two QUESTION and ANSWER lists when requested
* Split out 'playing' code into 'SoundPlayer'
* Split out video-related code into `VideoPlayer`
* remove 'videoView' parameter
* remove 'mBaseUrl' parameter
* define `SoundPlayer` interface + delegate to parameter
* remove legacy "tts" code
* extract `playAnotherSound()`
* cleanup VideoPlayer `null` path handling
* remove videoPlayer.onStop
* SingleSoundSide: ensures the wrong parameter can't be provided, cleaning up code paths
The CardBrowser kept track of the available decks by checking the DeckSpinnerSelection.dropDownDecks property, this
property wasn't updating when the user would create a new deck during the process of changing a card's deck. The fix is
making CardBrowser to use directly the method that DeckSpinnerSelection was using to update dropDownDecks.
* remove unused 'ScopedStorageMigrationDialog'
We no longer provide a confirmation dialog, this is performed in
`showDialogThatOffersToMigrateStorage`
Added in f3d762287e
Issue 5304
Removes:
* R.layout.scoped_storage_confirmation
* R.string.scoped_storage_initial_message
* R.string.scoped_storage_select_all_terms
* R.string.scoped_storage_term_1
* R.string.scoped_storage_term_1_ankiweb
* R.string.scoped_storage_term_2
* R.string.scoped_storage_terms_message
* rename: 'ScopedStorageMigrationDialog'
`ScopedStorageMigrationDialog` to `ScopedStorageMigrationDialog`
* fix queryIntentActivities deprecation
* Fix remaining lint and tests isssues
Because we moved from a platform method call on a class written in Java to a method written completely in kotlin, one of the
tests failed because mockito and kotlin don't play along very well(mockito passing null values for kotlin methods although they
expect non null types). I fixed this by using the actual `intent` value used in the method call in the class for which the test
was failing(see CustomTabsHelper).
---------
Co-authored-by: lukstbit <52494258+lukstbit@users.noreply.github.com>