Repository navigation
Focuno: screen time, blocking, focus timer with Strict mode, minimal UI and study tools - #1
Draft
MathewsV-Manoj wants to merge 34 commits into
Draft
MathewsV-Manoj wants to merge 34 commits into
MathewsV-Manoj wants to merge 34 commits into
Conversation
Sets up the full com.startup.focuno package structure up front so later phases only add files, never move them. Build uses a version catalog with AGP 9.4 (built-in Kotlin), Kotlin 2.4.20, KSP, Hilt, Room, DataStore, WorkManager and Compose BOM 2026.09.00. compileSdk is 37 because the current stable Compose stack requires it; targetSdk stays 36. The manifest declares the usage-stats, overlay, notification, foreground-service and boot permissions, strips INTERNET so the app stays fully on-device, and disables cloud backup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Every push to main or a claude/ branch builds the debug APK on GitHub and replaces the "focuno-debug" pre-release, giving one fixed download link for testing on a phone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Usage-event walk (screen-off aware, per-package activity sets, window clipping), focus score, schedule evaluation with overnight windows, bypass policy and streak calculation, all as pure code with unit tests. Room entities/DAOs for every table in the spec plus an hourly table for "worst hour", DataStore settings and the repositories on top. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
FocunoAccessibilityService reads package names only and feeds BlockEngine, which holds the foreground app as explicit state so the block never drops or flickers. The block screen is a Compose overlay (SYSTEM_ALERT_WINDOW, falling back to an accessibility overlay) with Back consumed. "I need this" runs a 15s countdown, a 15+ character reason, then a 5 minute unlock with a 30 minute cooldown, logging every stage. Also: rule-based nudges with rate limits, a foreground monitor service, boot receiver, 15-minute watchdog and a 00:05 rollup worker. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
…arding Focus dashboard with animated gauge, protection banner, streak and focus sessions; Apps breakdown with recategorising and a 7 day selector; Block tab with grouped schedules, quick block and a searchable add flow with Material 3 time pickers; Insights with trends, worst hour and bypass stats (no rankings); Settings, Privacy, Health Check with one-tap fixes, OEM keep-alive guidance, and an eight step onboarding. Strict windows lock editing while open. All text lives in strings.xml. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Screen time now counts every app Android Settings counts (only the home screen and system UI are left out), including Focuno itself and apps with no launcher icon, and a Screen time check screen lists what is counted and what is not. The blocker repairs missed window events by polling the active window every 2s, falls back to sending the user home if the overlay cannot be drawn, and keeps a blocker log in the Health check. Schedules gain a scope (whole app or only Reels/Shorts) with a v1 to v2 database migration. Reels/Shorts detection looks only at a few view ids, and window-content events are enabled only while such a rule is active. The add flow is now three big choices: app, what, when. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Home now centres on a drawn buddy that reacts to your day and grows accessories with your level, a level bar, a big start-focus button and three daily missions. Points only ever go up: actions score instantly and each finished day is banked once at rollup. Trophies shows level, how to earn points and a badge grid; level-ups and new badges get a confetti pop-up exactly once. Tabs are now Home, Shield, Stats and Trophies, the Shield tab shows a big ON/OFF status, and wording is shorter and friendlier. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
The "Allow restricted settings" menu only appears after the greyed-out Accessibility item has been tapped once, so say that first and add a note for when the menu is missing. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Android 13+ greys out Accessibility for sideloaded apps and an app cannot lift that itself. Blocking no longer depends on it: when the accessibility service is not running, the monitor service follows the foreground app from usage events (ForegroundTracker) and drives the same blocking engine through a fallback host, drawing the pause screen with the overlay permission. Accessibility stays as an optional upgrade for faster reactions and Reels/Shorts-only blocking. Protection status now reflects either path, a stopped background service is reported by the watchdog, and the copy says Accessibility is optional. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
The main tabs had too much text. They are now Focus, Block, Stats and Me: - Focus: a big timer ring, duration pills, one Start button. - Block: one row per block with a lock icon (green = Strict, amber = can end early) and an on/off switch. - Stats: the day's total, a helpful/okay/time-eater bar, and the app list. - Me: buddy, level bar, today's missions and badges. Cards are flat, the problem banner is one line, the pause screen shows a big countdown and a single Go back button, and onboarding copy is shorter. 91 strings that nothing used any more are removed. Strict mode: - Focus timers can now be strict. A strict timer cannot be ended early (the repository refuses) and its pause screen has no unlock. - While Strict is off, an amber note warns that the block can be ended early. It sits above the time presets, because a preset saves on tap. - Ending a non-strict timer asks first and suggests Strict next time. - A strict all-day, every-day block is no longer allowed, and an existing one is never locked: it would have had no gap in which to edit or remove it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Pick an app and a daily budget (15 min to 2 h). Once today's use reaches it, the pause screen shows until midnight, with a countdown. A heads-up appears once, five minutes before the time runs out. - Today's use is measured from usage events, the same way as the screen time numbers. While the app stays in front it keeps counting between measurements, and it is re-measured once a minute, so the limit lands on time without polling all day. - Strict limits have no unlock once used up, and cannot be raised, paused or deleted until midnight. Non-strict limits keep the usual wait-and-reason unlock. - Works in basic mode too: it uses the same blocking engine. - Add flow: pick an app, then "Daily time limit" next to the time presets. Limits get their own section on the Block tab with a "12m of 30m today" bar. - Database v3 adds an app_limit table (new table only, no data change). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
- Focus tab: a row of subject chips under the duration. Tap one to tag
the next timer, tap again to clear. "+ Subject" opens a small dialog to
add or remove subjects (kept in settings, in the order added).
- The pause screen shows the subject ("Signals") instead of the generic
"Focus session", and the running timer shows it under the clock.
- Stats > Trends: a "Study time" card with minutes per subject for the
chosen range. Time counts what was actually focused, so a timer ended
early counts up to where it stopped.
- Database v4 adds focus_session.subject (default empty), so older
sessions show as "No subject".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
A headphones button on the Focus tab picks a background sound: white noise, soft rain (pink noise), deep waterfall (brown noise) or ocean waves (brown noise that swells every nine seconds). The sound is generated on the phone, so nothing is downloaded and no internet is needed. - It starts with each focus timer and stops on its own when the timer ends, or right away on "End early". - Picking a sound during a timer switches at once; picking one while idle plays an 8-second preview. - It fades in over a second, and stops when another app takes audio focus (for example an incoming call). - Playback runs on its own thread with a generation counter, so switching sounds never leaves an old one playing and the UI never waits on audio. - NoiseGeneratorTest checks range, loudness, and that pink and brown are smoother than white. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
The Focus tab now has three modes: - Timer: as before, 15 to 90 minutes. - Pomodoro: 2, 3 or 4 rounds of 25 minutes with 5-minute breaks. Apps are paused only during focus rounds; the dial counts down each round or break and shows "Round 2 of 4". - Stopwatch: counts up until "Finish". It is never strict, stops by itself after 4 hours, and counts as a finished session after 10 min. How it works: - The running plan is stored as start, end, round and break lengths, and FocusPlan works out the current phase from them, so it survives app restarts. The blocker pauses apps only while the plan is in a focus phase, and the pause screen counts down to the end of the round. - A Pomodoro saves one session row per round, so each finished round earns its points; "End early" removes rounds that have not started. - An alarm at each phase boundary posts "Break time", "Back to focus" or "Focus done!", also with the screen off. It is an inexact alarm that needs no special permission, so Android may deliver it a little late when the phone has been idle for long. Boot and app updates set it again. - Strict covers the whole plan, breaks included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Widget (no new library; plain RemoteViews): - Shows today's screen time and the streak. - "Start 25 min focus" starts a non-strict timer in one tap, without opening the app. While a plan runs, the button turns into a live countdown (or count-up for a stopwatch) and opens the app instead. - Refreshes when a timer starts or stops, at every Pomodoro phase, and every few minutes from the background service, and skips all work when no widget is placed. FocusController now starts and stops focus plans for both the app and the widget: session rows, blocker plan, sound, phase alarms and widget. Focus calendar on the Me tab: one square per day for 12 weeks, shaded by focus time (none, under 25 min, under 1 h, under 2 h, 2 h+), with the total. A session that runs past midnight counts on both days. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Time-eater budget: - One daily limit for all apps marked as time-eaters together (30 min to 3 h, or off). It sits at the top of the Block tab with a "40m of 1h today" bar; tap it to change the amount or turn on Strict. - Once the budget is used up, every time-eater app shows the pause screen until midnight. A heads-up appears five minutes before. - It follows the same rules as a per-app limit (it is built as one), so a used-up strict budget cannot be changed until midnight. - The blocker now reads today's use once per measurement for every limited app and the budget together. Weekly report: - From Monday 08:00, a notification sums up last week: average screen time a day, the change against the week before, focus time, and days under the goal. Sent once per week, never for a week with no data, and checked by the background service with a single settings read. Also: notifications and the widget format durations the same way as the app (formatDuration), instead of their own copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Settings > Export my data asks where to save "focuno-<date>.csv" and writes two tables: daily screen time (total, time-eater, helpful, focus score, pickups) and every focus session (start, end, minutes, subject, finished). The person picks the location through Android's file picker, so Focuno needs no storage permission and nothing leaves the phone unless they move the file. Subjects with commas or quotes are quoted. Settings descriptions are shortened to a few words each. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
A row on the Focus tab says what a focus timer pauses. Tap it to choose: - Time-eaters (as before), or - All apps (Lock mode), with a list to tick the apps needed for study, for example a course app or a PDF reader. Phone (including the default dialer and emergency calls), Settings, permission and install screens, the keyboard and the home screen are never paused, so the phone always stays usable and Focuno can always be switched off in Settings. The choice is saved and also applies to timers started from the widget. The rule is a small pure function (FocusPauseRule) with tests. Ticking apps updates the screen at once and saves in the background. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
… Focus - Daily study goal (Settings, 30 min to 10 h, default 4 h). The Focus tab's top row shows "1h 20m / 4h" for today, counting every timer, Pomodoro round and stopwatch, and turns green with a tick once the goal is reached. - The pause screen offers "Focus 25 min instead": it starts a timer and leaves the blocked app, so an urge turns into study time. It is not offered when a focus timer is what paused the app, or mid-unlock. - The Focus tab no longer computes a week summary and top-distractions list that the redesign stopped showing, and the streak pill moved off the crowded top row (it stays on the Me tab and the widget). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Open caps:
- A daily limit can now cap opens ("at most 5 opens a day"), minutes, or
both. The fifth open runs, the sixth shows the pause screen ("No more
opens of Instagram today") until midnight. Strict open caps lock the
limit until midnight once used up, like time limits.
- Opens are read from usage events, counted the same way as the opens
shown in Stats. When an app is opened while a reading is already in
progress, the blocker reads again right after, so the cap is checked
against this open rather than a minute later.
- The limit editor has pills for time (Off, 15m to 2h) and opens (Off,
3, 5, 10, 20); a limit needs at least one. Rows show "12m of 30m today
· 3 of 5 opens", and the bar follows whichever is closer to running out.
- Database v5 adds app_limit.maxOpens (default 0, so existing limits are
unchanged).
Pause screen: the 15-second wait before an unlock is now a soft circle
that grows and shrinks every four seconds to breathe along with, with
the seconds left in the middle, instead of a progress bar and button.
Also: the Focus tab's top-row pills stay on one line.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
…d the widget
Settings > Your exam: a name ("GATE 2027") and a date from a date
picker. Then:
- the Focus tab shows "GATE 2027 · 123 days left" under the top row,
- the pause screen shows the same line under the app name, a reminder at
the exact moment of the urge,
- the widget shows it under today's screen time.
On the day itself it reads "GATE 2027 is today. You've got this!", and
it disappears once the date has passed.
The name is typed locally and saved when the keyboard closes, a date is
picked or Settings is left, so a slow save can never overwrite letters
typed after it. ExamCountdownTest covers day counting and parsing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Fixes: - Starting a new focus plan while another one is on a Pomodoro break (from the widget or the pause screen) left the old plan's future rounds in the database, where they would later count as finished sessions and give free points. A new plan now ends the running round unfinished and removes rounds still to come. - "Focus 25 min instead" on the pause screen could replace a running strict Pomodoro during its break with a non-strict timer. It is now shown only when no plan is running, and FocusController refuses to start anything while a strict plan runs. - Lock mode also keeps the stock in-call screen (com.android.incallui) open. Onboarding: the two permissions blocking needs (Usage access, Display over other apps) now come before the optional Accessibility step. README: what Focuno is, how to install the test build, features, permissions and why, privacy, how to build, project layout and known limits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Blocking only Reels or Shorts needs Accessibility to see which screen is open inside the app; basic mode (Usage access + overlay) can only see the app as a whole. On phones where Accessibility is off, such a rule used to save normally and then never fire. - When picking "Only Reels/Shorts" with Accessibility off, the editor says the rule won't work until Accessibility is on, and that whole-app blocking works without it. - On the Block tab, those rules show "Needs Accessibility to work". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
A softer tool than blocking, for apps you want to keep but open less. Pick an app, then "Pause before opening" next to the time choices. - Each time that app opens, Focuno shows "Opening Instagram · Take a breath. Do you really want to?" with a 5-second breathing circle. "Go back" is the big button; "Open Instagram" works once the five seconds are up. - Going back counts as a resisted urge (the same as giving up an unlock), so it earns points and shows in Trends. - Once opened, it stays quiet while the app is in use and asks again after the person has been away for five minutes. - It is not a block: it does not count as a pause screen shown, and never applies while a real block covers the app. - Paused apps get their own section on the Block tab, with a button to stop pausing each one. README lists the new option. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
Seven icon rows list what is new (focus modes and sounds, Strict, daily limits, Lock mode, pause before opening, exam countdown and study goal, the widget), so none of it goes unnoticed. It shows once, after onboarding is complete, and WHATS_NEW_VERSION can be raised for a future update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
- Quick Settings tile "Focus": tap to start a 25-minute timer from
anywhere. While a plan runs it is lit and shows "Until 10:45"; tapping
it then does nothing, so it can never end a timer by accident. The
start runs in a process-wide scope, so closing the shade cannot cancel
it half-way.
- While a plan runs, a quiet ongoing notification counts down to the end
of the current round or break ("Round 2 of 4", "Break · apps are
free"), or counts up for a stopwatch. It follows each Pomodoro phase
and goes away when the plan ends or is stopped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
- Health check: Accessibility is optional now that basic mode blocks apps, so when it is off it gets a grey "Optional" marker instead of a red "Needs fixing" warning, and it is listed last, after what blocking needs. Every row's explanation is shortened to one line. - Privacy: the text Focuno keeps now includes subject and exam names as well as unlock reasons, and it leaves the phone only through an export the person starts. - New users do not get "New in Focuno" right after setup. - Block tab: indentation fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
- Tapping an app in Stats opens a sheet with that day's time and opens, a seven-day bar chart (today highlighted), three pills to set its category (helpful, okay, time-eater), a "Pause before opening" switch, and a "Limit or block" button that opens the add flow for the app. The lock icon on each row still goes straight to limiting or blocking. - Under the day's total: "↓ 20% vs yesterday" in green or "↑ 15% vs yesterday" in amber (or "vs the day before" for past days), shown when that day has data. - Earlier days come from the saved daily history; today is read live. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
- Deep Work: focus for 2 hours in one day. - Goal Getter: reach the daily study goal on any day. - Focus Master: finish 50 focus sessions. The best day comes from the same 12-week focus history as the calendar, so people who already qualify get the badges (and the celebration) on their next visit to the Me tab. GameRulesTest covers the thresholds. README mentions the app detail sheet and the day comparison. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
- Pomodoro mode has two shapes: the classic 25/5 and a longer 50/10 for deep work, each for 2 to 4 rounds. The dial and the Strict lock time follow the chosen shape. - Stats > Trends shows the last eight focus sessions: subject, start time, length, and a tick for finished ones (a clock icon for ones ended early or still running). Pomodoro rounds that have not started yet are left out. - The app list no longer takes a category callback it stopped using. - README updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
- Subjects dialog: while no subjects exist, chips add a whole set at once: GATE ECE (Maths, Networks, Signals and Systems, Electronic Devices, Analog Circuits, Digital Circuits, Control Systems, Communications, Electromagnetics, Aptitude), JEE, NEET or UPSC. Subjects already there are skipped. - Setup gains a skippable "What are you preparing for?" step right after the welcome, with the same exam name and date editor as Settings (now a shared ExamEditor component), so new users get the countdown from day one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Focuno is a native Android app (Kotlin, Jetpack Compose, Material 3) that helps exam aspirants cut down on doomscrolling. It has no internet permission and keeps everything on the phone. The README covers install, features, permissions and limits.
Core
UsageStatsManager.queryEventsonly, screen-off aware, matching Android Settings (Settings → Screen time check compares them).This round (minimal redesign and new features)
app_limittable;focus_session.subject;app_limit.maxOpens). Existing data is kept.Test plan
assembleDebugpass on every push, latest run (new tests: DailyLimitPolicy, StrictLock, FocusPlan, FocusCalendar, FocusPauseRule, WeeklyReport, ExamCountdown, CsvExport, NoiseGenerator, plus new badge thresholds in GameRulesTest)🤖 Generated with Claude Code
https://claude.ai/code/session_01EJevkhMavqGnkAANzXJcEY