Skip to content

Shivendra1702/GeoTaskerApp

Repository files navigation

GeoTasker

Pin tasks to places. Get reminded when you arrive.

Location-first task manager for Android. Tasks fire when you walk into their geofence radius — never on a clock.

Built from the GeoTasker Design System (Claude-generated tokens, JSX prototypes, six language packs). React Native CLI 0.76, bare workflow, Hermes, Mapbox SDK v11, Transistorsoft background-geolocation, Notifee.


Prerequisites

  • Node 18+ (20.x LTS recommended)
  • JDK 17 (Temurin / Zulu)
  • Android Studio with SDK 34+ and an emulator or real device
  • A Mapbox account with two tokens:
    • Public token (pk.…) — for runtime map rendering
    • Downloads token (sk.… with Downloads:Read scope) — for fetching the SDK at build time

Setup

# 1. Install JS deps (already done if you scaffolded — re-run if node_modules is missing)
npm install --legacy-peer-deps

# 2. Mapbox public token (runtime)
cp .env.example .env
# Then edit .env and replace pk.placeholder_replace_me with your real public token.

# 3. Mapbox downloads token (build time)
# Add to ~/.gradle/gradle.properties (NOT committed):
echo 'MAPBOX_DOWNLOADS_TOKEN=sk.your_secret_token_here' >> ~/.gradle/gradle.properties

The downloads token must have the Downloads:Read scope, otherwise gradle will 401 when fetching the Mapbox Maven artifact.


Run

# Start Metro
npm start

# In another terminal — build and install on a connected device or emulator
npm run android

First build takes 5–10 min while gradle downloads native deps and compiles them. Subsequent builds are seconds.


Architecture

src/
  app/             root providers, bootstrap
  navigation/      RNN root stack + bottom tabs + modal stack
  screens/         Onboarding, Map, Tasks, AddTask, TaskDetail, Alerts, Settings
  components/
    primitives/    GTButton, GTFab, GTChip, GTSurface, GTSwitch, GTSlider
    icons/         Phosphor wrappers (Ico namespace)
    map/           TaskPin, ArrivalPing
    task/          TaskCard, AlertRow
  theme/           tokens.ts (CSS port), light.ts, dark.ts, useTheme
  i18n/            6 language packs + i18next init
  services/
    map/           Mapbox token init, style URLs
    geofence/      GeofenceService.sync(), permissions, headlessTask
    notifications/ Notifee channels, displayArrival, action handlers
    storage/       MMKV singleton
  store/           Zustand stores (tasks, settings) with MMKV persist
  models/          Task, Alert, ids
  utils/           distance (haversine + format), time (quiet hours), logger

Geofence flow

  1. User pins a task → tasksStore.addTask()tasksStore.subscribe triggers GeofenceService.sync()
  2. GeofenceService.sync() reconciles registered geofences against active (non-done) tasks via the Transistorsoft library
  3. Library runs a foreground service with a low-importance ongoing notification on channel geotasker_background
  4. When the user crosses a radius, the OS fires the geofence; the lib invokes the JS headless task
  5. headlessTask.ts reads MMKV, checks quiet hours + per-task cooldown, fires Notifee on channel geotasker_arrivals with Mark done + Snooze 15 min actions
  6. Action presses route through notifee.onBackgroundEvent (in index.js) → handleNotifeeEvent → store mutation

Theme

All visual decisions tokenized in src/theme/tokens.ts, mirrored from the design system's colors_and_type.css. Light/dark themes built in light.ts/dark.ts. ThemeProvider watches Appearance for the system theme mode.

i18n

6 packs in src/i18n/{en,hi,bn,mr,te,ta}.ts. Initial language = stored choice → device locale → en. Switching language in Settings live-updates everything (including the bottom-nav, since it consumes t()).


Testing the geofence end-to-end

Emulator (UI only — geofences are unreliable without real GPS):

adb emu geo fix -73.98566 40.74844     # set lat/lon

Real device (recommended for geofences):

  1. Fresh install → onboarding → grant fine + background location + notifications
  2. Tap "+" on Map → drop pin ~250 m from your current location → set radius 150 m → "Pin task here"
  3. Force-stop the app from system Settings (so we test the headless task path)
  4. Walk to the location
  5. Heads-up notification fires within ~30 s of crossing the radius
  6. Tap "Mark done" → app opens → task is checked off
  7. Reboot device, do not launch app, walk back into a different task's zone → notification still fires (verifies RECEIVE_BOOT_COMPLETED + startOnBoot)

Scripts

npm start           # Metro bundler
npm run android     # build + install Android app
npm run lint        # ESLint
npm test            # Jest
npx tsc --noEmit    # type check

Known gotchas

Issue Fix
Gradle 401 on Mapbox Maven repo Set MAPBOX_DOWNLOADS_TOKEN in ~/.gradle/gradle.properties (with Downloads:Read scope)
Map renders but tile fetches fail MAPBOX_PUBLIC_TOKEN missing or wrong in .env
Background notification never fires after kill Manufacturer battery optimization: add GeoTasker to "no battery restrictions" in Android Settings → Apps
Fonts fall back to Roboto Verify android/app/src/main/assets/fonts/ contains all 8 TTFs
Reanimated cryptic build error Check babel.config.js: react-native-reanimated/plugin MUST be the last plugin
Notifee actions don't trigger All 3 contexts must be wired: onBackgroundEvent (in index.js, before AppRegistry), onForegroundEvent (in App.tsx), and getInitialNotification (in linking.ts)
Snooze re-fires while user lingers Per-task 60-min cooldown in MMKV. Tune COOLDOWN_MS in src/services/geofence/headlessTask.ts

About

Location-based Android task manager — React Native + Mapbox + expo-location geofencing + Notifee. Six languages, full theme support.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors