Commit Graph
32 Commits
Author SHA1 Message Date
makiolaj a0a1daa920 Merge branch 'feat/25-screen-saver' into release/v1.0.0
# Conflicts:
#	app/src/main/AndroidManifest.xml
#	app/src/main/java/de/jeanlucmakiola/clockula/backup/BackupEngine.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/data/backup/BackupCodec.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/data/backup/BackupDto.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/data/di/TimeModule.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefs.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/data/time/AndroidClockChanges.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/domain/backup/BackupContent.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/domain/widget/NextAlarmWidgetModel.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/ui/alarms/AlarmsScreen.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/ui/common/AlarmTimeFormatter.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/ui/settings/ClockSettingsScreen.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/ui/worldclock/WorldClockFace.kt
#	app/src/main/res/values/strings.xml
#	app/src/test/java/de/jeanlucmakiola/clockula/data/backup/BackupCodecTest.kt
#	app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt
#	docs/ARCHITECTURE.md
#	docs/BACKUP.md
2026-10-26 20:59:33 +01:00
makiolaj fd7f5e8dcd Merge branch 'feat/23-world-clock-seconds' into release/v1.0.0
# Conflicts:
#	app/src/main/java/de/jeanlucmakiola/clockula/backup/BackupEngine.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/data/backup/BackupCodec.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/data/backup/BackupDto.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefs.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/domain/backup/BackupContent.kt
#	app/src/test/java/de/jeanlucmakiola/clockula/data/backup/BackupCodecTest.kt
#	app/src/test/java/de/jeanlucmakiola/clockula/ui/settings/SettingsViewModelTest.kt
#	docs/ARCHITECTURE.md
#	docs/BACKUP.md
2026-10-26 20:54:31 +01:00
makiolaj 48d09f7371 Merge branch 'feat/22-timer-vibrate-ramp' into release/v1.0.0
# Conflicts:
#	app/src/main/java/de/jeanlucmakiola/clockula/ClockulaApp.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefs.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/domain/ClockDefaults.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/domain/timer/TimerRing.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/ui/settings/SettingsViewModel.kt
#	app/src/main/java/de/jeanlucmakiola/clockula/ui/settings/TimerDefaultsScreen.kt
#	app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt
#	docs/ARCHITECTURE.md
2026-10-26 20:54:01 +01:00
makiolaj ea8e159b39 Merge branch 'feat/1-bedtime-mode' into release/v1.0.0
# Conflicts:
#	docs/ARCHITECTURE.md
2026-10-26 20:47:54 +01:00
makiolaj 69b436cffd feat(bedtime): add an opt-in bedtime mode under Settings
Clockula can now turn on a Do Not Disturb mode of its own at bedtime and
off at the wake-up time, on the nights the user picks, with an optional
reminder before it starts. Digital Wellbeing's Bedtime mode can't be
driven by a third-party app, so this is a separate rule: a typed mode
with grayscale, dimmed wallpaper, dark theme and hidden always-on display
on Android 15+, and a plain DND schedule rule on Android 10-14.

The rule's policy always allows alarms (and media). BedtimeEngine owns one
AlarmManager slot of its own, on its own receiver and request code, and
every bedtime call on the boot, time-change and launch paths runs after
the alarm and timer passes, guarded. The rule id is never stored: the
platform lists an app's own rules, so restores and reinstalls find or
recreate it. Turning bedtime off removes the rule. The screen walks the
user through granting DND access and explains the Wellbeing overlap.
Settings are part of the JSON backup; older files restore bedtime as off.

Refs #1
2026-10-22 11:19:38 +02:00
makiolaj bdcf780028 docs(roadmap): rewrap the Wear OS note
Refs #27
2026-10-22 11:15:52 +02:00
makiolaj 2927585608 docs(roadmap): name both data paths and F-Droid's real response
Refs #27
2026-10-22 11:13:55 +02:00
makiolaj b8968f5e19 docs(roadmap): settle the Wear OS note on what the docs say
Keep §5's own claim that only crash reports leave the phone, say the
dependency would ship in every channel, and keep the standalone app's
distribution caveat.

Refs #27
2026-10-22 11:12:18 +02:00
makiolaj dc23618c56 docs(roadmap): drop the AlarmClock route from the Wear OS note
AlarmClock intents only reach apps on the same device and can't read
state, so they are no route for a watch. Cite PRIVACY.md §4 and §5
together and say "no product flavours" precisely.

Refs #27
2026-10-22 11:10:38 +02:00
makiolaj da16ab23cc docs(roadmap): quote the policy and list the AlarmClock route for Wear OS
Cite PRIVACY.md's own wording, name F-Droid's non-free-dependency rule,
and note that third-party watch apps can already drive Clockula through
the AlarmClock intents.

Refs #27
2026-10-22 11:08:53 +02:00
makiolaj 99c052f94c docs(roadmap): state the Wear OS blocker against the policy as written
PRIVACY.md already documents Auto Backup and crash reports as ways data
can leave the phone, and there is a single build rather than an F-Droid
one. Say that, and call the entry blocked rather than unscoped.

Refs #27
2026-10-22 11:07:07 +02:00
makiolaj fe1c2a3d48 docs(roadmap): reduce the Wear OS note to the decision it needs
Any phone-to-watch channel sends data off the phone, which the privacy
policy rules out today, so the entry now states that decision and the
standalone alternative without speculating about notification bridging.

Refs #27
2026-10-22 11:05:53 +02:00
makiolaj cb5cd5123b docs(roadmap): keep the Wear OS note to what holds
Ringing notifications are foreground-service notifications, so making
them non-ongoing wouldn't bridge them; CompanionDeviceManager carries no
data; and watches pair through their makers' apps. Say only what holds
and note that a watch build has no F-Droid channel.

Refs #27
2026-10-22 11:03:44 +02:00
makiolaj 0213af1260 docs(roadmap): correct what a watch gets today
Ring and timer notifications are ongoing, which Wear OS doesn't bridge,
and bridging needs Google's Wear OS app anyway. Quote the privacy policy
exactly, drop the unchecked "only channel" claim, and list bridging the
ring as an option of its own.

Refs #27
2026-10-22 11:01:02 +02:00
makiolaj 95bb2d14ec docs(roadmap): record why a Wear OS companion is blocked on Play Services
A companion needs Google's Wearable Data Layer, which is a proprietary
service the privacy policy and the F-Droid build rule out. The roadmap
entry now records that constraint, what the bridged notifications
already give a watch, and the options if it is picked up.

Refs #27
2026-10-22 10:59:35 +02:00
makiolaj 1e29226364 feat(screensaver): add a screen saver with a dim night mode
A DreamService shows a full-screen clock, the date and the next alarm,
digital or as the world clock's analog face, on black. Night mode dims
every colour towards black and turns the display down; the clock moves
to a new spot each minute so nothing burns in. It wakes only on the
minute and on a time, zone or 12/24-hour change.

The tabs' settings gear becomes an overflow menu with "Screen saver" and
"Settings". An app cannot start the system's dream without a system
permission, so that item opens an activity with the same content, which
keeps the screen on only while charging. Style and night mode live in
Settings > Clock and in the dream's own settings screen, and are carried
in backups; older backups restore the defaults.

Fixes #25
2026-10-22 08:07:44 +02:00
makiolaj fbc3a192bf feat(timers): give timers their own vibration and gradual volume
Timers vibrated by the alarm vibration default and never ramped. Both are
now the timers' own app-wide settings, next to the default timer sound in
Settings > Timers: a Vibrate switch and the same Gradual volume picker
alarms use. Timer.resolveSettings reads them instead of the alarm default
and the old TimerRing.RAMP_SECONDS constant.

A fresh install starts with timer vibration off, as Google Clock does, and
no ramp. An existing install keeps what its timers did: a one-shot DataStore
migration writes the new key from the alarm vibration default before the
first read, so nobody's kitchen timer silently stops buzzing on update. A
fresh install is told apart by an empty store (anything that has run once
has written its boot id); the migration writes the default there too, so it
never runs twice.

Backups carry both new fields. A file without them restores the alarm
vibration default as the timers' (what that install's timers did) and a
flat ring.

Silent plus vibration off still signals: Silent gives the player no
sources, and its onSilenced callback starts the vibrator whatever the
setting says. The settings row says so.

Fixes #22
2026-10-21 18:49:45 +02:00
makiolaj 785adf715b feat(worldclock): add an option to display time with seconds
One switch in Settings > Clock adds seconds to the home readout and
every city row, in the same 12/24-hour and locale form as before, and
gives the analog face its second hand. Off by default.

The tab now ticks on the wall-clock boundary through a new
Ticker.alignedTicks: once a minute with seconds off, once a second only
with them on, replacing the free-running 200 ms tick. The setting is in
backups as world_clock_show_seconds; older files import with it off.

Fixes #23
2026-10-21 18:48:15 +02:00
makiolaj e870918a03 docs: plain-language pass over every doc
Removes AI-writing patterns across the docs, store listing and
templates: dash-heavy rhythm, not-X-but-Y contrasts, one-line kickers
and decorative bold. Facts, code, links and headings are unchanged.

Also fixes leftovers copied from the sibling apps: the crash report
template promised "no calendar content", and CONTRIBUTING described
Agendula's task-provider layout, test seams and commit style.
2026-10-06 19:14:11 +02:00
makiolaj 5d03c654bf docs: mark M10 done
ARCHITECTURE.md's package table gets the new domain/backup,
domain/selfcheck, domain/widget, data/backup, backup/, widget/,
ui/settings/ and ui/widget/ entries, and §9/§10 are brought up to date
with what M10 actually built (the exported-component count, the
permission list unchanged, which 'not built yet' rows are now done).
CHANGELOG and ROADMAP's current-state line follow.
2026-10-01 22:34:07 +02:00
makiolaj c8cc156691 docs: bring home-screen widgets into M10, out of post-v1
Widgets share M10's machinery end to end: the next-alarm and timer
state a widget mirrors is exactly what the settings/backup/self-check
work already touches, and a widget tap is just another caller of the
MainActivity door the AlarmClock contract already opens. Keeping them
parked in post-v1 would mean building the same read paths twice.

QS tile, screensaver and bedtime stay deferred — none of them shares
M10's surface the way widgets do.

Also tightens PLAN.md §4's DND wording (interruption-filter read, no
ACCESS_NOTIFICATION_POLICY) and §7's backup semantics (whole-state
replace, ring state excluded, Room column vocabulary) ahead of M10's
implementation.
2026-10-01 17:22:07 +02:00
makiolaj 3ff74dc1d5 docs: mark M9 done
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 8s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Failing after 6m50s
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Skipped
2026-09-23 11:02:24 +02:00
makiolaj cd26fefc69 docs: mark M8 done 2026-09-22 13:05:24 +02:00
makiolaj 8dec91fd4c docs: mark M7 done 2026-09-22 10:24:12 +02:00
makiolaj 6ea11f7bbd docs: mark M6 done 2026-09-12 16:49:05 +02:00
makiolajandClaude Opus 5 5a01efb7bf docs: mark M5 done
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wmy1BpCKi8KeSjaWhYuCPV
2026-09-12 14:44:23 +02:00
makiolajandClaude Opus 5 e8fceec240 docs: mark M4 done
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wmy1BpCKi8KeSjaWhYuCPV
2026-09-12 13:08:05 +02:00
makiolajandClaude Opus 5 12da168cc5 docs: mark M3 done
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 16:05:58 +02:00
makiolajandClaude Opus 5 5ea3c798b4 docs: mark M2 done
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 13:53:42 +02:00
makiolajandClaude Opus 5 29b213efc6 docs: mark M1 done
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 12:47:46 +02:00
Jean-Luc MakiolaandClaude Opus 5 7b7b730219 docs: project README, changelog, and M0 marked done
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Failing after 3m42s
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Skipped
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 6s
The README leads with the thing that is actually different about this app
rather than burying it: Calendula and Agendula front standards someone else
maintains, and Clockula cannot, because there is no open provider behind a
clock. Saying so plainly is better than implying a thesis the app does not
meet — and the three things that replace it (the AlarmClock contract, IANA
zones, an exportable format) are real commitments, not consolation.

CONTRIBUTING's scope section now names the trade this project will not make:
nothing ships that buys a feature by making an alarm less certain to ring.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L94fydiJC37LtxVusNQBDy
2026-09-11 11:47:23 +02:00
Jean-Luc MakiolaandClaude Opus 5 052c7b177d docs: lock the Clockula spec — PLAN, ROADMAP, docs index
Third floret after Calendula and Agendula: a Material 3 Expressive clock app
(alarms, timers, stopwatch, world clock).

The family thesis doesn't survive contact with a clock — there is no open
provider behind one — so PLAN opens by saying so plainly and relocates the
open-standards commitment to the three places it can actually live: the full
android.provider.AlarmClock intent contract, IANA tzdata, and a documented
JSON backup format.

Locked: four surfaces and no extras in v1, Room + DataStore + JSON export,
maximum alarm reliability including a self-check diagnostics screen, seed
#6B7A5C (completing the family's Calendula→Agendula colour rotation), four
tabs plus a live running-state pill, Codeberg-canonical from commit one, and
floret-kit from day one with core-prefs + core-di extracted up front.

ROADMAP carries M0–M11 as an ordered work queue with per-milestone done
criteria, written to be executed one milestone per loop iteration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L94fydiJC37LtxVusNQBDy
2026-09-11 11:27:57 +02:00