Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 42 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,48 @@ and rule traces back to a section (and often a community demand source) there.

| Area | State |
|---|---|
| Foundation: multi-module, M3 Expressive theme, Room (10 schema versions, auto-migrations), encrypted Vault (Tink+Keystore), foreground service, event bus + rules engine | ✅ |
| AI: Ollama streaming + on-device Gemma (MediaPipe), AiRouter w/ privacy tag + fallback, NotesRag | ✅ |
| Capture spine: quick capture, voice brain-dump w/ review sheet, structured logger | ✅ |
| Notes (Markdown files, vault option, backlinks, ask-my-notes) | ✅ |
| Time: exact reminders (lockscreen alarm, boot reschedule, NL times), to-do (lists+nesting), local calendar | ✅ |
| Message Center (notification listener), Email (IMAP to Proton Bridge) | ✅ |
| Rules live: R1 tracking→package+reminder · R2 invoice→task · R6 leave-by · R7 invite→event · R8 receipt→finance+warranty · R9 subscriptions · R10 brain-dump · R11 @scene tags · R12 quick-capture routing | ✅ |
| DHL tracking (hourly polling), Scan (CameraX+ML Kit receipts/boards), Finance (budget, subscriptions, warranties, CSV import) | ✅ |
| Books, Routes, Smart Home (HA REST), NAS browser + server-apps board, Planner "Jarvis" + Home top card | ✅ |
| Assistant role (long-press home → quick capture), Settings hub, theme palette picker, in-app Gemma model downloads | ✅ |
| Power-button capture auto-detects timers ("timer 6m"), reminders, calendar events, and time-stamped to-dos ("6pm feed cat") on-device | ✅ |
| Time-stamped to-dos surface in the Calendar; Clock has a Samsung-style wheel timer (mm:ss↔seconds toggle) + stopwatch laps; Routes embeds a native osmdroid OpenStreetMap | ✅ |
| Calendar v2: Month/Week/Day views, hour timeline, tap-to-edit, all-day + minute precision, Proton ICS one-way sync + .ics export | ✅ |
| Offline voice via open-source Vosk (one-time 40 MB model) — the Google recognizer is gone; nav hand-offs use plain geo: URIs | ✅ |
| Customizable bottom bar (toggle + reorder) + Home grid/list toggle with long-press drag-arrange; planner accept/skip persists (✓ completes the to-do); reminder alarms ring on the ALARM stream even in silent mode | ✅ |
| Clock (analog/digital/word faces, world clock, stopwatch, timer) | ✅ |
| ADHD tools: visual focus timer, streaks, overwhelm "What's next?" overlay (SYSTEM_ALERT_WINDOW) | ✅ |
| Memex archive: share-sheet clip + timeline, annotate-to-keep, 12-month auto-purge | ✅ |
| Agentic macros: natural-language → validated IR (MacroCompiler) → accessibility executor, dry-run gated | ✅ |
| Evolution layer: on-device interaction log + planner accept-rate; Planner accept/skip feeds it | ✅ |
| Calendar: one-way system Calendar Provider mirror + iCalendar (RFC 5545) codec (Proton ICS bridge, §8.6) | ✅ |
| Mail MCP client (JSON-RPC over HTTP/SSE) for the NAS Proton mail MCP; IMAP fallback stays primary | ✅ |
| Assistant overlay (Gemini-style): long-press home floats a glowing-border panel over any app — auto-listens (Vosk), text input, deep module commands (timers, packages, planner, to-dos) + AI fallback | ✅ |
| Foreground AlarmService rings reminders on the ALARM stream (silent-mode/app-killed proof) + "Test alarm" button; Clock gains a tap-to-add time-zone map and a zone converter | ✅ |
| Jarvis v3: chat is pure LLM (no pre-canned answers) — every module exposes live content via a prompt snapshot, and the model acts through `[[tool: args]]` lines the app executes + confirms (tasks, timers, reminders, events, notes, search); power phrases stay in the power menu/overlay | ✅ |
| New modules: Downloader (on-device stream extraction → Downloads, incl. HLS), Plants (offline care atlas + every-N-days watering reminders), News (RSS tile scroll: tagesschau, ZEIT, SZ, DLF, taz), hidden Vault (long-press "LifeOS" title, biometric/PIN, encrypted gallery w/ sort) | ✅ |
| Routes v2: tap-tap route planning with car/bike/foot timings + distance via OSRM, polyline on the osmdroid map | ✅ |
| Vault v2: dedicated screens per item — Proton-Pass-style logins (password generator, on-device TOTP 2FA, custom fields, attachments), Markdown secure texts, zoomable image gallery (downsampled, no OOM); hidden behind a 5-second hold on the Home title | ✅ |
| Notes editor: Word-style Markdown toolbar (bold/italic/heading/list/quote/code/link on the selection), rendered⇄raw toggle + pen; optional readable mirror to /Internal storage/LifeOS/Notes/*.md (all-files access) | ✅ |
| Focus timer: tap the ring for a custom HH:MM:SS time, plus an "Overlay" button that floats the countdown over any app (tap once for a close X that leaves it running); Overwhelm overlay now follows the theme | ✅ |
| Screen Time: mirrors Android digital-wellbeing into LifeOS and keeps it forever (survives Samsung's ~monthly purge) — weekly bars + average, week scrolling, tap a day for its own apps/unlocks, JSON export. Totals are derived from the raw RESUMED/PAUSED event stream, not `queryAndAggregateUsageStats` (which reports whole-bucket sums per day) | ✅ |
| Screen Time · Plants (custom photos + care atlas) · News · Downloader on Home; NAS server apps redesigned as an app-store list; Jarvis answers from a live data snapshot (note bodies included) and a Developer Options "Jarvis Debugging" toggle exposes snapshot/output/tool-calls with a copy button | ✅ |
| Brick (§Module Brick): tap-to-block modes — pick blocked apps + optional per-app daily allowances, turn a mode on/off by NFC tag, time window or by hand, strict mode refuses early exits; blocked apps hit a full-screen wall via an accessibility blocker (the only route Android gives a sideloaded app). Blocking rules covered by unit tests | ✅ |
| Deferred post-alpha: Glance home-screen widgets, HA WebSocket live state/zones, Vault unlock UI, first-run onboarding checklist (grants live in Settings → System access), FinTS bank sync | 🔜 |
| Foundation: multi-module, M3 Expressive theme, Room (10 schema versions, auto-migrations), encrypted Vault (Tink+Keystore), foreground service, event bus + rules engine | Done |
| AI: Ollama streaming + on-device Gemma (MediaPipe), AiRouter w/ privacy tag + fallback, NotesRag | Done |
| Capture spine: quick capture, voice brain-dump w/ review sheet, structured logger | Done |
| Notes (Markdown files, vault option, backlinks, ask-my-notes) | Done |
| Time: exact reminders (lockscreen alarm, boot reschedule, NL times), to-do (lists+nesting), local calendar | Done |
| Message Center (notification listener), Email (IMAP to Proton Bridge) | Done |
| Rules live: R1 tracking→package+reminder · R2 invoice→task · R6 leave-by · R7 invite→event · R8 receipt→finance+warranty · R9 subscriptions · R10 brain-dump · R11 @scene tags · R12 quick-capture routing | Done |
| DHL tracking (hourly polling), Scan (CameraX+ML Kit receipts/boards), Finance (budget, subscriptions, warranties, CSV import) | Done |
| Books, Routes, Smart Home (HA REST), NAS browser + server-apps board, Planner "Jarvis" + Home top card | Done |
| Assistant role (long-press home → quick capture), Settings hub, theme palette picker, in-app Gemma model downloads | Done |
| Power-button capture auto-detects timers ("timer 6m"), reminders, calendar events, and time-stamped to-dos ("6pm feed cat") on-device | Done |
| Time-stamped to-dos surface in the Calendar; Clock has a Samsung-style wheel timer (mm:ss↔seconds toggle) + stopwatch laps; Routes embeds a native osmdroid OpenStreetMap | Done |
| Calendar v2: Month/Week/Day views, hour timeline, tap-to-edit, all-day + minute precision, Proton ICS one-way sync + .ics export | Done |
| Offline voice via open-source Vosk (one-time 40 MB model) — the Google recognizer is gone; nav hand-offs use plain geo: URIs | Done |
| Customizable bottom bar (toggle + reorder) + Home grid/list toggle with long-press drag-arrange; planner accept/skip persists (✓ completes the to-do); reminder alarms ring on the ALARM stream even in silent mode | Done |
| Clock (analog/digital/word faces, world clock, stopwatch, timer) | Done |
| ADHD tools: visual focus timer, streaks, overwhelm "What's next?" overlay (SYSTEM_ALERT_WINDOW) | Done |
| Memex archive: share-sheet clip + timeline, annotate-to-keep, 12-month auto-purge | Done |
| Agentic macros: natural-language → validated IR (MacroCompiler) → accessibility executor, dry-run gated | Done |
| Evolution layer: on-device interaction log + planner accept-rate; Planner accept/skip feeds it | Done |
| Calendar: one-way system Calendar Provider mirror + iCalendar (RFC 5545) codec (Proton ICS bridge, §8.6) | Done |
| Mail MCP client (JSON-RPC over HTTP/SSE) for the NAS Proton mail MCP; IMAP fallback stays primary | Done |
| Assistant overlay (Gemini-style): long-press home floats a glowing-border panel over any app — auto-listens (Vosk), text input, deep module commands (timers, packages, planner, to-dos) + AI fallback | Done |
| Foreground AlarmService rings reminders on the ALARM stream (silent-mode/app-killed proof) + "Test alarm" button; Clock gains a tap-to-add time-zone map and a zone converter | Done |
| Jarvis v3: chat is pure LLM (no pre-canned answers) — every module exposes live content via a prompt snapshot, and the model acts through `[[tool: args]]` lines the app executes + confirms (tasks, timers, reminders, events, notes, search); power phrases stay in the power menu/overlay | Done |
| New modules: Downloader (on-device stream extraction → Downloads, incl. HLS), Plants (offline care atlas + every-N-days watering reminders), News (RSS tile scroll: tagesschau, ZEIT, SZ, DLF, taz), hidden Vault (long-press "LifeOS" title, biometric/PIN, encrypted gallery w/ sort) | Done |
| Routes v2: tap-tap route planning with car/bike/foot timings + distance via OSRM, polyline on the osmdroid map | Done |
| Vault v2: dedicated screens per item — Proton-Pass-style logins (password generator, on-device TOTP 2FA, custom fields, attachments), Markdown secure texts, zoomable image gallery (downsampled, no OOM); hidden behind a 5-second hold on the Home title | Done |
| Notes editor: Word-style Markdown toolbar (bold/italic/heading/list/quote/code/link on the selection), rendered⇄raw toggle + pen; optional readable mirror to /Internal storage/LifeOS/Notes/*.md (all-files access) | Done |
| Focus timer: tap the ring for a custom HH:MM:SS time, plus an "Overlay" button that floats the countdown over any app (tap once for a close X that leaves it running); Overwhelm overlay now follows the theme | Done |
| Screen Time: mirrors Android digital-wellbeing into LifeOS and keeps it forever (survives Samsung's ~monthly purge) — weekly bars + average, week scrolling, tap a day for its own apps/unlocks, JSON export. Totals are derived from the raw RESUMED/PAUSED event stream, not `queryAndAggregateUsageStats` (which reports whole-bucket sums per day) | Done |
| Screen Time · Plants (custom photos + care atlas) · News · Downloader on Home; NAS server apps redesigned as an app-store list; Jarvis answers from a live data snapshot (note bodies included) and a Developer Options "Jarvis Debugging" toggle exposes snapshot/output/tool-calls with a copy button | Done |
| Brick (§Module Brick): tap-to-block modes — pick blocked apps + optional per-app daily allowances, turn a mode on/off by NFC tag, time window or by hand, strict mode refuses early exits; blocked apps hit a full-screen wall via an accessibility blocker (the only route Android gives a sideloaded app). Blocking rules covered by unit tests | Done |
| Screen Time day insight: tapping a bar selects that day inline (others dim) and the stat cards switch to that day; the download button opens an export dialog (JSON, CSV by day, CSV by app; week or all history) writing to Downloads | Done |
| Calendar: long-press-and-drag in day/week view sweeps a time range (5/10/15/30/60-minute steps) and opens the editor pre-filled; pinch to zoom the time ladder between 5-minute and hourly steps; the event sheet opens fully expanded | Done |
| Pastebin module: create pastes with expiry, visibility, syntax format, password and burn-after-read; sign in to list, open and delete your pastes; share-sheet defaults live in its Settings tab | Done |
| Share to LifeOS: sharing text or a link shows a small floating chooser over the source app (LifeOS never opens) - log it to the capture inbox, or mint a Pastebin link with your share defaults and copy it | Done |
| Downloader: browsable catalogue of 70+ supported sites (ThisVid, LinkedIn, Threads, Reddit, Instagram, file hosts, broadcasters, audio) plus site helpers - Reddit post JSON, LinkedIn progressive streams, Instagram/Threads embeds, Vimeo player config, kt_player/KVS link decoding and one level of iframe following | Done |
| Navigation bar: any module can be a bottom-bar tab, not just Calendar/Jarvis/Inbox/Tasks | Done |
| Clock timer: tap an h/m/s wheel to type the value on a number keyboard; a full number hops to the field on the right automatically | Done |
| Clear Sky Map module: full clearoutside.com forecast for any spot (search, coordinates or device location) - hourly good/OK/bad ratings, total/low/medium/high cloud, visibility, fog, precipitation, wind, temperature, dew point, humidity, pressure, ozone, sun/moon ephemeris, dark windows and estimated sky quality/Bortle class. No API key needed; place lookup via OpenStreetMap Nominatim | Done |
| Deferred post-alpha: Glance home-screen widgets, HA WebSocket live state/zones, Vault unlock UI, first-run onboarding checklist (grants live in Settings → System access), FinTS bank sync | Planned |

**Google-free by design:** no Google service is ever called at runtime (no Play Services, no Google recognizer, no Google Maps). Remaining Google-*authored* open-source, fully on-device libraries: AndroidX/Jetpack (unavoidable on Android), MediaPipe (Gemma inference), ML Kit on-device OCR/barcode (no network) — swap candidates documented in the plan.

Expand Down
6 changes: 4 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ android {

defaultConfig {
applicationId = "com.lifeos"
versionCode = 18
versionName = "0.1.0-alpha.18"
versionCode = 19
versionName = "0.1.0-alpha.19"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down Expand Up @@ -87,6 +87,8 @@ dependencies {
implementation(projects.feature.vault)
implementation(projects.feature.screentime)
implementation(projects.feature.brick)
implementation(projects.feature.pastebin)
implementation(projects.feature.clearsky)

implementation(projects.core.model)
implementation(projects.core.network)
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/kotlin/com/lifeos/app/ui/LifeOsApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ import com.lifeos.feature.news.NewsRoute
import com.lifeos.feature.vault.VaultRoute
import com.lifeos.feature.screentime.ScreenTimeRoute
import com.lifeos.feature.brick.BrickRoute
import com.lifeos.feature.clearsky.ClearSkyRoute
import com.lifeos.feature.pastebin.PastebinRoute

/**
* Single-activity app shell (§1.3): adaptive scaffold, short M3E bottom bar,
Expand Down Expand Up @@ -193,6 +195,8 @@ fun LifeOsApp(captureRequests: Int = 0, navBarIds: List<String> = emptyList()) {
composable<LifeDestination.Vault> { VaultRoute() }
composable<LifeDestination.ScreenTime> { ScreenTimeRoute() }
composable<LifeDestination.Brick> { BrickRoute() }
composable<LifeDestination.Pastebin> { PastebinRoute() }
composable<LifeDestination.ClearSky> { ClearSkyRoute() }
}
}

Expand Down
14 changes: 14 additions & 0 deletions app/src/main/kotlin/com/lifeos/app/ui/screen/HomeScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ContentPaste
import androidx.compose.material.icons.filled.NightsStay
import androidx.compose.material.icons.automirrored.filled.Note
import androidx.compose.material.icons.filled.Insights
import androidx.compose.material.icons.automirrored.filled.MenuBook
Expand Down Expand Up @@ -211,6 +213,18 @@ fun HomeScreen(
icon = Icons.Filled.Timelapse,
destination = LifeDestination.ScreenTime,
),
AppGridItem(
label = "Pastebin",
description = "Create, share and manage pastes",
icon = Icons.Filled.ContentPaste,
destination = LifeDestination.Pastebin,
),
AppGridItem(
label = "Clear Sky Map",
description = "Stargazing forecast for any spot",
icon = Icons.Filled.NightsStay,
destination = LifeDestination.ClearSky,
),
)

// Hidden Vault reveal (§Module Vault): long-press the "LifeOS" title and a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class SettingsViewModel @Inject constructor(
val DEFAULT_HOME_ORDER = listOf(
"Notes", "Logger", "Packages", "Finance", "Scan", "Planner", "Books",
"Routes", "Smart home", "NAS", "Clock", "Focus", "Memex", "Macros", "Evolution",
"Downloader", "Plants", "News", "Brick", "Screen Time",
"Downloader", "Plants", "News", "Brick", "Screen Time", "Pastebin", "Clear Sky Map",
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,34 @@ internal class DataStoreSettingsRepository @Inject constructor(
dataStore.edit { prefs -> prefs[KEY_SCREEN_TIME_REBUILT] = done }
}

override val pastebinShareDefaults: Flow<String> =
dataStore.data.map { prefs -> prefs[KEY_PASTEBIN_SHARE_DEFAULTS] ?: "" }

override suspend fun setPastebinShareDefaults(value: String) {
dataStore.edit { prefs -> prefs[KEY_PASTEBIN_SHARE_DEFAULTS] = value }
}

override val pastebinUserKey: Flow<String> =
dataStore.data.map { prefs -> prefs[KEY_PASTEBIN_USER_KEY] ?: "" }

override suspend fun setPastebinUserKey(key: String) {
dataStore.edit { prefs -> prefs[KEY_PASTEBIN_USER_KEY] = key.trim() }
}

override val clearSkyPlaces: Flow<String> =
dataStore.data.map { prefs -> prefs[KEY_CLEAR_SKY_PLACES] ?: "" }

override suspend fun setClearSkyPlaces(value: String) {
dataStore.edit { prefs -> prefs[KEY_CLEAR_SKY_PLACES] = value }
}

override val clearSkyLastPlace: Flow<String> =
dataStore.data.map { prefs -> prefs[KEY_CLEAR_SKY_LAST_PLACE] ?: "" }

override suspend fun setClearSkyLastPlace(value: String) {
dataStore.edit { prefs -> prefs[KEY_CLEAR_SKY_LAST_PLACE] = value }
}

override val publicFolderMirror: Flow<Boolean> =
dataStore.data.map { prefs -> prefs[KEY_PUBLIC_FOLDER_MIRROR] ?: false }

Expand All @@ -124,5 +152,9 @@ internal class DataStoreSettingsRepository @Inject constructor(
val KEY_JARVIS_DEBUG = booleanPreferencesKey("jarvis_debug")
val KEY_PUBLIC_FOLDER_MIRROR = booleanPreferencesKey("public_folder_mirror")
val KEY_SCREEN_TIME_REBUILT = booleanPreferencesKey("screen_time_rebuilt_v2")
val KEY_PASTEBIN_SHARE_DEFAULTS = stringPreferencesKey("pastebin_share_defaults")
val KEY_PASTEBIN_USER_KEY = stringPreferencesKey("pastebin_user_key")
val KEY_CLEAR_SKY_PLACES = stringPreferencesKey("clear_sky_places")
val KEY_CLEAR_SKY_LAST_PLACE = stringPreferencesKey("clear_sky_last_place")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,27 @@ interface SettingsRepository {
val screenTimeRebuilt: Flow<Boolean>

suspend fun setScreenTimeRebuilt(done: Boolean)

/**
* Defaults applied to pastes created from the Android share sheet
* (§Module Pastebin): "EXPIRY|VISIBILITY|burn|password".
*/
val pastebinShareDefaults: Flow<String>

suspend fun setPastebinShareDefaults(value: String)

/** Pastebin account user key, minted from username/password once. */
val pastebinUserKey: Flow<String>

suspend fun setPastebinUserKey(key: String)

/** Saved Clear Sky observing spots, one "name~lat~lon" per line. */
val clearSkyPlaces: Flow<String>

suspend fun setClearSkyPlaces(value: String)

/** The Clear Sky place shown on open ("name~lat~lon"); empty = ask. */
val clearSkyLastPlace: Flow<String>

suspend fun setClearSkyLastPlace(value: String)
}
Loading
Loading