Skip to content

Develop - Island navigation, auto cleanup screenshots, widget stack persistency, notification DIY - #1425

Merged
sameerasw merged 24 commits into
mainfrom
develop
Oct 18, 2026
Merged

sameerasw merged 24 commits into
mainfrom
develop

Conversation

@sameerasw

Copy link
Copy Markdown
Owner

Description

This pull request introduces several new features and improvements, primarily focused on navigation notification support, enhanced screenshot management, and expanded DIY action capabilities. The main changes include adding a new navigation notification data model and parser, extending screenshot cleanup and auto-clean options, introducing a "Send Notification" DIY action, and updating feature and permission registries to reflect these enhancements.

Navigation Notification Support:

  • Added a new NavigationNotificationData data class and NavigationParser utility for parsing and handling navigation notifications, including distance parsing and exit action detection.
  • Introduced navigation-related settings in SettingsRepository, such as toggles for showing navigation, navigation-on-new behavior, peek-after-expand, and expand distance. [1] [2]
  • Registered navigation as a new island priority and entry for proper display ordering and handling. [1] [2]

Screenshot Management Enhancements:

  • Expanded screenshot cleanup functionality with new settings for auto-clean, cleanup delay, tracking cleaned count/bytes, and last cleaned ID. Synchronized methods for recording cleaned/restored screenshots were added. [1] [2]
  • Updated the feature registry to group screenshot-related features under a unified "Screenshots" feature, added new searchable settings, and adjusted device support requirements.
  • Updated permission registry to include POST_NOTIFICATIONS for the screenshots feature.
  • Registered a new screenshot cleanup receiver in the Android manifest.

DIY Actions:

  • Added a new SendNotification action to the DIY actions system, allowing users to configure and trigger notifications with custom titles and bodies. [1] [2]

Widget Stack Improvements:

  • Implemented position tracking for widget stacks, including methods to get and save positions, and ensured positions are cleaned up when stacks are deleted. [1] [2] [3]

Feature Registry and Search:

  • Added navigation and screenshot settings to the searchable settings in the feature registry, improving discoverability and configuration. [1] [2]

These changes collectively enhance the app's capabilities around navigation, screenshots, and user customization, while improving maintainability and discoverability of features.

Type of change

  • Bug fix
  • New feature
  • UI / visual update
  • Performance improvement
  • Refactoring / cleanup
  • Translations
  • Build / CI tooling

isaacsa51 and others added 23 commits October 13, 2026 11:45
…gation_plugin_connection

# Conflicts:
#	app/src/main/java/com/sameerasw/essentials/data/repository/SettingsRepository.kt
#	app/src/main/java/com/sameerasw/essentials/domain/registry/FeatureRegistry.kt
#	app/src/main/java/com/sameerasw/essentials/island/service/IslandCoordinator.kt
#	app/src/main/java/com/sameerasw/essentials/ui/features/display/IslandSettingsUI.kt
#	app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt
#	app/src/main/res/values/strings.xml
Moves "Delete shared screenshots" onto a new Screenshots page under Security
and adds:
- a delay after sharing (immediately, 1 hour, 1 day)
- auto-clean: every new screenshot is trashed after 1, 7 or 30 days, with a
  quiet notification offering Keep and Trash now; starred screenshots are kept
- a count of cleaned screenshots and the storage saved

New screenshots are picked up with a MediaStore ContentObserver and each
cleanup is a unique WorkManager job keyed by the media id.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
## Description
<!-- Describe what this PR changes and why. If it resolves an issue,
link it here: e.g. Closes #123 -->
Enable navigation popup on island when any type of navigation.

Navigation only accepts ongoing notifications that pass
isNavigationNotification. That means the channel ID is in the navigation
channel list or contains "navigation", or the category contains
"navigation".

Maps' Live Update has a progress bar, so it would also qualify for the
progress ring. While the island and its Navigation item are on,
extractLatestProgressNotification skips navigation notifications, so the
progress plugin doesn't show it a second time.

Inside the changes a couple of settings can be enabled inside the
toggle:
<img width="561" height="790" alt="image"
src="https://github.com/user-attachments/assets/d47c81a3-3254-49e1-a3c0-a48cc237d727"
/>

- New instruction: This options ask the user the behaviour of the island
when an going change of direction is headed at. By default this expands
the island with all info. (the user can set the island to only Line peek
the info, or do nothing)
 - Expand before turn: Kinda self explanatory.
- Line peek after expanding: Once the user pass a direction and
collapses by default, this renders the island with the line peek info,
off by default.

This implementation was only tested on a real device and on an emulator
with no issues, Waze doesn't create any notification with nav info apart
of the only persistent notification to keep the app alive.

## Type of change
- [ ] Bug fix
- [x] New feature
- [ ] UI / visual update
- [ ] Performance improvement
- [ ] Refactoring / cleanup
- [ ] Translations
- [ ] Build / CI tooling

## UI changes
<!-- Required if this PR changes or adds UI. Please attach screenshots
or a screen recording. -->


