30 Commits

Author SHA1 Message Date
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
a672c977a8 Fix Android image share workflow and add local plugin persistence
- Add SafeArea and SharedImage plugins to capacitor.plugins.json
- Create restore-local-plugins.js to persist plugins after cap sync
- Integrate plugin restoration into build scripts
- Improve Android share intent timing with retry logic
- Clean up debug logging while keeping essential error handling
- Add documentation for local plugin management

Fixes issue where SharedImage plugin wasn't recognized, causing
"UNIMPLEMENTED" errors. Image sharing now works correctly on Android.
2025-12-09 21:36:01 +08:00
Jose Olarte III
84983ee10b refactor(shared-image): replace temp file approach with native Capacitor plugins
Replace the buggy temp file polling mechanism with direct native-to-JS
communication via custom Capacitor plugins for iOS and Android. This
eliminates race conditions, file management complexity, and polling overhead.

BREAKING CHANGE: Removes backward compatibility with temp file approach.
Android minSdkVersion upgraded from 22 to 23.

Changes:
- iOS: Created SharedImagePlugin (CAPBridgedPlugin) and SharedImageUtility
  - Uses App Group UserDefaults for data sharing between extension and app
  - Implements getSharedImage() and hasSharedImage() methods
  - Removes temp file writing/reading logic from AppDelegate
- Android: Created SharedImagePlugin with @CapacitorPlugin annotation
  - Uses SharedPreferences for data storage instead of temp files
  - Implements same interface as iOS plugin
  - Removes temp file handling from MainActivity
- TypeScript: Added plugin definitions and registration
  - Created SharedImagePlugin interface and web fallback
  - Updated main.capacitor.ts to use plugin instead of Filesystem API
  - Removed pollForFileExistence() and related file I/O code
- Android: Upgraded minSdkVersion from 22 to 23
  - Required for SharedPreferences improvements and better API support

Benefits:
- Eliminates race conditions from file polling
- Removes file cleanup complexity
- Direct native-to-JS communication (no file I/O)
- Better performance (no polling overhead)
- More reliable data transfer between share extension and app
- Cleaner architecture with proper plugin abstraction
2025-12-04 18:03:47 +08:00
Jose Olarte III
0627cd32b7 refactor: remove unused ShareImage plugin code, simplify to temp file approach
Remove unused Capacitor plugin implementation and simplify shared image
handling to use only the temp file approach, which is already working
reliably for both iOS and Android.

Changes:
- Delete ios/App/App/ShareImagePlugin.swift (unused, never registered)
- Delete ios/App/App/ShareImageBridge.swift (only used by plugin)
- Remove ~80 lines of plugin fallback code from src/main.capacitor.ts
- Simplify error handling to single code path
- Add documentation comment explaining temp file approach and future
  plugin implementation possibility

Benefits:
- ~154 lines of code removed
- Single, consistent code path for both platforms
- Easier to maintain and debug
- No functional changes - temp file approach already working

The temp file approach uses Capacitor's Filesystem plugin to read shared
image data written by native code (AppDelegate on iOS, MainActivity on
Android). This is simpler and more reliable than the plugin approach,
which required registration and bridge setup.

Future improvement: Consider implementing Capacitor plugins for direct
native-to-JS communication if lower latency becomes a priority, though
the current approach performs well in production.
2025-11-27 21:23:34 +08:00
Jose Olarte III
e1eb91f26d feat: Add Android share target support for image sharing
Implement native Android share functionality to allow users to share
images from other apps directly to TimeSafari. This mirrors the iOS
share extension functionality and provides a seamless cross-platform
experience.

Changes:
- Add ACTION_SEND and ACTION_SEND_MULTIPLE intent filters to
  AndroidManifest.xml to register the app as a share target for images
- Implement share intent handling in MainActivity.java:
  - Process incoming share intents in onCreate() and onNewIntent()
  - Read shared image data from content URI using ContentResolver
  - Convert image to Base64 encoding
  - Write image data to temporary JSON file in app's internal storage
  - Use getFilesDir() which maps to Capacitor's Directory.Data
- Update src/main.capacitor.ts to support Android platform:
  - Extend checkAndStoreNativeSharedImage() to check for Android platform
  - Use Directory.Data for Android file operations (vs Directory.Documents for iOS)
  - Add Android to initial load and app state change listeners
  - Ensure shared image detection works on app launch and activation

The implementation follows the same pattern as iOS:
- Native layer (MainActivity) writes shared image to temp file
- JavaScript layer polls for file existence with exponential backoff
- Image is stored in temp database and user is navigated to SharedPhotoView

This enables users to share images from Gallery, Photos, and other apps
directly to TimeSafari on Android devices.
2025-11-26 20:01:14 +08:00
Jose Olarte III
09a230f43e refactor(ios): improve file polling and extract shared image storage logic
Replace hardcoded timeout with reliable file existence polling and extract
duplicate image storage code into reusable function.

File Polling Improvements:
- Replace hardcoded 300ms timeout with pollForFileExistence() function
- Use Filesystem.stat() to check file existence instead of guessing timing
- Implement exponential backoff (100ms, 200ms, 400ms, 800ms, 1600ms)
- Maximum 5 retries with configurable parameters
- More reliable: actually checks if file exists rather than fixed wait time

Code Deduplication:
- Extract storeSharedImageInTempDB() function to eliminate code duplication
- Consolidates clearing old data, base64-to-dataURL conversion, and DB storage
- Used in both temp file and plugin fallback code paths
- Improves maintainability and reduces risk of inconsistencies

This makes the code more robust and maintainable while ensuring the file
is actually available before attempting to read it.
2025-11-25 18:56:45 +08:00
Jose Olarte III
eff4126043 feat(ios): improve share extension UX and fix image reload issues
Improve iOS share extension implementation to skip interstitial UI and
fix issues with subsequent image shares not updating the view.

iOS Share Extension Improvements:
- Replace SLComposeServiceViewController with custom UIViewController
  to eliminate interstitial "Post" button UI
- Use minimal URL (timesafari://) instead of deep link for app launch
- Implement app lifecycle detection via Capacitor appStateChange listener
  instead of relying solely on deep links

Deep Link and Navigation Fixes:
- Remove "shared-photo" from deep link schemas (no longer needed)
- Add empty path URL handling for share extension launches
- Implement processing lock to prevent duplicate image processing
- Add retry mechanism (300ms delay) to handle race conditions with
  AppDelegate writing temp files
- Use router.replace() when already on /shared-photo route to force refresh
- Clear old images from temp DB before storing new ones
- Delete temp file immediately after reading to prevent stale data

SharedPhotoView Component:
- Add route watcher (@Watch) to reload image when fileName query
  parameter changes
- Extract image loading logic into reusable loadSharedImage() method
- Improve error handling to clear image state on failures

This fixes the issue where sharing a second image while already on
SharedPhotoView would display the previous image instead of the new one.
2025-11-25 18:22:43 +08:00
Jose Olarte III
ae49c0e907 feat(ios): implement native share target for images
Implement iOS Share Extension to enable native image sharing from Photos
and other apps directly into TimeSafari. Users can now share images from
the iOS share sheet, which will open in SharedPhotoView for use as gifts
or profile pictures.

iOS Native Implementation:
- Add TimeSafariShareExtension target with ShareViewController
- Configure App Groups for data sharing between extension and main app
- Implement ShareViewController to process shared images and convert to base64
- Store shared image data in App Group UserDefaults
- Add ShareImageBridge utility to read shared data from App Group
- Update AppDelegate to handle shared-photo deep link and bridge data to JS

JavaScript Integration:
- Add checkAndStoreNativeSharedImage() in main.capacitor.ts to read shared
  images from native layer via temporary file bridge
- Convert base64 data to data URL format for compatibility with base64ToBlob
- Integrate with existing SharedPhotoView component
- Add "shared-photo" to deep link validation schema

Build System:
- Integrate Xcode 26 / CocoaPods compatibility workaround into build-ios.sh
- Add run_pod_install_with_workaround() for explicit pod install
- Add run_cap_sync_with_workaround() for Capacitor sync (which runs pod
  install internally)
- Automatically detect project format version 70 and apply workaround
- Remove standalone pod-install-workaround.sh script

Code Cleanup:
- Remove verbose debug logs from ShareViewController, AppDelegate, and
  main.capacitor.ts
- Retain essential logger calls for production debugging

Documentation:
- Add ios-share-extension-setup.md with manual Xcode setup instructions
- Add ios-share-extension-git-commit-guide.md for version control best practices
- Add ios-share-implementation-status.md tracking implementation progress
- Add native-share-target-implementation.md with overall architecture
- Add xcode-26-cocoapods-workaround.md documenting the compatibility issue

The implementation uses a temporary file bridge (AppDelegate writes to Documents
directory, JS reads via Capacitor Filesystem plugin) as a workaround for
Capacitor plugin auto-discovery issues. This can be improved in the future by
properly registering ShareImagePlugin in Capacitor's plugin registry.
2025-11-24 20:46:58 +08:00
52b1e8ffa3 chore: move more logger infos to debugs 2025-09-05 19:52:53 -06:00
Matthew Raymer
b57be7670c refactor: improve logging levels and environment configuration
- Fix logging levels: change verbose debugging from info to debug level
  - TestView: component mounting, boot-time config, URL flow testing
  - main.capacitor.ts: deeplink processing steps and router state
  - HomeView: API call details, component state updates, template rendering

- Remove redundant environment variable override in vite.config.common.mts
  - Environment loading via dotenv works correctly
  - Manual override was defensive programming but unnecessary
  - Simplifies configuration and reduces maintenance burden

- Add comprehensive Playwright timeout behavior documentation
  - README.md: detailed timeout types, failure behavior, debugging guide
  - TESTING.md: timeout failure troubleshooting and common scenarios
  - Clarifies that timeout failures indicate real issues, not flaky tests

- Fix TypeScript configuration for .mts imports
  - tsconfig.node.json: add allowImportingTsExtensions for Vite config files
  - Resolves import path linting errors for .mts extensions

All changes maintain existing functionality while improving code quality
and reducing log noise in production environments.
2025-09-05 04:02:53 +00:00
Jose Olarte III
4ba58145d0 feat: implement safe area insets for Android and add development tooling
- Add @capacitor/status-bar dependency for safe area detection
- Implement SafeAreaPlugin for Android with proper inset calculation
- Create safeAreaInset.js utility for CSS custom property injection
- Update Android manifest and build configuration for plugin
- Integrate safe area handling across Vue components and views
- Update iOS Podfile and Android gradle configurations
- Add commitlint and husky for commit message validation

Technical changes:
- SafeAreaPlugin uses WindowInsets API for Android R+ devices
- Fallback detection for navigation bar and gesture bar heights
- CSS custom properties: --safe-area-inset-{top,bottom,left,right}
- Platform-specific detection (Android WebView only)
- StatusBar plugin integration for top inset calculation
2025-08-22 21:06:11 +08:00
Matthew Raymer
4422c82c08 fix: resolve deeplink listener registration and add comprehensive logging
- Fix Capacitor deeplink listener registration timing and duplicate function issues
- Add comprehensive logging throughout deeplink processing pipeline
- Enhance router navigation logging for better debugging
- Resolves deeplink navigation failures on Android platform
- Improves debugging capabilities for future deeplink issues
2025-08-20 06:41:37 +00:00
Matthew Raymer
8dd73950f5 Fix duplicate export declarations and migrate ContactsView with sub-components
- Remove duplicate NOTIFY_INVITE_MISSING and NOTIFY_INVITE_PROCESSING_ERROR exports
- Update InviteOneAcceptView.vue to use correct NOTIFY_INVITE_TRUNCATED_DATA constant
- Migrate ContactsView to PlatformServiceMixin and extract into modular sub-components
- Resolves TypeScript compilation errors preventing web build
2025-07-16 08:03:26 +00:00
Matthew Raymer
ac45d0747c Fix InviteOneAcceptView migration fence; remove USE_DEXIE_DB dependency
- Remove USE_DEXIE_DB import from app.ts constants
- Update InviteOneAcceptView to use PlatformServiceMixin pattern
- Remove legacy Dexie database access code
- Move WORKER_ONLY_DATABASE_IMPLEMENTATION.md to doc/ directory
- Remerge changes in router/index.ts

Fixes Electron build failure caused by missing USE_DEXIE_DB export.
2025-07-15 07:21:27 +00:00
c1eb242616 add first cut at deep-link redirecting, with one example contact-import that works on mobile 2025-06-18 13:16:17 -06:00
8092d1c576 convert all remaining DB writes & reads to SQL (with successful registration & claim) 2025-05-27 21:07:24 -06:00
Matt Raymer
d6956bb498 refactor: move lib directory to libs for consistency
- Move src/lib/capacitor to src/libs/capacitor
- Move src/lib/fontawesome.ts to src/libs/fontawesome.ts
- Update import paths in main.capacitor.ts and main.common.ts
- Remove empty src/lib directory

This change standardizes the project structure by using the 'libs'
directory consistently throughout the codebase.
2025-05-19 22:25:12 -04:00
Matthew Raymer
c9536dd643 refactor: Replace console logging with logger utility
- Add logger import across multiple view components
- Replace console.error/warn/log with logger methods
- Update error handling to use structured logging
- Improve type safety for error objects
- Add crypto-browserify polyfill for browser environment

The changes improve logging by:
1. Using consistent logging interface
2. Adding structured error logging
3. Improving error type safety
4. Centralizing logging configuration
5. Fixing browser compatibility issues

Affected files:
- Multiple view components
- vite.config.ts
- Build configuration
2025-03-11 09:35:55 +00:00
Matthew Raymer
24c7ba15af refactor: reorganize deep linking types and interfaces
Changes:
- Move deep link types from types/ to interfaces/
- Export baseUrlSchema for external use
- Add trailing commas for better git diffs
- Fix type inference for deepLinkSchemas
- Add deepLinks export to interfaces/index.ts
- Remove duplicate SuccessResult interface
- Update import paths in services/deepLinks.ts

This improves code organization by centralizing interface definitions
and fixing type inference issues.
2025-02-26 10:28:55 +00:00
Matthew Raymer
5bc2f19bc4 docs: add comprehensive deep linking documentation
Changes:
- Add detailed JSDoc headers to deep linking files
- Document type system and validation strategy
- Add architecture overview and error handling docs
- Include usage examples and integration points
- Improve code organization comments

This improves maintainability by documenting the deep linking
system's architecture, type safety, and integration points.
2025-02-26 09:45:08 +00:00
Matthew Raymer
64a04ec9a5 feat(deepLinks): implement comprehensive deep linking system
- Add type-safe deep link parameter validation using Zod
- Implement consistent error handling across all deep link routes
- Add support for query parameters in deep links
- Create comprehensive deep linking documentation
- Add logging for deep link operations

Security:
- Validate all deep link parameters before processing
- Sanitize and type-check query parameters
- Add error boundaries around deep link handling
- Implement route-specific parameter validation

Testing:
- Add parameter validation tests
- Add error handling tests
- Test query parameter support
2025-02-26 09:35:04 +00:00
Matthew Raymer
03178d35e7 refactor: improve router type safety and usage
- Add explicit Router type imports across views
- Replace $router type casting with proper typing
- Use $router.back() instead of $router.go(-1) for consistency
- Add proper route and router typings to components
- Clean up router navigation methods
- Fix router push/back method calls

This commit improves type safety and consistency in router usage across
the application's view components.
2025-02-26 06:50:08 +00:00
Matthew Raymer
52150dd6eb fix: update component and import paths
Changes:
- Update font-awesome component closing tag to match naming
- Change @capacitor/app import to use local wrapper
- Fix component self-closing tags in ContactScanView.vue

This improves consistency in component usage and centralizes
capacitor imports through our wrapper layer.
2025-02-25 09:58:31 +00:00
Matthew Raymer
73637d80dc refactor: move ProviderInfo interface to claims-result.ts
- Move ProviderInfo interface from ClaimView.vue to claims-result.ts
- Add JSDoc documentation to interface properties
- Update imports in ClaimView.vue
- Clean up route handling using vue-router types
- Remove outdated browser compatibility comment

This improves type organization and documentation while reducing
component-level interface definitions.
2025-02-25 09:03:18 +00:00
Matthew Raymer
79ef59c5a9 refactor: migrate interfaces to dedicated directory
Reorganizes TypeScript interfaces into a modular structure:
- Create dedicated interfaces directory with specialized files
- Split interfaces by domain (claims, common, limits, records, user)
- Update imports in endorserServer.ts to use new interface locations
- Replace 'any' types with 'unknown' for better type safety
- Add proper type imports and exports

This improves code organization and maintainability by:
- Centralizing interface definitions
- Reducing file size of endorserServer.ts
- Making interface relationships more explicit
- Improving type safety with stricter types
2025-02-24 11:21:08 +00:00
Matthew Raymer
90d688dba1 docs(capacitor): improve main.capacitor.ts documentation and error handling
- Add comprehensive JSDoc header with process flow
- Document supported deep link routes
- Improve error type handling in deep link handler
- Add debug logging for initialization steps
- Update version number to 0.4.4

This improves code maintainability and debugging capabilities for
the Capacitor platform entry point.
2025-02-24 09:37:30 +00:00
Matthew Raymer
f33d1f0af3 WIP: certificate view and dependency updates
- Update certificate view canvas rendering and QR code generation
- Upgrade dependencies (expo-file-system, expo-font, expo-keep-awake)
- Fix type imports for nostr-tools and dexie-export-import
- Update vite config for better dependency resolution
- Clean up main entry points (capacitor, electron, pywebview)
- Improve error handling in API and plan services
- Add type safety to API error handling
- Update build configuration for platform-specific builds

This is a work in progress commit focusing on certificate view improvements
and dependency maintenance. Some type definitions and build configurations
may need further refinement.
2025-02-21 09:47:24 +00:00
Matthew Raymer
b5b5d45b99 feat(logging): enhance debug logging across app
Improves application logging and error tracking:
- Add structured logging in main.common.ts for app initialization
- Enhance API error handling with detailed context in services
- Add deep link debugging in Capacitor platform
- Improve plan service logging with retry information
- Update endorser server logs for better cache debugging

Technical changes:
- Replace console.error with info for non-critical cache misses
- Add component context to global error handler
- Add detailed logging for plan loading and retries
- Improve deep link route matching logs
- Add mount state logging for Capacitor

This improves debugging capabilities across web and mobile platforms.
2025-02-20 10:36:47 +00:00
Matthew Raymer
1e22cdec82 feat(mobile): add deep linking support for Capacitor apps
Adds native deep linking capabilities:
- Configure timesafari:// URL scheme for iOS and Android
- Add @capacitor/app dependency and configuration
- Implement deep link handler with improved error logging
- Support parameterized routes like claim/:id
- Add debug logging for native platforms
- Handle app mounting state for deep links

Technical changes:
- Update AndroidManifest.xml with intent filters
- Add URL scheme to iOS Info.plist
- Add @capacitor/app to Podfile and Gradle
- Enhance main.capacitor.ts with robust deep link handling
2025-02-19 13:07:08 +00:00
Matthew Raymer
2746b8fe2b refactor: reorganize Vite config into modular files
Split monolithic vite.config.mjs into separate config files:
- vite.config.web.mts
- vite.config.electron.mts
- vite.config.capacitor.mts
- vite.config.pywebview.mts
- vite.config.common.mts
- vite.config.utils.mts

Updates:
- Modify package.json scripts to use specific config files
- Add electron-builder as dev dependency
- Update electron build configuration
- Fix electron resource paths
- Remove old vite.config.mjs and utils.js

This change improves maintainability by:
- Separating concerns for different build targets
- Making build configurations more explicit
- Reducing complexity in individual config files
2025-02-18 11:44:06 +00:00