All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Added detailed
[share.debug]parser instrumentation for Google Maps short-link expansion/fetch/parse steps to improve troubleshooting in Android logcat.
- Bumped
apps/mobileversion to1.1.51.
- Added a new
Aboutscreen in Settings that displays app version/build metadata in the UI (App Version,Build,Configured Version, andRuntime Version).
- Fixed Android app version reporting mismatch by sourcing native
versionNamefromapps/mobile/package.jsonin app Gradle config instead of using a hardcoded value.
- Added Settings navigation/linking support for the new
Aboutroute (settings/about). - Bumped
apps/mobileversion to1.1.50.
- Fixed remaining Google Maps short-link parse failures on Android by broadening coordinate extraction fallbacks to handle additional
window.CONFIGstate-array variants and static-map metadata (center=lat,lon) when previewpbtokens are missing. - Fixed short-link fallback fetch behavior by re-attempting page-content extraction even when URL expansion does not change the original short URL.
- Added regression tests for relaxed Google state-array parsing, static-map metadata coordinate extraction, and short-link re-fetch fallback when the first response body is empty.
- Bumped
apps/mobileversion to1.1.49.
- Fixed Google Maps short-link parsing for Android response variants that do not include
pb=%21...2d...3d...preview tokens by adding fallback extraction from embedded map-state coordinate arrays (for example[[distance,lon,lat],[0,0,0],[w,h],zoom]) in fetched HTML payloads.
- Added regression test coverage for short-link parsing using the Android-style Google Maps state payload coordinate format.
- Bumped
apps/mobileversion to1.1.48.
- Fixed Google Maps short-link parse failures on Android when the initial short-link fetch returns a final URL but no usable body for coordinate extraction by re-fetching the expanded Maps URL page and re-attempting preview-payload coordinate parsing.
- Added regression coverage for short-link parsing fallback that requires a second fetch against the expanded Google Maps URL.
- Bumped
apps/mobileversion to1.1.47.
- Fixed Android warm-start share-intent persistence by caching incoming
ACTION_SENDintents inMainActivity.onNewIntent, so pending share payloads remain retrievable from JS after app resume.
- Added temporary
[share.debug]instrumentation in share-intake paths (useShareIntentBridge+RootNavigator) to expose raw/parsed share payloads and map-link parse outcomes in logcat.
- Bumped
apps/mobileversion to1.1.46.
- Fixed share-intent gating for Android payloads that provide URL-like content via
meta.titlewithouttext/webUrlby treatingmeta.titleas a valid incoming-share signal and processing it through the existing shared-link intake path. - Fixed shared-intent effect dependency coverage so
meta.titleupdates trigger intake handling.
- Bumped
apps/mobileversion to1.1.45.
- Fixed Android shared-link cold-start intake timing by replacing direct
useShareIntentusage with a local bridge hook that attaches native listeners before requesting pending share-intent payloads. - Fixed potential dropped first-share behavior after launching from Google Maps share sheet by processing native intent refresh only after listener registration.
- Bumped
apps/mobileversion to1.1.44.
- Fixed shared Google Maps short links (
maps.app.goo.gl) that expanded to place URLs without direct coordinate query/path params by adding a fallback parser for encoded preview payload coordinates.
- Added regression test coverage for short-link parsing when coordinates are only present in Google preview payload data.
- Bumped
apps/mobileversion to1.1.43.
- Fixed non-interactive iOS EAS build failures caused by
ShareExtensioncredential setup requirements by disabling iOS share-extension target generation inexpo-share-intentplugin config for now (disableIOS: true).
- Kept Android share-link intake enabled through tracked native manifest intent filters while plugin Android mutation remains disabled (
disableAndroid: true). - Bumped
apps/mobileversion to1.1.42.
- Added shared map-link parsing support for Apple Maps and Google Maps links, including coordinate extraction from query params and Google
@lat,lonpath tokens. - Added short-link redirect expansion support for
maps.app.goo.glwith timeout-safe fallback behavior. - Added shared-link intake utilities and tests to normalize incoming linking/share payloads and keep parsing behavior deterministic.
- Added Android
ACTION_SEND(text/*) intent filter to accept shared text/map URLs in the tracked native manifest.
- Integrated incoming map-link handling into
RootNavigatorso supported links navigate toTimer, jump the pin to parsed coordinates, and showLocation loaded from shared map link. - Added shared-link dedupe guarding to avoid duplicate processing during cold-start intake (
getInitialURL+ runtime URL events). - Added
expo-share-intentintegration and wiring so share-target payloads feed the same parser/navigation pipeline as deep links. - Added pnpm
patchedDependenciesentry andxcode@3.0.1patch hardening to avoid known share-extension config-sync failures during native config generation. - Bumped
apps/mobileversion to1.1.41.
- Tightened
Photography Guidelandscape composite corona rendering so the ring appears only whenMAXis during true totality (C2 < MAX < C3) and never for non-total scenarios.
- Bumped
apps/mobileversion to1.1.40.
- Updated
Photography Guidelandscape composite visuals so corona rings render only fortotaleclipses atMAX(no corona forpartialorannulareclipses). - Updated composite moon styling to match the sky for non-
MAXshots, with moon rendered black atMAXonly forannularandtotaleclipses.
- Bumped
apps/mobileversion to1.1.39.
- Added landscape composite horizon direction markings (16-point compass labels) in the Photography Guide modal.
- Added a landscape composite toggle to show/hide markings, direction labels, and shot numbers together.
- Updated landscape composite rendering to hide sun/moon placements when the sampled sun is below the horizon.
- Bumped
apps/mobileversion to1.1.38.
- Fixed changelog version labeling for the previous release so it matches the mobile package version (
1.1.36). - Bumped
apps/mobileversion to1.1.37.
- Updated
Photography Guidelandscape composite framing soMAXis anchored at the center of the frame (horizontal + vertical), preventing MAX placement from being cut off in the modal.
- Updated landscape composite helper expectations/docs to reflect centered
MAXframing. - Bumped
apps/mobileversion to1.1.36.
- Added a local sun/moon horizontal-position utility for mobile (
apps/mobile/src/utils/sunMoonPosition.ts) that computes per-time azimuth, altitude, RA/Dec, distance, and apparent angular size for an observer. - Added regression tests validating Gibraltar 2027-08-02 sun/moon azimuth-altitude samples and angular-size ranges for 24mm framing.
- Corrected
Photography Guidelandscape composite geometry to use real observer-based sun/moon alt-az offsets per scheduled shot instead of synthetic hourly drift. - Fixed composite horizon placement to derive from actual MAX sun altitude, preventing above-horizon shots from being rendered below the horizon for the tested Gibraltar scenario.
- Fixed composite body sizing to use angular-size-to-frame scaling so sun/moon disks render smaller and more physically plausible for the 24mm simulation.
- Fixed moon rendering in the composite to display only when the moon disk is actually occluding the sun at that shot.
- Updated landscape composite layout payload to carry per-shot sun radius and dynamic horizon line values consumed by
PhotographyGuideScreen. - Updated total-eclipse landscape composite visuals to use a very dark-blue sky theme with a thin pink horizon glow, moon disk styled to match the sky, and a MAX-only corona ring; partial/annular visuals remain unchanged.
- Bumped
apps/mobileversion to1.1.34.
- Added a new timer-linked
Photography Guideflow with a splitPreview/Photo Guideaction row on the Timer screen. - Added schedule generation helpers for photo timing distribution across eclipse phases (
3/5/7/9shots), including phase buckets and preview-progress anchors. - Added in-guide shot schedule table rows with UTC/local timestamps, phase labels, and generated eclipse preview thumbnails per shot.
- Added landscape composite simulation modal with 24mm framing, fixed
MAXanchor placement, clamped edge indicators, and moon rendering only during occlusion windows. - Added regression tests for photography guide schedule logic and composite anchor/clamping behavior.
- Updated navigation wiring to include a dedicated
PhotographyGuideroute with timer circumstance payload (including contact bearings for preview direction). - Bumped
apps/mobileversion to1.1.33.
- Verified mobile checks pass:
pnpm -C apps/mobile typecheck,pnpm -C apps/mobile lint, andpnpm -C apps/mobile test.
- Added address/place geocoding search on the
Timerscreen to place the observer pin from text input. - Added address/place geocoding search on
Location Settingswith coordinate autofill for adding favorites. - Added reverse-geocoded address label formatting utilities and regression tests for address-label construction.
- Updated favorite save flows to prefer reverse-geocoded address naming when the user keeps the default/empty favorite name.
- Updated testing notes to reflect that geocoding search is now implemented (first-match behavior depends on platform geocoder/locale).
- Bumped
apps/mobileversion to1.1.32.
- Verified mobile checks pass:
pnpm -C apps/mobile typecheck,pnpm -C apps/mobile lint, andpnpm -C apps/mobile test.
- Added first-run onboarding walkthrough for new users with step-by-step guidance across
Landing,Timer, andSettings. - Added persisted onboarding completion state in app preferences with an explicit
Skipoption. - Added an in-app
Help & FAQscreen underSettingswith concise FAQ/troubleshooting content and deep links to full documentation. - Added regression tests for onboarding walkthrough configuration and Help content/doc-link validation.
- Updated
RootNavigatorto wire onboarding overlay behavior and Help route deep-link path (eclipsetimer://settings/help). - Updated
documents/planning/tech-debt.mdto markADD-11andADD-13as completed and remove them from pending execution order. - Bumped
apps/mobileversion to1.1.31.
- Verified mobile checks pass:
pnpm -C apps/mobile typecheck,pnpm -C apps/mobile lint, andpnpm -C apps/mobile test.
- Updated
.github/workflows/eas-build.ymlto upload the Wear OS AAB to Google Play internal track in addition to the phone Android AAB. - Made Wear OS Google Play upload non-blocking with
continue-on-errorand explicit failure logging so the workflow continues to GitHub release creation even if Wear upload fails. - Bumped
apps/mobileversion to1.1.30.
- Continued the theme-token migration to remaining app surfaces by tokenizing
EclipsePreviewScreenand removing hardcoded dark-only panel/background styling there. - Updated app error recovery UI to respect active app theme preference by wiring
ErrorBoundaryto theme colors through app state context. - Removed leftover hardcoded startup-shell fallback colors in
RootNavigatorstyles so startup visual tokens come from the active theme. - Bumped
apps/mobileversion to1.1.29.
- Verified mobile checks pass after this migration step:
pnpm -C apps/mobile typecheck,pnpm -C apps/mobile test, andpnpm -C apps/mobile lint.
- Added a new
Settingsparent screen that links toTheme Settings,Notification/Alarm Settings, andLocation Settings. - Added a dedicated
Theme Settingsscreen with persistedSystem,Light, andDarkappearance options. - Added centralized mobile theme infrastructure (
apps/mobile/src/theme/colors.ts,apps/mobile/src/theme/resolveAppTheme.ts,apps/mobile/src/theme/useAppTheme.ts) and app-state support for storing theme preference. - Added a theme-resolution regression test (
apps/mobile/tests/theme-resolution.test.ts). - Added archived internal testing feedback report at
documents/reports/testing-feedback_2026-02-26.pdf.
- Reorganized side-menu navigation to expose a single
Settingsdestination, with notification/location settings moved under the parent settings flow. - Wired React Navigation container theming to app preference + system appearance and updated shared/shell styling (
BurgerButton,Landing,Timer,Notification/Alarm Settings,Location Settings) to use theme tokens for light/dark support. - Updated Timer favorite empty-state guidance path to
Menu > Settings > Location Settings. - Updated
documents/planning/tech-debt.mdwith internal testing feedback mapping and new tracked backlog items (ADD-11..ADD-15,IMP-28..IMP-29). - Bumped
apps/mobileversion to1.1.28.
- Verified mobile checks pass after these changes:
pnpm -C apps/mobile typecheck,pnpm -C apps/mobile test, andpnpm -C apps/mobile lint.
- Updated Android phone app wearable listener manifest registration to replace deprecated
com.google.android.gms.wearable.BIND_LISTENERwith filteredMESSAGE_RECEIVEDintent handling for live-location Data Layer messages. - Resolved release build failure in CI caused by
WearableBindListenerlint fatal error during:app:lintVitalRelease.
- Bumped
apps/mobileversion to1.1.27.
- Added end-to-end Wear companion live pipeline: watch GPS payload publishing, phone-side active-eclipse computation, and live render payload sync with sun-only fallback when no active eclipse is found.
- Added Wear preview mode synchronization with strict phone
Previewroute gating, preview payload publishing, and two-way preview scrub messaging between phone and watch. - Added watch native eclipse renderer (
EclipseRenderView) with sun/moon drawing and totality ring/corona transitions, plus stale-live fallback handling and status messaging. - Added a Windows disposable phone+Wear emulator workflow guide for path-length-safe local native testing (
documents/guides/windows-disposable-phone-wear-emulator.md).
- Extended wearable shared preview payload schema with travel vector and contact progress anchors so phone and watch preview frames stay aligned while scrubbing.
- Improved Android Data Layer reliability with node-id caching/retry send flow, a listener service fallback handshake, and JS bridge
sendMessagesupport. - Updated Wear package/config wiring to use
com.lallimaven.eclipsetimerpackage naming in watch build/docs/workflows and to require watch location permissions. - Updated phone preview visuals to blend totality ring/corona effects and synchronize scrub progress with watch input.
- Excluded Android build output folders from Metro resolution to avoid duplicate module/path issues.
- Bumped
apps/mobileversion to1.1.26.
- Added regression tests for wear live payload computation, preview payload generation, preview scrub payload parsing, and totality glow blending behavior.
- Added Android and Wear OS screenshot workflow device presets with profile-resolution fallbacks for Samsung, Pixel, and generic Wear form factors.
- Added iPad simulator targets to the iOS screenshot workflow dispatch input options.
- Added
supportsTablet: trueinapps/mobile/app.jsonso iOS build metadata explicitly supports iPad.
- Improved Android and Wear screenshot automation to launch the app with
am start, verify foreground activity before capture, and use safer deep-link iteration handling. - Updated the Timer screen eclipse picker modal to auto-scroll to the selected eclipse (or first upcoming option) and recover reliably when
FlatListindex scrolling fails. - Bumped
apps/mobileversion to1.1.25.
- Tightened the Timer screen compact
MAX Viewpreview to show the sun-only disk area (without surrounding corona glow) and reduced its footprint so the hero layout fits more cleanly. - Bumped
apps/mobileversion to1.1.24.
- Added dedicated Android and Wear OS emulator screenshot workflows that build local APK artifacts, capture screenshots, package results into a single zip, and upload that zip to the latest GitHub release.
- Added Wear app deep-link handling for the
eclipsetimer://scheme in the Wear module so screenshot automation can drive deterministic screens by URL.
- Updated iOS simulator screenshot release publishing to upload one packaged screenshots zip asset instead of attaching each screenshot file individually.
- Updated the Wear OS screenshot workflow to support configurable deep-link inputs and per-link screenshot capture behavior.
- Bumped
apps/mobileversion to1.1.23.
- Fixed Wear OS release signing detection in
apps/mobile/android/wear/build.gradleso EAS local Android phone builds no longer fail during:wearproject configuration. - Scoped the Wear signing guard to
:wearrelease tasks and improved signing-property resolution for local EAS credential injection.
- Bumped
apps/mobileversion to1.1.22.
- Refined the Timer screen declutter pass by keeping the larger map while moving action controls out of the map viewport into a compact row below it, so map content is less obstructed.
- Simplified the Active Eclipse switcher to a single concise row to reduce vertical and textual chrome.
- Increased map viewport height to
420for stronger map-first focus on the Timer screen. - Bumped
apps/mobileversion to1.1.21.
- Moved the map direction legend controls to the lower-left legend stack so they no longer block the map action buttons.
- Simplified map legend labels by removing
On/Offstate text for direction, eclipse visibility, and central-path overlays. - Bumped
apps/mobileversion to1.1.20.
- Corrected Timer screen compact
MAX Viewmoon/sun sizing so moon-size ratios now match the full preview geometry instead of using oversized fixed moon radii.
- Bumped
apps/mobileversion to1.1.19.
- Added regression tests to verify compact-stage moon/sun ratio scaling and C1/C4 tangency distance in the Timer screen
MAX Viewsize profile.
- Split the Timer screen
Next Event Timerhero into a two-column layout with a compact right-sideMAX Viewsun preview.
- Bumped
apps/mobileversion to1.1.18.
- Updated Timer screen duration formatting to show
hh:mm:sswhen total minutes are greater than 60; durations at 60 minutes or below continue showingXm YYs. - Bumped
apps/mobileversion to1.1.17.
- Updated Timer screen summary metrics: replaced
MagnitudewithC1-C4 Duration(computed from first to last contact times) and renamedCentral DurationtoTotality Durationfor clearer eclipse-phase wording. - Bumped
apps/mobileversion to1.1.16.
- Removed the Android map-mode rebuild hint from the Timer screen.
- Bumped
apps/mobileversion to1.1.15.
- Bumped
apps/mobileversion to1.1.14to trigger a fresh mobile release build after rotating Google Maps key secrets in GitHub Actions.
- Corrected preview contact interpolation so C1/C2/C3/C4 remain geometrically consistent even when the moon track has a non-zero closest-approach offset.
- Improved satellite/hybrid map readability by reducing eclipse overlay opacity in photo map modes and forcing map remount when switching map type to refresh tile detail loading.
- Bumped
apps/mobileversion to1.1.13.
- Added a regression test that verifies C1/C4 tangency remains exact for partial eclipse preview geometry with non-zero closest approach and directional travel.
- Fixed eclipse preview moon trajectory to use contact-bearing motion vectors (including vertical drift), so locations like the 2024 eclipse path animate from lower-left toward upper-right when appropriate.
- Preview now shows a text summary of the computed moon-path direction relative to the sun for the selected GPS point.
- Added regression tests for diagonal travel vector behavior and user-facing direction labeling in preview geometry utilities.
- Updated preview mode moon motion so left/right travel direction follows local contact bearing progression when bearing data is available.
- Wired contact bearing values into preview payload construction so direction-aware geometry has access to C1/C2/C3/C4 bearing inputs.
- Added regression tests for bearing-based travel direction selection and fallback behavior when bearing pairs are incomplete.
- Improved eclipse preview moon-path geometry so contact phases align with expected tangency behavior: C1 starts at outer tangency, C2 reaches inner tangency, MAX is centered, and C3 remains at inner tangency before sun reappears.
- Added regression tests for preview geometry calculations to keep C1/C2/MAX/C3 positioning behavior verifiable.
- Added
production-wear-apkEAS build profile inapps/mobile/eas.jsonto produce Wear OS APK output (wear-release.apk) for release packaging.
- Updated
.github/workflows/eas-build.ymlto build both Wear OS artifacts (wear-release.aabandwear-release.apk) and attach both to GitHub releases. - Kept store submission scoped to the phone Android AAB only; Wear OS artifacts are released on GitHub and not uploaded to Google Play.
- Added a new docs guide set under
documents/guides/: setup and development, contributing, deployment, troubleshooting, and performance optimization. - Added
documents/REORGANIZATION.mdto document the new documentation layout and migration summary.
- Reorganized
documents/into purpose-based sections (guides/,planning/,reference/) and updateddocuments/README.mdwith quick-start, role-based reading paths, and maintenance standards. - Updated
.github/workflows/eas-build.ymlto temporarily disable Wear OS artifact validation, release asset packaging, and Google Play upload steps until the Wear package is ready in Play Console.
- Updated
.github/workflows/eas-build.ymlto upload the Wear OS AAB (com.lallimaven.eclipsetimer.wear) to Google Play internal track in addition to the phone AAB, so releases for both packages are created directly from CI.
- Updated the Wear module Android
applicationIdtocom.lallimaven.eclipsetimer.wearso the Wear APK installs as a distinct package instead of conflicting with the phone app package during install/update.
- Updated Play Store submission in
.github/workflows/eas-build.ymlto upload only the Android AAB and temporarily disable Wear APK upload after Google Play returnedAPKs are not allowed for this application..
- Updated mobile build artifact collection in
.github/workflows/eas-build.ymlto reliably distinguish phone and Wear APK outputs when EAS local builds emit genericbuild-*.apkfilenames.
- Added a dedicated
production-wearEAS build profile to produce a Wear release APK (android/wear/build/outputs/apk/release/wear-release.apk). - Added initial Wear OS companion module scaffolding and phone/watch Data Layer bridge wiring for Phase 0.
- Updated mobile release workflow to build iOS, Android (AAB + APK), and Wear APK in one run, and publish the Wear APK as a GitHub release asset.
- Updated Google Play internal-track submission to upload both the phone AAB and Wear APK in the same release edit.
- Reworked notification/alarm settings so eclipse-level
T-1handT-10mreminders always use system notifications. - Replaced
Test NotificationwithPlay Test TTS Alarmfor foreground in-app voice alarm testing. - Removed enabled in-app event alarm maintenance from Notification/Alarm Settings; per-event alarm toggles remain managed on the Timer screen.
- Removed the
Voice (TTS)toggle from Notification/Alarm Settings. - Removed notification-delivery TTS playback for background reminders.
- GitHub Release artifacts are now versioned as
eclipse-timer-v<version>.ipa,eclipse-timer-v<version>.aab, andeclipse-timer-v<version>.apkinstead of static names. - Updated in-app alarm TTS phrasing to use concise event keys for
a1prompts ("<a1> seconds to C1/C2/MAX/C3/C4") and event-specific completion phrases ("Partial eclipse started","Totality started","This is the maximum eclipse","Totality ended","Partial eclipse ended").
- Added a per-eclipse master toggle on the Timer screen (
Enable alarms and reminders for this eclipse) that gates all event alarms/reminders while preserving per-event selections. - Added foreground in-app alarm timing controls in Notification/Alarm Settings:
a1 lead (sec)anda2 countdown (sec)with validation (a1: 2..60,a2: 1..30,a2 < a1). - Added a dedicated in-app alarm engine for enabled event contacts that speaks:
a1phrase ("<a1> seconds to <Event>")- second-by-second countdown from
a2to1 - final phrase at event time (
"We're at <Event>")
- Added regression tests for alarm timing normalization, in-app alarm sequencing, and reminder schedule generation.
- Renamed
Notification SettingstoNotification/Alarm Settingsin UI labels/navigation. - Reworked reminder scheduling to fixed per-eclipse background reminders only:
- one reminder at
T-1hand one atT-10m - both anchored to the eclipse first event time
- no per-contact reminder scheduling
- one reminder at
- Preserved mock contact timeline compatibility with the new hybrid model for both fixed reminders and in-app event alarms.
- Updated testing scenarios and status documentation to reflect the hybrid alarm/reminder model and foreground-only precision alarm behavior.
- Added Android APK output (
android.apk) to the existing release pipeline artifacts while keepingios.ipaandandroid.aab. - Added a dedicated
production-apkEAS build profile for local Android APK generation in CI.
- GitHub Releases now use the current version section from
CHANGELOG.mdas the release body instead of empty/auto-generated notes.
- Added a configurable mock contact timeline for on-device alarm testing, with persisted settings for
C1offset and per-contact gap in Notification Settings.
- Replaced manual mock timeline apply flow with clearer toggle-driven behavior and inline ON/OFF status feedback in Notification Settings.
- Mock timeline notifications now schedule as a repeating cycle (
C1 -> C2 -> MAX -> C3 -> C4) and continue looping while mock mode is enabled. - Added a regression test covering mock contact timeline offset/gap behavior.
- Optimized GitHub Actions by removing duplicated setup/install work in
.github/workflows/eas-build.yml(CI checks and local mobile build now share a single job setup). - Added
paths-ignorefor docs/log-only changes in.github/workflows/ci.ymland.github/workflows/eas-build.ymlto avoid unnecessary runner usage. - Improved workflow runtime by preferring offline dependency installs (
pnpm install --frozen-lockfile --prefer-offline) across CI/build/screenshot workflows. - Reduced redundant release overhead in
.github/workflows/eas-build.ymlwith shallow checkouts plus tag fetch, and by running release gate checks in parallel with the build. - Made Android SDK install incremental in
.github/workflows/eas-build.ymlso only missing SDK components are installed. - Removed duplicate iOS submit step and fixed Play release-note truncation to stay within the 500-character limit.
- Timer screen now supports in-screen multi-eclipse switching via an eclipse picker modal.
eas-build.ymlnow always builds both iOS and Android in a single run.- Store submit now compares
apps/mobile/package.jsonversion to the latest Git release tag and runs only when incremented, so retries after failed builds can reuse the same version. - Store release notes are now sourced from
CHANGELOG.mdfor all versions between the last successful release tag and the current version, then attached to submissions where supported.
- Eclipse catalog — 200+ solar eclipses (1900–2100) with Besselian element polynomials, sourced from NASA data.
- Eclipse engine — computes five contact points (C1/C2/max/C3/C4), magnitude, obscuration, and eclipse kind for any observer location.
- Interactive map — tap or drag a pin to set observer location; toggle satellite/hybrid views.
- Overlay paths — penumbral and umbral/antumbral shadow paths rendered on the map, loaded lazily by decade.
- GPS location — one-tap "Use GPS" with pre-permission rationale dialog; location stays on-device.
- Live countdown — ticking countdown to the next eclipse contact event.
- Local time display — contact times shown in both UTC and device-local time.
- Search & filter — tokenized search on the eclipse landing list (by year, date, kind, ID).
- Notifications — per-contact local notification scheduling with configurable reminder lead times, sound, vibration, and TTS audio modes.
- Notification settings — dedicated screen for global and per-eclipse notification preferences, persisted via AsyncStorage.
- NASA GIF preview — prefetched/cached eclipse animation preview with loading placeholder and error fallback.
- Error boundary — catches runtime crashes with a recovery UI and Sentry reporting.
- Sentry crash reporting —
@sentry/react-nativeintegration (production-only). - Splash screen control — native splash held until catalog loads via
expo-splash-screen. - Accessibility — labels, roles, and states on all interactive elements (landing + notification settings screens).
- Privacy policy —
PRIVACY_POLICY.mdcovering location, Sentry, NASA GIF, notifications; iOS privacy manifest inapp.json. - Store metadata — descriptions, keywords, content rating answers, icon (alpha-stripped for iOS) in
documents/store-metadata.md. - CI/CD — GitHub Actions CI (typecheck/lint/test), EAS Build + Submit workflow,
expo-updatesOTA support. - Pre-commit hooks — Husky + lint-staged running Biome check on staged files.
- EAS Build profiles —
development,preview,productionineas.json.
- Refactored
App.tsxfrom ~1 000-line god component into screens, hooks, and utilities. - Replaced
ScrollView+.map()with virtualizedFlatListon landing screen. - Engine magnitude formula uses geometric
(L1obs - Δ) / (L1obs + L2obs)instead of hardcoded1. - Overlay polygons loaded lazily by decade instead of monolithic JSON.
evaluateAtTresults cached per-tduring contact solving to avoid duplicate evaluations.
- Countdown timer now ticks in real time (was static).
- GPS altitude wired through to engine
elevM(was hardcoded to 0).