Commit Graph

3992 Commits

Author SHA1 Message Date
Jose Olarte III
af63ab70e7 feat(notifications): add dev/test 10-minute rollover toggle and plugin spec
- Add dev-only "Use 10-minute rollover (testing)" toggle in Reminder
  Notifications (Account view). Visible only when not on prod API server
  (isNotProdServer). Toggle persists and reschedules reminder with
  rolloverIntervalMinutes when changed.
- Extend daily notification flow to pass optional rolloverIntervalMinutes
  to the plugin: NotificationService/NativeNotificationService options,
  PushNotificationPermission dialog options, first-time and edit flows.
- Add settings: reminderFastRolloverForTesting (Settings, AccountSettings,
  PlatformServiceMixin boolean mapping, migration 007).
- Centralize isNotProdServer(apiServer) in constants/app.ts; use in
  AccountViewView (toggle visibility), ImportAccountView, and TestView.
- Add docs/plugin-spec-rollover-interval-minutes.md for the plugin repo
  (configurable rollover interval and persistence after reboot).

Note: Daily notification plugin dependency is currently pointed at the
"rollover-interval" branch for testing this feature.
2026-03-03 21:31:07 +08:00
Jose Olarte III
96ae89bcfa docs: add daily notification duplicate/fallback analysis and plugin handoff 2026-03-02 20:35:08 +08:00
Jose Olarte III
7e2b16ddad docs: add plugin handoff for Android 6.0 (API 23) ZoneId fix
Add doc/plugin-feedback-android-6-api23-zoneid-fix.md for the
daily-notification-plugin repo: replace java.time.ZoneId with
TimeZone.getDefault().id so the plugin runs on API 23 without
affecting behavior on API 26+.
2026-02-27 21:50:39 +08:00
Jose Olarte III
29aff896be docs: add plugin feedback for Android rollover double-fire and user content
- New doc: rollover double-fire and missing user-set content diagnosis
- Link from DAILY_NOTIFICATION_BUG_DIAGNOSIS.md; include Cursor handoff section
2026-02-26 21:12:50 +08:00
Jose Olarte III
d4721f5f4c fix(help): improve notification troubleshooting copy and use app constants
- Fix typo in Android Chrome "Clear browsing data" step
- Use TimeSafari in Settings steps and clarify PWA vs native install
- Add Battery & background subsection (iOS and Android)
- Add Focus / Do Not Disturb note under Check App Permissions
- Add quick checklist at top before Full Test
- Replace hardcoded app names with AppString.APP_NAME and APP_NAME_NO_SPACES
2026-02-26 17:58:32 +08:00
Jose Olarte III
baac36607b fix: show readable copy for reminder notification toggle dialogs
Replace DIRECT_PUSH_TITLE in confirm and success messages with
"reminder notifications" so users see clear text instead of
the internal constant name.
2026-02-26 16:32:06 +08:00
Jose Olarte III
25c3cd99e4 docs: add plugin feedback for Android rollover after reboot
Document that boot recovery can skip rescheduling after device restart
(duplicate PendingIntent check), causing the next daily notification to
fail to fire on devices that clear AlarmManager alarms on reboot. Include
Scenario 1 logcat (notification fired when alarm survived), two-scenario
distinction, recommended fix (skipPendingIntentIdempotence in boot path),
duplicate-alarm clarification, and Cursor-ready implementation section
for the daily-notification-plugin repo.
2026-02-24 21:59:24 +08:00
Jose Olarte III
cd5f9f5317 docs: add plugin feedback for Android post-reboot notification fallback text
Document bug where daily reminder shows fallback text after device restart
(Intent extras not surviving reboot). Includes root cause, recommended
plugin fixes (persist/restore title/body, use DB in recovery), and
verification steps for the daily-notification-plugin repo.
2026-02-23 21:24:29 +08:00
8310152c34 bump version to 1.3.2 2026-02-18 19:38:31 -07:00
Jose Olarte III
c28c47a3c9 docs: add plugin feedback for Android duplicate reminder notification
Add docs/plugin-feedback-android-duplicate-reminder-notification.md
describing the duplicate notification on first-time reminder setup (one
correct + one fallback). Root cause: ScheduleHelper schedules the
static reminder alarm and also enqueues the prefetch worker, which
on fallback schedules a second alarm via DailyNotificationScheduler.

