0
0
mirror of https://github.com/ankidroid/Anki-Android.git synced 2024-09-20 12:02:16 +02:00
Commit Graph

16273 Commits

Author SHA1 Message Date
oakkitten
6af6f76039 Implement SensibleSwipeDismissBehavior
SensibleSwipeDismissBehavior is more a fix for the inconsistent behavior
of SwipeDismissBehavior, rather than a custom implementation.
This addresses the following issues:

  * When the snackbar is swiped to the right, its opacity changes,
    but not when swiped to the left;

  * When moving the snackbar to dismiss it, the target distance
    calculation does not take margins into account, which makes the
    snackbar briefly appear stuck near the edge;

  * Any amount of horizontal velocity will dismiss the snackbar,
    which can result in user dismissing the snackbar even though they
    didn't want to;

  * If you drag the snackbar to the right, and then flinging it to the
    left, it will suddenly change course and start moving to the right.
2022-08-18 13:36:36 -05:00
oakkitten
4b74d24d51 Refactor Snackbars 2022-08-18 13:36:36 -05:00
oakkitten
0cf4ff0b7b Streamline snackbar creation
This changes the way snackbars are created. Instead of calling a
function with many arguments, the new methods consistently only take
text, duration, and a builder block--whether it is called on an
activity or a view. I chose builder pattern instead of call chaining as
it makes sure that the snackbar is actually shown in the end.

Note that if showSnackbar is called on an Activity that does not have a
view with id root_layout--which does not allow proper placing and
interaction with snackbars--a runtime exception will be intentionally
thrown in a debug build. Release builds will show a toast with the
contents of the snackbar instead.

Some durations were changed, notably, Card browser's snackbar that allow
searching in all decks now stay until dismissed. This is something user
may want to do at any time later; and if the snackbar is in the way,
they can dismiss it by swiping.

In com.ichi2.anki.CoroutineHelpersKt.launchCatchingTask, a few unrelated
to this change TODO comments were added.
2022-08-18 13:36:36 -05:00
oakkitten
215077ccfb Fix snackbar sitting right on top of answer buttons 2022-08-18 13:36:36 -05:00
oakkitten
147770db0c Do not show snackbars over toolbar 2022-08-18 13:36:36 -05:00
oakkitten
c13bbdd7a3 Adjust fab behavior to work with material snackbar
Previously, snackbars were sliding from the bottom. Material snackbars
instead fade in, and slightly scale out. These snackbars are meant to be
placed above the fab, but our fab opens a menu, and what are you going
to do with that, huh?

This makes fab slide up with some deceleration when a snackbar starts
appearing, and down after it is removed. This plays well with fab's
rotating animation.
2022-08-18 13:36:36 -05:00
oakkitten
ae26c8c9c0 Add some snackbar color & letter spacing overrides
Colors were chosen somewhat arbitrarily to fit the themes.
2022-08-18 13:36:36 -05:00
oakkitten
aeaecc32ea Add basic material theming for snackbars
This changes the parent themes to Material Bridge themes, and adds the
necessary attributes to style snackbars. The colors for the action
button are not exactly right since current themes misuse colors a bit.

From the tutorial:

  Bridge themes inherit from AppCompat themes, but also define the new
  Material Components theme attributes for you. If you use a bridge
  theme, you can start using Material Design components without changing
  your app theme.
2022-08-18 13:36:36 -05:00
oakkitten
0ca7fe9843 Remove programmatic snackbar color tweaks
These will be set via the theme.
2022-08-18 13:36:36 -05:00
oakkitten
c42c9a93bf Remove utility function showDismissibleSnackbar
Snackbars, once called with a proper root, can be dismissed by swiping.
In the following commit they will be properly styled and look swipeable.
2022-08-18 13:36:36 -05:00
oakkitten
8167aa4fb1 Fix swiping on snackbar moving other views
The way SwipeDismissBehavior uses ViewDragHelper, event interception may
happen well past the initial start of the gesture. ViewDragHelper will
capture the view under the finger, which at this point might be some
unrelated view, and *that* view will be moved instead. Looks very funny.

This solves the issue by never intercepting touch events unless the
finger is over the snackbar.
2022-08-18 13:36:36 -05:00
oakkitten
3223b526cf Fix snackbar swipe to dismiss behavior
While you can can dismiss snackbars by flinging, due to a bug in the
library, they stay in place while you do so, and only ever disappear
to the right, which might not be the direction of the fling.

This makes snackbars move along with the finger.
2022-08-18 13:36:36 -05:00
oakkitten
f0e6ee7ac9 Fix fab getting stuck after removing snackbar with a swipe
This simply fixes a typo introduced in e7daa57a.
2022-08-18 13:36:36 -05:00
oakkitten
4d3ee7350b Move fab along with snackbar more consistently
The previous version of the logic failed to work properly
in some circumstances, for instance, if you turn the system
setting Navigation hint off.
2022-08-18 13:36:36 -05:00
oakkitten
0fad2a384c Fix snackbar appearing on the very bottom of the screen
Snackbars are dismissible by swiping and thus should appear above the
bottom gesture area. Some of the snackbars were appearing on the bottom
of the screen even though they were using CoordinatorLayout as the root,
this fixes it. Also, this fixes excessive relayout/remeasure while
snackbars are showing.

This does not fix snackbars not using CoordinatorLayout as the root.

An attentive reader might ask, what on Earth does this change have to do
with Snackbars? Well, let me tell you a story.

I noticed that in Full screen navigation drawer mode, which I was using,
snackbars are appearing too high. (This is another issue.) When I almost
made a commit to make them appear on the very bottom of the screen,
by setting bottomMarginGestureInsetRunnable to true, I realized that
while this does make snackbars look consistent, they shouldn't be at
the bottom of the screen in the first place. So in one case they were
too high, and in another case too low, and, if dismissed via swiping,
they left the fab too high. (This is yet another issue.)

After minute investigation, that totally didn't take several hours,
I found what I think is the issue. The timing is the problem.
Animating snackbars in should work like this:

  * Ask the framework for insets
  * Post a callback, bottomMarginGestureInsetRunnable,
    that adjusts margins taking insets into account
    * This removes any callbacks posted previously!
  * Post an animation

Looks okay? Well, turns out that if Full screen drawer mode is not on,
there's *a lot* of remeasuring going on. Remeasuring results in the
above callback getting reposted again and again, and it ends up running
*after* animation.

Here's a debug log in case of Full screen drawer mode:

  showing snackbar
  posting callback
  posting callback
  callback run
  animating

And here's one in regular mode:

  showing snackbar
  posting callback ¹
  posting callback ²
  posting callback †
  posting callback †
  posting callback †
  animating
  posting callback †
  callback run ‡
  posting callback
  callback run ‡
  posting callback
  callback run ‡
    (many more lines)
  posting callback
  callback run ‡

I guess you see the issue. What happens here:

  * Callback gets posted “normally” twice (¹, ²).
  * DrawerLayout.onMeasure sees if its child, CoordinatorLayout,
    fits system windows. Since it does, it calls its method
    dispatchApplyWindowInsets, which propagates to
    BaseTransientBottomBar's inset listener, which reposts
    bottomMarginGestureInsetRunnable (†).
  * The callback ends up running too late ... and when it is run, its
    parent has already ended its own layout. This is why, I think,
    its call to requestLayout propagates to the root, which begins to
    remeasure things again (‡).
  * The last two steps are repeated on and on in a loop.

Why does this happen? Well, I think that:

  * The positioning problem is an issue with Snackbar itself.
    It does not make sure that animation is run after inset listener
    has been called.
  * The loop problem is likely one of those weird Android issues that
    come out of nowhere. Maybe it's this particular combination of
    views? Or some funny flag somewhere deep in the code? Who knows.

