Skip to content

feat(settings): add aw-notify configuration panel - #923

Merged
ErikBjare merged 2 commits into
ActivityWatch:masterfrom
TimeToBuildBob:feat/aw-notify-settings
Aug 3, 2026
Merged

ErikBjare merged 2 commits into
ActivityWatch:masterfrom
TimeToBuildBob:feat/aw-notify-settings

Conversation

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

Summary

Adds a Notifications settings group with an AwNotifySettings component that reads and writes /api/0/settings/aw-notify — the same key the Android aw-notify NotifyWorker reads at startup (ActivityWatch/aw-android#202).

  • New settings component: src/views/settings/AwNotifySettings.vue
  • New "Notifications" tab in Settings.vue wired to the component
  • Reads existing config on mount with graceful 404 fallback to defaults
  • Lets users configure alert label, category filter, minute thresholds, and goal/warning type
  • Matches the JSON schema from feat(notify): read alert config from server settings, fall back to defaults aw-android#202:
    [
      {"category": null, "label": "All", "thresholdMinutes": [60, 120, 240], "positive": false},
      {"category": "Work", "label": "Work", "thresholdMinutes": [15, 30, 60], "positive": true}
    ]

Context

This is Goal 2 from ActivityWatch/aw-android#201: a shared webui config surface so users manage notification thresholds in one place regardless of client, once the config lives in the settings API (done via ActivityWatch/aw-android#202).

Default alerts mirror the trimmed set from ActivityWatch/aw-android#206.

Test plan

  • Navigate to Settings → Notifications — panel loads
  • On a server with no aw-notify setting, defaults (All 60/120/240 min, Work 15/30/60 min) appear
  • Edit thresholds and click Save — /api/0/settings/aw-notify is updated
  • Reload page — saved config persists
  • Add and remove alert rows
  • Verify Android app reads updated thresholds from /api/0/settings/aw-notify

Adds a new Notifications settings group with an AwNotifySettings
component that reads/writes /api/0/settings/aw-notify — the same
key the Android aw-notify NotifyWorker reads at startup (PR ActivityWatch#202).

Users can configure alert labels, category filters, minute
thresholds, and goal vs. warning notification type from the
Settings UI without editing server-side JSON directly.

Default alerts mirror the trimmed set from PR ActivityWatch#206:
- All time: 60/120/240 min (warning)
- Work:     15/30/60 min  (goal)

Related: ActivityWatch/aw-android#201
@greptile-apps

greptile-apps Bot commented Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds a Notifications settings panel for configuring Android aw-notify alerts through the server settings API.

  • Adds strict parsing and validation for comma-separated positive whole-minute thresholds.
  • Supports loading, editing, adding, removing, and saving notification configurations.
  • Preserves a saved empty alert array while using defaults only for missing or non-array settings.
  • Adds the Notifications tab and unit coverage for threshold parsing.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the current code preserves an empty saved configuration and rejects the malformed threshold inputs identified in the previous review.

Important Files Changed

Filename Overview
src/util/aw-notify.ts Adds strict positive-integer threshold parsing, addressing the prior silent truncation and filtering behavior.
src/views/settings/AwNotifySettings.vue Adds the notification configuration UI and preserves successfully loaded empty arrays, resolving both previously reported failures.
src/views/settings/Settings.vue Registers the new component and exposes it through a Notifications settings group.
test/unit/aw-notify.test.js Covers valid threshold parsing and rejection of empty, fractional, malformed, non-positive, and trailing-comma input.

Reviews (2): Last reviewed commit: "fix(settings): validate notification thr..." | Re-trigger Greptile

Comment thread src/views/settings/AwNotifySettings.vue Outdated
Comment on lines +125 to +129
if (Array.isArray(data) && data.length > 0) {
this.alerts = data.map(dtoToRow);
} else {
this.alerts = this.defaultAlerts();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Empty configuration restores defaults

When the user removes every alert and saves, the server-backed empty array enters this default branch on reload, causing the saved disabled state to be lost and the All and Work thresholds to become active again.

Suggested change
if (Array.isArray(data) && data.length > 0) {
this.alerts = data.map(dtoToRow);
} else {
this.alerts = this.defaultAlerts();
}
if (Array.isArray(data)) {
this.alerts = data.map(dtoToRow);
} else {
this.alerts = this.defaultAlerts();
}

Knowledge Base Used: Settings, Server Connection, Theme, and i18n

Comment thread src/views/settings/AwNotifySettings.vue Outdated
Comment on lines +87 to +91
const thresholds = row.thresholdStr
.split(',')
.map(s => parseInt(s.trim(), 10))
.filter(n => !isNaN(n) && n > 0);
return {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Threshold parser silently changes values

When a user enters a fractional or malformed threshold such as 60.5, abc, -5, parseInt truncates the fraction and the filter silently drops other entries, causing a different configuration to be persisted while the UI still reports that the settings were saved.

@codecov

codecov Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 38.80%. Comparing base (e304925) to head (269c0bb).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #923      +/-   ##
==========================================
+ Coverage   38.67%   38.80%   +0.13%     
==========================================
  Files          42       43       +1     
  Lines        2273     2278       +5     
  Branches      460      456       -4     
==========================================
+ Hits          879      884       +5     
  Misses       1315     1315              
  Partials       79       79              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

@greptileai review

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

CI-green and mergeable (Greptile 5/5) — waiting only on a maintainer click.

This PR is ready to merge, but the bot has pull-only access to this repo and can't self-merge — surfacing it here so it isn't lost. The monitoring loop will stop re-flagging it now that this note is posted.

@ErikBjare
ErikBjare merged commit 009f484 into ActivityWatch:master Aug 3, 2026
9 checks passed
@ErikBjare

Copy link
Copy Markdown
Member

@TimeToBuildBob Merged, but this needs to use the same format as https://github.com/ActivityWatch/aw-notify-rs so that desktop (aw-tauri) notifications also work out of the box with unified config.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

Fixed the schema mismatch in follow-up #924. The editor now reads/writes aw-notify-rs’s existing object + snake_case NotificationConfig shape, preserves desktop toggles, and migrates the briefly shipped Android array shape. Desktop server-settings consumption is tracked in ActivityWatch/aw-notify-rs#38; Android’s parser update remains under ActivityWatch/aw-android#201, which I reopened rather than falsely treating the shared-config goal as done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants