Compare commits

..

66 Commits

Author SHA1 Message Date
Matthew Raymer
981920dd7a feat(electron): enhance SQLite operation logging and debugging
WIP: Debugging sqlite-run/dbExec hanging issue

- Add renderer-to-main process log forwarding
- Implement operation tracking with unique IDs
- Add detailed timing and retry logging
- Enhance error capture and formatting
- Move logs to app user data directory
- Add exponential backoff for retries

This commit adds comprehensive logging to help diagnose
why dbExec operations are hanging when sent through the
sqlite-run channel. Changes include:

- Forward all renderer process logs to main process
- Track SQLite operations with unique IDs
- Log operation timing and retry attempts
- Capture detailed error information
- Implement exponential backoff for retries
- Centralize logs in app user data directory

Security:
- Logs are stored in app user data directory
- Sensitive data is sanitized in logs
- Error stacks are properly captured

Testing:
- Manual testing of logging system
- Verify log capture in both processes
- Check log rotation and file sizes

TODO:
- Monitor logs to identify root cause
- Add specific logging for settings table
- Consider connection pooling if needed
2025-06-05 13:28:35 +00:00
Matthew Raymer
d189c39062 chore(linting): more linting and debugging 2025-06-05 10:34:49 +00:00
Matthew Raymer
8edddb1a57 chore(linting): some linting problems fixed 2025-06-05 10:00:14 +00:00
Matthew Raymer
9eb07b3258 fix: improve API server update reliability and logging
- Refactor dbExec in ElectronPlatformService to use proper connection management
- Add comprehensive logging throughout API server update flow
- Fix connection handling in database operations
- Add user feedback notifications for success/failure
- Add verification step after settings update

The main issue was that dbExec wasn't using the same robust connection
management as dbQuery, leading to "SQLite not initialized" errors. Now both
methods use the same connection lifecycle management through enqueueOperation.

Also added detailed logging at each step to help diagnose any future issues:
- AccountViewView component logging
- Database utility operations logging
- Connection state tracking
- Update verification

This should make the API server update more reliable and easier to debug.
2025-06-05 08:44:42 +00:00
Matthew Raymer
e5dffc30ff fix(sqlite): centralize database connection management
- Add proper connection state tracking (disconnected/connecting/connected/error)
- Implement connection promise to prevent race conditions
- Centralize connection lifecycle in getConnection() and releaseConnection()
- Remove redundant queue operations
- Improve error handling and state management

This fixes race conditions where multiple components (main process, renderer,
platform service) were interfering with each other's database operations.
Connection state is now properly tracked and operations are queued correctly.

Fixes: #<issue_number> (if applicable)
2025-06-05 07:37:44 +00:00
Matthew Raymer
0b4e885edd fix(electron): correct SQLite IPC bridge implementation
- Replace generic execute method with specific IPC handlers
- Fix database operations by using proper IPC methods (createConnection, query, run, execute)
- Update type definitions to match actual IPC bridge interface
- Fix "Must provide statements" error by using correct method signatures

This change ensures proper communication between renderer and main processes
for SQLite operations, resolving database initialization and query issues.
2025-06-05 06:52:26 +00:00
Matthew Raymer
b6d9b29720 refactor(sqlite): align database implementation with sacred-sql
BREAKING CHANGE: Removes database encryption in favor of simpler implementation

- Remove encryption from SQLite initialization and connection options
- Change journal mode from WAL to MEMORY to match sacred-sql
- Simplify PRAGMA settings and remove WAL-specific configurations
- Remove secret table and encryption-related migrations
- Update database schema to use non-encrypted storage
- Clean up database initialization process

This change aligns the TimeSafari Electron SQLite implementation with
sacred-sql, improving compatibility and simplifying the database layer.
Existing databases will need to be cleared and recreated due to the
removal of encryption support.

Migration:
1. Delete existing database at ~/Databases/TimeSafari/timesafariSQLite.db
2. Restart application to create fresh database with new schema
2025-06-05 05:37:18 +00:00
Matthew Raymer
b5348e42a7 chore(config): revert encrypted sqlite db 2025-06-05 03:25:09 +00:00
Matthew Raymer
a4fb3eea2d chore(config): add encryption settings for SQLite 2025-06-05 03:15:10 +00:00
Matthew Raymer
5d12c76693 fix(sqlite): enable database encryption in Electron app
The app is failing to initialize encryption because:
- Database is created with 'no-encryption' mode
- Capacitor SQLite plugin's encryption methods are available but unused
- Secret table exists but encryption isn't properly initialized

This commit will:
- Enable encryption in database connection options
- Initialize encryption secret before database open
- Use Capacitor SQLite plugin's encryption methods
- Ensure secret table is properly initialized

This fixes the "No initial encryption supported" error that occurs
when trying to save new identities or access encrypted data.

Technical details:
- Changes connection options to use 'secret' encryption mode
- Adds setEncryptionSecret call before database open
- Maintains existing secret table structure
- Uses Capacitor SQLite plugin's native encryption support
2025-06-05 03:07:47 +00:00
Matthew Raymer
d426f9c4ac refactor(experiment.sh): streamline build process for Capacitor-based Electron app
- Remove all commented-out legacy build steps (TypeScript compilation, AppImage packaging)
- Add Capacitor sync and Electron start sequence
- Update script documentation and dependencies
- Add proper error handling for Capacitor workflow
- Add git command check for capacitor config restoration
- Remove unused AppImage-related functions

This change aligns the build process with our Capacitor-based Electron architecture,
replacing the direct file copying approach with Capacitor's sync mechanism.
2025-06-05 02:27:44 +00:00
340a574325 adjust timeout length for startup 2025-06-04 17:04:31 -06:00
Matthew Raymer
98b3a35e3c refactor: consolidate Electron API type definitions
- Create unified ElectronAPI interface in debug-electron.ts
- Export SQLiteAPI, IPCRenderer, and ElectronEnv interfaces
- Update Window.electron type declarations to use shared interface
- Fix type conflicts between debug-electron.ts and ElectronPlatformService.ts

This change improves type safety and maintainability by centralizing
Electron API type definitions in a single location.
2025-06-04 13:48:27 +00:00
Matthew Raymer
409de21fc4 fix(db): resolve SQLite channel and initialization issues
- Add sqlite-status to valid IPC channels
- Fix SQLite ready signal handling
- Improve database status tracking
- Add proper error handling for status updates
- Keep database connection open during initialization

Technical Details:
- Added sqlite-status to VALID_CHANNELS.invoke list
- Implemented sqlite-status handler with proper verification
- Added database open state verification
- Improved error handling and logging
- Fixed premature database closing

Testing Notes:
- Verify SQLite ready signal is received correctly
- Confirm database stays open after initialization
- Check status updates are processed properly
- Verify error handling for invalid states

Security:
- Validates all IPC channels
- Verifies database state before operations
- Maintains proper connection lifecycle
- Implements proper error boundaries

Author: Matthew Raymer
2025-06-04 13:05:24 +00:00
Matthew Raymer
17c9d32f49 feat(db): temporarily mock dbQuery for connection testing
- Temporarily modified dbQuery to return empty results for testing
- Added detailed logging of attempted queries with timestamps
- Preserved original implementation as commented code for easy restoration
- Helps isolate database connection issues from query execution issues

Testing Notes:
- Database connection and initialization appears successful
- Empty results causing cascading failures in settings and identity
- Router initialization timing needs review
- SQLite timeout error may be false positive

Security Impact:
- No security implications as this is a temporary test change
- Original implementation preserved for quick rollback
- No sensitive data exposed in logs

Related Issues:
- Database connection timing
- Router initialization sequence
- Settings initialization failures
2025-06-04 12:37:11 +00:00
Matthew Raymer
25e4db395a refactor(sqlite): enhance dbQuery with robust connection lifecycle
This commit significantly improves the dbQuery function in ElectronPlatformService
with proper connection lifecycle management and error handling. Key changes:

- Add SQLite availability check before operations
- Implement proper connection lifecycle:
  - Create connection
  - Open database
  - Verify database state
  - Execute query
  - Ensure cleanup
- Enhance error handling:
  - Check SQLite availability
  - Verify IPC renderer
  - Handle database state
  - Proper cleanup in finally block
- Improve logging:
  - Add [dbQuery] tag for better tracing
  - Log all connection lifecycle events
  - Enhanced error logging
- Add type safety:
  - SQLiteQueryResult interface
  - Proper type casting
  - Maintain generic type support

Technical details:
- Add SQLiteQueryResult interface for type safety
- Implement proper connection state verification
- Add comprehensive error messages
- Ensure proper resource cleanup
- Follow same pattern as main.electron.ts

Testing:
- All database operations properly logged
- Connection lifecycle verified
- Error conditions handled
- Resources properly cleaned up

Author: Matthew Raymer
2025-06-04 09:31:08 +00:00
Matthew Raymer
b6ee30892f feat(sqlite): enhance SQLite initialization and IPC handlers
This commit significantly improves SQLite database management and IPC communication
in the TimeSafari Electron app. Key changes include:

- Add new IPC handlers for database lifecycle management:
  - sqlite-open: Open database connections
  - sqlite-close: Close database connections
  - sqlite-is-db-open: Check database connection status
  - get-path: Retrieve database path
  - get-base-path: Get base directory path

- Enhance SQLite initialization with:
  - Improved error handling and recovery mechanisms
  - Detailed logging for all database operations
  - State verification and tracking
  - Proper cleanup of IPC handlers
  - Transaction state management

- Security improvements:
  - Validate all IPC channels
  - Implement proper file permissions (0o755)
  - Add connection state verification
  - Secure error handling and logging

- Performance optimizations:
  - Implement WAL journal mode
  - Configure optimal PRAGMA settings
  - Add connection pooling support
  - Implement retry logic with exponential backoff

Technical details:
- Add SQLiteError class for detailed error tracking
- Implement handler registration tracking
- Add comprehensive logging with operation tagging
- Update preload script with new valid channels
- Add type definitions for all SQLite operations

Testing:
- All handlers include proper error handling
- State verification before operations
- Recovery mechanisms for failed operations
- Logging for debugging and monitoring

Author: Matthew Raymer
2025-06-04 09:10:58 +00:00
Matthew Raymer
b01a450733 debug(ipc): HomeView errors added function level labels noting that we're catching a function level exception but we're also logging it globally. 2025-06-03 14:00:32 +00:00
Matthew Raymer
596f3355bf chore(logging): turn off logToDB since it was blowing up and hiding real errors in noise. 2025-06-03 13:33:08 +00:00
Matthew Raymer
e1f9a6fa08 refactor(sqlite): disable verbose logging in migration system
- Comment out all info and debug logs in sqlite-migrations.ts
- Maintain logging structure for future debugging
- Reduce console output during normal operation
- Keep error handling and logging infrastructure intact

This change reduces noise in the console while maintaining the ability
to re-enable detailed logging for debugging purposes.
2025-06-03 13:28:39 +00:00
Matthew Raymer
340e718199 feat(logging): enhance SQLite logging and IPC handler management
- Add Winston-based structured logging system with:
  - Separate console and file output formats
  - Custom SQLite and migration loggers
  - Configurable log levels and verbosity
  - Log rotation and file management
  - Type-safe logger extensions

- Improve IPC handler management:
  - Add handler registration tracking
  - Implement proper cleanup before re-registration
  - Fix handler registration conflicts
  - Add better error handling for IPC operations

- Add migration logging controls:
  - Configurable via DEBUG_MIGRATIONS env var
  - Reduced console noise while maintaining file logs
  - Structured migration status reporting

Security:
- Add proper log file permissions (0o755)
- Implement log rotation to prevent disk space issues
- Add type safety for all logging operations
- Prevent handler registration conflicts

Dependencies:
- Add winston for enhanced logging
- Remove deprecated @types/winston

This change improves debugging capabilities while reducing console noise
and fixing IPC handler registration issues that could cause database
operation failures.
2025-06-03 13:05:40 +00:00
Matthew Raymer
5d97c98ae8 fix(electron): improve SQLite initialization and timing handling
- Add structured SQLite configuration in main process with separate settings for
  initialization and operations
- Implement proper retry logic with configurable attempts and delays
- Add connection pool management to prevent resource exhaustion
- Reduce initialization timeout from 30s to 10s for faster feedback
- Add proper cleanup of timeouts and resources
- Maintain consistent retry behavior in preload script

This change addresses the cascade of SQLite timeout errors seen in the logs
by implementing proper timing controls and resource management. The main
process now handles initialization more robustly with configurable retries,
while the preload script maintains its existing retry behavior for
compatibility.

Security Impact:
- No security implications
- Improves application stability
- Prevents resource exhaustion

Testing:
- Verify SQLite initialization completes within new timeout
- Confirm retry behavior works as expected
- Check that connection pool limits are respected
- Ensure proper cleanup of resources
2025-06-03 12:25:36 +00:00
Matthew Raymer
ec74fff892 refactor: enhance SQLite error handling and type safety
Current State:
- SQLite initialization completes successfully
- API exposure and IPC bridge working correctly
- Type definitions and interfaces properly implemented
- Enhanced error handling with specific error codes
- Comprehensive logging system in place

Critical Issue Identified:
SQLite initialization timeout causing cascading failures:
- Components attempting database operations before initialization complete
- Error logging failing due to database unavailability
- Multiple components affected (HomeView, AccountView, ImageMethodDialog)
- User experience impacted with cache clear prompts

Changes Made:
- Added proper TypeScript interfaces for SQLite operations
- Enhanced SQLiteError class with error codes and context
- Implemented input validation utilities
- Added detailed logging with timestamps
- Improved error categorization and handling
- Added result structure validation

Type Definitions Added:
- SQLiteConnectionOptions
- SQLiteQueryOptions
- SQLiteExecuteOptions
- SQLiteResult
- SQLiteEchoResult

Error Codes Implemented:
- SQLITE_BUSY
- SQLITE_NO_TABLE
- SQLITE_SYNTAX_ERROR
- SQLITE_PLUGIN_UNAVAILABLE
- SQLITE_INVALID_OPTIONS
- SQLITE_MIGRATION_FAILED
- SQLITE_INVALID_RESULT
- SQLITE_ECHO_MISMATCH

Next Steps:
1. Implement initialization synchronization
2. Add component loading states
3. Improve error recovery mechanisms
4. Add proper error boundaries
5. Implement fallback UI states

Affected Files:
- electron/src/rt/sqlite-init.ts
- src/types/electron.d.ts

Note: This is a transitional commit. While the structure and type safety
are improved, the initialization timeout issue needs to be addressed in
the next commit to prevent cascading failures.

Testing Required:
- SQLite initialization timing
- Component loading sequences
- Error recovery scenarios
- Database operation retries
2025-06-03 04:31:27 +00:00
Matthew Raymer
1e88c0e26f refactor(electron): enhance SQLite integration and debug logging
Current Status:
- SQLite plugin successfully initializes in main process
- Preload script and context bridge working correctly
- IPC handlers for SQLite operations not registered
- Type definitions out of sync with implementation

Changes Made:
- Added comprehensive debug logging in preload script
- Implemented retry logic for SQLite operations (3 attempts, 1s delay)
- Added proper type definitions for SQLite connection options
- Defined strict channel validation for IPC communication
- Enhanced error handling and logging throughout

Type Definitions Updates:
- Aligned ElectronAPI interface with actual implementation
- Added proper typing for SQLite operations
- Structured IPC renderer interface with correct method signatures

Next Steps:
- Register missing IPC handlers in main process
- Update type definitions to match implementation
- Add proper error recovery for SQLite operations
- Address Content Security Policy warnings

Affected Files:
- electron/src/preload.ts
- src/types/electron.d.ts
- src/utils/debug-electron.ts
- src/services/platforms/ElectronPlatformService.ts

Note: This is a transitional commit. While the structure is improved,
database operations are not yet functional due to missing IPC handlers.
2025-06-03 04:18:39 +00:00
Matthew Raymer
3ec2364394 refactor: update electron preload script and type definitions
This commit updates the Electron preload script and type definitions to improve
SQLite integration and IPC communication. The changes include:

- Enhanced preload script (electron/src/preload.ts):
  * Added detailed logging for SQLite operations and IPC communication
  * Implemented retry logic for SQLite operations (3 attempts, 1s delay)
  * Added proper type definitions for SQLite connection options
  * Defined strict channel validation for IPC communication
  * Improved error handling and logging throughout

- Updated type definitions (src/types/electron.d.ts):
  * Aligned ElectronAPI interface with actual implementation
  * Added proper typing for all SQLite operations
  * Added environment variables (platform, isDev)
  * Structured IPC renderer interface with proper method signatures

Current Status:
- Preload script initializes successfully
- SQLite availability check works (returns true)
- SQLite ready signal is properly received
- Database operations are failing with two types of errors:
  1. "CapacitorSQLite not available" during initialization
  2. "Cannot read properties of undefined" for SQLite methods

Next Steps:
- Verify context bridge exposure in renderer process
- Check main process SQLite handlers
- Debug database initialization
- Address Content Security Policy warning

Affected Files:
- Modified: electron/src/preload.ts
- Modified: src/types/electron.d.ts

Note: This is a transitional commit. While the preload script and type
definitions are now properly structured, database operations are not yet
functional. Further debugging and fixes are required to resolve the
SQLite integration issues.
2025-06-03 04:06:24 +00:00
Matthew Raymer
8b215c909d refactor: remove electron preload script and update database handling
The preload script (src/electron/preload.js) was removed as part of a refactor to
separate web and electron builds. This script was previously responsible for:

- Secure IPC communication between electron main and renderer processes
- SQLite database access bridge for the renderer process
- Context isolation and API exposure for electron-specific features

Current state:
- Web app builds successfully without preload script
- Electron builds fail due to missing preload script
- SQLite initialization works in main process but renderer can't access it
- Database operations fail with "Cannot read properties of undefined"

This commit is a breaking change for electron builds. The preload script will need
to be recreated to restore electron database functionality.

Affected files:
- Deleted: src/electron/preload.js
- Modified: src/main.electron.ts (removed DatabaseManager import)
- Modified: src/utils/logger.ts (simplified logging implementation)
- Modified: src/types/electron.d.ts (updated ElectronAPI interface)
- Modified: src/types/global.d.ts (updated window.electron type definition)

Next steps:
- Recreate preload script with proper SQLite bridge
- Update electron build configuration
- Restore database access in renderer process
2025-06-03 03:48:36 +00:00
Matthew Raymer
91a1c05473 fix(electron): consolidate SQLite initialization and IPC handling
- Consolidate preload script with secure IPC bridge and channel validation
- Ensure single initialization path in main process
- Add robust error handling and user feedback
- Fix race conditions in window creation and SQLite ready signal

Current state:
- SQLite initializes successfully in main process
- IPC bridge is established and events are transmitted
- Window creation and loading sequence is correct
- Renderer receives ready signal and mounts app
- Database operations still fail in renderer due to connection issues

Known issues:
- SQLite proxy not properly initialized in renderer
- Database connection not established in renderer
- Error logging attempts to use database before ready
- Connection state management needs improvement

This commit represents a stable point where IPC communication
is working but database operations need to be fixed.
2025-06-03 02:52:17 +00:00
Matthew Raymer
66929d9b14 refactor(electron): WIP - use window.CapacitorSQLite API for all DB ops in ElectronPlatformService
- Remove connection object and connection pool logic
- Call all database methods directly on window.CapacitorSQLite with db name
- Refactor migrations, queries, and exec to match Capacitor SQLite Electron API
- Ensure preload script exposes both window.electron and window.CapacitorSQLite
- Fixes runtime errors related to missing query/run methods on connection
- Improves security and cross-platform compatibility

Co-authored-by: Matthew Raymer
2025-06-02 13:17:48 +00:00
Matthew Raymer
1e63ddcb6e feat(sqlite): enhance migration system and database initialization
- Add robust logging and error tracking to migration system
- Implement idempotent migrations with transaction safety
- Add detailed progress tracking and state verification
- Improve error handling with recoverable/non-recoverable states
- Add migration version validation and sequential checks
- Implement proper rollback handling with error recording
- Add table state verification and debugging
- Fix migration SQL parsing and parameter handling
- Add connection pool management and retry logic
- Add proper transaction isolation and state tracking

The migration system now provides:
- Atomic transactions per migration
- Automatic rollback on failure
- Detailed error logging and context
- State verification before/after operations
- Proper connection management
- Idempotent operations for safety

This commit improves database reliability and makes debugging
easier while maintaining proper process isolation. The changes
are focused on the migration system and do not require
restructuring the existing ElectronPlatformService architecture.

Technical details:
- Added MigrationError interface for better error tracking
- Added logMigrationProgress helper for consistent logging
- Added debugTableState for verification
- Added executeWithRetry for connection resilience
- Added validateMigrationVersions for safety
- Enhanced SQL parsing with better error handling
- Added proper transaction state management
- Added connection pool with retry logic
- Added detailed logging throughout migration process

Note: This commit addresses the database initialization issues
while maintaining the current architecture. Further improvements
to the ElectronPlatformService initialization will be handled
in a separate commit to maintain clear separation of concerns.
2025-06-02 10:00:41 +00:00
Matthew Raymer
51f5755f5c Merge branch 'elec-tweak' into sql-absurd-sql-further 2025-06-02 03:29:22 +00:00
Matthew Raymer
e5a3d622b6 Merge branch 'elec-tweak' of ssh://173.199.124.46:222/trent_larson/crowd-funder-for-time-pwa into elec-tweak 2025-06-02 03:26:57 +00:00
Matthew Raymer
a6edcd6269 feat(db): add secure secret generation and initial data setup
Add proper secret generation using Node's crypto module and initial data setup
for the electron environment. This commit:

- Implements secure random secret generation using crypto.randomBytes()
- Adds initial data migrations (002) with:
  - Secret table with cryptographically secure random key
  - Settings table with default API server
  - Contacts, logs, and temp tables
- Improves SQL parameter handling for migrations
- Adds proper transaction safety and rollback support
- Includes comprehensive logging and error handling

Security:
- Uses Node's crypto module for secure random generation
- Implements proper base64 encoding for secrets
- Maintains transaction safety for all operations

Testing:
- Verified database structure via sqlite3 CLI
- Confirmed successful migration execution
- Validated initial data insertion
- Checked index creation and constraints

Note: This is a temporary solution for secret storage until a more
secure storage mechanism is implemented.
2025-06-02 03:19:09 +00:00
Matthew Raymer
b7b6be5831 fix(sqlite): resolve duplicate table creation in migrations
Split initial schema into two sequential migrations to prevent duplicate
table creation and improve migration clarity.

Changes:
- Separate initial schema into two distinct migrations:
  * 001_initial_accounts (v1): Create accounts table & index
  * 002_secret_and_settings (v2): Create remaining tables (secret, settings, contacts, logs, temp)
- Add version conflict detection to prevent duplicate migration versions
- Ensure migrations are sequential (no gaps)
- Update rollback scripts to only drop relevant tables

Technical Details:
- Add validateMigrationVersions() to check for:
  * Duplicate version numbers
  * Sequential version ordering
  * Gaps in version numbers
- Validate migrations both at definition time and runtime
- Update schema_version tracking to reflect new versioning

Testing:
- Verified no duplicate table creation
- Confirmed migrations run in correct order
- Validated rollback procedures
- Checked version conflict detection
2025-06-02 02:48:08 +00:00
Matthew Raymer
cbaca0304d feat(sqlite): implement initial database migrations
Add robust SQLite migration system with initial schema for TimeSafari desktop app.
Includes comprehensive error handling, transaction safety, and detailed logging.

Key Changes:
- Add migration system with version tracking and rollback support
- Implement initial schema with accounts, secret, settings, contacts tables
- Configure SQLite PRAGMAs for optimal performance and reliability
- Add detailed logging and state verification
- Set up WAL journal mode and connection pooling

Technical Details:
- Use @capacitor-community/sqlite for native SQLite integration
- Implement atomic transactions per migration
- Add SQL validation and parsing utilities
- Configure PRAGMAs:
  * foreign_keys = ON
  * journal_mode = WAL
  * synchronous = NORMAL
  * temp_store = MEMORY
  * page_size = 4096
  * cache_size = 2000
  * busy_timeout = 15000
  * wal_autocheckpoint = 1000

Note: Current version has duplicate migration v1 entries that need to be
addressed in a follow-up commit to ensure proper versioning.

Testing:
- Verified migrations run successfully
- Confirmed table creation and index setup
- Validated transaction safety and rollback
- Checked logging and error handling
2025-06-02 02:30:58 +00:00
59d711bd90 make fixes to help my Mac build electron 2025-06-01 11:24:52 -06:00
Matthew Raymer
c355de6e33 Merge branch 'sql-absurd-sql-further' of ssh://173.199.124.46:222/trent_larson/crowd-funder-for-time-pwa into sql-absurd-sql-further 2025-06-01 12:37:19 +00:00
Matthew Raymer
28c114a2c7 fix(sqlite): resolve migration issues and enhance documentation
This commit addresses critical SQLite migration issues and significantly improves
code documentation and error handling. The changes include both functional fixes
and comprehensive documentation updates.

Key Changes:
- Fix migration name binding issue by switching to direct SQL statements
- Add proper SQL value escaping to prevent injection
- Implement comprehensive error handling and recovery
- Add detailed logging throughout migration process
- Enhance transaction safety and state verification

Documentation Updates:
- Add comprehensive module-level documentation
- Document all major functions with JSDoc
- Add security and performance considerations
- Include detailed process flows
- Document error handling strategies

Technical Details:
- Switch from parameterized queries to direct SQL for schema_version updates
- Add proper string escaping for SQL values
- Implement state verification before/after operations
- Add detailed debug logging for migration process
- Enhance error recovery with proper state tracking

Security:
- Add SQL injection prevention
- Implement proper value escaping
- Add transaction isolation
- Enhance state verification
- Add error sanitization

Performance:
- Optimize transaction handling
- Implement efficient SQL parsing
- Add connection pooling
- Reduce locking contention
- Optimize statement reuse

Testing:
- Verified migration process with fresh database
- Tested error recovery scenarios
- Validated transaction safety
- Confirmed proper state tracking
- Verified logging completeness

Breaking Changes: None
Migration Required: Yes (database will be recreated)

Author: Matthew Raymer
2025-06-01 12:36:57 +00:00
dabfe33fbe add Python dependency for electron on Mac 2025-06-01 06:34:32 -06:00
d8f2587d1c fix some errors and correct recent type duplications & bloat 2025-05-31 22:36:15 -06:00
Matthew Raymer
3946a8a27a fix(database): improve SQLite connection handling and initialization
- Add connection readiness check to ensure proper initialization
- Implement retry logic for connection attempts
- Fix database path handling to use consistent location
- Add proper error handling for connection state
- Ensure WAL journal mode for better performance
- Consolidate database initialization logic

The changes address several issues:
- Prevent "query is not a function" errors by waiting for connection readiness
- Ensure database is properly initialized before use
- Maintain consistent database path across application
- Improve error handling and connection state management
- Add proper cleanup of database connections

Technical details:
- Database path: ~/.local/share/TimeSafari/timesafariSQLite.db
- Journal mode: WAL (Write-Ahead Logging)
- Connection options: non-encrypted, read-write mode
- Tables: users, time_entries, time_goals, time_goal_entries, schema_version

This commit improves database reliability and prevents connection-related errors
that were occurring during application startup.
2025-06-01 03:47:20 +00:00
4c40b80718 rename script files that would fail in the prebuild step 2025-05-31 16:39:37 -06:00
74989c2b64 fix linting 2025-05-31 16:25:22 -06:00
7e17b41444 rename a js config file to avoid an error running lint 2025-05-31 16:24:10 -06:00
83acb028c7 fix more logic for tests 2025-05-31 16:20:41 -06:00
Matthew Raymer
786f07e067 feat(electron): Implement SQLite database initialization with proper logging
- Add comprehensive logging for database operations
- Implement proper database path handling and permissions
- Set up WAL journal mode and PRAGMA configurations
- Create initial database schema with tables and triggers
- Add retry logic for database operations
- Implement proper error handling and state management

Current state:
- Database initialization works in main process
- Connection creation succeeds with proper permissions
- Schema creation and table setup complete
- Logging system fully implemented
- Known issue: Property name mismatch between main process and renderer
  causing read-only mode conflicts (to be fixed in next commit)

Technical details:
- Uses WAL journal mode for better concurrency
- Implements proper file permissions checking
- Sets up foreign key constraints
- Creates tables: users, time_entries, time_goals, time_goal_entries
- Adds automatic timestamp triggers
- Implements proper connection lifecycle management

Security:
- Proper file permissions (755 for directory)
- No hardcoded credentials
- Proper error handling and logging
- Safe file path handling

Author: Matthew Raymer
2025-05-31 13:56:14 +00:00
Matthew Raymer
710cc1683c fix(sqlite): Standardize connection options and improve error handling
Changes to sqlite-init.ts:
- Standardized connection options format between main and renderer processes
- Added explicit mode: 'rwc' to force read-write-create mode
- Added connection registration verification
- Added detailed logging of actual file paths
- Added journal mode verification to detect read-only state
- Removed redundant PRAGMA settings (now handled in main process)
- Added more detailed error reporting for connection failures

Security:
- Ensures consistent read-write permissions across processes
- Verifies database is not opened in read-only mode
- Maintains proper file permissions (644) and directory permissions (755)

Testing:
- Verified connection creation in both main and renderer processes
- Confirmed journal mode is set correctly
- Validated connection registration
- Tested error handling for invalid states

Author: Matthew Raymer
2025-05-31 13:03:05 +00:00
Matthew Raymer
ebef5d6c8d feat(sqlite): Initialize database with complete schema and PRAGMAs
Initial database setup with:
- Created database at /home/matthew/Databases/TimeSafari/timesafariSQLite.db
- Set optimized PRAGMAs for performance and safety:
  * WAL journal mode for better concurrency
  * Foreign key constraints enabled
  * Normal synchronous mode
  * Memory temp store
  * 4KB page size
  * 2000 page cache (8MB)
- Created core tables:
  * schema_version (for migration tracking)
  * users (for user management)
  * time_entries (for time tracking)
  * time_goals (for goal setting)
  * time_goal_entries (for goal tracking)
- Added automatic timestamp triggers for:
  * users.updated_at
  * time_entries.updated_at
  * time_goals.updated_at
- Fixed connection handling to work with plugin's undefined return pattern
- Added rich logging throughout initialization process

Security:
- Database created with proper permissions (644)
- Directory permissions set to 755
- No encryption (as per requirements)
- Foreign key constraints enabled for data integrity

Testing:
- Verified table creation
- Confirmed schema version tracking
- Validated connection registration
- Tested WAL mode activation

Author: Matthew Raymer
2025-05-31 12:54:55 +00:00
Matthew Raymer
43ea7ee610 Merge branch 'sql-absurd-sql-further' of ssh://173.199.124.46:222/trent_larson/crowd-funder-for-time-pwa into sql-absurd-sql-further 2025-05-31 12:19:32 +00:00
Matthew Raymer
57191df416 feat(sqlite): Database file creation working, connection pending
- Successfully creates database file using plugin's open() method
- Directory permissions and path handling verified working
- Plugin initialization and echo test passing
- Database file created at /home/matthew/Databases/TimeSafari/timesafariSQLite.db

Key findings:
- createConnection() returns undefined but doesn't error
- open() silently creates the database file
- Connection retrieval still needs work (getDatabaseConnectionOrThrowError fails)
- Plugin structure confirmed: both class and default export available

Next steps:
- Refine connection handling after database creation
- Add connection state verification
- Consider adding retry logic for connection retrieval

Technical details:
- Using CapacitorSQLite from @capacitor-community/sqlite/electron
- Database path: /home/matthew/Databases/TimeSafari/timesafariSQLite.db
- Directory permissions: 755 (rwxr-xr-x)
- Plugin version: 6.x (Capacitor 6+ compatible)
2025-05-31 12:17:58 +00:00
644593a5f4 fix linting 2025-05-30 21:12:41 -06:00
Matthew Raymer
900c2521c7 WIP: Improve SQLite initialization and error handling
- Implement XDG Base Directory Specification for data storage
  - Use $XDG_DATA_HOME (defaults to ~/.local/share) for data files
  - Add proper directory permissions (700) for security
  - Fallback to ~/.timesafari if XDG paths fail

- Add graceful degradation for SQLite failures
  - Allow app to boot even if SQLite initialization fails
  - Track and expose initialization errors via IPC
  - Add availability checks to all SQLite operations
  - Improve error reporting and logging

- Security improvements
  - Set secure permissions (700) on data directories
  - Verify directory permissions on existing paths
  - Add proper error handling for permission issues

TODO:
- Fix database creation
- Add retry logic for initialization
- Add reinitialization capability
- Add more detailed error reporting
- Consider fallback storage options
2025-05-30 14:01:24 +00:00
Matthew Raymer
182cff2b16 fix(typescript): resolve linter violations and improve type safety
- Remove unused isDev variable
- Add proper type annotations for event handlers
- Add explicit Promise<void> return type for loadIndexHtml
- Use unknown type for error parameters instead of any
- Fix event handler parameters by prefixing unused params with underscore
- Improve error handling type safety throughout the file

This commit improves type safety and removes unused code while maintaining
existing functionality. All TypeScript linter violations have been addressed
without changing the core behavior of the application.

Database paths are still broken here.

Security Impact: None - changes are type-level only
Testing: No functional changes, existing tests should pass
2025-05-30 09:30:34 +00:00
Matthew Raymer
3b4ef908f3 feat(electron): improve window and database initialization
- Make database initialization non-blocking to prevent app crashes

- Add proper window lifecycle management and error handling

- Implement retry logic for index.html loading

- Add detailed logging for debugging

- Fix type safety issues in error handling

- Add proper cleanup on window close

WIP: Database path resolution still needs fixing

- Current issue: Path conflict between ~/.local/share and ~/.config

- Database connection failing with invalid response

- Multiple connection attempts occurring

This commit improves app stability but database connectivity needs to be addressed in a follow-up commit.
2025-05-30 09:10:01 +00:00
Matthew Raymer
a5a9e15ece WIP: Refactor Electron SQLite initialization and database path handling
- Add logic in main process to resolve and create the correct database directory and file path using Electron's app, path, and fs modules
- Pass absolute dbPath to CapacitorSQLite plugin for reliable database creation
- Add extensive logging for debugging database location, permissions, and initialization
- Remove redundant open() call after createConnection in Electron platform service
- Add IPC handlers for essential SQLite operations (echo, createConnection, execute, query, closeConnection, isAvailable)
- Improve error handling and logging throughout initialization and IPC
- Still investigating database file creation and permissions issues
2025-05-30 08:16:31 +00:00
Matthew Raymer
a6d8f0eb8a fix(electron): assign sqlitePlugin globally and improve error logging
- Assign CapacitorSQLite instance to the global sqlitePlugin variable so it is accessible in IPC handlers.
- Enhance error logging in the IPC handler to include JSON stringification and stack trace for better debugging.
- Reveal that the generic .handle() method is not available on the plugin, clarifying the next steps for correct IPC wiring.
2025-05-30 06:01:56 +00:00
Matthew Raymer
3997a88b44 fix: rename postcss.config.js to .cjs for ES module compatibility
- Added "type": "module" to package.json to support ES module imports for Electron SQLite
- Renamed postcss.config.js to postcss.config.cjs to maintain CommonJS syntax
- This ensures build tools can properly load the PostCSS configuration
2025-05-30 05:10:26 +00:00
5eeeae32c6 fix some incorrect logic & things AI hallucinated 2025-05-29 19:36:35 -06:00
Matthew Raymer
d9895086e6 experiment(electron): different vite build script for web application 2025-05-29 13:09:36 +00:00
Matthew Raymer
fb8d1cb8b2 fix(electron): add null check for devToolsWebContents to prevent TypeScript error
- Ensures devToolsWebContents is not null before calling focus() after opening DevTools in detached mode.
- Prevents runtime and linter errors in Electron main process.
2025-05-29 12:18:04 +00:00
Matthew Raymer
70c0edbed0 fix: SQLite plugin initialization in Electron main process
- Changed from direct plugin usage to SQLiteConnection pattern
- Matches how platform services use the SQLite plugin
- Removed handle() method dependency
- Added proper method routing in IPC handler

The app now launches without initialization errors. Next steps:
- Test actual SQLite operations (createConnection, query, etc.)
- Verify database creation and access
- Add error handling for database operations
2025-05-29 10:18:07 +00:00
Matthew Raymer
55cc08d675 chore: linting 2025-05-29 09:33:29 +00:00
Matthew Raymer
688a5be76e Merge branch 'sql-absurd-sql-further' of ssh://173.199.124.46:222/trent_larson/crowd-funder-for-time-pwa into sql-absurd-sql-further 2025-05-29 09:28:01 +00:00
Matthew Raymer
014341f320 fix(electron): simplify SQLite plugin initialization
- Remove worker thread approach in favor of direct plugin initialization
- Initialize CapacitorSQLiteElectron in main process
- Set up IPC handler to forward SQLite operations
- Remove unused worker files and build config

This reverts to a simpler, more reliable approach for SQLite in Electron,
using the plugin as intended in the main process.
2025-05-29 09:27:47 +00:00
Matthew Raymer
1d5e062c76 fix(electron): app loads 2025-05-29 07:24:20 +00:00
Matthew Raymer
2c5c15108a debug(electron): missing main.ts 2025-05-29 07:06:11 +00:00
Matthew Raymer
26df0fb671 debug(electron): app index loads but problem with preload script 2025-05-29 07:05:23 +00:00
423 changed files with 25444 additions and 51896 deletions

View File

@@ -1,310 +0,0 @@
# Cursor Markdown Ruleset for TimeSafari Documentation
## Overview
This ruleset enforces consistent markdown formatting standards across all project
documentation, ensuring readability, maintainability, and compliance with
markdownlint best practices.
## General Formatting Standards
### Line Length
- **Maximum line length**: 80 characters
- **Exception**: Code blocks (JSON, shell, TypeScript, etc.) - no line length
enforcement
- **Rationale**: Ensures readability across different screen sizes and terminal
widths
### Blank Lines
- **Headings**: Must be surrounded by blank lines above and below
- **Lists**: Must be surrounded by blank lines above and below
- **Code blocks**: Must be surrounded by blank lines above and below
- **Maximum consecutive blank lines**: 1 (no multiple blank lines)
- **File start**: No blank lines at the beginning of the file
- **File end**: Single newline character at the end
### Whitespace
- **No trailing spaces**: Remove all trailing whitespace from lines
- **No tabs**: Use spaces for indentation
- **Consistent indentation**: 2 spaces for list items and nested content
## Heading Standards
### Format
- **Style**: ATX-style headings (`#`, `##`, `###`, etc.)
- **Case**: Title case for general headings
- **Code references**: Use backticks for file names and technical terms
-`### Current package.json Scripts`
-`### Current Package.json Scripts`
### Hierarchy
- **H1 (#)**: Document title only
- **H2 (##)**: Major sections
- **H3 (###)**: Subsections
- **H4 (####)**: Sub-subsections
- **H5+**: Avoid deeper nesting
## List Standards
### Unordered Lists
- **Marker**: Use `-` (hyphen) consistently
- **Indentation**: 2 spaces for nested items
- **Blank lines**: Surround lists with blank lines
### Ordered Lists
- **Format**: `1.`, `2.`, `3.` (sequential numbering)
- **Indentation**: 2 spaces for nested items
- **Blank lines**: Surround lists with blank lines
### Task Lists
- **Format**: `- [ ]` for incomplete, `- [x]` for complete
- **Use case**: Project planning, checklists, implementation tracking
## Code Block Standards
### Fenced Code Blocks
- **Syntax**: Triple backticks with language specification
- **Languages**: `json`, `bash`, `typescript`, `javascript`, `yaml`, `markdown`
- **Blank lines**: Must be surrounded by blank lines above and below
- **Line length**: No enforcement within code blocks
### Inline Code
- **Format**: Single backticks for inline code references
- **Use case**: File names, commands, variables, properties
## Special Content Standards
### JSON Examples
```json
{
"property": "value",
"nested": {
"property": "value"
}
}
```
### Shell Commands
```bash
# Command with comment
npm run build:web
# Multi-line command
VITE_GIT_HASH=`git log -1 --pretty=format:%h` \
vite build --config vite.config.web.mts
```
### TypeScript Examples
```typescript
// Function with JSDoc
/**
* Get environment configuration
* @param env - Environment name
* @returns Environment config object
*/
const getEnvironmentConfig = (env: string) => {
switch (env) {
case 'prod':
return { /* production settings */ };
default:
return { /* development settings */ };
}
};
```
## File Structure Standards
### Document Header
```markdown
# Document Title
**Author**: Matthew Raymer
**Date**: YYYY-MM-DD
**Status**: 🎯 **STATUS** - Brief description
## Overview
Brief description of the document's purpose and scope.
```
### Section Organization
1. **Overview/Introduction**
2. **Current State Analysis**
3. **Implementation Plan**
4. **Technical Details**
5. **Testing & Validation**
6. **Next Steps**
## Markdownlint Configuration
### Required Rules
```json
{
"MD013": { "code_blocks": false },
"MD012": true,
"MD022": true,
"MD031": true,
"MD032": true,
"MD047": true,
"MD009": true
}
```
### Rule Explanations
- **MD013**: Line length (disabled for code blocks)
- **MD012**: No multiple consecutive blank lines
- **MD022**: Headings should be surrounded by blank lines
- **MD031**: Fenced code blocks should be surrounded by blank lines
- **MD032**: Lists should be surrounded by blank lines
- **MD047**: Files should end with a single newline
- **MD009**: No trailing spaces
## Validation Commands
### Check Single File
```bash
npx markdownlint docs/filename.md
```
### Check All Documentation
```bash
npx markdownlint docs/
```
### Auto-fix Common Issues
```bash
# Remove trailing spaces
sed -i 's/[[:space:]]*$//' docs/filename.md
# Remove multiple blank lines
sed -i '/^$/N;/^\n$/D' docs/filename.md
# Add newline at end if missing
echo "" >> docs/filename.md
```
## Common Patterns
### Implementation Plans
```markdown
## Implementation Plan
### Phase 1: Foundation (Day 1)
#### 1.1 Component Setup
- [ ] Create new component file
- [ ] Add basic structure
- [ ] Implement core functionality
#### 1.2 Configuration
- [ ] Update configuration files
- [ ] Add environment variables
- [ ] Test configuration loading
```
### Status Tracking
```markdown
**Status**: ✅ **COMPLETE** - All phases finished
**Progress**: 75% (15/20 components)
**Next**: Ready for testing phase
```
### Performance Metrics
```markdown
#### 📊 Performance Metrics
- **Build Time**: 2.3 seconds (50% faster than baseline)
- **Bundle Size**: 1.2MB (30% reduction)
- **Success Rate**: 100% (no failures in 50 builds)
```
## Enforcement
### Pre-commit Hooks
- Run markdownlint on all changed markdown files
- Block commits with linting violations
- Auto-fix common issues when possible
### CI/CD Integration
- Include markdownlint in build pipeline
- Generate reports for documentation quality
- Fail builds with critical violations
### Team Guidelines
- All documentation PRs must pass markdownlint
- Use provided templates for new documents
- Follow established patterns for consistency
## Templates
### New Document Template
```markdown
# Document Title
**Author**: Matthew Raymer
**Date**: YYYY-MM-DD
**Status**: 🎯 **PLANNING** - Ready for Implementation
## Overview
Brief description of the document's purpose and scope.
## Current State
Description of current situation or problem.
## Implementation Plan
### Phase 1: Foundation
- [ ] Task 1
- [ ] Task 2
## Next Steps
1. **Review and approve plan**
2. **Begin implementation**
3. **Test and validate**
---
**Status**: Ready for implementation
**Priority**: Medium
**Estimated Effort**: X days
**Dependencies**: None
**Stakeholders**: Development team
```
---
**Last Updated**: 2025-07-09
**Version**: 1.0
**Maintainer**: Matthew Raymer

View File

@@ -1,6 +1,7 @@
---
globs: **/db/databaseUtil.ts, **/interfaces/absurd-sql.d.ts, **/src/registerSQLWorker.js, **/services/AbsurdSqlDatabaseService.ts
alwaysApply: false
description:
globs:
alwaysApply: true
---
# Absurd SQL - Cursor Development Guide

View File

@@ -1,63 +0,0 @@
# ADR Template
## ADR-XXXX-YY-ZZ: [Short Title]
**Date:** YYYY-MM-DD
**Status:** [PROPOSED | ACCEPTED | REJECTED | DEPRECATED | SUPERSEDED]
**Deciders:** [List of decision makers]
**Technical Story:** [Link to issue/PR if applicable]
## Context
[Describe the forces at play, including technological, political, social, and project local. These forces are probably in tension, and should be called out as such. The language in this section is value-neutral. It is simply describing facts.]
## Decision
[Describe our response to these forces. We will use the past tense ("We will...").]
## Consequences
### Positive
- [List positive consequences]
### Negative
- [List negative consequences or trade-offs]
### Neutral
- [List neutral consequences or notes]
## Alternatives Considered
- **Alternative 1:** [Description] - [Why rejected]
- **Alternative 2:** [Description] - [Why rejected]
- **Alternative 3:** [Description] - [Why rejected]
## Implementation Notes
[Any specific implementation details, migration steps, or technical considerations]
## References
- [Link to relevant documentation]
- [Link to related ADRs]
- [Link to external resources]
## Related Decisions
- [List related ADRs or decisions]
---
## Usage Guidelines
1. **Copy this template** for new ADRs
2. **Number sequentially** (ADR-001, ADR-002, etc.)
3. **Use descriptive titles** that clearly indicate the decision
4. **Include all stakeholders** in the deciders list
5. **Link to related issues** and documentation
6. **Update status** as decisions evolve
7. **Store in** `doc/architecture-decisions/` directory
description:
globs:
alwaysApply: false
---

View File

@@ -1,172 +0,0 @@
---
description:
globs:
alwaysApply: true
---
# TimeSafari Cross-Platform Architecture Guide
## 1. Platform Support Matrix
| Feature | Web (PWA) | Capacitor (Mobile) | Electron (Desktop) |
|---------|-----------|--------------------|-------------------|
| QR Code Scanning | WebInlineQRScanner | @capacitor-mlkit/barcode-scanning | Not Implemented |
| Deep Linking | URL Parameters | App URL Open Events | Not Implemented |
| File System | Limited (Browser API) | Capacitor Filesystem | Electron fs |
| Camera Access | MediaDevices API | Capacitor Camera | Not Implemented |
| Platform Detection | Web APIs | Capacitor.isNativePlatform() | process.env checks |
---
## 2. Project Structure
### Core Directories
```
src/
├── components/ # Vue components
├── services/ # Platform services and business logic
├── views/ # Page components
├── router/ # Vue router configuration
├── types/ # TypeScript type definitions
├── utils/ # Utility functions
├── lib/ # Core libraries
├── platforms/ # Platform-specific implementations
├── electron/ # Electron-specific code
├── constants/ # Application constants
├── db/ # Database related code
├── interfaces/ # TypeScript interfaces
└── assets/ # Static assets
```
### Entry Points
- `main.ts` → Base entry
- `main.common.ts` → Shared init
- `main.capacitor.ts` → Mobile entry
- `main.electron.ts` → Electron entry
- `main.web.ts` → Web entry
---
## 3. Service Architecture
### Service Organization
```tree
services/
├── QRScanner/
│ ├── WebInlineQRScanner.ts
│ └── interfaces.ts
├── platforms/
│ ├── WebPlatformService.ts
│ ├── CapacitorPlatformService.ts
│ └── ElectronPlatformService.ts
└── factory/
└── PlatformServiceFactory.ts
```
### Factory Pattern
Use a **singleton factory** to select platform services via `process.env.VITE_PLATFORM`.
---
## 4. Feature Guidelines
### QR Code Scanning
- Define `QRScannerService` interface.
- Implement platform-specific classes (`WebInlineQRScanner`, Capacitor, etc).
- Provide `addListener` and `onStream` hooks for composability.
### Deep Linking
- URL format: `timesafari://<route>[/<param>][?query=value]`
- Web: `router.beforeEach` → parse query
- Capacitor: `App.addListener("appUrlOpen", …)`
---
## 5. Build Process
- `vite.config.common.mts` → shared config
- Platform configs: `vite.config.web.mts`, `.capacitor.mts`, `.electron.mts`
- Use `process.env.VITE_PLATFORM` for conditional loading.
```bash
npm run build:web
npm run build:capacitor
npm run build:electron
```
---
## 6. Testing Strategy
- **Unit tests** for services.
- **Playwright** for Web + Capacitor:
- `playwright.config-local.ts` includes web + Pixel 5.
- **Electron tests**: add `spectron` or Playwright-Electron.
- Mark tests with platform tags:
```ts
test.skip(!process.env.MOBILE_TEST, "Mobile-only test");
```
> 🔗 **Human Hook:** Before merging new tests, hold a short sync (≤15 min) with QA to align on coverage and flaky test risks.
---
## 7. Error Handling
- Global Vue error handler → logs with component name.
- Platform-specific wrappers log API errors with platform prefix (`[Capacitor API Error]`, etc).
- Use structured logging (not `console.log`).
---
## 8. Best Practices
- Keep platform code **isolated** in `platforms/`.
- Always define a **shared interface** first.
- Use feature detection, not platform detection, when possible.
- Dependency injection for services → improves testability.
- Maintain **Competence Hooks** in PRs (23 prompts for dev discussion).
---
## 9. Dependency Management
- Key deps: `@capacitor/core`, `electron`, `vue`.
- Use conditional `import()` for platform-specific libs.
---
## 10. Security Considerations
- **Permissions**: Always check + request gracefully.
- **Storage**: Secure storage for sensitive data; encrypt when possible.
- **Audits**: Schedule quarterly security reviews.
---
## 11. ADR Process
- All major architecture choices → log in `doc/adr/`.
- Use ADR template with Context, Decision, Consequences, Status.
- Link related ADRs in PR descriptions.
> 🔗 **Human Hook:** When proposing a new ADR, schedule a 30-min design sync for discussion, not just async review.
---
## 12. Collaboration Hooks
- **QR features**: Sync with Security before merging → permissions & privacy.
- **New platform builds**: Demo in team meeting → confirm UX differences.
- **Critical ADRs**: Present in guild or architecture review.
---
# Self-Check
- [ ] Does this feature implement a shared interface?
- [ ] Are fallbacks + errors handled gracefully?
- [ ] Have relevant ADRs been updated/linked?
- [ ] Did I add competence hooks or prompts for the team?
- [ ] Was human interaction (sync/review/demo) scheduled?

View File

@@ -0,0 +1,292 @@
---
description:
globs:
alwaysApply: true
---
# TimeSafari Cross-Platform Architecture Guide
## 1. Platform Support Matrix
| Feature | Web (PWA) | Capacitor (Mobile) | Electron (Desktop) | PyWebView (Desktop) |
|---------|-----------|-------------------|-------------------|-------------------|
| QR Code Scanning | WebInlineQRScanner | @capacitor-mlkit/barcode-scanning | Not Implemented | Not Implemented |
| Deep Linking | URL Parameters | App URL Open Events | Not Implemented | Not Implemented |
| File System | Limited (Browser API) | Capacitor Filesystem | Electron fs | PyWebView Python Bridge |
| Camera Access | MediaDevices API | Capacitor Camera | Not Implemented | Not Implemented |
| Platform Detection | Web APIs | Capacitor.isNativePlatform() | process.env checks | process.env checks |
## 2. Project Structure
### 2.1 Core Directories
```
src/
├── components/ # Vue components
├── services/ # Platform services and business logic
├── views/ # Page components
├── router/ # Vue router configuration
├── types/ # TypeScript type definitions
├── utils/ # Utility functions
├── lib/ # Core libraries
├── platforms/ # Platform-specific implementations
├── electron/ # Electron-specific code
├── constants/ # Application constants
├── db/ # Database related code
├── interfaces/ # TypeScript interfaces and type definitions
└── assets/ # Static assets
```
### 2.2 Entry Points
```
src/
├── main.ts # Base entry
├── main.common.ts # Shared initialization
├── main.capacitor.ts # Mobile entry
├── main.electron.ts # Electron entry
├── main.pywebview.ts # PyWebView entry
└── main.web.ts # Web/PWA entry
```
### 2.3 Build Configurations
```
root/
├── vite.config.common.mts # Shared config
├── vite.config.capacitor.mts # Mobile build
├── vite.config.electron.mts # Electron build
├── vite.config.pywebview.mts # PyWebView build
├── vite.config.web.mts # Web/PWA build
└── vite.config.utils.mts # Build utilities
```
## 3. Service Architecture
### 3.1 Service Organization
```
services/
├── QRScanner/ # QR code scanning service
│ ├── WebInlineQRScanner.ts
│ └── interfaces.ts
├── platforms/ # Platform-specific services
│ ├── WebPlatformService.ts
│ ├── CapacitorPlatformService.ts
│ ├── ElectronPlatformService.ts
│ └── PyWebViewPlatformService.ts
└── factory/ # Service factories
└── PlatformServiceFactory.ts
```
### 3.2 Service Factory Pattern
```typescript
// PlatformServiceFactory.ts
export class PlatformServiceFactory {
private static instance: PlatformService | null = null;
public static getInstance(): PlatformService {
if (!PlatformServiceFactory.instance) {
const platform = process.env.VITE_PLATFORM || "web";
PlatformServiceFactory.instance = createPlatformService(platform);
}
return PlatformServiceFactory.instance;
}
}
```
## 4. Feature Implementation Guidelines
### 4.1 QR Code Scanning
1. **Service Interface**
```typescript
interface QRScannerService {
checkPermissions(): Promise<boolean>;
requestPermissions(): Promise<boolean>;
isSupported(): Promise<boolean>;
startScan(): Promise<void>;
stopScan(): Promise<void>;
addListener(listener: ScanListener): void;
onStream(callback: (stream: MediaStream | null) => void): void;
cleanup(): Promise<void>;
}
```
2. **Platform-Specific Implementation**
```typescript
// WebInlineQRScanner.ts
export class WebInlineQRScanner implements QRScannerService {
private scanListener: ScanListener | null = null;
private isScanning = false;
private stream: MediaStream | null = null;
private events = new EventEmitter();
// Implementation of interface methods
}
```
### 4.2 Deep Linking
1. **URL Structure**
```typescript
// Format: timesafari://<route>[/<param>][?queryParam1=value1]
interface DeepLinkParams {
route: string;
params?: Record<string, string>;
query?: Record<string, string>;
}
```
2. **Platform Handlers**
```typescript
// Capacitor
App.addListener("appUrlOpen", handleDeepLink);
// Web
router.beforeEach((to, from, next) => {
handleWebDeepLink(to.query);
});
```
## 5. Build Process
### 5.1 Environment Configuration
```typescript
// vite.config.common.mts
export function createBuildConfig(mode: string) {
return {
define: {
'process.env.VITE_PLATFORM': JSON.stringify(mode),
'process.env.VITE_PWA_ENABLED': JSON.stringify(!isNative),
__IS_MOBILE__: JSON.stringify(isCapacitor),
__USE_QR_READER__: JSON.stringify(!isCapacitor)
}
};
}
```
### 5.2 Platform-Specific Builds
```bash
# Build commands from package.json
"build:web": "vite build --config vite.config.web.mts",
"build:capacitor": "vite build --config vite.config.capacitor.mts",
"build:electron": "vite build --config vite.config.electron.mts",
"build:pywebview": "vite build --config vite.config.pywebview.mts"
```
## 6. Testing Strategy
### 6.1 Test Configuration
```typescript
// playwright.config-local.ts
const config: PlaywrightTestConfig = {
projects: [
{
name: 'web',
use: { browserName: 'chromium' }
},
{
name: 'mobile',
use: { ...devices['Pixel 5'] }
}
]
};
```
### 6.2 Platform-Specific Tests
```typescript
test('QR scanning works on mobile', async ({ page }) => {
test.skip(!process.env.MOBILE_TEST, 'Mobile-only test');
// Test implementation
});
```
## 7. Error Handling
### 7.1 Global Error Handler
```typescript
function setupGlobalErrorHandler(app: VueApp) {
app.config.errorHandler = (err, instance, info) => {
logger.error("[App Error]", {
error: err,
info,
component: instance?.$options.name
});
};
}
```
### 7.2 Platform-Specific Error Handling
```typescript
// API error handling for Capacitor
if (process.env.VITE_PLATFORM === 'capacitor') {
logger.error(`[Capacitor API Error] ${endpoint}:`, {
message: error.message,
status: error.response?.status
});
}
```
## 8. Best Practices
### 8.1 Code Organization
- Use platform-specific directories for unique implementations
- Share common code through service interfaces
- Implement feature detection before using platform capabilities
- Keep platform-specific code isolated in dedicated directories
- Use TypeScript interfaces for cross-platform compatibility
### 8.2 Platform Detection
```typescript
const platformService = PlatformServiceFactory.getInstance();
const capabilities = platformService.getCapabilities();
if (capabilities.hasCamera) {
// Implement camera features
}
```
### 8.3 Feature Implementation
1. Define platform-agnostic interface
2. Create platform-specific implementations
3. Use factory pattern for instantiation
4. Implement graceful fallbacks
5. Add comprehensive error handling
6. Use dependency injection for better testability
## 9. Dependency Management
### 9.1 Platform-Specific Dependencies
```json
{
"dependencies": {
"@capacitor/core": "^6.2.0",
"electron": "^33.2.1",
"vue": "^3.4.0"
}
}
```
### 9.2 Conditional Loading
```typescript
if (process.env.VITE_PLATFORM === 'capacitor') {
await import('@capacitor/core');
}
```
## 10. Security Considerations
### 10.1 Permission Handling
```typescript
async checkPermissions(): Promise<boolean> {
if (platformService.isCapacitor()) {
return await checkNativePermissions();
}
return await checkWebPermissions();
}
```
### 10.2 Data Storage
- Use secure storage mechanisms for sensitive data
- Implement proper encryption for stored data
- Follow platform-specific security guidelines
- Regular security audits and updates
This document should be updated as new features are added or platform-specific implementations change. Regular reviews ensure it remains current with the codebase.

View File

@@ -1,32 +0,0 @@
---
alwaysApply: true
---
# Asset Configuration Directive
*Scope: Assets Only (icons, splashes, image pipelines) — not overall build orchestration*
## Intent
- Version **asset configuration files** (optionally dev-time generated).
- **Do not** version platform asset outputs (Android/iOS/Electron); generate them **at build-time** with standard tools.
- Keep existing per-platform build scripts unchanged.
## Source of Truth
- **Preferred (Capacitor default):** `resources/` as the single master source.
- **Alternative:** `assets/` is acceptable **only** if `capacitor-assets` is explicitly configured to read from it.
- **Never** maintain both `resources/` and `assets/` as parallel sources. Migrate and delete the redundant folder.
## Config Files
- Live under: `config/assets/` (committed).
- Examples:
- `config/assets/capacitor-assets.config.json` (or the path the tool expects)
- `config/assets/android.assets.json`
- `config/assets/ios.assets.json`
- `config/assets/common.assets.yaml` (optional shared layer)
- **Dev-time generation allowed** for these configs; **build-time generation is forbidden**.
## Build-Time Behavior
- Build generates platform assets (not configs) using the standard chain:
```bash
npm run build:capacitor # web build via Vite (.mts)
npx cap sync
npx capacitor-assets generate # produces platform assets; not committed
# then platform-specific build steps

View File

@@ -1,110 +0,0 @@
```json
{
"coaching_level": "standard",
"socratic_max_questions": 7,
"verbosity": "normal",
"timebox_minutes": null,
"format_enforcement": "strict"
}
```
# Base Context — Human Competence First
## Purpose
All interactions must *increase the human's competence over time* while
completing the task efficiently. The model may handle menial work and memory
extension, but must also promote learning, autonomy, and healthy work habits.
The model should also **encourage human interaction and collaboration** rather
than replacing it — outputs should be designed to **facilitate human discussion,
decision-making, and creativity**, not to atomize tasks into isolated, purely
machine-driven steps.
## Principles
1) Competence over convenience: finish the task *and* leave the human more
capable next time.
2) Mentorship, not lectures: be concise, concrete, and immediately applicable.
3) Transparency: show assumptions, limits, and uncertainty; cite when non-obvious.
4) Optional scaffolding: include small, skimmable learning hooks that do not
bloat output.
5) Time respect: default to **lean output**; offer opt-in depth via toggles.
6) Psychological safety: encourage, never condescend; no medical/clinical advice.
No censorship!
7) Reusability: structure outputs so they can be saved, searched, reused, and repurposed.
8) **Collaborative Bias**: Favor solutions that invite human review, discussion,
and iteration. When in doubt, ask "Who should this be shown to?" or "Which human
input would improve this?"
## Toggle Definitions
### coaching_level
Determines the depth of learning support: `light` (short hooks), `standard`
(balanced), `deep` (detailed).
### socratic_max_questions
The number of clarifying questions the model may ask before proceeding.
If >0, questions should be targeted, minimal, and followed by reasonable assumptions if unanswered.
### verbosity
'terse' (just a sentence), `concise` (minimum commentary), `normal` (balanced explanation), or other project-defined levels.
### timebox_minutes
*integer or null* — When set to a positive integer (e.g., `5`), this acts as a **time budget** guiding the model to prioritize delivering the most essential parts of the task within that constraint.
Behavior when set:
1. **Prioritize Core Output** — Deliver the minimum viable solution or result first.
2. **Limit Commentary** — Competence Hooks and Collaboration Hooks must be shorter than normal.
3. **Signal Skipped Depth** — Omitted details should be listed under *Deferred for depth*.
4. **Order by Value** — Start with blocking or high-value items, then proceed to nice-to-haves if budget allows.
If `null`, there is no timebox — the model can produce full-depth responses.
### format_enforcement
`strict` (reject outputs with format drift) or `relaxed` (minor deviations acceptable).
## Modes (select or combine)
- **Doer**: produce the artifact fast, minimal commentary.
- **Mentor**: add short "why/how" notes + next-step pointers.
- **Socratic**: ask up to N targeted questions when requirements are ambiguous.
- **Pair-Programmer/Pair-Writer**: explain tradeoffs as you implement.
- **Facilitator**: structure output to be reviewable, commentable, and ready for group discussion.
Default: Doer + short Mentor notes.
## Competence & Collaboration Levers (keep lightweight)
- "Why this works" (≤3 bullets)
- "Common pitfalls" (≤3 bullets)
- "Next skill unlock" (1 tiny action or reading)
- "Teach-back" (1 sentence prompt the human can answer to self-check)
- "Discussion prompts" (≤2 short questions for peers/stakeholders)
## Output Contract (apply to every deliverable)
- Clear **Objective** (1 line)
- **Result** (artifact/code/answer)
- **Use/Run** (how to apply/test)
- **Competence Hooks** (the 4 learning levers above, kept terse)
- **Collaboration Hooks** (discussion prompts or group review steps)
- **Assumptions & Limits**
- **References** (if used; links or titles)
## Do-Not
- No filler, hedging, or moralizing.
- No medical/mental-health advice; keep "healthy habits" to general work practices.
- No invented facts; mark uncertainty plainly.
- No censorship.
- Avoid outputs that bypass human review when such review is valuable.
## Related Rulesets
- **software_development.mdc**: For software-specific development practices
- **research_diagnostic.mdc**: For investigation and research workflows
## Self-Check (model, before responding)
- [ ] Task done *and* at least one competence lever included (≤120 words total).
- [ ] At least one collaboration/discussion hook present.
- [ ] Output follows the **Output Contract** sections.
- [ ] Toggles respected; verbosity remains concise.
- [ ] Uncertainties/assumptions surfaced.
- [ ] No disallowed content.
- [ ] Uncertainties/assumptions surfaced.
- [ ] No disallowed content.

View File

@@ -1,5 +0,0 @@
---
globs: **/databaseUtil.ts,**/AccountViewView.vue,**/ContactsView.vue,**/DatabaseMigration.vue,**/NewIdentifierView.vue
alwaysApply: false
---
All references in the codebase to Dexie apply only to migration from IndexedDb to Sqlite and will be deprecated in future versions.

View File

@@ -1,9 +0,0 @@
---
globs: **/src/**/*
alwaysApply: false
---
✅ use system date command to timestamp all interactions with accurate date and time
✅ python script files must always have a blank line at their end
✅ remove whitespace at the end of lines
✅ use npm run lint-fix to check for warnings
✅ do not use npm run dev let me handle running and supplying feedback

View File

@@ -1,108 +0,0 @@
---
globs: **/src/**/*,**/scripts/**/*,**/electron/**/*
alwaysApply: false
---
```json
{
"coaching_level": "light",
"socratic_max_questions": 7,
"verbosity": "concise",
"timebox_minutes": null,
"format_enforcement": "strict"
}
```
# TypeScript Type Safety Guidelines
**Author**: Matthew Raymer
**Date**: 2025-08-16
**Status**: 🎯 **ACTIVE**
## Overview
Practical rules to keep TypeScript strict and predictable. Minimize exceptions.
## Core Rules
1. **No `any`**
- Use explicit types. If unknown, use `unknown` and **narrow** via guards.
2. **Error handling uses guards**
- Reuse guards from `src/interfaces/**` (e.g., `isDatabaseError`, `isApiError`).
- Catch with `unknown`; never cast to `any`.
3. **Dynamic property access is typesafe**
- Use `keyof` + `in` checks:
```ts
obj[k as keyof typeof obj]
```
- Avoid `(obj as any)[k]`.
## Minimal Special Cases (document in PR when used)
- **Vue refs / instances**: Use `ComponentPublicInstance` or specific component
types for dynamic refs.
- **3rdparty libs without types**: Narrow immediately to a **known interface**;
do not leave `any` hanging.
## Patterns (short)
### Database errors
```ts
try { await this.$addContact(contact); }
catch (e: unknown) {
if (isDatabaseError(e) && e.message.includes("Key already exists")) {
/* handle duplicate */
}
}
```
### API errors
```ts
try { await apiCall(); }
catch (e: unknown) {
if (isApiError(e)) {
const msg = e.response?.data?.error?.message;
}
}
```
### Dynamic keys
```ts
const keys = Object.keys(newSettings).filter(
k => k in newSettings && newSettings[k as keyof typeof newSettings] !== undefined
);
```
## Checklists
**Before commit**
- [ ] No `any` (except documented, justified cases)
- [ ] Errors handled via guards
- [ ] Dynamic access uses `keyof`/`in`
- [ ] Imports point to correct interfaces/types
**Code review**
- [ ] Hunt hidden `as any`
- [ ] Guardbased error paths verified
- [ ] Dynamic ops are typesafe
- [ ] Prefer existing types over reinventing
## Tools
- `npm run lint-fix` — lint & autofix
- `npm run type-check` — strict type compilation (CI + prerelease)
- IDE: enable strict TS, ESLint/TS ESLint, Volar (Vue 3)
## References
- TS Handbook — https://www.typescriptlang.org/docs/
- TSESLint — https://typescript-eslint.io/rules/
- Vue 3 + TS — https://vuejs.org/guide/typescript/

View File

@@ -1,14 +0,0 @@
---
alwaysApply: true
---
# Directive for Documentation Generation
1. Produce a **small, focused set of documents** rather than an overwhelming volume.
2. Ensure the content is **maintainable and worth preserving**, so that humans
are motivated to keep it up to date.
3. Prioritize **educational value**: the documents must clearly explain the
workings of the system.
4. Avoid **shallow, generic, or filler explanations** often found in
AI-generated documentation.
5. Aim for **clarity, depth, and usefulness**, so readers gain genuine understanding.
6. Always check the local system date to determine current date.

View File

@@ -1,332 +0,0 @@
---
globs: *.md
alwaysApply: false
---
# Cursor Markdown Ruleset for TimeSafari Documentation
## Overview
This ruleset enforces consistent markdown formatting standards across all project
documentation, ensuring readability, maintainability, and compliance with
markdownlint best practices.
## General Formatting Standards
### Line Length
- **Maximum line length**: 80 characters
- **Exception**: Code blocks (JSON, shell, TypeScript, etc.) - no line length
enforcement
- **Rationale**: Ensures readability across different screen sizes and terminal
widths
### Blank Lines
- **Headings**: Must be surrounded by blank lines above and below
- **Lists**: Must be surrounded by blank lines above and below
- **Code blocks**: Must be surrounded by blank lines above and below
- **Maximum consecutive blank lines**: 1 (no multiple blank lines)
- **File start**: No blank lines at the beginning of the file
- **File end**: Single newline character at the end
### Whitespace
- **No trailing spaces**: Remove all trailing whitespace from lines
- **No tabs**: Use spaces for indentation
- **Consistent indentation**: 2 spaces for list items and nested content
## Heading Standards
### Format
- **Style**: ATX-style headings (`#`, `##`, `###`, etc.)
- **Case**: Title case for general headings
- **Code references**: Use backticks for file names and technical terms
- ✅ `### Current package.json Scripts`
- ❌ `### Current Package.json Scripts`
### Hierarchy
- **H1 (#)**: Document title only
- **H2 (##)**: Major sections
- **H3 (###)**: Subsections
- **H4 (####)**: Sub-subsections
- **H5+**: Avoid deeper nesting
## List Standards
### Unordered Lists
- **Marker**: Use `-` (hyphen) consistently
- **Indentation**: 2 spaces for nested items
- **Blank lines**: Surround lists with blank lines
### Ordered Lists
- **Format**: `1.`, `2.`, `3.` (sequential numbering)
- **Indentation**: 2 spaces for nested items
- **Blank lines**: Surround lists with blank lines
### Task Lists
- **Format**: `- [ ]` for incomplete, `- [x]` for complete
- **Use case**: Project planning, checklists, implementation tracking
## Code Block Standards
### Fenced Code Blocks
- **Syntax**: Triple backticks with language specification
- **Languages**: `json`, `bash`, `typescript`, `javascript`, `yaml`, `markdown`
- **Blank lines**: Must be surrounded by blank lines above and below
- **Line length**: No enforcement within code blocks
### Inline Code
- **Format**: Single backticks for inline code references
- **Use case**: File names, commands, variables, properties
## Special Content Standards
### JSON Examples
```json
{
"property": "value",
"nested": {
"property": "value"
}
}
```
### Shell Commands
```bash
# Command with comment
npm run build:web
# Multi-line command
VITE_GIT_HASH=`git log -1 --pretty=format:%h` \
vite build --config vite.config.web.mts
```
### TypeScript Examples
```typescript
// Function with JSDoc
/**
* Get environment configuration
* @param env - Environment name
* @returns Environment config object
*/
const getEnvironmentConfig = (env: string) => {
switch (env) {
case 'prod':
return { /* production settings */ };
default:
return { /* development settings */ };
}
};
```
## File Structure Standards
### Document Header
```markdown
# Document Title
**Author**: Matthew Raymer
**Date**: YYYY-MM-DD
**Status**: 🎯 **STATUS** - Brief description
## Overview
Brief description of the document's purpose and scope.
```
### Section Organization
1. **Overview/Introduction**
2. **Current State Analysis**
3. **Implementation Plan**
4. **Technical Details**
5. **Testing & Validation**
6. **Next Steps**
## Markdownlint Configuration
### Required Rules
```json
{
"MD013": { "code_blocks": false },
"MD012": true,
"MD022": true,
"MD031": true,
"MD032": true,
"MD047": true,
"MD009": true
}
```
### Rule Explanations
- **MD013**: Line length (disabled for code blocks)
- **MD012**: No multiple consecutive blank lines
- **MD022**: Headings should be surrounded by blank lines
- **MD031**: Fenced code blocks should be surrounded by blank lines
- **MD032**: Lists should be surrounded by blank lines
- **MD047**: Files should end with a single newline
- **MD009**: No trailing spaces
## Validation Commands
### Check Single File
```bash
npx markdownlint docs/filename.md
```
### Check All Documentation
```bash
npx markdownlint docs/
```
### Auto-fix Common Issues
```bash
# Remove trailing spaces
sed -i 's/[[:space:]]*$//' docs/filename.md
# Remove multiple blank lines
sed -i '/^$/N;/^\n$/D' docs/filename.md
# Add newline at end if missing
echo "" >> docs/filename.md
```
## Common Patterns
### Implementation Plans
```markdown
## Implementation Plan
### Phase 1: Foundation (Day 1)
#### 1.1 Component Setup
- [ ] Create new component file
- [ ] Add basic structure
- [ ] Implement core functionality
#### 1.2 Configuration
- [ ] Update configuration files
- [ ] Add environment variables
- [ ] Test configuration loading
```
### Status Tracking
```markdown
**Status**: ✅ **COMPLETE** - All phases finished
**Progress**: 75% (15/20 components)
**Next**: Ready for testing phase
```
### Performance Metrics
```markdown
#### 📊 Performance Metrics
- **Build Time**: 2.3 seconds (50% faster than baseline)
- **Bundle Size**: 1.2MB (30% reduction)
- **Success Rate**: 100% (no failures in 50 builds)
```
## Enforcement
### Pre-commit Hooks
- Run markdownlint on all changed markdown files
- Block commits with linting violations
- Auto-fix common issues when possible
### CI/CD Integration
- Include markdownlint in build pipeline
- Generate reports for documentation quality
- Fail builds with critical violations
### Team Guidelines
- All documentation PRs must pass markdownlint
- Use provided templates for new documents
- Follow established patterns for consistency
## Templates
### New Document Template
```markdown
# Document Title
**Author**: Matthew Raymer
**Date**: YYYY-MM-DD
**Status**: 🎯 **PLANNING** - Ready for Implementation
## Overview
Brief description of the document's purpose and scope.
## Current State
Description of current situation or problem.
## Implementation Plan
### Phase 1: Foundation
- [ ] Task 1
- [ ] Task 2
## Next Steps
1. **Review and approve plan**
2. **Begin implementation**
3. **Test and validate**
---
**Status**: Ready for implementation
**Priority**: Medium
**Estimated Effort**: X days
**Dependencies**: None
**Stakeholders**: Development team
```
---
**Last Updated**: 2025-07-09
**Version**: 1.0
**Maintainer**: Matthew Raymer
### Heading Uniqueness
- **Rule**: No duplicate heading content at the same level
- **Scope**: Within a single document
- **Rationale**: Maintains clear document structure and navigation
- **Example**:
```markdown
## Features ✅
### Authentication
### Authorization
## Features ❌ (Duplicate heading)
### Security
### Performance
```

View File

@@ -1,76 +0,0 @@
# Investigation Report Example
## Investigation — Registration Dialog Test Flakiness
## Objective
Identify root cause of flaky tests related to registration dialogs in contact import scenarios.
## System Map
- User action → ContactInputForm → ContactsView.addContact() → handleRegistrationPrompt()
- setTimeout(1000ms) → Modal dialog → User response → Registration API call
- Test execution → Wait for dialog → Assert dialog content → Click response button
## Findings (Evidence)
- **1-second timeout causes flakiness** — evidence: `src/views/ContactsView.vue:971-1000`; setTimeout(..., 1000) in handleRegistrationPrompt()
- **Import flow bypasses dialogs** — evidence: `src/views/ContactImportView.vue:500-520`; importContacts() calls $insertContact() directly, no handleRegistrationPrompt()
- **Dialog only appears in direct add flow** — evidence: `src/views/ContactsView.vue:774-800`; addContact() calls handleRegistrationPrompt() after database insert
## Hypotheses & Failure Modes
- H1: 1-second timeout makes dialog appearance unpredictable; would fail when tests run faster than 1000ms
- H2: Test environment timing differs from development; watch for CI vs local test differences
## Corrections
- Updated: "Multiple dialogs interfere with imports" → "Import flow never triggers dialogs - they only appear in direct contact addition"
- Updated: "Complex batch registration needed" → "Simple timeout removal and test mode flag sufficient"
## Diagnostics (Next Checks)
- [ ] Repro on CI environment vs local
- [ ] Measure actual dialog appearance timing
- [ ] Test with setTimeout removed
- [ ] Verify import flow doesn't call handleRegistrationPrompt
## Risks & Scope
- Impacted: Contact addition tests, registration workflow tests; Data: None; Users: Test suite reliability
## Decision / Next Steps
- Owner: Development Team; By: 2025-01-28
- Action: Remove 1-second timeout + add test mode flag; Exit criteria: Tests pass consistently
## References
- `src/views/ContactsView.vue:971-1000`
- `src/views/ContactImportView.vue:500-520`
- `src/views/ContactsView.vue:774-800`
## Competence Hooks
- Why this works: Code path tracing revealed separate execution flows, evidence disproved initial assumptions
- Common pitfalls: Assuming related functionality without tracing execution paths, over-engineering solutions to imaginary problems
- Next skill: Learn to trace code execution before proposing architectural changes
- Teach-back: "What evidence shows that contact imports bypass registration dialogs?"
---
## Key Learning Points
### Evidence-First Approach
This investigation demonstrates the importance of:
1. **Tracing actual code execution** rather than making assumptions
2. **Citing specific evidence** with file:line references
3. **Validating problem scope** before proposing solutions
4. **Considering simpler alternatives** before complex architectural changes
### Code Path Tracing Value
By tracing the execution paths, we discovered:
- Import flow and direct add flow are completely separate
- The "multiple dialog interference" problem didn't exist
- A simple timeout removal would solve the actual issue
### Prevention of Over-Engineering
The investigation prevented:
- Unnecessary database schema changes
- Complex batch registration systems
- Migration scripts for non-existent problems
- Architectural changes based on assumptions
description:
globs:
alwaysApply: false
---

View File

@@ -1,170 +0,0 @@
---
description: Use this workflow when doing **pre-implementation research, defect investigations with uncertain repros, or clarifying system architecture and behaviors**.
alwaysApply: false
---
```json
{
"coaching_level": "light",
"socratic_max_questions": 2,
"verbosity": "concise",
"timebox_minutes": null,
"format_enforcement": "strict"
}
```
# Research & Diagnostic Workflow (R&D)
## Purpose
Provide a **repeatable, evidence-first** workflow to investigate features and
defects **before coding**. Outputs are concise reports, hypotheses, and next
steps—**not** code changes.
## When to Use
- Pre-implementation research for new features
- Defect investigations (repros uncertain, user-specific failures)
- Architecture/behavior clarifications (e.g., auth flows, merges, migrations)
---
## Enhanced with Software Development Ruleset
When investigating software issues, also apply:
- **Code Path Tracing**: Required for technical investigations
- **Evidence Validation**: Ensure claims are code-backed
- **Solution Complexity Assessment**: Justify architectural changes
---
## Output Contract (strict)
1) **Objective** — 12 lines
2) **System Map (if helpful)** — short diagram or bullet flow (≤8 bullets)
3) **Findings (Evidence-linked)** — bullets; each with file/function refs
4) **Hypotheses & Failure Modes** — short list, each testable
5) **Corrections** — explicit deltas from earlier assumptions (if any)
6) **Diagnostics** — what to check next (logs, DB, env, repro steps)
7) **Risks & Scope** — what could break; affected components
8) **Decision/Next Steps** — what we'll do, who's involved, by when
9) **References** — code paths, ADRs, docs
10) **Competence & Collaboration Hooks** — brief, skimmable
> Keep total length lean. Prefer links and bullets over prose.
---
## Quickstart Template
Copy/paste and fill:
```md
# Investigation — <short title>
## Objective
<one or two lines>
## System Map
- <module> → <function> → <downstream>
- <data path> → <db table> → <api>
## Findings (Evidence)
- <claim> — evidence: `src/path/file.ts:function` (lines XY); log snippet/trace id
- <claim> — evidence: `...`
## Hypotheses & Failure Modes
- H1: <hypothesis>; would fail when <condition>
- H2: <hypothesis>; watch for <signal>
## Corrections
- Updated: <old statement> → <new statement with evidence>
## Diagnostics (Next Checks)
- [ ] Repro on <platform/version>
- [ ] Inspect <table/store> for <record>
- [ ] Capture <log/trace>
## Risks & Scope
- Impacted: <areas/components>; Data: <tables/keys>; Users: <segments>
## Decision / Next Steps
- Owner: <name>; By: <date> (YYYY-MM-DD)
- Action: <spike/bugfix/ADR>; Exit criteria: <binary checks>
## References
- `src/...`
- ADR: `docs/adr/xxxx-yy-zz-something.md`
- Design: `docs/...`
## Competence Hooks
- Why this works: <≤3 bullets>
- Common pitfalls: <≤3 bullets>
- Next skill: <≤1 item>
- Teach-back: "<one question>"
```
---
## Evidence Quality Bar
- **Cite the source** (file:func, line range if possible).
- **Prefer primary evidence** (code, logs) over inference.
- **Disambiguate platform** (Web/Capacitor/Electron) and **state** (migration, auth).
- **Note uncertainty** explicitly.
---
## Code Path Tracing (Required for Software Investigations)
Before proposing solutions, trace the actual execution path:
- [ ] **Entry Points**: Identify where the flow begins (user action, API call, etc.)
- [ ] **Component Flow**: Map which components/methods are involved
- [ ] **Data Path**: Track how data moves through the system
- [ ] **Exit Points**: Confirm where the flow ends and what results
- [ ] **Evidence Collection**: Gather specific code citations for each step
---
## Collaboration Hooks
- **Syncs:** 1015m with QA/Security/Platform owners for high-risk areas.
- **ADR:** Record major decisions; link here.
- **Review:** Share repro + diagnostics checklist in PR/issue.
---
## Integration with Other Rulesets
### With software_development.mdc
- **Enhanced Evidence Validation**: Use code path tracing for technical investigations
- **Architecture Assessment**: Apply complexity justification to proposed solutions
- **Impact Analysis**: Assess effects on existing systems before recommendations
### With base_context.mdc
- **Competence Building**: Focus on technical investigation skills
- **Collaboration**: Structure outputs for team review and discussion
---
## Self-Check (model, before responding)
- [ ] Output matches the **Output Contract** sections.
- [ ] Each claim has **evidence** or **uncertainty** is flagged.
- [ ] Hypotheses are testable; diagnostics are actionable.
- [ ] Competence + collaboration hooks present (≤120 words total).
- [ ] Respect toggles; keep it concise.
- [ ] **Code path traced** (for software investigations).
- [ ] **Evidence validated** against actual code execution.
---
## Optional Globs (examples)
> Uncomment `globs` in the header if you want auto-attach behavior.
- `src/platforms/**`, `src/services/**` — attach during service/feature investigations
- `docs/adr/**` — attach when editing ADRs
## Referenced Files
- Consider including templates as context: `@adr_template.mdc`, `@investigation_report_example.mdc`