https://github.com/user-attachments/assets/018fc3de-b2fd-4cd4-b60f-df4f1f6749a0


[Screen_recording_20261013_115734.webm](https://github.com/user-attachments/assets/c21fd215-ac12-46c9-9d4e-e265d986fe54)




## Checklist
Before submitting, please make sure:
- [x] The base branch is set to `develop` (not `main`).
- [x] The app builds cleanly locally with `./gradlew assembleDebug`.
- [x] Unit tests pass with `./gradlew testDebugUnitTest`.
- [x] You tested the changes on a device or emulator (including Shizuku
or Root if applicable).
- [x] New preferences use `SettingsRepository` for keys and
getter/setter methods.
- [x] New user-facing settings are registered in `FeatureRegistry.kt`
for search indexing.
- [x] New UI follows the design system in `ui/core/`
(`RoundedCardContainer`, `IconToggleItem`, etc.).
- [x] Strings are added to `res/values/strings.xml` and drawables use
rounded variants (`R.drawable.rounded_*`).
<!-- claude-projects-attribution: {"github_login":"jawzf"} -->
_Requested by **Joe** · [project
thread](https://claude.ai/code/project/chan_01FyKGsodrf7JS5wLrjvnZmV?thread=cmsg_01FyKGsodrf7JS5wLrjvnZmVMzi9Au2zRtq95Xj3iAzWwM)_

## Description
Follow-up to #1380 (merged).

Before: screenshot cleanup was a single "Delete shared screenshots"
toggle that trashed a screenshot right after you shared it.

After: a dedicated Screenshots page under Security with:
- **After sharing**: the existing toggle, plus a delay of Immediately, 1
hour or 1 day before the shared screenshot is trashed.
- **Auto-clean**: trashes every new screenshot after 1, 7 or 30 days.
Each new screenshot gets a quiet, grouped notification with a preview
and Keep / Trash now actions, which times out after an hour. Screenshots
starred in Photos are always kept.
- **Cleaned so far**: how many screenshots were cleaned and the storage
saved.

How: a MediaStore `ContentObserver` in the accessibility service picks
up newly saved screenshots (only ones added in the last minute, with the
last seen id stored so restarts don't re-notify). Each one gets a unique
per-screenshot WorkManager job; Keep cancels it, and Trash now runs it
immediately. Trashing still uses the `IS_TRASHED` update from #1380, so
screenshots stay restorable for 30 days, and starred ones are skipped by
the automatic cleanup. No new permissions.

## Type of change
- [ ] Bug fix
- [x] New feature
- [x] UI / visual update
- [ ] Performance improvement
- [ ] Refactoring / cleanup
- [ ] Translations
- [ ] Build / CI tooling

## UI changes
<img width="1344" height="2992" alt="1_screenshots_page"
src="https://github.com/user-attachments/assets/35693295-c270-4459-9e29-e0981ca9a4d0"
/>

<!-- 1_screenshots_page.png -->
The new Screenshots page.

<!-- 2_auto_clean_notification.png -->
<img width="1344" height="2992" alt="2_auto_clean_notification"
src="https://github.com/user-attachments/assets/9e62eb5f-6c08-46bc-a746-8e1d1d238bbf"
/>

The auto-clean notification with Keep and Trash now.

<!-- 3_share_delay_toast.png -->
<img width="359" height="800" alt="3_share_delay_toast"
src="https://github.com/user-attachments/assets/95e830ca-0b84-463f-831c-69919188289e"
/>

The message shown when a shared screenshot is scheduled for later.

<!-- 4_grouped_notifications.png -->
<img width="1344" height="2992" alt="4_grouped_notifications"
src="https://github.com/user-attachments/assets/e2c568e3-efb6-4889-a508-322cac998923"
/>

Several screenshot notifications grouped together.

## Checklist
Before submitting, please make sure:
- [x] The base branch is set to `develop` (not `main`).
- [x] The app builds cleanly locally with `./gradlew assembleDebug`.
- [x] Unit tests pass with `./gradlew testDebugUnitTest`.
- [x] You tested the changes on a device or emulator (including Shizuku
or Root if applicable).
- [x] New preferences use `SettingsRepository` for keys and
getter/setter methods.
- [x] New user-facing settings are registered in `FeatureRegistry.kt`
for search indexing.
- [x] New UI follows the design system in `ui/core/`
(`RoundedCardContainer`, `IconToggleItem`, etc.).
- [x] Strings are added to `res/values/strings.xml` and drawables use
rounded variants (`R.drawable.rounded_*`).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01CVTvKLdph38zfD5D45PjJh
Each stack's current widget was only kept in memory, so a reboot, app
update or killed process sent every stack back to its first widget.
Positions are now saved per stack in widget_stack_prefs after an arrow
or edge step, when the screen turns off and when the app is moved to
the background, and restored (clamped to the hosted widgets) on start.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
## Description
Follow-up to #1328 (widget stack).

Before: each stack's current widget was only kept in memory, so after a
reboot, an app update or the process being killed, every stack went back
to its first widget.

After: a stack comes back showing the widget it was on.

How: positions are saved per stack in the existing `widget_stack_prefs`
file (`position_<stackWidgetId>`), next to the stack configs, and
restored when `StackHost` starts. A small `StackPositions.restore`
clamps each saved position to the stack's current widgets and drops
positions for stacks that no longer exist. Positions are saved:
- right after an arrow or edge step,
- when the screen turns off,
- when the app is moved to the background (`onTrimMemory`), because a
cached app gets frozen and doesn't receive `SCREEN_OFF` until it wakes.

They aren't saved on every timer tick, so a running stack doesn't write
to disk every few seconds. Removing a stack also removes its saved
position.

## Type of change
- [ ] Bug fix
- [x] New feature
- [ ] UI / visual update
- [ ] Performance improvement
- [ ] Refactoring / cleanup
- [ ] Translations
- [ ] Build / CI tooling

## UI changes
None.

## Checklist
- [x] The base branch is set to `develop` (not `main`).
- [x] The app builds cleanly locally with `./gradlew assembleDebug`.
- [x] Unit tests pass with `./gradlew testDebugUnitTest` (new
`StackPositionsTest`, 6 tests).
- [x] Tested on the Android 17 emulator: stepped a 3-widget stack to the
2nd widget, rebooted, same widget shown; removed a widget so the saved
position was out of range, rebooted, last widget shown without errors;
confirmed nothing is written on timer ticks.
- [x] Positions stay in `WidgetStackRepository` alongside the stack
configs, as the widget stack already stores its data there; no new
user-facing preference.
- [x] No new settings, so nothing to register in `FeatureRegistry.kt`.
- [x] No UI changes.
- [x] No new strings or drawables.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Posts a notification with a user-set title, message and label (shown as
subtext next to the app name) on its own "Automation notifications"
channel. Running the same action again replaces its notification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
## Description
Adds a **Send notification** action to DIY automations, under System
actions next to Wait.

Before: automations could only post failure notices; there was no way to
show your own message.

After: add Send notification to any automation and fill in:
- **Title**
- **Message** (multi-line)
- **Label** (optional): shown next to the app name in the header, e.g.
"Essentials • Home". Android always shows the posting app's name there,
so the label is set as the notification's subtext.

Save stays disabled until there's a title or a message, and blank fields
are left off the notification. The action row shows "Send notification ·
<title>".

How: `Action.SendNotification` is a configurable action like `Wait`,
saved through the existing `ActionGsonAdapter`.
`AutomationNotificationPoster` posts it on a new **Automation
notifications** channel, separate from the failure notices so either can
be muted on its own. Each action uses its own notification id, so
running the same action again replaces its notification while different
actions stack. The action needs `POST_NOTIFICATIONS`; the editor shows
the existing permission sheet when it's missing, and at run time a
missing permission is skipped without a crash.

## Type of change
- [ ] Bug fix
- [x] New feature
- [ ] UI / visual update
- [ ] Performance improvement
- [ ] Refactoring / cleanup
- [ ] Translations
- [ ] Build / CI tooling

## UI changes
<!-- 1_notification.png -->
<img width="1344" height="2992" alt="1_notification"
src="https://github.com/user-attachments/assets/3a6cbb20-726f-468a-809b-f482f9b8ca07"
/>

The posted notification with title, message and label.

<!-- 2_two_notifications.png -->
<img width="1344" height="2992" alt="2_two_notifications"
src="https://github.com/user-attachments/assets/e3e93305-0578-4d04-8897-00dfafbc0f49"
/>

Two different Send notification actions stack; the one with only a title
has no empty lines.

## Checklist
- [x] The base branch is set to `develop` (not `main`).
- [x] The app builds cleanly locally with `./gradlew assembleDebug` (and
`assembleRelease`).
- [x] Unit tests pass with `./gradlew testDebugUnitTest` (2 new tests in
`ActionListJsonTest`: round trip, and missing fields load as empty).
- [x] Tested on the Android 17 emulator: action listed under System;
Save disabled when empty; notification shows title, message and
"Essentials • <label>"; blank fields omitted; same action twice shows
one notification, two actions show two; without notification permission
the editor shows the permission sheet and running the automation doesn't
crash; actions keep their text after a force-stop.
- [x] Reuses `EssentialsBottomSheet`, `RoundedCardContainer` and the
existing permission sheet.
- [x] New strings are in `strings.xml` (English only).
- [x] No new settings, so nothing to register in `FeatureRegistry.kt`.
- [x] No new dependencies or permissions in the manifest.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@sameerasw sameerasw self-assigned this Oct 18, 2026
@sameerasw sameerasw added the enhancement New feature or request label Oct 18, 2026
@sameerasw
sameerasw merged commit 62608b6 into main Oct 18, 2026
1 check passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Essentials Progress Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants