2022-11-16 14:48:22 +08:00
2026-10-12 17:03:46 -06:00
2026-10-12 17:03:46 -06:00
2024-12-08 21:22:03 -07:00
2026-10-11 19:51:39 -06:00

TimeSafari.app - Crowd-Funder for Time - PWA

Time Safari allows people to ease into collaboration: start with expressions of gratitude and expand to crowd-fund with time & money, then record and see the impact of contributions.

Roadmap

See ClickUp for current priorities.

Setup & Building

Quick start:

  • For setup, we recommend pkgx, which installs what you need (either automatically or with the dev command). Core dependencies are typescript & npm; when building for other platforms, you'll need other things such as those in the pkgx.yaml & BUILDING.md files.
npm install

Web

npm run dev

Then go to the test page and click "Become User 0" to take action on the platform.

Android

npm run build:android:test:run

Assumes ADB is installed; see Android Build for SDK, emulator, and PATH setup.

iOS

npm run build:ios:studio

Assumes Xcode and Xcode Command Line Tools are installed.

See BUILDING.md for comprehensive build instructions for all platforms (Web, Electron, iOS, Android, Docker).

Tests

npm run test:web

# ... or do every check:
npm run test:all

🛡️ Build Architecture Guard

This project uses Husky Git hooks to protect the build system architecture. When you modify build-critical files, the system automatically blocks commits until you update BUILDING.md.

Quick Setup

npm run guard:setup  # Install and activate the guard

How It Works

  • Pre-commit: Blocks commits if build files changed without BUILDING.md updates
  • Pre-push: Blocks pushes if commits contain undocumented build changes
  • Protected paths: scripts/, vite.config.*, electron/, android/, ios/, etc.

Usage

# Test the guard manually
npm run guard:test

# Emergency bypass (use sparingly)
git commit --no-verify
git push --no-verify

📚 Full documentation: See doc/README-BUILD-GUARD.md

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

# 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 for complete details.

Notification Debug Panel (dev builds)

In non-production bundles (for example vite dev or a Vite build whose mode is not production), the Notification Debug Panel at /dev/notifications helps you test FCM token registration, AlertSearch authorization upload, FCM wakeup delivery (/debug/send-wakeup), and local schedule inspection on native builds. The app no longer consumes WAKEUP_PING to call /notifications/refresh or schedule api_* notifications.

Access: Account → enable Show All General Advanced Functions → Notification Debug Panel.

Key configuration (independent settings):

  • Notification Backend URL — which notification server receives API calls
  • Test Mode — testMode sent in JSON request bodies (default on)
  • Skip JWT Authentication (Local Development Only) — omit JWT headers for local unauthenticated backends (default off)

See doc/notification-debug-panel.md for controls, recommended settings (hosted test server vs local ngrok), and troubleshooting.

Platform-specific end-to-end guides:

Database Clearing (development)

Quick Usage

# Run the database clearing script
./scripts/clear-database.sh

# Then restart your development server
npm run build:electron:dev  # For Electron
npm run 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

# Linux
rm -rf ~/.config/TimeSafari/*

# macOS  
rm -rf ~/Library/Application\ Support/TimeSafari/*

# Windows
rmdir /s /q %APPDATA%\TimeSafari

Web Browser (Custom Data Directory)

# 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

// 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

Tests

See 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

Asset Generation

  • 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

# 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

Environment Setup & Dependencies

Before building the application, ensure your development environment is properly configured:

# Install all dependencies (required first time and after updates)
npm install

# Validate your development environment
npm run check:dependencies

# Check prerequisites for testing
npm run test:prerequisites

Common Issues & Solutions:

  • "tsx: command not found": Run npm install to install devDependencies
  • "capacitor-assets: command not found": Ensure @capacitor/assets is installed
  • Build failures: Run npm run check:dependencies to diagnose environment issues

Required Versions:

  • Node.js: 18+ (LTS recommended)
  • npm: 8+ (comes with Node.js)
  • Platform-specific tools: Android Studio, Xcode (for mobile builds)

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.

Other

Reference Material

  • Notifications can be type of toast (self-dismiss), info, success, warning, and danger. They are done via notiwind and set up in App.vue.

  • Customize Vue configuration.

  • If you are deploying in a subdirectory, add it to publicPath in vue.config.js, eg: publicPath: "/app/time-tracker/",

Code Organization

The project uses a centralized approach to type definitions and interfaces:

  • src/interfaces/ - Contains all TypeScript interfaces and type definitions
    • deepLinks.ts - Deep linking type system and Zod validation schemas
    • give.ts - Give-related interfaces and type definitions
    • claims.ts - Claim-related interfaces and verifiable credentials
    • common.ts - Shared interfaces and utility types
    • Other domain-specific interface files

Key principles:

  • All interfaces and types are defined in the interfaces folder
  • Zod schemas are used for runtime validation and type generation
  • Domain-specific interfaces are separated into their own files
  • 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

Development Guidelines:

  • Always use PlatformServiceMixin for database operations in components
  • Test with PlatformServiceMixin for new features
  • 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 for detailed rationale.

📁 Project Structure

timesafari/
├── 📁 src/              # Source code
├── 📁 scripts/          # Build and automation scripts
├── 📁 electron/         # Electron configuration
├── 📁 android/          # Android configuration  
├── 📁 ios/              # iOS configuration
├── 📁 .husky/           # Git hooks (Build Architecture Guard)
├── 📄 BUILDING.md       # Build system documentation
├── 📄 pull_request_template.md # PR template
└── 📄 doc/README-BUILD-GUARD.md # Guard system documentation

Building an APK for Android 6 (API 23)

App versions up to 1.4.6 support Android 6.0 (API 23); later versions require Android 7.0 (API 24) or newer. To run the app on an Android 6 device, build your own APK from the 1.4.6 release commit (6183afc2, "bump version to 1.4.6").

Prerequisites: git, Node.js 20 (see .nvmrc), Java 21, and the Android SDK with ANDROID_HOME set (see Android Emulator Without Android Studio for an SDK setup that skips Android Studio). With pkgx, prefix the commands with pkgx, e.g. pkgx npm ci.

  1. Get the 1.4.6 source:

    git clone https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa.git
    cd crowd-funder-for-time-pwa
    git checkout 6183afc2
    
  2. Confirm the minimum SDK is 23:

    grep minSdkVersion android/variables.gradle   # expect: minSdkVersion = 23
    
  3. Install dependencies and build a production APK:

    npm ci
    npm run build:android:prod -- --apk
    

    npm ci installs the exact dependency versions locked for 1.4.6. build:android:prod -- --apk builds the web app with production server settings, syncs it into the Android project, and runs ./gradlew assembleDebug. The result is signed with your local Android debug key, so it installs on any device without a release keystore.

  4. Find the APK at android/app/build/outputs/apk/debug/app-debug.apk and install it, either with adb install android/app/build/outputs/apk/debug/app-debug.apk (USB debugging enabled on the phone) or by copying the file to the phone and opening it (allow "Install unknown apps" for the file manager).

Notes:

  • Back up your identity first. A self-built APK has a different signature from the Play Store app, so Android refuses to install it over the store version. Uninstalling the store version deletes the app's local data, including your identifier keys. Back up your seed phrase (Profile page → "Backup Identifier Seed") before uninstalling, then import it into the self-built app.
  • This build has Firebase disabled, so push notifications through Google's FCM service are off.
  • The daily notification plugin calls java.time, which Android provides only from 8.0 (API 26). On Android 6, scheduling a daily reminder can crash the app; leave daily reminders off. See doc/plugin-feedback-android-6-api23-zoneid-fix.md.
  • Barcode scanning uses Google Play Services; on devices without them, scanning fails while the rest of the app works.
  • A self-built APK does not auto-update.

🤝 Contributing

  1. Follow the Build Architecture Guard - Update BUILDING.md when modifying build files
  2. Test your changes - Ensure builds work on affected platforms
  3. Document updates - Keep BUILDING.md current and accurate

Kudos

Gifts make the world go 'round!

S
Description
No description provided
Readme
116 MiB
2024-03-01 22:54:50 +00:00
Languages
Vue 50.5%
TypeScript 33.8%
Shell 9.1%
JavaScript 3.1%
Java 1.1%
Other 2.3%