No longer bind the views as they become visible. This resulted in
the same view being bound multiple times, but that was unneccesary.
Given that there is only five types of view, and each view type only
ever gets used once, the binding can happen when the view holder is
created, rather than each time it is shown. This fixed a few bugs to
do with views being inflated multiple times.
Shows progress and download complete now, but left a few TODOs
lying around. These are mainly around the ability to then deal with
installing an app once download is complete.
The styles used by the app details showed good padding on either
side of the buttons text. This was because they had a certain amount
of screen space to fill up which resulted in nice empty space on either
side of the text. Other buttons do not have this type of layout, so
need to have a minimum amount of padding thrust upon them.
Required breaking out into values-v17 too, so refactored common styles
into base style to make this easier.
As per the main screens feature image behind the "Recently added"
items, also use the same abstract artwork as a placeholder for the
feature image in app details.
Draws two rows of triangles, each coloured randomly according to
the dominant colour in the apps icon.
Given that the colour is probably assigned to the FeatureImage in response to
a network request finally downloading an image, there is a period of no feature
image. After the colour is provided, then if it is set instantly it tends to
look jerky. This eases in the colouring of the feature image.
Happy to discuss whether this is a good idea or not, but right now
there is no way to update repositories so often you are left with
an empty first screen.
This doesn't worry about state management (e.g. remembering
whether we are refreshing or not and showing this when we resume the
activity). Instead, it listens for the refresh listener, and when
triggered it will set the refreshing state to not refreshing. For now
the notification can act as the feedback that something is happening.
This is a little bit flakey at this point, because the weird asynchronous nature of
adding fragments. If swiping to the second-to-last entry on the bottom navigation view,
it will populate the settings fragment in the UI and then it will dissapear. Need to
fix this.
Show a "Chip" in the search box whcih indicates the user is viewing
a particular category. This chip:
* Gets remtoved when the user presses backspace from in front of it.
* Can be re-added by typing the name of a category and then a colon.
* Follows the material design guidelines.
* Has an accessibility hint that tells screen readers it is a category name.
This is different to the old categories drop down, because that also
included meta-categories of "Whats New" and "Recently Updated". Given
we now show them on the first page, this categories screen can do away
with them.
Each category entry loads a few apps to show to the user.
Note: The "View all" button next to each category doesn't currently
go anywhere. It will soon be hooked up to an app list that is filtered
to the selected category.
Not fully featured yet, because it doesn't listen for broadcasts
from the installers, but it is shows the correct list of apps and
allows users to queue up downloads of all updateable apps.
Smooshes the recently updated and recently added lists into one,
and adds a status line under each app saying which of the two it
is (i.e. "Recnelty Updated" or "Whats New".
It doesn't load up the entire swap activity at this point. Instead it
is an entry point to direct the user to that activity.
Also added stubs for the remaining screens which need to be implemented
to the MainAdapter and MainController.
The fragment was quite straightforward to roll into the activity. Most
of the code moved across almost exactly as is.
Also added a theme for the toolbar so that in the future it will be
easier to support dark/night themes as well.
Also, add code to AppDetails2 to match AppDetails, keeping track of
currently viewed app. Moved the nulling of this info to onStop instead
of onPause, since alerts may be shown on top of the details page, while
still visible.
The `setApkInternal` method had to infer the intent of the caller
based on the arguments which were passed on, and then do specific
things depending on the input. Instead, this change has three
distinct actions which can happen (add/remove/update). Each of
these methods does only one thing, and doesn't have to guess
the intent of the caller. The only exception may be "add", which
will (for convenience) delegate to "update" if it already knows
about the apk in question.
The only time `status == null` was when coming from `removeApk()`. By
moving the logic out of `setApkInternal()` into `removeApk()` it makes
it easier to reason about `setApkInternal()` as it now does less. Also,
it was doubling up on the `syncrhonized (appMapping)` and `if (entry !=
null)` logic which is no longer required, because `removeApk()` was
already doing that.
While here, also make explicit the fact that `status` can no longer be
`null`.
Because of the way that this can be misused without the compiler knowing
(e.g. by forgetting to call `endBatchUpdates()`) it may be safer to move
it to an internal implementation detail of the class.
It could probably be done away with completely if the `notify*` methods
were moved out of the respective `*ApkInternal()` methods, but that
requires more significant refactoring to get right without code
duplication.
It seems that `setContentIntent()` will do fine if we pass it a null
argument. The default value is `null` anyway, and it doesn't mandate
a non-null argument.
Given that none of the callers need the functionality of the builder,
lets make it explicit that we don't expect the builder to be further
customized once it is returned. Instead, return a notification to hint
that no further customization is required/desired.