Suggested fix: for static-reminder schedules, do not enqueue prefetch
(or have prefetch skip scheduleNotificationIfNeeded). The suggested
plugin changes were applied and fixed the issue.
2026-02-18 19:52:41 +08:00
Jose Olarte III
1b97ac08fd fix(electron): preserve electron-plugins.js during clean
Exclude electron/src/rt/electron-plugins.js from clean in build-electron.sh
so the hand-maintained plugin list is not deleted. Update Podfile.lock
(TimesafariDailyNotificationPlugin 1.1.0 → 1.1.6) and electron
package-lock.json.
2026-02-17 18:57:27 +08:00
Jose Olarte III
17ccfd1fea Fix: Android reminder toast and boot recovery
- Toast/notify: Keep dialog open until schedule flow finishes so success/error
  $notify runs while component is mounted (fixes missing toast on Android).
  Add success/error notify in edit-reminder callback (AccountViewView).
- Boot recovery: Split BootReceiver intent-filter so BOOT_COMPLETED and
  LOCKED_BOOT_COMPLETED use a filter without <data>; use a separate filter
  with <data scheme="package"/> for MY_PACKAGE_REPLACED/PACKAGE_REPLACED.
  Boot broadcasts have no Uri and were not matching the previous filter,
  so daily reminder now reschedules after device restart.
2026-02-17 17:55:13 +08:00
Jose Olarte III
0e096b1a46 Fix: Android daily notification: single schedule on edit, no double-cancel
Resolves long-standing issue where the second scheduled time (after editing
the reminder) did not fire on Android.

- PushNotificationPermission: add open(..., options?: { skipSchedule }).
  When skipSchedule is true (edit flow), dialog only invokes callback with
  time/message; parent is sole scheduler so the plugin is not called twice.
- AccountViewView: pass { skipSchedule: true } when opening the dialog for
  edit; keep cancel (iOS only) + single scheduleDailyNotification in callback.
- NativeNotificationService: serialize scheduleDailyNotification so only one
  schedule runs at a time (scheduleLock + doScheduleDailyNotification).
- AccountViewView: guard edit-reminder callback with editReminderScheduleInProgress
  so one schedule per user action.
- Gate pre-cancel on Android in edit flow (CONSUMING_APP brief): skip
  cancelDailyNotification before schedule on Android; plugin cancels internally.
- Use single stable reminder id and always pass id on both platforms (plugin 1.1.2+).
- Add doc/plugin-android-edit-reschedule-alarm-not-firing.md for plugin repo
  (cancel-before-reschedule may cancel the PendingIntent used for setAlarmClock).
2026-02-16 21:25:07 +08:00
dc3f12d53b bump version for testing (1.2.x), and for the eventual 1.3.0 release 2026-02-15 13:39:09 -07:00
Jose Olarte III
ec55a74cbf WIP: Daily notification – optional id cleanup; Android issue not fixed
- NativeNotificationService: use single stable reminder id on iOS and Android,
  always pass id in scheduleOptions (plugin v1.1.2+ optional cleanup).
- Add doc/plugin-fix-scheduleExactNotification-calls.md for plugin repo
  (fix Java call sites for scheduleExactNotification 8th parameter).
- package-lock.json: update lockfile.

Android second-schedule issue still present; to be revisited.
2026-02-13 21:17:04 +08:00
Jose Olarte III
c2fb493073 WIP: android daily notification re-schedule + plugin handoff doc
- NativeNotificationService: platform-specific schedule/cancel
  - iOS: pass id "daily_timesafari_reminder", call cancelDailyReminder before schedule
  - Android: no id (plugin uses "daily_notification"), skip pre-cancel to match test app
- Verification: return true when schedule succeeds but reminder not found (avoids error dialog)
- doc: android-daily-notification-second-schedule-issue.md
  - Symptom, timing (re-schedule-too-soon), test app vs TimeSafari
  - Plugin-side section: entry point, files, likely cause, suggested fixes, repro steps
  - For use in plugin repo (e.g. Cursor) to fix second-schedule

Re-scheduled notifications on Android still fail to fire; fix expected in plugin (see doc).
2026-02-13 18:44:38 +08:00
Jose Olarte III
c05dff6654 feat(android): integrate daily notification plugin with native fetcher
Add native Android components for daily notification plugin integration:
- TimeSafariApplication: Custom Application class to register native fetcher
- TimeSafariNativeFetcher: Implements NativeNotificationContentFetcher interface
- network_security_config.xml: Allow cleartext for local development

Configuration updates:
- AndroidManifest.xml: Link custom Application class, add required permissions
- build.gradle: Add Java 17 compile options and required dependencies
- capacitor.config.ts: Add DailyNotification plugin configuration
- NativeNotificationService.ts: Use "daily_" prefixed ID for schedule rollover

Note: Subsequent notification scheduling after first fire still has issues
that require further investigation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 21:20:52 +08:00
Jose Olarte III
a7fbb26847 docs: add Android physical device deployment guide
Add comprehensive guide for building and testing TimeSafari on physical
Android devices, covering device setup, USB debugging, network
configuration for local development servers, and troubleshooting.

- Create doc/android-physical-device-guide.md with full instructions
- Update BUILDING.md to reference the new guide in two places
2026-02-12 17:45:21 +08:00
Jose Olarte III
0a88f23bc7 docs(BUILDING): add Android emulator guide without Android Studio
- Add "Android Emulator Without Android Studio" section under Android Build
- Document env setup, SDK components, and API 36 system images
- Include Mac Silicon (arm64-v8a) and Intel (x86_64) AVD instructions
- Add steps: start emulator, build, install APK, and launch app
- Document one-shot build-and-run (debug:run, test:run)
- Update Prerequisites to mention command-line-only option and link to section
- Link to doc/android-emulator-deployment-guide.md for troubleshooting
2026-02-06 17:16:01 +08:00
Jose Olarte III
fe9cdd6398 fix(ios): use Xcode 26 workaround in sync-only mode
--sync was calling npx cap sync ios directly, so pod install failed
on Xcode 26 (objectVersion 70). Define run_cap_sync_with_workaround
once before sync-only and use it for both --sync and the full build;
remove the duplicate definition at Step 6.6.
2026-02-06 16:50:53 +08:00
Jose Olarte III
f5cb70ec8b docs: mark daily-notification Android receiver issue as resolved
Plugin fix is in @timesafari/daily-notification-plugin (explicit
PendingIntent component + id in Intent). Document resolution date,
summary of the fix, and follow-up steps (npm install, cap sync,
restore-local-plugins, test on device).
2026-02-06 15:52:35 +08:00
Matthew
a71bd09b78 docs: Add investigation documentation and test scripts for notification receiver issue
After changing DailyNotificationReceiver to exported="true", testing revealed
that while the receiver works when manually triggered, AlarmManager broadcasts
are not reaching it when alarms fire automatically. Alarms are scheduled and
fire correctly, but the PendingIntent broadcast does not trigger the receiver.

Added comprehensive documentation and diagnostic tools:

1. Documentation (doc/daily-notification-plugin-android-receiver-issue.md):
   - Complete problem analysis with evidence from logs and dumpsys
   - Root cause hypotheses focusing on PendingIntent creation in plugin
   - Testing steps and expected behavior after fix
   - Technical details for plugin maintainer reference

2. Test scripts:
   - scripts/test-notification-receiver.sh: Manually trigger receiver to
     verify it works and test with/without ID parameter
   - scripts/check-alarm-logs.sh: Check logs and verify alarm scheduling

Findings:
- Receiver registration is correct (exported="true" works for manual tests)
- Alarms schedule and fire successfully (confirmed via dumpsys alarm)
- Issue is in plugin's PendingIntent creation - broadcasts don't reach receiver
- Additional issue: Intent extras missing scheduleId (causes "missing_id" error)

The exported="true" change was necessary and correct. The remaining issue
requires a fix in the plugin's PendingIntent creation code to explicitly
set the component and include the scheduleId in Intent extras.

This documentation is intended for use when working on the plugin project
to fix the PendingIntent delivery issue.
2026-02-05 03:07:18 -08:00
Matthew
80cc09de95 WIP: Change DailyNotificationReceiver to exported=true for AlarmManager broadcasts
The DailyNotificationReceiver was not being triggered when scheduled alarms
fired, preventing notifications from appearing at the scheduled time.

Changed android:exported from "false" to "true" to allow AlarmManager
broadcasts to reach the receiver, especially when the app is closed or
the device is in doze mode.

This is a work-in-progress change to diagnose why notifications aren't
firing. The receiver should log "DN|RECEIVE_START" when triggered, but
we were not seeing these logs even when alarms were scheduled.

Next steps:
- Test if receiver is now triggered when alarm fires
- Verify notifications appear at scheduled time
- Consider adding permission check if keeping exported=true for security
2026-02-02 06:18:32 -08:00
Matthew
d0878507a6 fix(android): Auto-detect Java/SDK and fix KAPT Java 17+ compatibility
- Auto-detect Java from Android Studio (JBR/JRE) or system PATH
- Auto-detect Android SDK from common locations or local.properties
- Auto-write SDK location to local.properties for Gradle
- Add KAPT JVM args to gradle.properties for Java 17+ module access
- Fix Java version command quoting for paths with spaces
- Comment out DailyNotificationPlugin (Java class not implemented)

Eliminates manual JAVA_HOME/ANDROID_HOME setup requirements and fixes
KAPT compilation errors when using Java 17+.

Author: Matthew Raymer
2026-02-02 02:06:44 -08:00
Jose Olarte III
1345118b79 refactor(push-notification): use native time input and polish notification UI
PushNotificationPermission:
- Swap hour/minute number inputs and AM/PM toggle for native <input type="time">
- Add timeValue computed to keep existing hour/minute/AM-PM state in sync
- Remove unused checkHourInput and checkMinuteInput
- Tighten copy and layout: headings, labels, char count, button spacing

AccountViewView:
- Show reminder time and message in a bordered box with Time/Message labels
- Adjust spacing in notifications section
2026-01-30 15:35:47 +08:00
Jose Olarte III
22c3ac80c2 feat(notifications): enable foreground notifications and rollover recovery
- iOS: set UNUserNotificationCenter delegate and implement willPresent
  so notifications show in foreground and DailyNotificationDelivered is
  posted for rollover; implement didReceive for tap handling; re-set
  delegate in applicationDidBecomeActive
- Android: move DailyNotificationReceiver and BootReceiver inside
  <application>; add NotifyReceiver; extend BootReceiver with
  LOCKED_BOOT_COMPLETED, MY_PACKAGE_REPLACED, directBootAware
- main.capacitor: import daily-notification-plugin at startup so
  plugin (and recovery) load on launch
- doc: add daily-notification-alignment-outline.md

Fixes foreground notifications not showing and rollover recovery;
Android receivers were previously declared outside <application>.
2026-01-29 21:10:34 +08:00
Jose Olarte III
fb4ea08f3c fix(ios): add missing background task identifiers for daily notification plugin
Add com.timesafari.dailynotification.fetch and com.timesafari.dailynotification.notify
to BGTaskSchedulerPermittedIdentifiers in Info.plist to resolve registration
rejection errors. The plugin was attempting to register these identifiers but
they were not declared in the app's Info.plist, causing iOS to reject the
background task registrations.

Fixes Xcode log errors:
- Registration rejected; com.timesafari.dailynotification.fetch is not advertised
- Registration rejected; com.timesafari.dailynotification.notify is not advertised
2026-01-28 20:20:01 +08:00
Jose Olarte III
88f69054f4 Update AccountViewView.vue
fix(notifications): Reminder Notification toggle not turning off on native platforms

The toggle wasn't turning off on iOS/Android because:
1. Checkbox was being toggled directly before dialog confirmation
2. turnOffNotifications only handles web push, not native notifications

Fixed by:
- Preventing direct checkbox toggling with readonly and event handlers
- Adding native platform handling to cancel notifications via
  NotificationService.cancelDailyNotification() directly
- Bypassing web push unsubscribe flow on native platforms
2026-01-28 17:08:42 +08:00
Jose Olarte III
77e8d2d2ab fix(ios): run podspec fix script before pod install
Move the Daily Notification Plugin podspec fix script to execute before
the first pod install operation. Previously, the fix script ran after
pod install but before Capacitor sync, causing "No podspec found for
TimesafariDailyNotificationPlugin" errors when pod install tried to
resolve dependencies.

The Podfile expects TimesafariDailyNotificationPlugin.podspec, but the
plugin package only includes CapacitorDailyNotification.podspec. The
fix script creates the expected podspec file, but it must run before
CocoaPods attempts to resolve dependencies.

Fixes build failures on fresh installations where the podspec file
doesn't exist yet.
2026-01-27 15:53:11 +08:00
Jose Olarte III
31dfeb0988 fix(notifications): fix iOS notification scheduling and enable UI for native platforms
- Fix permission request to use correct iOS method (requestNotificationPermissions)
- Add robust handling for varying permission result formats
- Fix cancelDailyReminder to pass object parameter matching Swift plugin expectation
- Add notification cancellation before rescheduling to prevent duplicates
- Add verification after scheduling to ensure notification was actually scheduled
- Fix getStatus to handle both array and object response formats
- Enable notifications section in AccountView for native platforms (iOS/Android)
- Add edit button to allow users to modify existing notification time and message
- Add editReminderNotification method with form pre-population
- Add parseTimeTo24Hour helper for time format conversion

Fixes issues where:
- Notifications were stored but not actually scheduled with UNUserNotificationCenter
- cancelDailyReminder failed due to parameter type mismatch
- Notification time updates didn't properly cancel old notifications
- Users couldn't easily edit existing notification settings

The notification section is now visible on native platforms and includes an edit
button that opens the notification dialog with current values pre-populated.
2026-01-26 21:35:20 +08:00
Jose Olarte III
5a4ab84bfe feat(notifications): integrate DailyNotificationPlugin with UI for native platforms
Integrate DailyNotificationPlugin with notification UI to enable native
notifications on iOS/Android while maintaining web push for web/PWA.

- Add platform detection to PushNotificationPermission component
- Implement native notification flow via NotificationService
- Hide push server setting on native platforms (not needed)
- Add time conversion (AM/PM to 24-hour) for native plugin
- Add comprehensive documentation

Breaking Changes: None (backward compatible)
2026-01-23 19:06:16 +08:00
Jose Olarte III
84c3f79c57 fix(ios): resolve build errors for daily notification plugin
- Add podspec file for daily notification plugin with correct name
  - Create TimesafariDailyNotificationPlugin.podspec to match Capacitor's
    expected naming convention
  - Podspec name must match Podfile reference for CocoaPods compatibility
- Update Podfile to reference TimesafariDailyNotificationPlugin
- Add automated fix script for podspec creation
  - scripts/fix-daily-notification-podspec.sh creates podspec with correct
    name before Capacitor sync
  - Integrated into build-ios.sh build process
- Fix typo in package.json: change "pina" to "pinia" (^2.1.7)

Fixes:
- Vite build error: "Failed to resolve import 'pinia'"
- CocoaPods error: "No podspec found for 'TimesafariDailyNotificationPlugin'"
- CocoaPods error: "The name of the given podspec doesn't match the expected one"

The podspec file is created automatically during the build process to ensure
Capacitor sync can find the plugin with the expected name, while maintaining
compatibility with the actual podspec file name in the plugin package.
2026-01-22 18:03:14 +08:00
Jose Olarte III
14ffcb5434 feat: integrate daily notification plugin for native iOS/Android
Add native notification support via @timesafari/daily-notification-plugin
while maintaining existing Web Push for web/PWA builds. Platform detection
automatically selects the appropriate notification system at runtime.

