When an unrecoverable authentication error occurs, automatically log
the user out. This seems better than leaving the user wondering why
the UI is unresponsive or why each track they try to play fails with a
quickly disappearing toast.
Unrecoverable authentication errors typically mean the server has
timed out the session out or the session token has been deleted on the
server. Tokens expire after 14 days without use.
Part-of: <https://dev.funkwhale.audio/funkwhale/funkwhale-android/-/merge_requests/342>
Most of this was added to debug issue !102. So these are vestigial.
The exception here is the handling of AuthorizationException type 2.
These are produced by racing authentication requests and are
successfully managed. So we need not report these.
Part-of: <https://dev.funkwhale.audio/funkwhale/funkwhale-android/-/merge_requests/342>
With landscape view enabled (e.g. e06b2c7) in the app and auto
rotation enabled on the phone, switching between portrait and
landscape orientations leaks instances of MainActivity. This prevents
garbage collection of not just the MainActivity object, but fragments
and other objects referenced by the Activity.
This is caused by repositories, the AppContext instance, the player
service, and authentication code maintaining a reference to the
context which with they are initialized. So rather than initialize
these with an Activity context, pass them the Application context.
Activities are torn down and rebuilt on screen rotation. The
Application context is not.
To enable instantiation of the FavoritedRepository with the
Application context, delay that repository’s initialization until
first use. This ensures the Application context is fully initialized.
It is not fully initialized until the MainActivity has been fully
initialized.
With the BottomSheet open, while trying to tap one of the
controls (esp. add to playlist and favorite buttons) it is easy to
miss the touch point and tap directly on the BottomSheet.
This tap bleeds through to whatever fragment is currently displayed in
the navigation area (Artist, Album, Playlists, etc.). That tap
changes the view in the navigation panel. For example, if the Artist
fragment it current, it will open a list of the artists albums.
That change may be surprising when the BottomSheet is toggled closed.
So, ignore BottomSheet taps outside the active controls.
Having changed the context object in CoverArt from a received function
parameter to an initialization time derived variable, withContext no
longer needs a Context parameter.
That leaves the method misnamed. So rename withContext ->
requestCreator and drop the first parameter.
Address "java.lang.IllegalStateException: Too many receivers"
exceptions. (See Issue #145). Each new Picasso object registers its
own NetworkBroadcastReceiver. Worse, we create a new Picasso object
each time we transform an AlbumCover image. So do not create
unnecessary Picasso objects.
Rather than depend on receiving a Context object when called to load
an cover art, fetch the Application context as returned from FFA.get()
at singleton construction time. The Application context is long
lived.
This has an additional advantage. Not generation new Picasso objects
for each CoverArt image avoids holding a reference to an object that
cannot, later, be garbage collected.
This is part of an effort to resolve deprecation warnings.
Most of this is simple refactoring of interfaces that change between
the two Player implementations. There are a few other changes that
deserve further explanation.
Testing indicated that the play/pause button was being reset to pause
in MainActivity:refreshCurrentTrack. In the past this was likely
masked by the ordering of other callbacks. We have removed the
nowPlayingToggle.icon update from MainActivity, leaving that UI update
to PlayerService.
One of the bigger refactorings in PlayerService was forced by the
deprecation of Player.EventListener.onPlayerStateChanged. That forced
separation of handling playWhenReady and playbackState transitions.
In the SimpleExoPlayer implementations, where these transitions were
combined, the module attempted to work out playing state from a
combination of these two state variables.
In addition to separating the reaction to these state changes, we have
added a listener to onIsPlayingChanged, eliminating the need for some
of the earlier logic in Player.EventListener.onPlayerStateChanged.
This addition, along with the separation of state transition
processing, seems to provide a simpler implementation. But it is,
certainly, a possible source of bugs.
Migrate startActivityForResult/onActivityResult to
StartActivityForResult/registerForActivityResult in
LoginActivity/OAuth.
This moves responsibility for scheduling the starting Intent from
OAuth to LoginActivity.
OAuth still generates the Intent. But instead of starting the intent
directly in OAuth, the intent is returned to LoginActivity. This
better associates processing the activity result with its invocation.
OAuthTest module updated to accommodate internal API change.
Replace FragmentPagerAdapter with FragmentStateAdapter in
BrowseTabsAdapter.kt. Refactored getPageTitle as a function that
returns tab name. Tab text update moved to BrowseFragment.
This requires replacement of setupWithViewPager with
TabMediator.attach in BrowseFragment.
Also requires replacing widget declaration
androidx.viewpager.widget.ViewPager with
androidx.viewpager2.widget.ViewPager2 in fragment_browwse.xml.