- Make semantic colors and the page indicator theme-aware so they keep
adequate contrast in dark mode instead of using fixed values.
- Seed a full brand color scheme (#6C63FF) for devices without dynamic
color (Android 11 and below) instead of falling back to Material's
purple baseline; align the XML AppTheme accent accordingly.
- Stop manually forcing transparent system bar colors in the Compose
theme; those setters are no-ops on Android 15+ and stripped the system
contrast scrim, causing the half-gray navigation bar on One UI. Keep
syncing the bar icon appearance with the active theme.
- Add a dynamic-color opt-out toggle (Android 12+), defaulting off on
One UI where Samsung's palette extraction tends to look off.
DeepLinkConfirmActivity shared the default task affinity with the main
Aurora task, so when the app was already running the system brought the
existing task to the foreground instead of launching the gate. Giving
the trampoline an empty task affinity decouples it from the main task,
so the confirmation sheet and target listing load every time.
Resolves#1494
Allow signed-in users to rate, review, edit, and delete an installed app's
review directly from its details screen. The form is hidden from anonymous
accounts and only shown for installed apps.
Submitted reviews are cached locally in a new Room "review" table (db v9) so
they appear immediately while Google publishes them, and are reconciled with
the Play API: edits made on the Play Store are mirrored, and a review deleted
there (or via the new delete action) is removed locally. Deletion relies on
gplayapi 3.6.3.
The install event isn't delivered when the app replaces its own APK, so a
self-update could linger in the Updates list as "installing forever" after the
update completed and the app restarted.
- UpdateHelper: clear a stale self-update row on launch, flavor-aware — nightly
by its commit-tagged version name (the version code is static), release/preload
by the version code.
- DownloadHelper: finalize a self-update download stuck in INSTALLING (the commit
killed the process before it could advance) to INSTALLED on launch.
The deep-link router matched "/apps/dev" as a substring, so publisher
links (/store/apps/developer?id=<name>) were treated as developer-stream
links and failed to resolve. Match the exact action keyword (last path
segment, or host for market:// links) instead, and add a
Screen.PublisherProfile that renders the publisher-search overload of
DevProfileScreen.
Both /dev and /developer links may carry either a numeric developer id
(curated developer stream) or a developer name (publisher search), so
the id is parsed to long to decide which screen to open.
Also drop the now-dead ACTION_VIEW branch from ComposeActivity, since
DeepLinkConfirmActivity owns all external VIEW deep links.
The DevProfileScreen(developerId) overload was an empty stub, so
play.google.com/store/apps/dev?id= deep links rendered a black screen.
Render the developer's stream bundle via the existing StreamCarousel,
observing DevProfileViewModel for loading, error/retry and per-cluster
pagination.
Ad networks can exploit Aurora's market:// and play.google.com VIEW
intent-filters to launch the app straight into a listing without user
intent (issue #1450). Route these external deep links through a new
translucent DeepLinkConfirmActivity that shows a Play Store-style
bottom sheet over the launching app; the listing only opens after an
explicit tap, defeating auto-launch regardless of referrer.
- DeepLinkConfirmActivity: resolves the listing, shows the sheet, then
forwards to ComposeActivity via the Screen parcel (Open) or finishes
(Cancel). Forwards directly when the user opts out.
- DeepLinkConfirmSheet: bottom sheet matching the existing sheets/
convention; shows the target id and the launching app when known.
- Move the VIEW intent-filters off ComposeActivity onto the new
activity, using a transparent edge-to-edge translucent theme.
- Add a "Confirm external links" toggle in Security (default on).
Addresses #1508
Add an 'Install all' action to the Favourites screen that bulk-fetches
details and enqueues every installable favourite (skipping already
installed apps and paid apps anonymous accounts can't acquire), gated
behind a confirmation dialog that warns about per-app install prompts.
Show live state on each favourite row: an installed tick that updates
on install/uninstall events, and download/install progress mirroring the
Updates screen. Hide 'Install all' once every favourite is installed.
Treat only non-finished download statuses as in progress on both the
Favourites and Updates rows so a dismissed system install prompt no
longer leaves a row stuck showing 'Installing'.
Resolves#1499
Surface a 'Buy @ price' action on the install error sheet for paid apps
on signed-in accounts, opening the Play Store listing to purchase. For
anonymous accounts, show the price on a disabled install button and
disable manual downloads since paid apps can't be acquired.
Group the five channels under two headings in the system notification
settings so they're easier to navigate: "Downloads & updates" (progress,
installed, updates, export) and "Alerts" (errors and action-required).
Purely organisational; channel importances and behaviour are unchanged.
There was no in-app control over notifications. Add a Notifications
preference screen under Settings offering:
- "Show download progress": when off, downloads/updates no longer post
per-tick progress; a single quiet foreground notification keeps the
work running in the background (honouring the mandatory FGS rule).
- Deep links into each notification category's system settings (O+) so
users can tune sound and importance per channel.
- A shortcut to enable notifications when they're turned off at the
system level, so the screen degrades gracefully.
The download worker reads the progress preference live, keeping its
foreground notification minimal and skipping progress refreshes when
the user has opted out. POST_NOTIFICATIONS is already handled by the
onboarding permission flow, so no duplicate prompt is added here.
A bulk update produced one standalone notification per app for both
successes and failures, flooding the shade. Bundle these terminal
notifications into two groups, each with a collapsible summary that
lists the apps via InboxStyle:
- "N apps installed" on the (LOW, silent) installed channel, expiring
on its own since it's informational.
- "N apps failed" on the (HIGH) alerts channel, persisting until
handled and carrying a Retry action per app.
Summaries are rebuilt from the live posted notifications rather than
tracked state, so they stay correct across retries, dismissals and
process restarts, and are only posted on Android N+ where the system
actually renders groups.
Retry re-queues the download via a new DownloadRetryReceiver; the
worker resumes from verified files on disk, so retrying an install
failure re-installs without re-downloading.
The download worker posted a separate per-app notification for every
internal phase transition, keyed by package hash and distinct from the
ongoing foreground progress notification. In practice this meant:
- a blank, non-dismissable notification while "purchasing" (no branch
rendered it), and
- a transient "download complete" notice for every app that was then
immediately replaced by the install-success notification.
During a bulk update this produced a burst of redundant notifications.
Suppress the purchasing/verifying phases (the ongoing progress
notification already conveys activity) and only surface completion when
the user must act on it (apps that can't be installed silently get a
tap-to-install notice). Silently-installable apps now go straight to a
single "installed" notification.
Also clear any stale per-app notification on these phases and on
cancellation, fixing a leak where a cancelled download left its last
notification behind, and refresh the foreground notification to an
"Installing" state so the user sees a clean downloading -> installing
progression instead of a download bar stuck at 100%.