How this solves it? Well, I looked at why this is not an issue if Full
screen navigation drawer setting is on. As mentioned above,
DrawerLayout.onMeasure checks if its child fits system windows, and then
calls dispatchApplyWindowInsets. In this case, CoordinatorLayout is
wrapped in FullDraggableContainer, which does not have the fit system
windows flag set. Removing this flag in CoordinatorLayout makes the
behavior the same.

***

For reference, here's tracebacks for ¹ and ²:

  Breakpoint reached
    at com.google.android.material.snackbar.BaseTransientBottomBar.updateMargins(BaseTransientBottomBar.java:438)
    at com.google.android.material.snackbar.BaseTransientBottomBar.onAttachedToWindow(BaseTransientBottomBar.java:737)
    at com.google.android.material.snackbar.BaseTransientBottomBar$SnackbarBaseLayout.onAttachedToWindow(BaseTransientBottomBar.java:1221)
    at android.view.View.dispatchAttachedToWindow(View.java:20479)
    at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3489)
    at android.view.ViewGroup.addViewInner(ViewGroup.java:5278)
    at android.view.ViewGroup.addView(ViewGroup.java:5064)
    at android.view.ViewGroup.addView(ViewGroup.java:5004)
    at android.view.ViewGroup.addView(ViewGroup.java:4976)
    at com.google.android.material.snackbar.BaseTransientBottomBar$SnackbarBaseLayout.addToTargetParent(BaseTransientBottomBar.java:1275)
    at com.google.android.material.snackbar.BaseTransientBottomBar.showView(BaseTransientBottomBar.java:715)
    at com.google.android.material.snackbar.BaseTransientBottomBar$1.handleMessage(BaseTransientBottomBar.java:244)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    ...
  Breakpoint reached
    at com.google.android.material.snackbar.BaseTransientBottomBar.updateMargins(BaseTransientBottomBar.java:438)
    at com.google.android.material.snackbar.BaseTransientBottomBar.recalculateAndUpdateMargins(BaseTransientBottomBar.java:840)
    at com.google.android.material.snackbar.BaseTransientBottomBar.showView(BaseTransientBottomBar.java:716)
    at com.google.android.material.snackbar.BaseTransientBottomBar$1.handleMessage(BaseTransientBottomBar.java:244)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    ...

And here's traceback for †

  Breakpoint reached
    at com.google.android.material.snackbar.BaseTransientBottomBar.updateMargins(BaseTransientBottomBar.java:438)
    at com.google.android.material.snackbar.BaseTransientBottomBar.access$900(BaseTransientBottomBar.java:96)
    at com.google.android.material.snackbar.BaseTransientBottomBar$3.onApplyWindowInsets(BaseTransientBottomBar.java:383)
    at androidx.core.view.ViewCompat$Api21Impl$1.onApplyWindowInsets(ViewCompat.java:4858)
    at android.view.View.dispatchApplyWindowInsets(View.java:11309)
    at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:7320)
    at android.view.ViewGroup.brokenDispatchApplyWindowInsets(ViewGroup.java:7334)
    at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:7325)
    at android.view.ViewGroup.brokenDispatchApplyWindowInsets(ViewGroup.java:7334)
    at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:7325)
    at androidx.drawerlayout.widget.DrawerLayout.onMeasure(DrawerLayout.java:1128)
    at android.view.View.measure(View.java:25466)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:145)
    at android.view.View.measure(View.java:25466)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at android.view.View.measure(View.java:25466)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at android.view.View.measure(View.java:25466)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
    at android.view.View.measure(View.java:25466)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6957)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at com.android.internal.policy.DecorView.onMeasure(DecorView.java:747)
    at android.view.View.measure(View.java:25466)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3402)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2246)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2544)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1948)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8177)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
    at android.view.Choreographer.doCallbacks(Choreographer.java:796)
    at android.view.Choreographer.doFrame(Choreographer.java:731)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
2022-08-18 13:36:36 -05:00
Divyansh Kushwaha
b13b2a0480
[GSoC] Simplify add note task (#12070)
* Removed unnecessary callbacks

When adding a single note, it is not required to show continuous progress since it a short task and user can be notified after the task has been finished. So instead of using onProgressUpdate callback, it is good to use onPostExecute for UI updates while adding notes.

* Code simplification in NoteEditor.SaveNoteHandler

Both the conditions perform same task, sequential execution of both eventually nullifies the effect of !closeEditorAfterSave, so can be removed.
2022-08-18 19:07:45 +03:00
Divyansh Kushwaha
ae5e648bdd Variable names cleanup 2022-08-18 07:53:27 +03:00
Brayan Oliveira
cd0ba35a9e lint: add rule to avoid hardcoded keys on preferences 2022-08-18 07:15:18 +03:00
Brayan Oliveira
f699dec48e Use key constants on preferences_custom_sync_server.xml 2022-08-18 07:15:18 +03:00
Brayan Oliveira
4e81ef438d Extract all cram_deck_options.xml pref keys to constants 2022-08-18 07:15:18 +03:00
Brayan Oliveira
4e32fcd9b1 Extract all deck_options.xml pref keys to constants 2022-08-18 07:15:18 +03:00
Brayan Oliveira
73d69b5206 Move ThemeUtils.kt methods to Themes.kt
Themes.kt goal is to fit Themes utilities.

Having two files to do the same thing is confusing, scatters the code and may be overcomplicated especially for new contributors.

Change the javadoc of Themes, as it was describing the same as `updateCurrentTheme()`
2022-08-18 06:49:19 +03:00
Brayan Oliveira
cfc8f603d0 Rename getThemedColor to getColorFromAttr
getThemedColor is just a convenience method to call getColorFromAttr, so it's best to keep just one name
2022-08-18 06:49:19 +03:00
David Allison
ec36137661 refactor: Convert ExportingTest to Kotlin
com.ichi2.libanki.ExportingTest
2022-08-17 18:42:38 +05:30
David Allison
5576868421 refactor: Rename ExportingTest.java to .kt
com.ichi2.libanki.ExportingTest
2022-08-17 18:42:38 +05:30
Arthur Milchior
2656c0d9d5 NF: replace Long by NotetypeId
NotetypeId is defined upstream in models.py.

Since we may not convert Models.java, using the definition from PythonTypes is
the best solution.

Those variables were found by searching for "mid: Long" and "odelId: Long".
2022-08-17 00:26:14 +01:00
Damien Elmes
f827d5528b Fix time taken in v3 scheduler being capped to maximum
Closes #12024
2022-08-16 15:59:38 -05:00
Mike Hardy
5ad4ffc802 Bumped version to 2.16alpha78 2022-08-16 15:27:53 +00:00
Mike Hardy
20c618399d
Dependency updates 20220816 (#12036)
* Bump gradle from 7.2.1 to 7.2.2

Bumps gradle from 7.2.1 to 7.2.2.

---
updated-dependencies:
- dependency-name: com.android.tools.build:gradle
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

* Bump lint_version from 30.2.1 to 30.2.2

Bumps `lint_version` from 30.2.1 to 30.2.2.

Updates `lint-api` from 30.2.1 to 30.2.2

Updates `lint` from 30.2.1 to 30.2.2

Updates `lint-tests` from 30.2.1 to 30.2.2

---
updated-dependencies:
- dependency-name: com.android.tools.lint:lint-api
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: com.android.tools.lint:lint
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: com.android.tools.lint:lint-tests
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

* Bump protobuf-kotlin from 3.21.4 to 3.21.5

Bumps protobuf-kotlin from 3.21.4 to 3.21.5.

---
updated-dependencies:
- dependency-name: com.google.protobuf:protobuf-kotlin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

* Bump fragments_version from 1.5.1 to 1.5.2

Bumps `fragments_version` from 1.5.1 to 1.5.2.

Updates `fragment-ktx` from 1.5.1 to 1.5.2

Updates `fragment-testing` from 1.5.1 to 1.5.2

---
updated-dependencies:
- dependency-name: androidx.fragment:fragment-ktx
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: androidx.fragment:fragment-testing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

* Bump mockito-inline from 4.6.1 to 4.7.0

Bumps [mockito-inline](https://github.com/mockito/mockito) from 4.6.1 to 4.7.0.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v4.6.1...v4.7.0)

---
updated-dependencies:
- dependency-name: org.mockito:mockito-inline
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-16 10:23:02 -05:00
Damien Elmes
771056c641 Delay pop-up of progress window
Closes #12027
2022-08-16 09:48:12 -05:00
Damien Elmes
3e7ad6a9e6 Shift launchCatchingTask to FragmentActivity; hook undo up in StudyOptions
Change based on https://github.com/ankidroid/Anki-Android/pull/12011#issuecomment-1214170607
2022-08-16 09:48:12 -05:00
Damien Elmes
061abf87c3 Fix error when undoing in card browser 2022-08-16 09:48:12 -05:00
Damien Elmes
e62024b909 Remove invalidateOptionsMenu() call
Theoretically it should be unnecessary, as it's called in refreshState()
2022-08-16 09:48:12 -05:00
Damien Elmes
55d5aab7d0 Unify isOnMainThread implementations 2022-08-16 09:48:12 -05:00
Damien Elmes
c55edd262b Remove wildcard import 2022-08-16 09:48:12 -05:00
Damien Elmes
d782901b2b Catch IO errors in media check with new schema
Closes #12026
2022-08-16 09:48:12 -05:00
Damien Elmes
f84baf6a07 Legacy undo & v2 queues must be cleared on backend op
Fixes #12007
2022-08-16 09:48:12 -05:00
Damien Elmes
06741b6c2d Fix deck picker options flickering + error on full sync
https://github.com/ankidroid/Anki-Android/pull/11849#issuecomment-1211775736

Android's onCreateOptionsMenu does not play well with coroutines, as
it expects the menu to have been fully configured by the time the routine
returns. This results in flicker, as the menu gets blanked out, and then
configured a moment later when the coroutine runs. To work around this,
the current state is stored in the deck picker, so that we can redraw the
menu immediately, and then make any potential changes in the background.

Other changes:
- refactored onCreateOptionsMenu to make it simpler
- instead of the sdCardAvailable checks (which I assume is a proxy for
"col is available"), the entire menu is wrapped in a group, and the
visibility of the group is toggled depending on whether the col is available
or not. This also fixes the error on a full sync.
- there are three sets of unit tests (one for search icon, one for sync icon,
one for entire menu) that have been a pain since I originally introduced
this PR, and and I've sunk a number of hours into trying to get them to work
properly at this point. The issue appears to be that when mixing coroutine
calls and invalidateOptionsMenu(), onCreateOptionsMenu() is not getting called
before trying to await the job, leading to a hang or stale data. I tried
advancing robolectric, but it did not help. Maybe someone more experienced
in this area can figure it out, but for now I've changed these routines
to be more of a unit test and less of an integration test: rather than
checking the menu itself, they directly invoke the function that updates
the menu state, and check the state instead. This takes onCreateOptionsMenu()
out of the loop, and avoids the problems (and probably allows these tests
to be re-enabled on Windows as well). The sync tests I've removed, as the
entire menu is hidden/shown now when the col is closed, so they are redundant.
2022-08-16 09:48:12 -05:00
Damien Elmes
c69f273496 Fix expand state not updating in V16
This regressed in 9644f5724c

+ Fix incorrect private find() implementation in CardContentProvider, and
move into shared file.

Closes #11999
2022-08-16 09:48:12 -05:00
Damien Elmes
cfb21276ad Rely on the backend to fetch the current deck id
Fixes a startup crash when the current deck ID is set to an invalid value
2022-08-16 09:48:12 -05:00
Damien Elmes
3d7c534699 Re-enable card template editor GUI in V16 schema
The unit tests were re-enabled some time back, but this was missed.
2022-08-16 09:48:12 -05:00
Damien Elmes
0a5ac3ab03 Fix play icons not appearing with V16
Closes #11979
2022-08-16 09:48:12 -05:00
Damien Elmes
065b0d0ea2 Fix crash after changing theme
Closes #11981
2022-08-16 09:48:12 -05:00
Damien Elmes
deb3a539ec Add script to test all commits in a branch
It skips lint-rules:test, as it still doesn't seem to work for me.
2022-08-16 09:48:12 -05:00
Damien Elmes
60b1ac3aed Skip a flaky v3 test for 2 hours of the day 2022-08-16 09:48:12 -05:00
Damien Elmes
747c41086b Use backend to update sync status; trigger media sync on auto full sync
+ Update sync status after normal media sync completes

Closes #11902
2022-08-16 09:48:12 -05:00
Damien Elmes
d86e6181ec Hook apkg/colpkg exports up to UI 2022-08-16 09:48:12 -05:00
Damien Elmes
036b882677 Introduce CollectionManager for preventing concurrent access
Currently there are many instances in the AnkiDroid codebase where
the collection is accessed a) on the UI thread, blocking the UI, and
b) in unsafe ways (eg by checking to see if the collection is open,
and then assuming it will remain open for the rest of a method call.
"Fix full download crashing in new schema case" (159a108dcb) demonstrates
a few of these cases.

This PR is an attempt at addressing those issues. It introduces
a `withCol` function that is intended to be used instead of
CollectionHelper.getCol(). For example, code that previously looked
like:

        val col = CollectionHelper.getInstance().getCol(this)
        val count = col.decks.count()

Can now be used like this:

        val count = withCol { decks.count() }

The block is run on a background thread, and other withCol calls made
in parallel will be queued up and executed sequentially. Because of
the exclusive access, routines can safely close and reopen the
collection inside the block without fear of affecting other callers.

It's not practical to update all the legacy code to use withCol
immediately - too much work is required, and coroutines are not
accessible from Java code. The intention here is that this new path is
gradually bought into. Legacy code can continue calling CollectionHelper.
getCol(), which internally delegates to CollectionManager.

Two caveats to be aware of:
- Legacy callers will wait for other pending operations to complete
before they receive the collection handle, but because they retain it,
subsequent access is not guaranteed to be exclusive.
- Because getCol() and colIsOpen() are often used on the main thread,
they will block the UI if a background operation is already running.
Logging has been added to help diagnose this, eg messages like:

E/CollectionManager: blocked main thread for 2626ms:
    com.ichi2.anki.DeckPicker.onCreateOptionsMenu(DeckPicker.kt:624)

Other changes:

- simplified CoroutineHelpers
- added TR function for accessing translations without a col reference
- onCreateOptionsMenu() needed refactoring to avoid blocking the UI.
- The blocking colIsOpen() call in onPrepareOptionsMenu() had to be
removed. I can not reproduce the issue it reports, and the code checks
for col in onCreateOptionsMenu().
- The subscribers in ChangeManager need to be cleared out at the start
of each test, or two tests are flaky when run with the new schema.
2022-08-16 09:48:12 -05:00
AnkiDroid Translations
dcb0c81331 Updated strings from Crowdin 2022-08-16 09:47:18 -05:00
yshubham8419
80123471b5 fixing #10767 unnecessary rebuild after opening filter deck option 2022-08-16 08:46:38 -05:00