Key Changes:
- Created NotificationService abstraction layer with unified API
- Implemented NativeNotificationService for iOS/Android
- Stubbed WebPushNotificationService for future web integration
- Registered DailyNotificationPlugin in Capacitor plugin system

Android Configuration:
- Added notification permissions (POST_NOTIFICATIONS, SCHEDULE_EXACT_ALARM, etc.)
- Registered DailyNotificationReceiver for alarm-based notifications
- Registered BootReceiver to restore schedules after device restart
- Added Room, WorkManager, and Coroutines dependencies
- Registered plugin in MainActivity.java

iOS Configuration:
- Added UIBackgroundModes (fetch, processing) to Info.plist
- Configured BGTaskSchedulerPermittedIdentifiers
- Added NSUserNotificationAlertStyle

Documentation:
- Created comprehensive integration guide
- Added architecture overview with diagrams
- Created implementation checklist
- Documented platform-specific behavior

Manual Steps Required:
- iOS: Enable Background Modes capability in Xcode
- iOS: Run `pod install` to install CapacitorDailyNotification pod
- Run `npx cap sync` to sync native projects

Platform Support:
- iOS: Native UNUserNotificationCenter (requires Xcode setup)
- Android: Native NotificationManager with AlarmManager
- Web/PWA: Existing Web Push (coexists, not yet wired to service)
- Electron: Ready (uses native implementation)

Status: Phase 1 complete - infrastructure ready for UI integration
Next: Update PushNotificationPermission.vue to use NotificationService
2026-01-21 22:22:48 +08:00
Jose Olarte III
679c4d6456 feat: integrate daily-notification-plugin from Gitea repository
- Add @timesafari/daily-notification-plugin dependency from private Gitea repo
- Configure .npmrc to be ignored by git to protect authentication tokens
- Remove .npmrc from version control (contains sensitive Gitea token)
- Update package-lock.json with new dependency

The plugin is installed via git URL and automatically builds during npm install
thanks to the prepare script in the plugin repository.

Installation requires Gitea personal access token configured in local .npmrc file.
2026-01-19 19:05:54 +08:00
1fc7e4726d do the same for the recipient: allow editing on the details page 2026-01-18 20:03:54 -07:00
b500a1e7c0 feat: allow changing the giver when they get to the give-detail screen 2026-01-18 19:50:55 -07:00
46f2cbfcc6 allow application of labels to contacts that are imported 2026-01-17 16:28:33 -07:00
08f91e4c96 fix deletion of labels when deleting contact, only make-all-visible on new contacts 2026-01-14 20:26:27 -07:00
e94effd111 import labels from an export 2026-01-14 19:37:37 -07:00
84cad0e169 export labels within contacts 2026-01-13 20:46:03 -07:00
b6704b348b guard against errors when there are no results in certain contact queries 2026-01-12 20:14:39 -07:00
662da79df8 add labels for contacts (as a way to group them) 2026-01-11 19:07:08 -07:00
02eb891ee9 have the user accept an invitation (to avoid previews from stealing it) 2026-01-10 18:46:01 -07:00
051af89476 fix error retrieving active DIDs; don't pop-up redundant toast warning when using current DID 2026-01-08 19:51:48 -07:00
9b2d14b418 allow deep-link for 'did' page with no parameter (to show current user) 2026-01-08 19:51:17 -07:00
6e73ab4a84 fix complaint about a very long style line 2026-01-04 16:22:03 -07:00
11736b5751 for project changes, make the description into a colored diff that's easier to compare 2026-01-04 16:19:58 -07:00
85e7682b90 fix UI test 2026-01-02 10:02:34 -07:00
b91d387815 fix the clipboard testing and add test 40 back to the testing 2026-01-01 20:46:03 -07:00
4a3b968ee2 fix test 40 for adding contacts (though clipboard is still broken) 2026-01-01 20:25:40 -07:00