Skip to content

Precise eclipse contact times and countdowns for any location on Earth.

Notifications You must be signed in to change notification settings

c0d3rb4b4/eclipse-timer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

156 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

eclipse-timer

eclipse-timer is a TypeScript monorepo for an eclipse-focused mobile app and a reusable eclipse computation engine.

It combines:

  • A React Native + Expo app for selecting an eclipse, choosing an observer location, and viewing event timings.
  • A Besselian-element-driven engine that computes local contact circumstances (C1/C2/MAX/C3/C4), local eclipse kind, magnitude, and duration.
  • Catalog tooling for generating typed eclipse datasets and map overlay polygons.

Project Overview

The current MVP is built around a two-screen flow:

  1. Landing screen
    • Loads eclipse records from the local generated catalog.
    • Sorts eclipses by date and marks entries as past/upcoming.
    • Shows a preview animation URL (NASA animation endpoint per eclipse).
  2. Timer screen
    • Displays a map with observer marker and eclipse overlays (visible band + central band when available).
    • Lets the user set location via map tap/drag, GPS, or jump-to-center preset.
    • Runs the engine for the selected eclipse at the observer location.
    • Shows contact times, next-event countdown, and alarm toggles/test alarm behavior.

Monorepo Architecture

Packages

  • apps/mobile
    • Expo app (navigation, landing flow, timer/map UI, GPS integration, engine trigger).
  • packages/engine
    • Eclipse circumstance solver and numeric helpers.
  • packages/catalog
    • Generated eclipse catalog + scripts for CSV filtering and overlay generation.
  • packages/shared
    • Shared type contracts (EclipseRecord, Observer, Circumstances, etc.).

Internal dependency graph

@eclipse-timer/mobile
  -> @eclipse-timer/catalog
  -> @eclipse-timer/engine
  -> @eclipse-timer/shared

@eclipse-timer/engine
  -> @eclipse-timer/shared

@eclipse-timer/catalog
  -> @eclipse-timer/shared