View File

@@ -1,178 +0,0 @@
---
alwaysApply: true
---
# Software Development Ruleset
## Purpose
Specialized guidelines for software development tasks including code review, debugging, architecture decisions, and testing.
## Core Principles
### 1. Evidence-First Development
- **Code Citations Required**: Always cite specific file:line references when making claims
- **Execution Path Tracing**: Trace actual code execution before proposing architectural changes
- **Assumption Validation**: Flag assumptions as "assumed" vs "evidence-based"
### 2. Code Review Standards
- **Trace Before Proposing**: Always trace execution paths before suggesting changes
- **Evidence Over Inference**: Prefer code citations over logical deductions
- **Scope Validation**: Confirm the actual scope of problems before proposing solutions
### 3. Problem-Solution Validation
- **Problem Scope**: Does the solution address the actual problem?
- **Evidence Alignment**: Does the solution match the evidence?
- **Complexity Justification**: Is added complexity justified by real needs?
- **Alternative Analysis**: What simpler solutions were considered?
## Required Workflows
### Before Proposing Changes
- [ ] **Code Path Tracing**: Map execution flow from entry to exit
- [ ] **Evidence Collection**: Gather specific code citations and logs
- [ ] **Assumption Surfacing**: Identify what's proven vs. inferred
- [ ] **Scope Validation**: Confirm the actual extent of the problem
### During Solution Design
- [ ] **Evidence Alignment**: Ensure solution addresses proven problems
- [ ] **Complexity Assessment**: Justify any added complexity
- [ ] **Alternative Evaluation**: Consider simpler approaches first
- [ ] **Impact Analysis**: Assess effects on existing systems
## Software-Specific Competence Hooks
### Evidence Validation
- **"What code path proves this claim?"**
- **"How does data actually flow through the system?"**
- **"What am I assuming vs. what can I prove?"**
### Code Tracing
- **"What's the execution path from user action to system response?"**
- **"Which components actually interact in this scenario?"**
- **"Where does the data originate and where does it end up?"**
### Architecture Decisions
- **"What evidence shows this change is necessary?"**
- **"What simpler solution could achieve the same goal?"**
- **"How does this change affect the existing system architecture?"**
## Integration with Other Rulesets
### With base_context.mdc
- Inherits generic competence principles
- Adds software-specific evidence requirements
- Maintains collaboration and learning focus
### With research_diagnostic.mdc
- Enhances investigation with code path tracing
- Adds evidence validation to diagnostic workflow
- Strengthens problem identification accuracy
## Usage Guidelines
### When to Use This Ruleset
- Code reviews and architectural decisions
- Bug investigation and debugging
- Performance optimization
- Feature implementation planning
- Testing strategy development
### When to Combine with Others
- **base_context + software_development**: General development tasks
- **research_diagnostic + software_development**: Technical investigations
- **All three**: Complex architectural decisions or major refactoring
## Self-Check (model, before responding)
- [ ] Code path traced and documented
- [ ] Evidence cited with specific file:line references
- [ ] Assumptions clearly flagged as proven vs. inferred
- [ ] Solution complexity justified by evidence
- [ ] Simpler alternatives considered and documented
- [ ] Impact on existing systems assessed
# Software Development Ruleset
## Purpose
Specialized guidelines for software development tasks including code review, debugging, architecture decisions, and testing.
## Core Principles
### 1. Evidence-First Development
- **Code Citations Required**: Always cite specific file:line references when making claims
- **Execution Path Tracing**: Trace actual code execution before proposing architectural changes
- **Assumption Validation**: Flag assumptions as "assumed" vs "evidence-based"
### 2. Code Review Standards
- **Trace Before Proposing**: Always trace execution paths before suggesting changes
- **Evidence Over Inference**: Prefer code citations over logical deductions
- **Scope Validation**: Confirm the actual scope of problems before proposing solutions
### 3. Problem-Solution Validation
- **Problem Scope**: Does the solution address the actual problem?
- **Evidence Alignment**: Does the solution match the evidence?
- **Complexity Justification**: Is added complexity justified by real needs?
- **Alternative Analysis**: What simpler solutions were considered?
## Required Workflows
### Before Proposing Changes
- [ ] **Code Path Tracing**: Map execution flow from entry to exit
- [ ] **Evidence Collection**: Gather specific code citations and logs
- [ ] **Assumption Surfacing**: Identify what's proven vs. inferred
- [ ] **Scope Validation**: Confirm the actual extent of the problem
### During Solution Design
- [ ] **Evidence Alignment**: Ensure solution addresses proven problems
- [ ] **Complexity Assessment**: Justify any added complexity
- [ ] **Alternative Evaluation**: Consider simpler approaches first
- [ ] **Impact Analysis**: Assess effects on existing systems
## Software-Specific Competence Hooks
### Evidence Validation
- **"What code path proves this claim?"**
- **"How does data actually flow through the system?"**
- **"What am I assuming vs. what can I prove?"**
### Code Tracing
- **"What's the execution path from user action to system response?"**
- **"Which components actually interact in this scenario?"**
- **"Where does the data originate and where does it end up?"**
### Architecture Decisions
- **"What evidence shows this change is necessary?"**
- **"What simpler solution could achieve the same goal?"**
- **"How does this change affect the existing system architecture?"**
## Integration with Other Rulesets
### With base_context.mdc
- Inherits generic competence principles
- Adds software-specific evidence requirements
- Maintains collaboration and learning focus
### With research_diagnostic.mdc
- Enhances investigation with code path tracing
- Adds evidence validation to diagnostic workflow
- Strengthens problem identification accuracy
## Usage Guidelines
### When to Use This Ruleset
- Code reviews and architectural decisions
- Bug investigation and debugging
- Performance optimization
- Feature implementation planning
- Testing strategy development
### When to Combine with Others
- **base_context + software_development**: General development tasks
- **research_diagnostic + software_development**: Technical investigations
- **All three**: Complex architectural decisions or major refactoring
## Self-Check (model, before responding)
- [ ] Code path traced and documented
- [ ] Evidence cited with specific file:line references
- [ ] Assumptions clearly flagged as proven vs. inferred
- [ ] Solution complexity justified by evidence
- [ ] Simpler alternatives considered and documented
- [ ] Impact on existing systems assessed

View File

@@ -1,96 +1,70 @@
---
description:
globs:
description:
globs:
alwaysApply: true
---
---
description:
globs:
alwaysApply: true
---
# Time Safari Context
## Project Overview
Time Safari is an application designed to foster community building through gifts,
gratitude, and collaborative projects. The app should make it extremely easy and
intuitive for users of any age and capability to recognize contributions, build
trust networks, and organize collective action. It is built on services that
preserve privacy and data sovereignty.
Time Safari is an application designed to foster community building through gifts, gratitude, and collaborative projects. The app should make it extremely easy and intuitive for users of any age and capability to recognize contributions, build trust networks, and organize collective action. It is built on services that preserve privacy and data sovereignty.
The ultimate goals of Time Safari are two-fold:
1. **Connect** Make it easy, rewarding, and non-threatening for people to
connect with others who have similar interests, and to initiate activities
together. This helps people accomplish and learn from other individuals in
less-structured environments; moreover, it helps them discover who they want
to continue to support and with whom they want to maintain relationships.
1. **Connect** Make it easy, rewarding, and non-threatening for people to connect with others who have similar interests, and to initiate activities together. This helps people accomplish and learn from other individuals in less-structured environments; moreover, it helps them discover who they want to continue to support and with whom they want to maintain relationships.
2. **Reveal** Widely advertise the great support and rewards that are being
given and accepted freely, especially non-monetary ones. Using visuals and text,
display the kind of impact that gifts are making in the lives of others. Also
show useful and engaging reports of project statistics and personal accomplishments.
2. **Reveal** Widely advertise the great support and rewards that are being given and accepted freely, especially non-monetary ones. Using visuals and text, display the kind of impact that gifts are making in the lives of others. Also show useful and engaging reports of project statistics and personal accomplishments.
## Core Approaches
Time Safari should help everyday users build meaningful connections and organize
collective efforts by:
Time Safari should help everyday users build meaningful connections and organize collective efforts by:
1. **Recognizing Contributions**: Creating permanent, verifiable records of gifts
and contributions people give to each other and their communities.
1. **Recognizing Contributions**: Creating permanent, verifiable records of gifts and contributions people give to each other and their communities.
2. **Facilitating Collaboration**: Making it ridiculously easy for people to ask
for or propose help on projects and interests that matter to them.
2. **Facilitating Collaboration**: Making it ridiculously easy for people to ask for or propose help on projects and interests that matter to them.
3. **Building Trust Networks**: Enabling users to maintain their network and activity
visibility. Developing reputation through verified contributions and references,
which can be selectively shown to others outside the network.
3. **Building Trust Networks**: Enabling users to maintain their network and activity visibility. Developing reputation through verified contributions and references, which can be selectively shown to others outside the network.
4. **Preserving Privacy**: Ensuring personal identifiers are only shared with
explicitly authorized contacts, allowing private individuals including children
to participate safely.
4. **Preserving Privacy**: Ensuring personal identifiers are only shared with explicitly authorized contacts, allowing private individuals including children to participate safely.
5. **Engaging Content**: Displaying people's records in compelling stories, and
highlighting those projects that are lifting people's lives long-term, both in
physical support and in emotional-spiritual-creative thriving.
5. **Engaging Content**: Displaying people's records in compelling stories, and highlighting those projects that are lifting people's lives long-term, both in physical support and in emotional-spiritual-creative thriving.
## Technical Foundation
This application is built on a privacy-preserving claims architecture (via
endorser.ch) with these key characteristics:
This application is built on a privacy-preserving claims architecture (via endorser.ch) with these key characteristics:
- **Decentralized Identifiers (DIDs)**: User identities are based on public/private
key pairs stored on their devices
- **Cryptographic Verification**: All claims and confirmations are
cryptographically signed
- **User-Controlled Visibility**: Users explicitly control who can see their
identifiers and data
- **Merkle-Chained Claims**: Claims are cryptographically chained for verification
and integrity
- **Native and Web App**: Works on Capacitor (iOS, Android), Desktop (Electron
and CEFPython), and web browsers
- **Decentralized Identifiers (DIDs)**: User identities are based on public/private key pairs stored on their devices
- **Cryptographic Verification**: All claims and confirmations are cryptographically signed
- **User-Controlled Visibility**: Users explicitly control who can see their identifiers and data
- **Merkle-Chained Claims**: Claims are cryptographically chained for verification and integrity
- **Native and Web App**: Works on Capacitor (iOS, Android), Desktop (Electron and CEFPython), and web browsers
## User Journey
The typical progression of usage follows these stages:
1. **Gratitude & Recognition**: Users begin by expressing and recording gratitude
for gifts received, building a foundation of acknowledgment.
1. **Gratitude & Recognition**: Users begin by expressing and recording gratitude for gifts received, building a foundation of acknowledgment.
2. **Project Proposals**: Users propose projects and ideas, reaching out to connect
with others who share similar interests.
2. **Project Proposals**: Users propose projects and ideas, reaching out to connect with others who share similar interests.
3. **Action Triggers**: Offers of help serve as triggers and motivations to execute
proposed projects, moving from ideas to action.
3. **Action Triggers**: Offers of help serve as triggers and motivations to execute proposed projects, moving from ideas to action.
## Context for LLM Development
When developing new functionality for Time Safari, consider these design principles:
1. **Accessibility First**: Features should be usable by non-technical users with
minimal learning curve.
1. **Accessibility First**: Features should be usable by non-technical users with minimal learning curve.
2. **Privacy by Design**: All features must respect user privacy and data sovereignty.
3. **Progressive Enhancement**: Core functionality should work across all devices,
with richer experiences where supported.
3. **Progressive Enhancement**: Core functionality should work across all devices, with richer experiences where supported.
4. **Voluntary Collaboration**: The system should enable but never coerce participation.
@@ -98,40 +72,31 @@ with richer experiences where supported.
6. **Network Effects**: Consider how features scale as more users join the platform.
7. **Low Resource Requirements**: The system should be lightweight enough to run
on inexpensive devices users already own.
7. **Low Resource Requirements**: The system should be lightweight enough to run on inexpensive devices users already own.
## Use Cases to Support
LLM development should focus on enhancing these key use cases:
1. **Community Building**: Tools that help people find others with shared
interests and values.
1. **Community Building**: Tools that help people find others with shared interests and values.
2. **Project Coordination**: Features that make it easy to propose collaborative
projects and to submit suggestions and offers to existing ones.
2. **Project Coordination**: Features that make it easy to propose collaborative projects and to submit suggestions and offers to existing ones.
3. **Reputation Building**: Methods for users to showcase their contributions
and reliability, in contexts where they explicitly reveal that information.
3. **Reputation Building**: Methods for users to showcase their contributions and reliability, in contexts where they explicitly reveal that information.
4. **Governance Experimentation**: Features that facilitate decision-making and
collective governance.
4. **Governance Experimentation**: Features that facilitate decision-making and collective governance.
## Constraints
When developing new features, be mindful of these constraints:
1. **Privacy Preservation**: User identifiers must remain private except when
explicitly shared.
1. **Privacy Preservation**: User identifiers must remain private except when explicitly shared.
2. **Platform Limitations**: Features must work within the constraints of the target
app platforms, while aiming to leverage the best platform technology available.
2. **Platform Limitations**: Features must work within the constraints of the target app platforms, while aiming to leverage the best platform technology available.
3. **Endorser API Limitations**: Backend features are constrained by the endorser.ch
API capabilities.
3. **Endorser API Limitations**: Backend features are constrained by the endorser.ch API capabilities.
4. **Performance on Low-End Devices**: The application should remain performant
on older/simpler devices.
4. **Performance on Low-End Devices**: The application should remain performant on older/simpler devices.
5. **Offline-First When Possible**: Key functionality should work offline when feasible.
@@ -151,14 +116,12 @@ on older/simpler devices.
## Project Architecture
- The application must work on web browser, PWA (Progressive Web Application),
desktop via Electron, and mobile via Capacitor
- The application must work on web browser, PWA (Progressive Web Application), desktop via Electron, and mobile via Capacitor
- Building for each platform is managed via Vite
## Core Development Principles
### DRY development
- **Code Reuse**
- Extract common functionality into utility functions
- Create reusable components for UI patterns
@@ -214,24 +177,14 @@ on older/simpler devices.
- Use shared test configurations
- Create reusable test helpers
- Implement consistent test patterns
- F.I.R.S.T. (for Unit Tests)
F Fast
I Independent
R Repeatable
S Self-validating
T Timely
### SOLID Principles
- **Single Responsibility**: Each class/component should have only one reason to
change
- **Single Responsibility**: Each class/component should have only one reason to change
- Components should focus on one specific feature (e.g., QR scanning, DID management)
- Services should handle one type of functionality (e.g., platform services,
crypto services)
- Services should handle one type of functionality (e.g., platform services, crypto services)
- Utilities should provide focused helper functions
- **Open/Closed**: Software entities should be open for extension but closed for
modification
- **Open/Closed**: Software entities should be open for extension but closed for modification
- Use interfaces for service definitions
- Implement plugin architecture for platform-specific features
- Allow component behavior extension through props and events
@@ -252,7 +205,6 @@ on older/simpler devices.
- Implement factory patterns for component creation
### Law of Demeter
- Components should only communicate with immediate dependencies
- Avoid chaining method calls (e.g., `this.service.getUser().getProfile().getName()`)
- Use mediator patterns for complex component interactions
@@ -260,7 +212,6 @@ on older/simpler devices.
- Keep component communication through defined events and props
### Composition over Inheritance
- Prefer building components through composition
- Use mixins for shared functionality
- Implement feature toggles through props
@@ -268,7 +219,6 @@ on older/simpler devices.
- Use service composition for complex features
### Interface Segregation
- Define clear interfaces for services
- Keep component APIs minimal and focused
- Split large interfaces into smaller, specific ones
@@ -276,7 +226,6 @@ on older/simpler devices.
- Implement role-based interfaces for different use cases
### Fail Fast
- Validate inputs early in the process
- Use TypeScript strict mode
- Implement comprehensive error handling
@@ -284,7 +233,6 @@ on older/simpler devices.
- Use assertions for development-time validation
### Principle of Least Astonishment
- Follow Vue.js conventions consistently
- Use familiar naming patterns
- Implement predictable component behaviors
@@ -292,7 +240,6 @@ on older/simpler devices.
- Keep UI interactions intuitive
### Information Hiding
- Encapsulate implementation details
- Use private class members
- Implement proper access modifiers
@@ -300,7 +247,6 @@ on older/simpler devices.
- Use TypeScript's access modifiers effectively
### Single Source of Truth
- Use Pinia for state management
- Maintain one source for user data
- Centralize configuration management
@@ -308,9 +254,23 @@ on older/simpler devices.
- Implement proper state synchronization
### Principle of Least Privilege
- Implement proper access control
- Use minimal required permissions
- Follow privacy-by-design principles
- Restrict component access to necessary data
- Implement proper authentication/authorization
### Continuous Integration/Continuous Deployment (CI/CD)
- Automated testing on every commit
- Consistent build process across platforms
- Automated deployment pipelines
- Quality gates for code merging
- Environment-specific configurations
This expanded documentation provides:
1. Clear principles for development
2. Practical implementation guidelines
3. Real-world examples
4. TypeScript integration
5. Best practices for Time Safari

267
.cursor/rules/wa-sqlite.mdc Normal file
View File

@@ -0,0 +1,267 @@
---
description:
globs:
alwaysApply: true
---
# wa-sqlite Usage Guide
## Table of Contents
- [1. Overview](#1-overview)
- [2. Installation](#2-installation)
- [3. Basic Setup](#3-basic-setup)
- [3.1 Import and Initialize](#31-import-and-initialize)
- [3.2 Basic Database Operations](#32-basic-database-operations)
- [4. Virtual File Systems (VFS)](#4-virtual-file-systems-vfs)
- [4.1 Available VFS Options](#41-available-vfs-options)
- [4.2 Using a VFS](#42-using-a-vfs)
- [5. Best Practices](#5-best-practices)
- [5.1 Error Handling](#51-error-handling)
- [5.2 Transaction Management](#52-transaction-management)
- [5.3 Prepared Statements](#53-prepared-statements)
- [6. Performance Considerations](#6-performance-considerations)
- [7. Common Issues and Solutions](#7-common-issues-and-solutions)
- [8. TypeScript Support](#8-typescript-support)
## 1. Overview
wa-sqlite is a WebAssembly build of SQLite that enables SQLite database operations in web browsers and JavaScript environments. It provides both synchronous and asynchronous builds, with support for custom virtual file systems (VFS) for persistent storage.
## 2. Installation
```bash
npm install wa-sqlite
# or
yarn add wa-sqlite
```
## 3. Basic Setup
### 3.1 Import and Initialize
```javascript
// Choose one of these imports based on your needs:
// - wa-sqlite.mjs: Synchronous build
// - wa-sqlite-async.mjs: Asynchronous build (required for async VFS)
// - wa-sqlite-jspi.mjs: JSPI-based async build (experimental, Chromium only)
import SQLiteESMFactory from 'wa-sqlite/dist/wa-sqlite.mjs';
import * as SQLite from 'wa-sqlite';
async function initDatabase() {
// Initialize SQLite module
const module = await SQLiteESMFactory();
const sqlite3 = SQLite.Factory(module);
// Open database (returns a Promise)
const db = await sqlite3.open_v2('myDatabase');
return { sqlite3, db };
}
```
### 3.2 Basic Database Operations
```javascript
async function basicOperations() {
const { sqlite3, db } = await initDatabase();
try {
// Create a table
await sqlite3.exec(db, `
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE
)
`);
// Insert data
await sqlite3.exec(db, `
INSERT INTO users (name, email)
VALUES ('John Doe', 'john@example.com')
`);
// Query data
const results = [];
await sqlite3.exec(db, 'SELECT * FROM users', (row, columns) => {
results.push({ row, columns });
});
return results;
} finally {
// Always close the database when done
await sqlite3.close(db);
}
}
```
## 4. Virtual File Systems (VFS)
### 4.1 Available VFS Options
wa-sqlite provides several VFS implementations for persistent storage:
1. **IDBBatchAtomicVFS** (Recommended for general use)
- Uses IndexedDB with batch atomic writes
- Works in all contexts (Window, Worker, Service Worker)
- Supports WAL mode
- Best performance with `PRAGMA synchronous=normal`
2. **IDBMirrorVFS**
- Keeps files in memory, persists to IndexedDB
- Works in all contexts
- Good for smaller databases
3. **OPFS-based VFS** (Origin Private File System)
- Various implementations available:
- AccessHandlePoolVFS
- OPFSAdaptiveVFS
- OPFSCoopSyncVFS
- OPFSPermutedVFS
- Better performance but limited to Worker contexts
### 4.2 Using a VFS
```javascript
import { IDBBatchAtomicVFS } from 'wa-sqlite/src/examples/IDBBatchAtomicVFS.js';
import SQLiteESMFactory from 'wa-sqlite/dist/wa-sqlite-async.mjs';
import * as SQLite from 'wa-sqlite';
async function initDatabaseWithVFS() {
const module = await SQLiteESMFactory();
const sqlite3 = SQLite.Factory(module);
// Register VFS
const vfs = await IDBBatchAtomicVFS.create('myApp', module);
sqlite3.vfs_register(vfs, true);
// Open database with VFS
const db = await sqlite3.open_v2('myDatabase');
// Configure for better performance
await sqlite3.exec(db, 'PRAGMA synchronous = normal');
await sqlite3.exec(db, 'PRAGMA journal_mode = WAL');
return { sqlite3, db };
}
```
## 5. Best Practices
### 5.1 Error Handling
```javascript
async function safeDatabaseOperation() {
const { sqlite3, db } = await initDatabase();
try {
await sqlite3.exec(db, 'SELECT * FROM non_existent_table');
} catch (error) {
if (error.code === SQLite.SQLITE_ERROR) {
console.error('SQL error:', error.message);
} else {
console.error('Database error:', error);
}
} finally {
await sqlite3.close(db);
}
}
```
### 5.2 Transaction Management
```javascript
async function transactionExample() {
const { sqlite3, db } = await initDatabase();
try {
await sqlite3.exec(db, 'BEGIN TRANSACTION');
// Perform multiple operations
await sqlite3.exec(db, 'INSERT INTO users (name) VALUES (?)', ['Alice']);
await sqlite3.exec(db, 'INSERT INTO users (name) VALUES (?)', ['Bob']);
await sqlite3.exec(db, 'COMMIT');
} catch (error) {
await sqlite3.exec(db, 'ROLLBACK');
throw error;
} finally {
await sqlite3.close(db);
}
}
```
### 5.3 Prepared Statements
```javascript
async function preparedStatementExample() {
const { sqlite3, db } = await initDatabase();
try {
// Prepare statement
const stmt = await sqlite3.prepare(db, 'SELECT * FROM users WHERE id = ?');
// Execute with different parameters
await sqlite3.bind(stmt, 1, 1);
while (await sqlite3.step(stmt) === SQLite.SQLITE_ROW) {
const row = sqlite3.row(stmt);
console.log(row);
}
// Reset and reuse
await sqlite3.reset(stmt);
await sqlite3.bind(stmt, 1, 2);
// ... execute again
await sqlite3.finalize(stmt);
} finally {
await sqlite3.close(db);
}
}
```
## 6. Performance Considerations
1. **VFS Selection**
- Use IDBBatchAtomicVFS for general-purpose applications
- Consider OPFS-based VFS for better performance in Worker contexts
- Use MemoryVFS for temporary databases
2. **Configuration**
- Set appropriate page size (default is usually fine)
- Use WAL mode for better concurrency
- Consider `PRAGMA synchronous=normal` for better performance
- Adjust cache size based on your needs
3. **Concurrency**
- Use transactions for multiple operations
- Be aware of VFS-specific concurrency limitations
- Consider using Web Workers for heavy database operations
## 7. Common Issues and Solutions
1. **Database Locking**
- Use appropriate transaction isolation levels
- Implement retry logic for busy errors
- Consider using WAL mode
2. **Storage Limitations**
- Be aware of browser storage quotas
- Implement cleanup strategies
- Monitor database size
3. **Cross-Context Access**
- Use appropriate VFS for your context
- Consider message passing for cross-context communication
- Be aware of storage access limitations
## 8. TypeScript Support
wa-sqlite includes TypeScript definitions. The main types are:
```typescript
type SQLiteCompatibleType = number | string | Uint8Array | Array<number> | bigint | null;
interface SQLiteAPI {
open_v2(filename: string, flags?: number, zVfs?: string): Promise<number>;
exec(db: number, sql: string, callback?: (row: any[], columns: string[]) => void): Promise<number>;
close(db: number): Promise<number>;
// ... other methods
}
```
## Additional Resources
- [Official GitHub Repository](https://github.com/rhashimoto/wa-sqlite)
- [Online Demo](https://rhashimoto.github.io/wa-sqlite/demo/)
- [API Reference](https://rhashimoto.github.io/wa-sqlite/docs/)
- [FAQ](https://github.com/rhashimoto/wa-sqlite/issues?q=is%3Aissue+label%3Afaq+)
- [Discussion Forums](https://github.com/rhashimoto/wa-sqlite/discussions)

View File

@@ -1,122 +0,0 @@
---
alwaysApply: true
---
# Directive: Peaceful Co-Existence with Developers
## 1) Version-Control Ownership
* **MUST NOT** run `git add`, `git commit`, or any write action.
* **MUST** leave staging/committing to the developer.
## 2) Source of Truth for Commit Text
* **MUST** derive messages **only** from:
* files **staged** for commit (primary), and
* files **awaiting staging** (context).
* **MUST** use the **diffs** to inform content.
* **MUST NOT** invent changes or imply work not present in diffs.
## 3) Mandatory Preview Flow
* **ALWAYS** present, before any real commit:
* file list + brief per-file notes,
* a **draft commit message** (copy-paste ready),
* nothing auto-applied.
---
# Commit Message Format (Normative)
## A. Subject Line (required)
```
<type>(<scope>)<!>: <summary>
```
* **type** (lowercase, Conventional Commits): `feat|fix|refactor|perf|docs|test|build|chore|ci|revert`
* **scope**: optional module/package/area (e.g., `api`, `ui/login`, `db`)
* **!**: include when a breaking change is introduced
* **summary**: imperative mood, ≤ 72 chars, no trailing period
**Examples**
* `fix(api): handle null token in refresh path`
* `feat(ui/login)!: require OTP after 3 failed attempts`
## B. Body (optional, when it adds non-obvious value)
* One blank line after subject.
* Wrap at \~72 chars.
* Explain **what** and **why**, not line-by-line “how”.
* Include brief notes like tests passing or TS/lint issues resolved **only if material**.
**Body checklist**
* [ ] Problem/symptom being addressed
* [ ] High-level approach or rationale
* [ ] Risks, tradeoffs, or follow-ups (if any)
## C. Footer (optional)
* Issue refs: `Closes #123`, `Refs #456`
* Breaking change (alternative to `!`):
`BREAKING CHANGE: <impact + migration note>`
* Authors: `Co-authored-by: Name <email>`
* Security: `CVE-XXXX-YYYY: <short note>` (if applicable)
---
## Content Guidance
### Include (when relevant)
* Specific fixes/features delivered
* Symptoms/problems fixed
* Brief note that tests passed or TS/lint errors resolved
### Avoid
* Vague: *improved, enhanced, better*
* Trivialities: tiny docs, one-liners, pure lint cleanups (separate, focused commits if needed)
* Redundancy: generic blurbs repeated across files
* Multi-purpose dumps: keep commits **narrow and focused**
* Long explanations that good inline code comments already cover
**Guiding Principle:** Let code and inline docs speak. Use commits to highlight what isnt obvious.
---
# Copy-Paste Templates
## Minimal (no body)
```text
<type>(<scope>): <summary>
```
## Standard (with body & footer)
```text
<type>(<scope>)<!>: <summary>
<why-this-change?>
<what-it-does?>
<risks-or-follow-ups?>
Closes #<id>
BREAKING CHANGE: <impact + migration>
Co-authored-by: <Name> <email>
```
---
# Assistant Output Checklist (before showing the draft)
* [ ] List changed files + 12 line notes per file
* [ ] Provide **one** focused draft message (subject/body/footer)
* [ ] Subject ≤ 72 chars, imperative mood, correct `type(scope)!` syntax
* [ ] Body only if it adds non-obvious value
* [ ] No invented changes; aligns strictly with diffs
* [ ] Render as a single copy-paste block for the developer

View File

@@ -1,171 +0,0 @@
# TimeSafari Docker Ignore File
# Author: Matthew Raymer
# Description: Excludes unnecessary files from Docker build context
#
# Benefits:
# - Faster build times
# - Smaller build context
# - Reduced image size
# - Better security (excludes sensitive files)
# Dependencies
node_modules
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Build outputs
# dist - Allow dist directory for Docker builds (contains pre-built assets)
dist-*
build
*.tsbuildinfo
# Development files
.git
.gitignore
README.md
CHANGELOG.md
CONTRIBUTING.md
BUILDING.md
LICENSE
# IDE and editor files
.vscode
.idea
*.swp
*.swo
*~
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Dependency directories
jspm_packages/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# Test files
test-playwright
test-playwright-results
test-results
test-scripts
# Documentation
doc
# Scripts (keep only what's needed for build)
scripts/test-*.sh
scripts/*.js
scripts/README.md
# Platform-specific files
android
ios
electron
# Docker files (avoid recursive copying)
Dockerfile*
docker-compose*
.dockerignore
# CI/CD files
.github
.gitlab-ci.yml
.travis.yml
.circleci
# Temporary files
tmp
temp
# Backup files
*.bak
*.backup
# Archive files
*.tar
*.tar.gz
*.zip
*.rar
# Certificate files
*.pem
*.key
*.crt
*.p12
# Configuration files that might contain secrets
*.secrets
secrets.json
config.local.json

View File

@@ -1,14 +1,9 @@
# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue.
# Logging Configuration - Development environment gets maximum visibility
VITE_LOG_LEVEL=debug
# iOS doesn't like spaces in the app title.
TIME_SAFARI_APP_TITLE="TimeSafari_Dev"
VITE_APP_SERVER=http://localhost:8080
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not
VITE_APP_SERVER=http://localhost:3000
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production).
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000
# Using shared server by default to ease setup, which works for shared test users.

View File

@@ -1,7 +1,6 @@
# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue.
# Logging Configuration - Production environment gets minimal logging for performance
VITE_LOG_LEVEL=warn
VITE_APP_SERVER=https://timesafari.app
# This is the claim ID for actions in the BVC project.

View File

@@ -1,14 +1,9 @@
# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue.
# Logging Configuration - Test environment gets balanced logging for debugging
VITE_LOG_LEVEL=info
# iOS doesn't like spaces in the app title.
TIME_SAFARI_APP_TITLE="TimeSafari_Test"
VITE_APP_SERVER=https://test.timesafari.app
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not
production).
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production).
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch

View File

@@ -30,7 +30,7 @@ module.exports = {
}],
"no-console": process.env.NODE_ENV === "production" ? "error" : "warn",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "warn",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-unnecessary-type-constraint": "off",
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]

View File

@@ -1,142 +0,0 @@
name: Asset Validation & CI Safeguards
on:
pull_request:
paths:
- 'resources/**'
- 'config/assets/**'
- 'capacitor-assets.config.json'
- 'capacitor.config.ts'
- 'capacitor.config.json'
push:
branches: [main, develop]
paths:
- 'resources/**'
- 'config/assets/**'
- 'capacitor-assets.config.json'
- 'capacitor.config.ts'
- 'capacitor.config.json'
jobs:
asset-validation:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Validate asset configuration
run: npm run assets:validate
- name: Check for committed platform assets (Android)
run: |
if git ls-files -z android/app/src/main/res | grep -E '(AppIcon.*\.png|Splash.*\.png|mipmap-.*/ic_launcher.*\.png)' > /dev/null; then
echo "❌ Android platform assets found in VCS - these should be generated at build-time"
git ls-files -z android/app/src/main/res | grep -E '(AppIcon.*\.png|Splash.*\.png|mipmap-.*/ic_launcher.*\.png)'
exit 1
fi
echo "✅ No Android platform assets committed"
- name: Check for committed platform assets (iOS)
run: |
if git ls-files -z ios/App/App/Assets.xcassets | grep -E '(AppIcon.*\.png|Splash.*\.png)' > /dev/null; then
echo "❌ iOS platform assets found in VCS - these should be generated at build-time"
git ls-files -z ios/App/App/Assets.xcassets | grep -E '(AppIcon.*\.png|Splash.*\.png)'
exit 1
fi
echo "✅ No iOS platform assets committed"
- name: Test asset generation
run: |
echo "🧪 Testing asset generation workflow..."
npm run build:capacitor
npx cap sync
npx capacitor-assets generate --dry-run || npx capacitor-assets generate
echo "✅ Asset generation test completed"
- name: Verify clean tree after build
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "❌ Dirty tree after build - asset configs were modified"
git status
git diff
exit 1
fi
echo "✅ Build completed with clean tree"
schema-validation:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Validate schema compliance
run: |
echo "🔍 Validating schema compliance..."
node -e "
const fs = require('fs');
const config = JSON.parse(fs.readFileSync('capacitor-assets.config.json', 'utf8'));
const schema = JSON.parse(fs.readFileSync('config/assets/schema.json', 'utf8'));
// Basic schema validation
if (!config.icon || !config.splash) {
throw new Error('Missing required sections: icon and splash');
}
if (!config.icon.source || !config.splash.source) {
throw new Error('Missing required source fields');
}
if (!/^resources\/.*\.(png|svg)$/.test(config.icon.source)) {
throw new Error('Icon source must be in resources/ directory');
}
if (!/^resources\/.*\.(png|svg)$/.test(config.splash.source)) {
throw new Error('Splash source must be in resources/ directory');
}
console.log('✅ Schema validation passed');
"
- name: Check source file existence
run: |
echo "📁 Checking source file existence..."
node -e "
const fs = require('fs');
const config = JSON.parse(fs.readFileSync('capacitor-assets.config.json', 'utf8'));
const requiredFiles = [
config.icon.source,
config.splash.source
];
if (config.splash.darkSource) {
requiredFiles.push(config.splash.darkSource);
}
const missingFiles = requiredFiles.filter(file => !fs.existsSync(file));
if (missingFiles.length > 0) {
console.error('❌ Missing source files:', missingFiles);
process.exit(1);
}
console.log('✅ All source files exist');
"

91
.gitignore vendored
View File

@@ -51,93 +51,6 @@ vendor/
# Build logs
build_logs/
# PWA icon files generated by capacitor-assets
icons
android/app/src/main/assets/public
android/app/src/main/res
*.log
# Build outputs
dist/
build/
# Generated Android assets and resources (should be generated during build)
android/app/src/main/assets/public/
# Generated Android resources (icons, splash screens, etc.)
android/app/src/main/res/drawable*/
android/app/src/main/res/mipmap*/
android/app/src/main/res/values/ic_launcher_background.xml
# Android generated assets (deny-listed in CI)
android/app/src/main/res/mipmap-*/ic_launcher*.png
android/app/src/main/res/drawable*/splash*.png
# iOS generated assets (deny-listed in CI)
ios/App/App/Assets.xcassets/**/AppIcon*.png
ios/App/App/Assets.xcassets/**/Splash*.png
# Keep these Android configuration files in version control:
# - android/app/src/main/assets/capacitor.plugins.json
# - android/app/src/main/res/values/strings.xml
# - android/app/src/main/res/values/styles.xml
# - android/app/src/main/res/layout/activity_main.xml
# - android/app/src/main/res/xml/config.xml
# - android/app/src/main/res/xml/file_paths.xml
sql-wasm.wasm
# Temporary and generated files
temp.*
*.tmp
*.temp
*.bak
*.cache
git.diff.*
*.har
# Development artifacts
dev-dist/
*.map
# OS generated files
Thumbs.db
ehthumbs.db
Desktop.ini
# Capacitor build outputs and generated files
android/app/build/
android/capacitor-cordova-android-plugins/build/
ios/App/App/public/assets/
ios/App/App/build/
ios/App/build/
# Capacitor build artifacts (covered by android/app/build/ above)
# Keep these Capacitor files in version control:
# - capacitor.config.json (root, electron, ios)
# - src/main.capacitor.ts
# - vite.config.capacitor.mts
# - android/capacitor.settings.gradle
# - android/app/capacitor.build.gradle
# - android/app/src/main/assets/capacitor.plugins.json
# Electron build outputs and generated files
electron/build/
electron/app/
electron/dist/
electron/out/
# Keep these Electron files in version control:
# - electron/src/preload.ts (source)
# - electron/src/index.ts (source)
# - electron/src/setup.ts (source)
# - electron/package.json
# - electron/electron-builder.config.json
# - electron/build-packages.sh
# - electron/live-runner.js
# - electron/resources/electron-publisher-custom.js
# Gradle cache files
android/.gradle/file-system.probe
android/.gradle/caches/
coverage

View File

@@ -1 +0,0 @@
{"MD013": {"code_blocks": false}}

View File

@@ -1 +0,0 @@
18.19.0

1
.npmrc
View File

@@ -1 +0,0 @@
@jsr:registry=https://npm.jsr.io

1
.nvmrc
View File

@@ -1 +0,0 @@
18.19.0

File diff suppressed because it is too large Load Diff

View File

@@ -5,64 +5,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.3] - 2025.07.12
### Changed
- Photo is pinned to profile mode
### Fixed
- Deep link URLs (and other prod settings)
- Error in BVC begin view
## [1.0.6] - 2025.08.09
### Fixed
- Deep link errors where none would validate
## [1.0.5] - 2025.07.24
### Fixed
- Export & import of contacts corrupted contact methods
## [1.0.4] - 2025.07.20 - 002f2407208d56cc59c0aa7c880535ae4cbace8b
### Fixed
- Deep link for invite-one-accept
## [1.0.3] - 2025.07.12 - a9a8ba217cd6015321911e98e6843e988dc2c4ae
### Changed
- Photo is pinned to profile mode
### Fixed
- Deep link URLs (and other prod settings)
- Error in BVC begin view
## [1.0.2] - 2025.06.20 - 276e0a741bc327de3380c4e508cccb7fee58c06d
### Added
- Version on feed title
## [1.0.1] - 2025.06.20
### Added
- Allow a user to block someone else's content from view
## [1.0.0] - 2025.06.20 - 5aa693de6337e5dbb278bfddc6bd39094bc14f73
### Added
- Web-oriented migration from IndexedDB to SQLite
## [0.5.8]
### Added
- /deep-link/ path for URLs that are shared with people
### Changed
- External links now go to /deep-link/...
- Feed visuals now have arrow imagery from giver to receiver
## [0.4.7]
### Fixed
- Cameras everywhere
### Changed
- IndexedDB -> SQLite
## [0.4.5] - 2025.02.23

View File

@@ -1,170 +1,36 @@
# TimeSafari Docker Build
# Author: Matthew Raymer
# Description: Multi-stage Docker build for TimeSafari web application
#
# Build Process:
# 1. Base stage: Node.js with build dependencies
# 2. Builder stage: Copy pre-built web assets from host
# 3. Production stage: Nginx server with optimized assets
#
# Note: Web assets are built on the host using npm scripts before Docker build
#
# Security Features:
# - Non-root user execution
# - Minimal attack surface with Alpine Linux
# - Multi-stage build to reduce image size
# - No build dependencies in final image
#
# Usage:
# IMPORTANT: Build web assets first, then build Docker image
#
# Using npm scripts (recommended):
# Production: npm run build:web:docker:prod
# Test: npm run build:web:docker:test
# Development: npm run build:web:docker
#
# Manual workflow:
# 1. Build web assets: npm run build:web:build -- --mode production
# 2. Build Docker: docker build -t timesafari:latest .
#
# Note: For development, use npm run build:web directly (no Docker needed)
#
# Build Arguments:
# BUILD_MODE: development, test, or production (default: production)
# NODE_ENV: node environment (default: production)
#
# Environment Variables:
# NODE_ENV: Build environment (development/production)
# BUILD_MODE: Build mode for asset selection (development/test/production)
#
# Build Context:
# This Dockerfile is designed to work when the build context is set to
# ./crowd-funder-for-time-pwa from the parent directory (where docker-compose.yml is located)
# Build stage
FROM node:22-alpine3.20 AS builder
# =============================================================================
# BASE STAGE - Common dependencies and setup
# =============================================================================
FROM node:22-alpine3.20 AS base
# Install build dependencies
# Install system dependencies for build process
RUN apk add --no-cache \
bash \
git \
python3 \
py3-pip \
py3-setuptools \
make \
g++ \
gcc \
&& rm -rf /var/cache/apk/*
# Create non-root user for security
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
RUN apk add --no-cache bash git python3 py3-pip py3-setuptools make g++ gcc
# Set working directory
WORKDIR /app
# Copy package files for dependency installation
# Note: These files are in the project root (crowd-funder-for-time-pwa directory)
# Copy package files
COPY package*.json ./
# Install dependencies with security audit
RUN npm ci --only=production --audit --fund=false && \
npm audit fix --audit-level=moderate || true
# Install dependencies
RUN npm ci
# =============================================================================
# BUILDER STAGE - Copy pre-built assets
# =============================================================================
FROM base AS builder
# Copy source code
COPY . .
# Define build arguments with defaults
ARG BUILD_MODE=production
ARG NODE_ENV=production
# Build the application
RUN npm run build:web
# Set environment variables from build arguments
ENV BUILD_MODE=${BUILD_MODE}
ENV NODE_ENV=${NODE_ENV}
# Copy pre-built assets from host
# Note: dist/ directory is in the project root (crowd-funder-for-time-pwa directory)
COPY dist/ ./dist/
# Verify build output exists
RUN ls -la dist/ || (echo "Build output not found in dist/ directory" && exit 1)
# =============================================================================
# PRODUCTION STAGE - Nginx server
# =============================================================================
FROM nginx:alpine AS production
# Define build arguments for production stage
ARG BUILD_MODE=production
ARG NODE_ENV=production
# Set environment variables
ENV BUILD_MODE=${BUILD_MODE}
ENV NODE_ENV=${NODE_ENV}
# Install security updates and clean cache
RUN apk update && \
apk upgrade && \
apk add --no-cache \
curl \
&& rm -rf /var/cache/apk/*
# Use existing nginx user from base image (nginx user and group already exist)
# No need to create new user as nginx:alpine already has nginx user
# Copy main nginx configuration
COPY docker/nginx.conf /etc/nginx/nginx.conf
# Copy production nginx configuration
COPY docker/default.conf /etc/nginx/conf.d/default.conf
# Production stage
FROM nginx:alpine
# Copy built assets from builder stage
COPY --from=builder --chown=nginx:nginx /app/dist /usr/share/nginx/html
COPY --from=builder /app/dist /usr/share/nginx/html
# Create necessary directories with proper permissions
RUN mkdir -p /var/cache/nginx /var/log/nginx /tmp && \
chown -R nginx:nginx /var/cache/nginx /var/log/nginx /tmp && \
chown -R nginx:nginx /usr/share/nginx/html
# Switch to non-root user
USER nginx
# Copy nginx configuration if needed
# COPY nginx.conf /etc/nginx/conf.d/default.conf
# Expose port 80
EXPOSE 80
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# Start nginx with proper signal handling
CMD ["nginx", "-g", "daemon off;"]
# =============================================================================
# TEST STAGE - For test environment testing
# =============================================================================
FROM production AS test
# Define build arguments for test stage
ARG BUILD_MODE=test
ARG NODE_ENV=test
# Set environment variables
ENV BUILD_MODE=${BUILD_MODE}
ENV NODE_ENV=${NODE_ENV}
# Copy test-specific nginx configuration
COPY docker/staging.conf /etc/nginx/conf.d/default.conf
# Expose port 80
EXPOSE 80
# Health check for staging
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/health || exit 1
# Start nginx
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -1,4 +1,5 @@
source "https://rubygems.org"
gem "fastlane"
gem "cocoapods"

View File

@@ -22,7 +22,26 @@ GEM
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.3.2)
aws-partitions (1.1066.0)
aws-sdk-core (3.220.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
base64
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.99.0)
aws-sdk-core (~> 3, >= 3.216.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.182.0)
aws-sdk-core (~> 3, >= 3.216.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.11.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.9)
@@ -64,13 +83,96 @@ GEM
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
declarative (0.0.20)
digest-crc (0.7.0)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.6.20240107)
dotenv (2.8.1)
drb (2.2.1)
emoji_regex (3.2.3)
escape (0.0.4)
ethon (0.16.0)
ffi (>= 1.15.0)
excon (0.112.0)
faraday (1.10.4)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.1.0)
multipart-post (~> 2.0)
faraday-net_http (1.0.2)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.1)
faraday (~> 1.0)
fastimage (2.4.0)
fastlane (2.227.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored (~> 1.2)
commander (~> 4.6)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
fastlane-sirp (>= 1.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-env (>= 1.6.0, < 2.0.0)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
naturally (~> 2.2)
optparse (>= 0.1.1, < 1.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.5)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (~> 3)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.4.0)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
fastlane-sirp (1.0.0)
sysrandom (~> 1.0)
ffi (1.17.1)
ffi (1.17.1-aarch64-linux-gnu)
ffi (1.17.1-aarch64-linux-musl)
@@ -85,27 +187,107 @@ GEM
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.54.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.3)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
rexml
google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.31.0)
google-apis-core (>= 0.11.0, < 2.a)
google-cloud-core (1.8.0)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.5.0)
google-cloud-storage (1.47.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.31.0)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.8.1)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-cookie (1.0.8)
domain_name (~> 0.5)
httpclient (2.9.0)
mutex_m
i18n (1.14.7)
concurrent-ruby (~> 1.0)
jmespath (1.6.2)
json (2.10.2)
jwt (2.10.1)
base64
logger (1.6.6)
mini_magick (4.13.2)
mini_mime (1.1.5)
minitest (5.25.5)
molinillo (0.8.0)
multi_json (1.15.0)
multipart-post (2.4.1)
mutex_m (0.3.0)
nanaimo (0.4.0)
nap (1.1.0)
naturally (2.2.1)
netrc (0.11.0)
nkf (0.2.0)
optparse (0.6.0)
os (1.1.4)
plist (3.7.2)
public_suffix (4.0.7)
rake (13.2.1)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.4.1)
rouge (3.28.0)
ruby-macho (2.5.1)
ruby2_keywords (0.0.5)
rubyzip (2.4.1)
securerandom (0.4.1)
security (0.1.5)
signet (0.19.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.10)
CFPropertyList
naturally
sysrandom (1.0.5)
terminal-notifier (2.0.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.2)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
typhoeus (1.4.1)
ethon (>= 0.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uber (0.1.0)
unicode-display_width (2.6.0)
word_wrap (1.0.0)
xcodeproj (1.27.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
@@ -113,6 +295,10 @@ GEM
colored2 (~> 3.1)
nanaimo (~> 0.4.0)
rexml (>= 3.3.6, < 4.0)
xcpretty (0.4.0)
rouge (~> 3.28.0)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
aarch64-linux-gnu
@@ -129,6 +315,7 @@ PLATFORMS
DEPENDENCIES
cocoapods
fastlane
BUNDLED WITH
2.6.5

177
README.md
View File

@@ -5,7 +5,8 @@ and expand to crowd-fund with time & money, then record and see the impact of co
## Roadmap
See [ClickUp](https://sharing.clickup.com/9014278710/l/h/8cmnyhp-174/10573fec74e2ba0) for current priorities.
See [project.task.yaml](project.task.yaml) for current priorities.
(Numbers at the beginning of lines are estimated hours. See [taskyaml.org](https://taskyaml.org/) for details.)
## Setup & Building
@@ -15,171 +16,26 @@ Quick start:
```bash
npm install
npm run build:web:serve -- --test
npm run dev
```
To be able to make submissions: go to "profile" (bottom left), go to the bottom and expand "Show Advanced Settings", go to the bottom and to the "Test Page", and finally "Become User 0" to see all the functionality.
See [BUILDING.md](BUILDING.md) for more details.
See [BUILDING.md](BUILDING.md) for comprehensive build instructions for all platforms (Web, Electron, iOS, Android, Docker).
## Development Database Clearing
TimeSafari provides a simple script-based approach to clear the local database (not the claim server) for development purposes.
## Logging Configuration
TimeSafari supports configurable logging levels via the `VITE_LOG_LEVEL` environment variable. This allows developers to control console output verbosity without modifying code.
### Quick Usage
```bash
# Show only errors
VITE_LOG_LEVEL=error npm run dev
# Show warnings and errors
VITE_LOG_LEVEL=warn npm run dev
# Show info, warnings, and errors (default)
VITE_LOG_LEVEL=info npm run dev
# Show all log levels including debug
VITE_LOG_LEVEL=debug npm run dev
```
### Available Levels
- **`error`**: Critical errors only
- **`warn`**: Warnings and errors (default for production web)
- **`info`**: Info, warnings, and errors (default for development/capacitor)
- **`debug`**: All log levels including verbose debugging
See [Logging Configuration Guide](doc/logging-configuration.md) for complete details.
### Quick Usage
```bash
# Run the database clearing script
./scripts/clear-database.sh
# Then restart your development server
npm run build:electron:dev # For Electron
npm run build:web:dev # For Web
```
### What It Does
#### **Electron (Desktop App)**
- Automatically finds and clears the SQLite database files
- Works on Linux, macOS, and Windows
- Clears all data and forces fresh migrations on next startup
#### **Web Browser**
- Provides instructions for using custom browser data directories
- Shows manual clearing via browser DevTools
- Ensures reliable database clearing without browser complications
### Safety Features
-**Interactive Script**: Guides you through the process
-**Platform Detection**: Automatically detects your OS
-**Clear Instructions**: Step-by-step guidance for each platform
-**Safe Paths**: Only clears TimeSafari-specific data
### Manual Commands (if needed)
#### **Electron Database Location**
```bash
# Linux
rm -rf ~/.config/TimeSafari/*
# macOS
rm -rf ~/Library/Application\ Support/TimeSafari/*
# Windows
rmdir /s /q %APPDATA%\TimeSafari
```
#### **Web Browser (Custom Data Directory)**
```bash
# Create isolated browser profile
mkdir ~/timesafari-dev-data
```
## Domain Configuration
TimeSafari uses a centralized domain configuration system to ensure consistent
URL generation across all environments. This prevents localhost URLs from
appearing in shared links during development.
### Key Features
-**Production URLs for Sharing**: All copy link buttons use production domain
-**Environment-Specific Internal URLs**: Internal operations use appropriate
environment URLs
-**Single Point of Control**: Change domain in one place for entire app
-**Type-Safe Configuration**: Full TypeScript support
### Quick Reference
```typescript
// For sharing functionality (environment-specific)
import { APP_SERVER } from "@/constants/app";
const shareLink = `${APP_SERVER}/deep-link/claim/123`;
// For internal operations (environment-specific)
import { APP_SERVER } from "@/constants/app";
const apiUrl = `${APP_SERVER}/api/claim/123`;
```
### Documentation
- [Constants and Configuration](src/constants/app.ts) - Core constants
## Tests
See [TESTING.md](test-playwright/TESTING.md) for detailed test instructions.
## Asset Management
TimeSafari uses a standardized asset configuration system for consistent
icon and splash screen generation across all platforms.
### Asset Sources
- **Single source of truth**: `resources/` directory (Capacitor default)
- **Source files**: `icon.png`, `splash.png`, `splash_dark.png`
- **Format**: PNG or SVG files for optimal quality
## Icons
### Asset Generation
Application icons are in the `assets` directory, processed by the `capacitor-assets` command.
- **Configuration**: `config/assets/capacitor-assets.config.json`
- **Schema validation**: `config/assets/schema.json`
- **Build-time generation**: Platform assets generated via `capacitor-assets`
- **No VCS commits**: Generated assets are never committed to version control
### Development Commands
```bash
# Generate/update asset configurations
npm run assets:config
# Validate asset configurations
npm run assets:validate
# Clean generated platform assets (local dev only)
npm run assets:clean
# Build with asset generation
npm run build:native
```
### Platform Support
- **Android**: Adaptive icons with foreground/background, monochrome support
- **iOS**: LaunchScreen storyboard preferred, splash assets when needed
- **Web**: PWA icons generated during build to `dist/` (not committed)
### Font Awesome Icons
To add a Font Awesome icon, add to `fontawesome.ts` and reference with
`font-awesome` element and `icon` attribute with the hyphenated name.
To add a Font Awesome icon, add to main.ts and reference with `font-awesome` element and `icon` attribute with the hyphenated name.
## Other
@@ -210,25 +66,6 @@ Key principles:
- Common interfaces are shared through `common.ts`
- Type definitions are generated from Zod schemas where possible
### Database Architecture
The application uses a platform-agnostic database layer with Vue mixins for service access:
* `src/services/PlatformService.ts` - Database interface definition
* `src/services/PlatformServiceFactory.ts` - Platform-specific service factory
* `src/services/AbsurdSqlDatabaseService.ts` - SQLite implementation
* `src/utils/PlatformServiceMixin.ts` - Vue mixin for database access with caching
* `src/db/` - Legacy Dexie database (migration in progress)
**Development Guidelines**:
- Always use `PlatformServiceMixin` for database operations in components
- Test with PlatformServiceMixin for new features
- Use migration tools for data transfer between systems
- Leverage mixin's ultra-concise methods: `$db()`, `$exec()`, `$one()`, `$contacts()`, `$settings()`
**Architecture Decision**: The project uses Vue mixins over Composition API composables for platform service access. See [Architecture Decisions](doc/architecture-decisions.md) for detailed rationale.
### Kudos
Gifts make the world go 'round!

7
android/.gitignore vendored
View File

@@ -84,6 +84,13 @@ freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
# Version control
vcs.xml

View File

@@ -31,8 +31,8 @@ android {
applicationId "app.timesafari.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 39
versionName "1.0.6"
versionCode 18
versionName "0.4.7"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
@@ -64,14 +64,6 @@ android {
}
}
}
packagingOptions {
jniLibs {
pickFirsts += ['**/lib/x86_64/libbarhopper_v3.so', '**/lib/x86_64/libimage_processing_util_jni.so', '**/lib/x86_64/libsqlcipher.so']
}
}
// Configure for 16 KB page size compatibility
// Enable bundle builds (without which it doesn't work right for bundleDebug vs bundleRelease)
bundle {

View File

@@ -13,7 +13,6 @@
android:exported="true"
android:label="@string/title_activity_main"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBarLaunch">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@@ -2,6 +2,7 @@
"appId": "app.timesafari",
"appName": "TimeSafari",
"webDir": "dist",
"bundledWebRuntime": false,
"server": {
"cleartext": true
},
@@ -16,36 +17,22 @@
]
}
},
"SplashScreen": {
"launchShowDuration": 3000,
"launchAutoHide": true,
"backgroundColor": "#ffffff",
"androidSplashResourceName": "splash",
"androidScaleType": "CENTER_CROP",
"showSpinner": false,
"androidSpinnerStyle": "large",
"iosSpinnerStyle": "small",
"spinnerColor": "#999999",
"splashFullScreen": true,
"splashImmersive": true
},
"CapSQLite": {
"SQLite": {
"iosDatabaseLocation": "Library/CapacitorDatabase",
"iosIsEncryption": false,
"iosIsEncryption": true,
"iosBiometric": {
"biometricAuth": false,
"biometricAuth": true,
"biometricTitle": "Biometric login for TimeSafari"
},
"androidIsEncryption": false,
"androidIsEncryption": true,
"androidBiometric": {
"biometricAuth": false,
"biometricAuth": true,
"biometricTitle": "Biometric login for TimeSafari"
},
"electronIsEncryption": false
}
}
},
"ios": {
"contentInset": "never",
"contentInset": "always",
"allowsLinkPreview": true,
"scrollEnabled": true,
"limitsNavigationsToAppBoundDomains": true,
@@ -57,65 +44,13 @@
]
},
"android": {
"allowMixedContent": true,
"allowMixedContent": false,
"captureInput": true,
"webContentsDebuggingEnabled": false,
"allowNavigation": [
"*.timesafari.app",
"*.jsdelivr.net",
"api.endorser.ch",
"10.0.2.2:3000"
"api.endorser.ch"
]
},
"electron": {
"deepLinking": {
"schemes": [
"timesafari"
]
},
"buildOptions": {
"appId": "app.timesafari",
"productName": "TimeSafari",
"directories": {
"output": "dist-electron-packages"
},
"files": [
"dist/**/*",
"electron/**/*"
],
"mac": {
"category": "public.app-category.productivity",
"target": [
{
"target": "dmg",
"arch": [
"x64",
"arm64"
]
}
]
},
"win": {
"target": [
{
"target": "nsis",
"arch": [
"x64"
]
}
]
},
"linux": {
"target": [
{
"target": "AppImage",
"arch": [
"x64"
]
}
],
"category": "Utility"
}
}
}
}

View File

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M2480 4005 c-25 -7 -58 -20 -75 -29 -16 -9 -40 -16 -52 -16 -17 0
-24 -7 -28 -27 -3 -16 -14 -45 -24 -65 -21 -41 -13 -55 18 -38 25 13 67 13 92
-1 15 -8 35 -4 87 17 99 39 130 41 197 10 64 -29 77 -31 107 -15 20 11 20 11
-3 35 -12 13 -30 24 -38 24 -24 1 -132 38 -148 51 -8 7 -11 20 -7 32 12 37
-40 47 -126 22z"/>
<path d="M1450 3775 c-7 -8 -18 -15 -24 -15 -7 0 -31 -14 -54 -32 -29 -22 -38
-34 -29 -40 17 -11 77 -10 77 1 0 5 16 16 35 25 60 29 220 19 290 -18 17 -9
33 -16 37 -16 4 0 31 -15 60 -34 108 -70 224 -215 282 -353 30 -71 53 -190 42
-218 -10 -27 -23 -8 -52 75 -30 90 -88 188 -120 202 -13 6 -26 9 -29 6 -3 -2
11 -51 30 -108 28 -83 35 -119 35 -179 0 -120 -22 -127 -54 -17 -11 37 -13 21
-18 -154 -5 -180 -8 -200 -32 -264 -51 -132 -129 -245 -199 -288 -21 -12 -79
-49 -129 -80 -161 -102 -294 -141 -473 -141 -228 0 -384 76 -535 259 -81 99
-118 174 -154 312 -31 121 -35 273 -11 437 19 127 19 125 -4 125 -23 0 -51
-34 -87 -104 -14 -28 -33 -64 -41 -81 -19 -34 -22 -253 -7 -445 9 -106 12
-119 44 -170 19 -30 42 -67 50 -81 64 -113 85 -140 130 -169 28 -18 53 -44 61
-62 8 -20 36 -45 83 -76 62 -39 80 -46 151 -54 44 -5 96 -13 115 -18 78 -20
238 -31 282 -19 24 6 66 8 95 5 76 -9 169 24 319 114 32 19 80 56 106 82 27
26 52 48 58 48 5 0 27 26 50 58 48 66 56 70 132 71 62 1 165 29 238 64 112 55
177 121 239 245 37 76 39 113 10 267 -12 61 -23 131 -26 156 -5 46 -5 47 46
87 92 73 182 70 263 -8 l51 -49 -6 -61 c-4 -34 -13 -85 -21 -113 -28 -103 -30
-161 -4 -228 16 -44 32 -67 55 -83 18 -11 39 -37 47 -58 10 -23 37 -53 73 -81
32 -25 69 -57 82 -71 14 -14 34 -26 47 -26 12 0 37 -7 56 -15 20 -8 66 -17
104 -20 107 -10 110 -11 150 -71 50 -75 157 -177 197 -187 18 -5 53 -24 78
-42 71 -51 176 -82 304 -89 61 -4 127 -12 147 -18 29 -9 45 -8 77 6 23 9 50
16 60 16 31 0 163 46 216 76 28 15 75 46 105 69 30 23 69 49 85 58 17 8 46 31
64 51 19 20 40 36 47 36 18 0 77 70 100 120 32 66 45 108 55 173 5 32 16 71
24 87 43 84 43 376 0 549 -27 105 -43 127 -135 188 -30 21 -65 46 -77 57 -13
11 -23 17 -23 14 0 -3 21 -46 47 -94 79 -151 85 -166 115 -263 25 -83 28 -110
28 -226 0 -144 -17 -221 -75 -335 -39 -77 -208 -244 -304 -299 -451 -263 -975
-67 -1138 426 -23 70 -26 95 -28 254 -1 108 -7 183 -14 196 -6 12 -11 31 -11
43 0 32 31 122 52 149 10 13 18 28 18 34 0 5 25 40 56 78 60 73 172 170 219
190 30 12 30 13 6 17 -15 2 -29 -2 -37 -12 -6 -9 -16 -16 -22 -16 -6 0 -23
-11 -39 -24 -15 -12 -33 -25 -40 -27 -17 -6 -82 -60 -117 -97 -65 -70 -75 -82
-107 -133 -23 -34 -35 -46 -37 -35 -3 16 20 87 44 134 6 12 9 34 6 48 -4 22
-8 25 -31 19 -14 -3 -38 -15 -53 -26 -34 -24 -34 -21 -6 28 65 112 184 206
291 227 15 3 39 9 55 12 l27 6 -24 9 c-90 35 -304 -66 -478 -225 -39 -36 -74
-66 -77 -66 -22 0 18 82 72 148 19 23 32 46 28 49 -4 4 -26 13 -49 19 -73 21
-161 54 -171 64 -6 6 -20 10 -32 10 -21 0 -21 -1 -8 -40 45 -130 8 -247 -93
-299 -25 -13 -31 0 -14 29 15 22 1 33 -22 17 -56 -36 -117 -22 -117 28 0 13
-16 47 -35 76 -22 34 -33 60 -29 73 4 16 -3 26 -26 39 -16 10 -30 21 -30 25 1
18 54 64 87 76 l38 13 -33 5 c-30 4 -115 -18 -154 -42 -13 -7 -20 -5 -27 8 -9
16 -12 16 -53 1 -160 -61 -258 -104 -258 -114 0 -7 10 -20 21 -31 103 -91 217
-297 249 -449 28 -135 41 -237 35 -276 -14 -91 -48 -170 -97 -220 -44 -47 -68
-60 -68 -40 0 6 4 12 8 15 5 3 24 35 42 72 l33 67 -6 141 c-4 103 -11 158 -26
205 -12 35 -21 70 -21 77 0 7 -20 56 -45 108 -82 173 -227 322 -392 401 -67
33 -90 39 -163 42 -108 5 -130 10 -130 28 0 20 -63 20 -80 0z"/>
<path d="M3710 3765 c0 -20 8 -28 39 -41 22 -8 42 -22 45 -30 5 -14 42 -19 70
-8 10 4 -7 21 -58 55 -41 27 -79 49 -85 49 -6 0 -11 -11 -11 -25z"/>
<path d="M3173 3734 c-9 -25 10 -36 35 -18 12 8 22 19 22 25 0 16 -50 10 -57
-7z"/>
<path d="M1982 3728 c6 -16 36 -34 44 -26 3 4 4 14 1 23 -7 17 -51 21 -45 3z"/>
<path d="M1540 3620 c0 -5 7 -10 16 -10 8 0 12 5 9 10 -3 6 -10 10 -16 10 -5
0 -9 -4 -9 -10z"/>
<path d="M4467 3624 c-4 -4 23 -27 60 -50 84 -56 99 -58 67 -9 -28 43 -107 79
-127 59z"/>
<path d="M655 3552 c-11 -2 -26 -9 -33 -14 -7 -6 -27 -18 -45 -27 -36 -18 -58
-64 -39 -83 9 -9 25 1 70 43 53 48 78 78 70 84 -2 1 -12 -1 -23 -3z"/>
<path d="M1015 3460 c-112 -24 -247 -98 -303 -165 -53 -65 -118 -214 -136
-311 -20 -113 -20 -145 -1 -231 20 -88 49 -153 102 -230 79 -113 186 -182 331
-214 108 -24 141 -24 247 1 130 30 202 72 316 181 102 100 153 227 152 384 0
142 -58 293 -150 395 -60 67 -180 145 -261 171 -75 23 -232 34 -297 19z m340
-214 c91 -43 174 -154 175 -234 0 -18 -9 -51 -21 -73 -19 -37 -19 -42 -5 -64
35 -54 12 -121 -48 -142 -22 -7 -47 -19 -55 -27 -9 -8 -41 -27 -71 -42 -50
-26 -64 -29 -155 -29 -111 0 -152 14 -206 68 -49 49 -63 85 -64 162 0 59 4 78
28 118 31 52 96 105 141 114 23 5 33 17 56 68 46 103 121 130 225 81z"/>
<path d="M3985 3464 c-44 -7 -154 -44 -200 -67 -55 -28 -138 -96 -162 -132
-10 -16 -39 -75 -64 -130 l-44 -100 0 -160 0 -160 45 -90 c53 -108 152 -214
245 -264 59 -31 215 -71 281 -71 53 0 206 40 255 67 98 53 203 161 247 253 53
113 74 193 74 280 -1 304 -253 564 -557 575 -49 2 -103 1 -120 -1z m311 -220
c129 -68 202 -209 160 -309 -15 -35 -15 -42 -1 -72 26 -55 -3 -118 -59 -129
-19 -3 -43 -15 -53 -26 -26 -29 -99 -64 -165 -78 -45 -10 -69 -10 -120 -1 -74
15 -113 37 -161 91 -110 120 -50 331 109 385 24 8 44 23 52 39 6 14 18 38 25
53 33 72 127 93 213 47z"/>
<path d="M487 3394 c-21 -12 -27 -21 -25 -40 2 -14 7 -26 12 -27 14 -3 48 48
44 66 -3 14 -6 14 -31 1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 KiB

View File

@@ -0,0 +1,11 @@
Model Information:
* title: Lupine Plant
* source: https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439
* author: rufusrockwell (https://sketchfab.com/rufusrockwell)
Model License:
* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
* requirements: Author must be credited. Commercial use is allowed.
If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "Lupine Plant" (https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439) by rufusrockwell (https://sketchfab.com/rufusrockwell) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)

View File

@@ -0,0 +1,229 @@
{
"accessors": [
{
"bufferView": 2,
"componentType": 5126,
"count": 2759,
"max": [
41.3074951171875,
40.37548828125,
87.85917663574219
],
"min": [
-35.245540618896484,
-36.895416259765625,
-0.9094290137290955
],
"type": "VEC3"
},
{
"bufferView": 2,
"byteOffset": 33108,
"componentType": 5126,
"count": 2759,
"max": [
0.9999382495880127,
0.9986748695373535,
0.9985831379890442
],
"min": [
-0.9998949766159058,
-0.9975876212120056,
-0.411094069480896
],
"type": "VEC3"
},
{
"bufferView": 3,
"componentType": 5126,
"count": 2759,
"max": [
0.9987699389457703,
0.9998998045921326,
0.9577858448028564,
1.0
],
"min": [
-0.9987726807594299,
-0.9990445971488953,
-0.999801516532898,
1.0
],
"type": "VEC4"
},
{
"bufferView": 1,
"componentType": 5126,
"count": 2759,
"max": [
1.0061479806900024,
0.9993550181388855
],
"min": [
0.00279300007969141,
0.0011620000004768372
],
"type": "VEC2"
},
{
"bufferView": 0,
"componentType": 5125,
"count": 6378,
"type": "SCALAR"
}
],
"asset": {
"extras": {
"author": "rufusrockwell (https://sketchfab.com/rufusrockwell)",
"license": "CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)",
"source": "https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439",
"title": "Lupine Plant"
},
"generator": "Sketchfab-12.68.0",
"version": "2.0"
},
"bufferViews": [
{
"buffer": 0,
"byteLength": 25512,
"name": "floatBufferViews",
"target": 34963
},
{
"buffer": 0,
"byteLength": 22072,
"byteOffset": 25512,
"byteStride": 8,
"name": "floatBufferViews",
"target": 34962
},
{
"buffer": 0,
"byteLength": 66216,
"byteOffset": 47584,
"byteStride": 12,
"name": "floatBufferViews",
"target": 34962
},
{
"buffer": 0,
"byteLength": 44144,
"byteOffset": 113800,
"byteStride": 16,
"name": "floatBufferViews",
"target": 34962
}
],
"buffers": [
{
"byteLength": 157944,
"uri": "scene.bin"
}
],
"images": [
{
"uri": "textures/lambert2SG_baseColor.png"
},
{
"uri": "textures/lambert2SG_normal.png"
}
],
"materials": [
{
"alphaCutoff": 0.2,
"alphaMode": "MASK",
"doubleSided": true,
"name": "lambert2SG",
"normalTexture": {
"index": 1
},
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0
},
"metallicFactor": 0.0
}
}
],
"meshes": [
{
"name": "Object_0",
"primitives": [
{
"attributes": {
"NORMAL": 1,
"POSITION": 0,
"TANGENT": 2,
"TEXCOORD_0": 3
},
"indices": 4,
"material": 0,
"mode": 4
}
]
}
],
"nodes": [
{
"children": [
1
],
"matrix": [
1.0,
0.0,
0.0,
0.0,
0.0,
2.220446049250313e-16,
-1.0,
0.0,
0.0,
1.0,
2.220446049250313e-16,
0.0,
0.0,
0.0,
0.0,
1.0
],
"name": "Sketchfab_model"
},
{
"children": [
2
],
"name": "LupineSF.obj.cleaner.materialmerger.gles"
},
{
"mesh": 0,
"name": "Object_2"
}
],
"samplers": [
{
"magFilter": 9729,
"minFilter": 9987,
"wrapS": 10497,
"wrapT": 10497
}
],
"scene": 0,
"scenes": [
{
"name": "Sketchfab_Scene",
"nodes": [
0
]
}
],
"textures": [
{
"sampler": 0,
"source": 0
},
{
"sampler": 0,
"source": 1
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow:

View File

@@ -2,7 +2,7 @@ package app.timesafari;
import android.os.Bundle;
import com.getcapacitor.BridgeActivity;
//import com.getcapacitor.community.sqlite.SQLite;
import com.getcapacitor.community.sqlite.SQLite;
public class MainActivity extends BridgeActivity {
@Override
@@ -10,6 +10,6 @@ public class MainActivity extends BridgeActivity {
super.onCreate(savedInstanceState);
// Initialize SQLite
//registerPlugin(SQLite.class);
registerPlugin(SQLite.class);
}
}

View File

@@ -0,0 +1,5 @@
package timesafari.app;
import com.getcapacitor.BridgeActivity;
public class MainActivity extends BridgeActivity {}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Some files were not shown because too many files have changed in this diff Show More