Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Focus Mate icon

Focus Mate

Stay sharp. Don't drift.

An anti-drowsiness focus timer for work and study sessions. Set an interval; when it expires, a math problem blocks the screen. You can't dismiss it without solving the problem — so even if you start dozing off, the app forces a periodic cognitive break.

Install · Features · How it works · Architecture · Build from source · Contributing


✨ Why Focus Mate?

Common focus tools Focus Mate
❌ Play music and hope you don't drift ✅ Forces you to engage every interval
❌ Pomodoro timer with no engagement check ✅ Math challenge to prove you're still with it
❌ Silently buzzes while you doze ✅ Escalates to a continuous alarm if you don't respond
❌ All UI, no follow-through ✅ Unskippable challenges, real cognitive breaks

The science is simple: drowsiness is reversible with a 10-second engagement break. A stretch, a sip of water, or solving a math problem. Focus Mate makes that break non-negotiable and cognitively active — perfect for coding sessions, deep work, or study marathons.


📱 Screenshots

Home (idle) Home (focusing) Math challenge
home-idle home-running challenge
Set interval, start session Live countdown with progress ring Math problem to solve
Settings Escalation alarm Editor (custom interval)
settings red pulsing UI + looping alarm scroll wheel + manual editor

🚀 Features

🎯 Core

  • Customizable intervals — 1 to 240 minutes via scroll wheel or manual editor
  • Math challenge — 5 difficulty tiers (single-digit → 3-digit arithmetic) on a 60-second grace period
  • Anti-bypass lockPopScope + wakelock + ongoing notification = can't swipe away or screen-off
  • Foreground service — math challenges survive backgrounding, app kill, even device reboot (Android 8+)

🛡️ Escalation

  • 60-second grace period (configurable: 15s/30s/60s/120s) to solve the challenge normally
  • Looping alarm + vibration kicks in if you don't respond — continues until you touch the screen
  • Visual urgency — red pulsing background overlay + "TOUCH SCREEN" pill + "STOP ALARM & SUBMIT" button
  • Bypasses Do Not Disturb — uses USAGE_ALARM audio attribute on Android

📊 Tracking

  • Today stats — focused time, problems solved, alarms triggered
  • Streak counter — consecutive days using the app
  • Persistent settings — everything in SharedPreferences, survives restart + reboot

🎨 Polish

  • Custom two-tone alarm — procedurally generated C5-E5 ascending bell (no copyrighted assets)
  • Aurora animated background — soft drifting gradients
  • Plus Jakarta Sans + JetBrains Mono typography
  • Haptic feedback on every interaction
  • Material 3 design language with custom dark theme

🧠 How it works

T = 0          [Start focus session]
                  ↓
T = 0..N       [Live countdown with progress ring]
                  ↓
T = N          [Alert fires, challenge starts]
                  ↓
T = N..N+60    [User has 60s to solve math problem]
                  ↓
T = N+60       [If unsolved: ESCALATION]
                  ├─ Looping alarm tone (C5-E5)
                  ├─ Vibration pattern (400ms on, 200ms off)
                  ├─ Red pulsing background
                  └─ "TOUCH SCREEN" indicator
                  ↓
[User touches screen OR types in answer]
                  ↓
                  ├─ Alarm silences
                  ├─ User gets another 60s to solve
                  ↓
[Correct answer submitted]
                  ↓
                  ├─ Stats updated (focus time, problems solved)
                  ├─ Next interval scheduled
                  └─ Return to T = 0..N

🏗️ Architecture

lib/
├── main.dart                       # App entry, MaterialApp, timezone setup
├── core/
│   ├── math_problem.dart           # MathProblem + MathProblemGenerator
│   ├── theme.dart                  # Brand colors, design tokens, Material 3 theme
│   └── alarm_sound_registry.dart   # Preset alarm sound definitions
├── services/
│   ├── notification_service.dart   # flutter_local_notifications wrapper + MethodChannel
│   ├── settings_repository.dart    # SharedPreferences-backed AppSettings + PomodoroSettings
│   └── stats_repository.dart       # Daily stat persistence + streak tracking
├── providers/
│   └── focus_provider.dart         # ChangeNotifier state machine (idle → running → challengeActive → escalated)
├── screens/
│   ├── home_screen.dart            # Idle + running views, today stats card
│   ├── challenge_screen.dart       # Full-screen math problem + escalation UI
│   └── settings_screen.dart        # Interval, difficulty, escalation, alarm toggles
└── widgets/
    ├── aurora_background.dart      # Animated mesh-gradient background
    ├── brand_mark.dart             # Custom-painted target/aperture logo
    ├── interval_wheel.dart         # Vertical scroll wheel with landmark values
    └── pulse_rings.dart            # Animated focus rings