Catalog build scripts (packages/catalog/scripts/*) use @eclipse-timer/engine as a dev dependency.

End-to-End Flow (High Level)

  1. @eclipse-timer/mobile loads catalog records through loadCatalog() from @eclipse-timer/catalog.
  2. Catalog loader merges base eclipse records with generated polygon overlays (visible + central paths) when available.
  3. User selects an eclipse on the landing screen and moves to the timer screen.
  4. User chooses observer coordinates (map tap/drag, GPS fix, or center preset).
  5. App calls computeCircumstances(eclipse, observer) from @eclipse-timer/engine.
  6. Engine solves eclipse contact timings and derived fields, then returns a typed Circumstances payload.
  7. UI renders event timings, countdown state, and per-contact alarm toggles.

Engine Summary

At a high level, the engine:

  • Evaluates Besselian-element polynomials (x, y, d, mu, l1, l2) at candidate times.
  • Solves contact roots for penumbral and umbral/antumbral boundaries.
  • Computes local visibility and eclipse kind (none, partial, total, annular).
  • Converts TT-relative solved times into UTC ISO strings using record deltaTSeconds.
  • Returns additional derived metrics like magnitude and central duration (when applicable).

Dataset Scope

  • Source records are generated in packages/catalog/generated/catalog.generated.json.
  • Current filtered range targets years 1900-2100.
  • Overlay polygons are generated into packages/catalog/generated/overlays.generated.json.
  • Catalog/test integration currently validates a 454-eclipse generated dataset.

Tech Stack

  • Language: TypeScript
  • Monorepo/tooling: pnpm workspaces
  • Mobile: Expo SDK 54, React Native 0.81, React Navigation
  • Maps/location: react-native-maps, expo-location
  • Testing: Vitest
  • Data processing: Node scripts + csv-parse

Prerequisites

Required for all platforms

  • Node.js 18+ (LTS recommended)
  • pnpm (repo is pinned to pnpm@9)

Check versions:

node -v
pnpm -v

Install/activate pnpm via Corepack (recommended):

corepack enable
corepack prepare pnpm@9 --activate

If corepack is not found, use a fallback install:

npm install -g pnpm@9

macOS (iOS + Android simulators)

  1. Install Node.js (either method):
    • Homebrew:
      brew install node
    • nvm:
      curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
      nvm install --lts
  2. Enable pnpm with Corepack:
    corepack enable
    corepack prepare pnpm@9 --activate
  3. Install Xcode from the App Store and verify where it is installed:
    ls -1 /Applications | grep -i xcode
    If nothing is listed, full Xcode is not installed yet (only Command Line Tools are present).
  4. Point xcode-select to full Xcode (not Command Line Tools):
    # Default App Store path
    sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
    
    # If your app name is different (for example Xcode-beta.app), use that path instead:
    # sudo xcode-select -s /Applications/<YourXcodeName>.app/Contents/Developer
    Verify:
    xcode-select -p
    xcodebuild -version
  5. Run first-launch setup:
    sudo xcodebuild -runFirstLaunch
    If you still need to accept the license explicitly:
    sudo xcodebuild -license accept
  6. Open Xcode once, then install an iOS runtime in Xcode -> Settings -> Platforms.
  7. Install Android Studio. In SDK Manager, install:
    • Android SDK Platform (latest stable)
    • Android SDK Build-Tools
    • Android SDK Command-line Tools
    • Android Emulator
  8. Create and start an Android Virtual Device (AVD) in Device Manager.

Windows (Android emulator only)

  1. Install Node.js LTS (example with winget):
    winget install OpenJS.NodeJS.LTS
  2. Enable pnpm with Corepack:
    corepack enable
    corepack prepare pnpm@9 --activate
  3. Install Android Studio:
    winget install Google.AndroidStudio
  4. In Android Studio SDK Manager, install:
    • Android SDK Platform (latest stable)
    • Android SDK Build-Tools
    • Android SDK Command-line Tools
    • Android Emulator
  5. Create and start an AVD in Device Manager.
  6. iOS Simulator is not available on Windows. Use a macOS machine for iOS Simulator runs.

Linux (Android emulator only)

  1. Install Node.js (nvm recommended):
    curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
    nvm install --lts
    nvm use --lts
  2. Enable pnpm with Corepack:
    corepack enable
    corepack prepare pnpm@9 --activate
  3. Install Android Studio (example with Snap):
    sudo snap install android-studio --classic
  4. In Android Studio SDK Manager, install:
    • Android SDK Platform (latest stable)
    • Android SDK Build-Tools
    • Android SDK Command-line Tools
    • Android Emulator
  5. Create and start an AVD in Device Manager.
  6. iOS Simulator is not available on Linux. Use a macOS machine for iOS Simulator runs.

Android SDK environment variables (recommended)

Set ANDROID_SDK_ROOT and add platform tools to your PATH so CLI launches work reliably:

  • macOS: ~/Library/Android/sdk
  • Linux: ~/Android/Sdk
  • Windows: %LOCALAPPDATA%\Android\Sdk

Installation

Clone and install:

git clone <your-repo-url>
cd eclipse-timer
pnpm install

If you already have the repo locally, running pnpm install at the root is enough.

Google Maps API Key Setup (Local + CI)

Android uses react-native-maps, so a Google Maps Android API key is required. This repo now reads the key from GOOGLE_MAPS_ANDROID_API_KEY at build/config time.

Local development

  1. Copy the example env file:
    cp apps/mobile/.env.example apps/mobile/.env.local
    On Windows PowerShell:
    Copy-Item apps/mobile/.env.example apps/mobile/.env.local
  2. Edit apps/mobile/.env.local and set:
    GOOGLE_MAPS_ANDROID_API_KEY=your_real_android_maps_key
  3. Rebuild the Android app after changing the key:
    pnpm -C apps/mobile android

GitHub Actions (EAS build workflow)

  1. In GitHub, add repository secret:
    • Name: GOOGLE_MAPS_ANDROID_API_KEY
    • Value: your Android Maps key
  2. The workflow .github/workflows/eas-build.yml injects this secret into the build job.
  3. Android/all builds fail early with a clear message if the secret is missing.
  4. Builds run on a self-hosted macOS runner with label eclipse-timer. Runner setup instructions: documents/self-hosted-macos-runner.md.

Security recommendations

  • Restrict the key in Google Cloud Console to:
    • Application restriction: Android apps
    • Package: com.lallimaven.eclipsetimer
    • SHA-1: your debug/release certificate fingerprints
  • Restrict API usage to Maps SDK for Android.
  • If a key was ever committed, rotate it in Google Cloud and replace it in local/CI secrets.

Getting Started (Quick Start)

From the repo root:

pnpm dev:mobile

This starts the Expo dev server for apps/mobile.

For first-time setup, a recommended sequence is:

pnpm install
pnpm typecheck
pnpm test
pnpm dev:mobile

Running the App in Expo

Option 1: Physical device (Expo Go)

  1. Install Expo Go on your phone.
  2. Run:
    pnpm dev:mobile
  3. Scan the QR code shown in the terminal/Expo UI.

Option 2: iOS simulator

Use one of:

# Start Expo and press "i" in the interactive terminal
pnpm dev:mobile

# Or run directly
pnpm -C apps/mobile ios

Option 3: Android emulator

Use one of:

# Start Expo and press "a" in the interactive terminal
pnpm dev:mobile

# Or run directly
pnpm -C apps/mobile android

Option 4: Web preview

pnpm -C apps/mobile web

Option 5: Wear OS emulator (native watch module)

The Wear OS companion app is a separate native module (apps/mobile/android/wear) and is not launched by Expo commands above. Live mode now computes sun/moon geometry on-watch from watch GPS + UTC time, so it works without a connected phone. Phone connectivity is only needed for preview sync mode.

Use the local simulator build/install/run guide in:

Running Tests and Quality Checks

From the repo root:

pnpm typecheck
pnpm lint
pnpm test

Package-level examples:

pnpm -C packages/engine test
pnpm -C packages/catalog test
pnpm -C apps/mobile test

Current test coverage includes:

  • Engine math/time/geometry/circumstance behavior
  • Full generated-catalog sweeps at greatest-eclipse coordinates
  • Catalog script integration checks and generated artifact stability

Common Commands

# Mobile dev server
pnpm dev:mobile

# Workspace-wide checks
pnpm typecheck
pnpm lint
pnpm test

# Engine local dev script
pnpm -C packages/engine dev:one

# Catalog generation pipeline
pnpm -C packages/catalog data:all

Catalog Data Pipeline

Catalog tooling lives in packages/catalog.

Useful commands:

pnpm -C packages/catalog data:filter
pnpm -C packages/catalog data:build
pnpm -C packages/catalog data:overlays

Run all steps:

pnpm -C packages/catalog data:all

Generated artifacts are written under packages/catalog/generated/.

Repository Layout

apps/
  mobile/                 Expo app
packages/
  engine/                 Eclipse computation engine
  catalog/                Generated dataset + build scripts
  shared/                 Shared TypeScript types
documents/
  high-level/             Architecture and workflow docs
  low-level/              Algorithm/data/internal design docs

Documentation

  • documents/README.md
  • documents/high-level/system-overview.md
  • documents/high-level/development-workflow.md
  • documents/high-level/user-flow-and-product-behavior.md
  • documents/low-level/engine-algorithm.md
  • documents/low-level/mobile-app-internals.md
  • documents/low-level/data-contracts.md

Current Status and Limits

  • MVP behavior is implemented and usable for local exploration.
  • Workspace lint/format tooling is configured with Biome; current codebase still has existing lint warnings to address incrementally.
  • Alarm/reminder behavior now uses fixed per-eclipse local reminders (T-1h, T-10m) plus foreground-only in-app per-event a1/a2 voice alarms from Notification/Alarm Settings.
  • Product polish and persistence/history features are intentionally limited while core engine/data reliability is prioritized.