This fixes an issue where Steam OTP's were displayed in the wrong
format. The underlying issue has been present for a while, but it first
became apparent in e4c9a584f4.
This also includes changes to make the status guard hack work
on Android 15 and a couple of small adjustments to support edge-to-edge
in all activities.
I've held off on this in the past, because I was concerned about the
security issues related to Java object deserialization. To circumvent
that, I've written a parser that understands just enough of the Java
Object Serialization format to parse FreeOTP 2 backups.
Unfortunately there are a number of issues in FreeOTP 2 that may result in
corrupt backups. The importer warns the user about this and tries to
salvage as many entries as possible.
Gets rid of all of the custom logic we had for notifying the
RecyclerView about changes in the entry list. This will allow for more
simplifications in the future around non-persisted changes to state in
the entry list.
A neat side effect is that any filtering/ordering changes in the entry
list are now also animated: https://alexbakker.me/u/4a4ie5yzpj.mp4
This touches the fundamentals of the entry list, so lots of careful
testing required.
The following crash could occur when trying to import an icon pack for
which an empty folder still exists on disk:
```
Exception java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 1
at jdk.internal.util.Preconditions.outOfBounds (Preconditions.java:64)
at jdk.internal.util.Preconditions.outOfBoundsCheckIndex (Preconditions.java:70)
at jdk.internal.util.Preconditions.checkIndex (Preconditions.java:266)
at java.util.Objects.checkIndex (Objects.java:359)
at java.util.ArrayList.remove (ArrayList.java:511)
at com.beemdevelopment.aegis.ui.views.IconPackAdapter.removeIconPack (IconPackAdapter.java:38)
at com.beemdevelopment.aegis.ui.fragments.preferences.IconPacksManagerFragment.removeIconPack (IconPacksManagerFragment.java:158)
at com.beemdevelopment.aegis.ui.fragments.preferences.IconPacksManagerFragment.lambda$importIconPack$3 (IconPacksManagerFragment.java:133)
at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage (AlertController.java:167)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loopOnce (Looper.java:226)
at android.os.Looper.loop (Looper.java:313)
at android.app.ActivityThread.main (ActivityThread.java:8762)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)
```
To reproduce on a debug build of Aegis with the latest aegis-icons
imported into the app, run the following commands and then try to import
the same aegis-icons ZIP again:
```
$ adb shell
$ su
# rm -r /data/data/com.beemdevelopment.aegis.debug/files/icons/c1018b93-4e8c-490a-b575-30dde62a833e/20230523/*
```
This fixes the following crash I noticed in the developer console:
```
Exception java.lang.AssertionError:
at com.beemdevelopment.aegis.util.UUIDMap.getByUUID (UUIDMap.java:127)
at com.beemdevelopment.aegis.vault.VaultRepository.getEntryByUUID (VaultRepository.java:229)
at com.beemdevelopment.aegis.ui.fragments.preferences.AuditLogPreferencesFragment.lambda$onViewCreated$0 (AuditLogPreferencesFragment.java:70)
at androidx.lifecycle.LiveData.considerNotify (LiveData.java:133)
at androidx.lifecycle.LiveData.dispatchingValue (LiveData.java:151)
at androidx.lifecycle.LiveData.setValue (LiveData.java:309)
at androidx.lifecycle.LiveData$1.run (LiveData.java:93)
at android.os.Handler.handleCallback (Handler.java:959)
at android.os.Handler.dispatchMessage (Handler.java:100)
at android.os.Looper.loopOnce (Looper.java:232)
at android.os.Looper.loop (Looper.java:317)
at android.app.ActivityThread.main (ActivityThread.java:8592)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:580)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:878)
```
This is another attempt to fix a rare crash we're seeing in the
developer console:
```
Exception android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.view.ViewRootImpl.setView (ViewRootImpl.java:1423)
at android.view.WindowManagerGlobal.addView (WindowManagerGlobal.java:408)
at android.view.WindowManagerImpl.addView (WindowManagerImpl.java:148)
at android.widget.PopupWindow.invokePopup (PopupWindow.java:1583)
at android.widget.PopupWindow.showAsDropDown (PopupWindow.java:1430)
at android.widget.PopupWindow.showAsDropDown (PopupWindow.java:1386)
at com.beemdevelopment.aegis.ui.AuthActivity.lambda$showPasswordReminder$5 (AuthActivity.java:253)
at android.os.Handler.handleCallback (Handler.java:942)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loopOnce (Looper.java:211)
at android.os.Looper.loop (Looper.java:300)
at android.app.ActivityThread.main (ActivityThread.java:8294)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:580)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1028)
```
This slightly simplifies the approach we use to animate the advanced
entry settings into view, by defaulting its alpha to 0 and setting it to
VISIBLE before the animation starts. That way, we're not dependent on
"animation ended" callbacks that apparently don't fire in all cases.
The XML diff looks a bit scary, but it basically just removes a
wrapping ``RelativeLayout`` that appears to not be necessary.