Native (Android) — android/app/src/main/kotlin/id/focusmate/focus_mate/MainActivity.kt

  • MethodChannel handler for id.focusmate.alarm
  • MediaPlayer with isLooping = true for the alarm sound
  • Vibrator with repeating pattern
  • AudioAttributes.USAGE_ALARM to bypass silent mode

Native (iOS) — ios/Runner/AppDelegate.swift

  • Same MethodChannel pattern
  • AVAudioPlayer with numberOfLoops = -1 (loop forever)

State machine

  • FocusState enum: idle, running, challengeActive, escalated
  • State transitions are explicit and gated (e.g. can only escalate from challengeActive)
  • All timers cancelled on state transition to prevent leaks

📦 Install

Android (sideload)

  1. Download the latest FocusMate-arm64-vX.Y.Z-release-signed.apk from Releases
  2. Transfer to your Android device
  3. Enable "Install unknown apps" for your file manager / browser (Settings → Apps → Special access → Install unknown apps)
  4. Open the APK and tap Install

Note on signing: v1.0.0–v1.0.5 used the Android debug key. v1.1.0+ use a proper release keystore. If you have an older version installed, uninstall it first (signatures don't match).

iOS

Build from source — see Build from source below. (TestFlight / App Store distribution not yet set up.)

Permissions

First launch will request:

  • Notifications — required for the math challenge alert
  • Exact alarms — required for interval-accurate scheduling
  • Battery optimization exemption — prevents Android from killing the timer

🛠️ Build from source

Prerequisites

  • Flutter 3.44+ (Dart 3.12+)
  • Android SDK 34+ (for Android builds)
  • Xcode 15+ (for iOS builds)
  • Java 17+ (for Android Gradle builds)

Setup

git clone https://github.com/hellogunawan99/focus-mate.git
cd focus-mate
flutter pub get

Android

flutter build apk --release --target-platform android-arm64
# Output: build/app/outputs/flutter-apk/app-arm64-v8a-release.apk

iOS

cd ios && pod install && cd ..
flutter build ios --release
# Then open ios/Runner.xcworkspace in Xcode for device deployment

Run in debug mode

flutter run                    # picks first connected device
flutter run -d <device-id>     # specific device

Run tests

flutter test                   # all unit + widget tests
flutter test test/math_test.dart  # specific file

🧪 Testing

  • Unit tests for MathProblemGenerator (problem difficulty, operator distribution)
  • Widget tests for IntervalWheel (centering, scroll range, editor behavior, fling-bound clamps)
  • All tests run on every commit via widget test suite
$ flutter test
+0: All tests passed!

🤝 Contributing

This is a personal-use project, but PRs and bug reports are welcome!

Reporting bugs

  1. Check Issues first
  2. Open a new issue with:
    • Device model + Android version
    • Focus Mate version (Settings → About)
    • Reproduction steps
    • Expected vs actual behavior

Submitting PRs

  1. Fork the repo
  2. Create a feature branch (git checkout -b feature/awesome-thing)
  3. Add tests for new behavior
  4. Run flutter analyze + flutter test — must pass clean
  5. Open a PR with a clear description

Code style

  • flutter analyze clean
  • Prefer widget tests for any picker/scroll/offset math
  • Document any new design tokens in lib/core/theme.dart

📄 License

MIT — see LICENSE for details.


🙏 Credits

  • App icon — procedurally generated target/aperture mark (custom)
  • Alarm sound — procedurally generated C5-E5 sine wave (custom)
  • FontsPlus Jakarta Sans, JetBrains Mono (both open-source)
  • Built withFlutter, Dart, Material 3, and a lot of flutter_local_notifications debugging

Focus Mate v1.1.3 · hellogunawan99 · 2026

⬆ Back to top

About

Anti-drowsiness focus timer with math-challenge enforcement. Flutter.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages