feat(Frontlight): auto brightness and warmth - #590
Conversation
1505f47 to
3015a4f
Compare
8d8c0e5 to
204d511
Compare
204d511 to
2916e0d
Compare
2916e0d to
62bb996
Compare
62bb996 to
44d7308
Compare
44d7308 to
6e575a1
Compare
6e575a1 to
2c235ac
Compare
2c235ac to
3489b8b
Compare
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (30)
✅ Files skipped from review due to trivial changes (3)
🚧 Files skipped from review as they are similar to previous changes (25)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (4)crates/core/**/*.rs📄 CodeRabbit inference engine (crates/core/AGENTS.md)
Files:
crates/core/**/*.{sql,rs}📄 CodeRabbit inference engine (crates/core/AGENTS.md)
Files:
crates/core/**/*.{ftl,rs}📄 CodeRabbit inference engine (crates/core/AGENTS.md)
Files:
**/*.rs📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (1)📚 Learning: 2026-05-23T14:57:43.820ZApplied to files:
🔇 Additional comments (2)
WalkthroughThis PR implements automatic frontlight warmth and brightness adjustment based on the sun's position. It introduces a Sequence DiagramsequenceDiagram
participant TimeSyncTask
participant geolocation as geolocation module
participant TimeManager
participant Home
participant AutoFrontlightTask
participant app as app.rs event loop
participant Frontlight as Frontlight hardware
rect rgba(100, 149, 237, 0.5)
Note over TimeSyncTask,Home: Time sync with shared geolocation fetch
TimeSyncTask->>geolocation: fetch_geolocation(client)
geolocation-->>TimeSyncTask: GeoLocation { coords, timezone }
TimeSyncTask->>TimeManager: sync(ntp_host, manual, Some(geo))
TimeSyncTask->>Home: Event::AutoFrontlightCoordinates(coords)
Home->>Home: store auto_frontlight_last_coordinates
Home->>app: Event::AutoFrontlightConfigChanged
end
rect rgba(60, 179, 113, 0.5)
Note over AutoFrontlightTask,Frontlight: Periodic auto-frontlight update (every 5 min)
AutoFrontlightTask->>app: Event::UpdateAutoFrontlight
app->>app: resolve_coordinates(settings)
app->>app: compute_auto_frontlight_levels(now, coords, night_brightness, intensity)
app->>app: SetFrontlightLevels(levels)
app->>Frontlight: set_intensity(levels.intensity)
app->>Frontlight: set_warmth(levels.warmth)
end
Possibly Related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Warning Review ran into problems🔥 ProblemsStopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (3)
crates/core/src/frontlight/standard.rs (1)
25-27: ⚡ Quick winDocument the ioctl safety contract.
This
unsafecall may be required, but the block still needs a shortSAFETY:note explaining whyself.interface.as_raw_fd()and the request code satisfy the kernel contract.As per coding guidelines:
Avoid unsafe unless required and documented in Rust.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/core/src/frontlight/standard.rs` around lines 25 - 27, The unsafe block containing the write_frontlight_intensity call lacks a SAFETY documentation comment explaining the safety contract. Add a SAFETY comment immediately before the unsafe block that documents why self.interface.as_raw_fd() provides a valid file descriptor and why the request code passed to write_frontlight_intensity satisfies the kernel ioctl contract requirements. The comment should be brief but specific about what makes this unsafe operation sound.Source: Coding guidelines
crates/core/src/view/settings_editor/kinds/general.rs (1)
953-1029: ⚡ Quick winAdd tests for
AutoFrontlightConfigChangedbus dispatch.These tests cover parsing well, but they don’t assert that
handle(...)enqueuesEvent::AutoFrontlightConfigChanged, which is the key integration signal for task resync.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/core/src/view/settings_editor/kinds/general.rs` around lines 953 - 1029, The tests in the auto_frontlight module verify that apply_text correctly parses input and updates settings, but they are missing assertions that verify the critical integration behavior: that handle(...) properly enqueues Event::AutoFrontlightConfigChanged to the bus when settings are modified. Enhance each test (brightness_apply_text_parses_and_updates, brightness_apply_text_ignores_invalid_input, manual_coordinates_apply_text_parses_and_updates, manual_coordinates_apply_text_clears_on_empty_input, and manual_coordinates_apply_text_ignores_invalid_input) by adding assertions that confirm Event::AutoFrontlightConfigChanged is enqueued on the bus as the key signal for task resync.crates/core/src/view/settings_editor/category_editor.rs (1)
800-801: ⚡ Quick winAdd a regression test for the new auto-frontlight input close paths.
This match is a hand-maintained allowlist of closeable overlays. A focused test that opens
AutoFrontlightBrightnessInputandAutoFrontlightManualCoordinatesInput, then assertsEvent::Close(...)removes the child and clears focus, would make futureViewIdchurn a lot safer.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/core/src/view/settings_editor/category_editor.rs` around lines 800 - 801, A regression test is needed to ensure the newly added closeable overlay ViewIds (AutoFrontlightBrightnessInput and AutoFrontlightManualCoordinatesInput) in the allowlist match statement are properly handled when receiving a Close event. Create a focused test that opens each of these overlay views, sends an Event::Close, and then asserts that the child is removed from the view hierarchy and focus is cleared. This test will prevent future regressions when ViewId definitions are modified.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@contrib/Settings-sample.toml`:
- Around line 20-21: The comment for auto-frontlight-night-brightness states the
range is 0.0 to 1.0, but this setting is backed by LightLevel which uses a 0.0
to 100.0 scale, creating misleading documentation that can result in much dimmer
values than intended. Update the comment to correctly state the range as 0.0 to
100.0 instead of 0.0 to 1.0, and adjust the example value from 0.10 to an
appropriate value on the 0-100 scale (such as 10 for 10% brightness).
In `@crates/cadmus/src/app.rs`:
- Around line 1313-1353: The Event::UpdateAutoFrontlight handler sends
SetFrontlightLevels which unconditionally stops the AutoFrontlight task, causing
the periodic auto-update task to stop after its first execution. Additionally,
UpdateAutoFrontlight ignores the context.settings.frontlight on/off flag,
potentially re-enabling the light after the user has disabled it. Fix this by
applying the frontlight levels directly in the UpdateAutoFrontlight handler
instead of routing through SetFrontlightLevels, checking
context.settings.frontlight before applying the levels, and keeping the
task-stop logic only in the SetFrontlightLevels handler for manual adjustments.
In `@crates/core/i18n/en-GB/cadmus_core.ftl`:
- Around line 53-57: The settings-general-auto-frontlight and related keys
(settings-general-auto-frontlight-brightness,
settings-general-auto-frontlight-brightness-input,
settings-general-auto-frontlight-manual-coordinates, and
settings-general-auto-frontlight-manual-coordinates-input) are currently placed
after settings-general-auto-time, breaking alphabetical ordering. Move these
five auto-frontlight keys to their correct alphabetical position before the
auto-time keys, since "auto-frontlight" comes alphabetically before "auto-time"
in the Settings - General section.
In `@crates/core/src/frontlight/auto.rs`:
- Around line 109-125: The make_dt() function treats its input strings as UTC
and converts to Local timezone, while compute_expected_sun_times() returns raw
UTC minutes without timezone conversion, causing a mismatch in test assertions
on non-UTC systems. Fix this by aligning both helpers to work end-to-end in the
same timezone: either modify compute_expected_sun_times() to return local
wall-clock minutes instead of raw UTC minutes by applying the same timezone
conversion logic used in make_dt(), or alternatively modify make_dt() to treat
input strings as local time directly without the UTC intermediate step. Ensure
whichever approach you choose is used consistently throughout the test logic so
that the times passed to make_dt() match what compute_expected_sun_times()
returns.
In `@crates/core/src/frontlight/mod.rs`:
- Around line 100-103: The from_fraction() method in the LightLevel newtype
directly multiplies the input without validation, allowing out-of-range values
when the input is outside [0.0, 1.0] or due to floating-point precision errors.
Fix this by computing the fraction times 100 and then passing the result through
the LightLevel constructor (likely via From<f32> or Self::new) to ensure the
value is properly clamped to the valid 0-100 range, maintaining the newtype
invariant.
In `@crates/core/src/frontlight/premixed.rs`:
- Around line 46-58: Change the Frontlight trait signature to return Result<(),
Error> instead of () for the set_intensity and set_warmth methods (anchor site
in crates/core/src/frontlight/premixed.rs lines 46-58). Replace the unwrap()
call in set_intensity and the expect() calls in set_warmth with the ? operator
to propagate errors. Apply the same Result return type change to the
corresponding methods in the sibling NaturalFrontlight implementation
(crates/core/src/frontlight/natural.rs lines 101-112) and StandardFrontlight.
Update all callers of these methods in reader/mod.rs and context.rs to handle
the returned Result values using ? or explicit error handling. This approach
ensures sysfs write failures are propagated as recoverable errors rather than
panicking the application.
In `@crates/core/src/task/auto_frontlight.rs`:
- Line 21: The code at line 21 uses `.ok()` on the hub.send call, which silently
swallows any SendError if the receiver is no longer available, hiding a broken
event path and making debugging difficult. Replace the `.ok()` call with
explicit error handling for the send operation on Event::UpdateAutoFrontlight;
either log the error when the channel send fails or handle it appropriately so
that broken event paths are visible and not silently ignored.
In `@crates/core/src/task/time_sync.rs`:
- Line 44: Fix the typo in the structured log field name in the tracing::error!
call where the geolocation fetch fails. Change the field key from `erro` to
`error` in the macro call to ensure that log filtering and aggregation systems
can properly match this error field with the standard error field name.
- Around line 31-49: The NTP time synchronization is currently skipped when
geolocation fetch or HTTP client creation fails, which silently disables
auto-time updates on transient failures. Restructure the code so that
TimeManager::sync is always called regardless of geolocation success. Create the
HTTP client first, then attempt to fetch geolocation, but ensure that sync is
invoked with either Some(geo) if geolocation succeeds or None if it fails. Keep
the hub.send(Event::AutoFrontlightCoordinates) call conditional on geolocation
success, but make sure the sync call at the TimeManager::sync invocation always
executes when the client is available.
In `@crates/core/src/view/frontlight.rs`:
- Around line 253-263: The set_frontlight_levels method only updates the slider
UI but slider handlers still merge changes against the stale
context.frontlight.levels(), causing consecutive interactions to compose against
old state. Add a field to FrontlightWindow to cache the current LightLevels as a
local source of truth, update this cache whenever set_frontlight_levels is
called, and modify the slider event handlers (which appear to be in the ranges
around lines 287-296 and 365-380) to merge against this cached value instead of
context.frontlight.levels() until the apply event is processed.
---
Nitpick comments:
In `@crates/core/src/frontlight/standard.rs`:
- Around line 25-27: The unsafe block containing the write_frontlight_intensity
call lacks a SAFETY documentation comment explaining the safety contract. Add a
SAFETY comment immediately before the unsafe block that documents why
self.interface.as_raw_fd() provides a valid file descriptor and why the request
code passed to write_frontlight_intensity satisfies the kernel ioctl contract
requirements. The comment should be brief but specific about what makes this
unsafe operation sound.
In `@crates/core/src/view/settings_editor/category_editor.rs`:
- Around line 800-801: A regression test is needed to ensure the newly added
closeable overlay ViewIds (AutoFrontlightBrightnessInput and
AutoFrontlightManualCoordinatesInput) in the allowlist match statement are
properly handled when receiving a Close event. Create a focused test that opens
each of these overlay views, sends an Event::Close, and then asserts that the
child is removed from the view hierarchy and focus is cleared. This test will
prevent future regressions when ViewId definitions are modified.
In `@crates/core/src/view/settings_editor/kinds/general.rs`:
- Around line 953-1029: The tests in the auto_frontlight module verify that
apply_text correctly parses input and updates settings, but they are missing
assertions that verify the critical integration behavior: that handle(...)
properly enqueues Event::AutoFrontlightConfigChanged to the bus when settings
are modified. Enhance each test (brightness_apply_text_parses_and_updates,
brightness_apply_text_ignores_invalid_input,
manual_coordinates_apply_text_parses_and_updates,
manual_coordinates_apply_text_clears_on_empty_input, and
manual_coordinates_apply_text_ignores_invalid_input) by adding assertions that
confirm Event::AutoFrontlightConfigChanged is enqueued on the bus as the key
signal for task resync.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 1165f537-072d-4136-b4a2-9e1e2f3965d5
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (29)
contrib/Settings-sample.tomlcrates/cadmus/src/app.rscrates/core/Cargo.tomlcrates/core/i18n/en-GB/cadmus_core.ftlcrates/core/src/context.rscrates/core/src/frontlight/auto.rscrates/core/src/frontlight/mod.rscrates/core/src/frontlight/natural.rscrates/core/src/frontlight/premixed.rscrates/core/src/frontlight/standard.rscrates/core/src/geolocation.rscrates/core/src/lib.rscrates/core/src/settings/mod.rscrates/core/src/task/auto_frontlight.rscrates/core/src/task/mod.rscrates/core/src/task/time_sync.rscrates/core/src/time_manager.rscrates/core/src/view/frontlight.rscrates/core/src/view/home/mod.rscrates/core/src/view/mod.rscrates/core/src/view/settings_editor/category.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/view/settings_editor/kinds/general.rscrates/core/src/view/settings_editor/kinds/identity.rscrates/core/src/view/settings_editor/kinds/mod.rscrates/emulator/src/main.rsdocs/src/SUMMARY.mddocs/src/auto-frontlight.mddocs/src/settings/index.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
docs/src/**/*.md
📄 CodeRabbit inference engine (docs/AGENTS.md)
docs/src/**/*.md: Use conversational and friendly tone in user-facing documentation
Use active voice in user-facing documentation (e.g., 'Copy the file' instead of 'The file should be copied')
Avoid jargon in user-facing documentation: replace 'artifact' with 'file' or 'package', 'deploy' with 'install' or 'download', 'configure' with 'set up', 'bundle' with 'package', 'on-device' with 'on your Kobo' or 'wirelessly'
Use standardized admonition syntax for documentation: [!NOTE], [!TIP], [!IMPORTANT], [!WARNING], [!CAUTION]
Files:
docs/src/auto-frontlight.mddocs/src/SUMMARY.mddocs/src/settings/index.md
docs/**/*.md
📄 CodeRabbit inference engine (docs/AGENTS.md)
docs/**/*.md: Format Markdown with Prettier
Ensure Markdown passes markdownlint
Use code blocks with language tags in Markdown
Files:
docs/src/auto-frontlight.mddocs/src/SUMMARY.mddocs/src/settings/index.md
crates/core/**/*.rs
📄 CodeRabbit inference engine (crates/core/AGENTS.md)
crates/core/**/*.rs: Rustdoc examples should follow this preference order: fully compilable >no_run>ignore. Useno_runwhen the example compiles but cannot execute (file I/O, network, database). Useignoreonly for private/pub(crate)items unreachable from the test harness with a comment explaining why. Use#to hide boilerplate setup lines. Verify withcargo test --doc.
Use typed SQL macros (sqlx::query!,sqlx::query_as!,sqlx::query_scalar!) in Rust code. Never use untypedsqlx::query()/sqlx::query_as()/sqlx::query_scalar(). Use.flatten()onquery_scalar!results for nullable columns (Option<Option<T>>→Option<T>).
Untyped SQL queries are allowed only for dynamic SQL (e.g. runtimeORDER BYcolumn) if and only if the function has unit tests covering every dynamic path, with a comment explaining why the typed macro cannot be used.
All user-visible strings must use thefl!macro (use crate::fl;). Never hardcode string literals for labels, buttons, placeholders, or notifications. User-visible strings include:label()implementations onSettingKindtraits, input fieldlabelstrings inEvent::OpenNamedInput, menu entry text (EntryKind::Command,EntryKind::RadioButton, etc.), and button labels, notification text.
Files:
crates/core/src/task/time_sync.rscrates/core/src/view/settings_editor/kinds/mod.rscrates/core/src/lib.rscrates/core/src/view/settings_editor/category.rscrates/core/src/view/settings_editor/kinds/identity.rscrates/core/src/view/home/mod.rscrates/core/src/time_manager.rscrates/core/src/task/auto_frontlight.rscrates/core/src/view/mod.rscrates/core/src/frontlight/natural.rscrates/core/src/geolocation.rscrates/core/src/context.rscrates/core/src/frontlight/auto.rscrates/core/src/view/settings_editor/kinds/general.rscrates/core/src/frontlight/premixed.rscrates/core/src/settings/mod.rscrates/core/src/frontlight/standard.rscrates/core/src/task/mod.rscrates/core/src/frontlight/mod.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/view/frontlight.rs
crates/core/**/*.{sql,rs}
📄 CodeRabbit inference engine (crates/core/AGENTS.md)
All SQL queries must list explicit column names. Do not use
SELECT *.
Files:
crates/core/src/task/time_sync.rscrates/core/src/view/settings_editor/kinds/mod.rscrates/core/src/lib.rscrates/core/src/view/settings_editor/category.rscrates/core/src/view/settings_editor/kinds/identity.rscrates/core/src/view/home/mod.rscrates/core/src/time_manager.rscrates/core/src/task/auto_frontlight.rscrates/core/src/view/mod.rscrates/core/src/frontlight/natural.rscrates/core/src/geolocation.rscrates/core/src/context.rscrates/core/src/frontlight/auto.rscrates/core/src/view/settings_editor/kinds/general.rscrates/core/src/frontlight/premixed.rscrates/core/src/settings/mod.rscrates/core/src/frontlight/standard.rscrates/core/src/task/mod.rscrates/core/src/frontlight/mod.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/view/frontlight.rs
crates/core/**/*.{ftl,rs}
📄 CodeRabbit inference engine (crates/core/AGENTS.md)
Every user-visible string needs a Fluent message ID in
crates/core/i18n/en-GB/cadmus_core.ftl. Usefl!("message-id")at the call site. For parameterised strings, use Fluent variables ({ $var }) in the.ftlfile and pass values viafl!("id", var = value).
Files:
crates/core/src/task/time_sync.rscrates/core/src/view/settings_editor/kinds/mod.rscrates/core/src/lib.rscrates/core/src/view/settings_editor/category.rscrates/core/i18n/en-GB/cadmus_core.ftlcrates/core/src/view/settings_editor/kinds/identity.rscrates/core/src/view/home/mod.rscrates/core/src/time_manager.rscrates/core/src/task/auto_frontlight.rscrates/core/src/view/mod.rscrates/core/src/frontlight/natural.rscrates/core/src/geolocation.rscrates/core/src/context.rscrates/core/src/frontlight/auto.rscrates/core/src/view/settings_editor/kinds/general.rscrates/core/src/frontlight/premixed.rscrates/core/src/settings/mod.rscrates/core/src/frontlight/standard.rscrates/core/src/task/mod.rscrates/core/src/frontlight/mod.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/view/frontlight.rs
**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.rs: Prefer?operator overunwrap()/expect()in library and app code
Usethiserrorfor custom error types andanyhowfor ad-hoc errors in Rust
Use iterators over index-based loops in Rust
Use&stroverStringin function parameters when ownership is not needed
Prefer borrowing over cloning in Rust
Inline expressions directly into struct fields — avoid intermediate bindings solely to pass them into a struct literal
Avoidunsafeunless required and documented in Rust
Avoid prematurecollect()— keep iterators lazy in Rust
Ensure Rust code compiles without warnings
Prefer newtype wrappers over raw primitives for domain concepts (e.g.,Fingerprint(String)instead of bareString)
WrapString,i64, and similar primitives when the value represents a specific domain concept (fingerprints, file kinds, identifiers, etc.)
ImplementDisplay,FromStr, and other standard traits on newtype wrappers to keep them ergonomic
Match on enum variants instead of string comparisons — the compiler catches missing arms
Comment why, not what. Avoid inline comments — extract code into well-named, documented functions instead
Avoid dead-code comments (commented-out code) in Rust
Avoid changelog comments (Modified by X on date) in Rust
Avoid divider comments (//=====) in Rust
Annotations (TODO,FIXME,HACK,NOTE) are acceptable with context in Rust
Use structured fields with thetracingcrate — never use string formatting for log data
Use only structured fields for logging — data goes in fields, not format strings
Do not use module prefixes in logs — instrumentation scope provides context
Do not mix structured fields with format arguments in logging
Usedebuglog level for development and troubleshooting detail
Useinfolog level for important runtime events
Usewarnlog level for recoverable issues (retries, fallbacks)
Useerrorlog level for failures requiring attention
Return domain types directly from sqlx queries instead of parsin...
Files:
crates/core/src/task/time_sync.rscrates/core/src/view/settings_editor/kinds/mod.rscrates/core/src/lib.rscrates/core/src/view/settings_editor/category.rscrates/core/src/view/settings_editor/kinds/identity.rscrates/emulator/src/main.rscrates/core/src/view/home/mod.rscrates/core/src/time_manager.rscrates/core/src/task/auto_frontlight.rscrates/core/src/view/mod.rscrates/core/src/frontlight/natural.rscrates/core/src/geolocation.rscrates/core/src/context.rscrates/core/src/frontlight/auto.rscrates/core/src/view/settings_editor/kinds/general.rscrates/core/src/frontlight/premixed.rscrates/core/src/settings/mod.rscrates/core/src/frontlight/standard.rscrates/core/src/task/mod.rscrates/core/src/frontlight/mod.rscrates/cadmus/src/app.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/view/frontlight.rs
**/Cargo.toml
📄 CodeRabbit inference engine (AGENTS.md)
**/Cargo.toml: Use caret requirements for most dependencies in Cargo.toml
Alphabetize dependencies within logical groups in Cargo.toml
Usedefault-features = falsewhen fine-grained control is needed in Cargo.toml
Keep related crate families at compatible versions (e.g. allopentelemetry-*crates) in Cargo.toml
Files:
crates/core/Cargo.toml
crates/core/**/*.ftl
📄 CodeRabbit inference engine (crates/core/AGENTS.md)
crates/core/**/*.ftl: Keep Fluent message keys (.ftlfile keys) sorted alphabetically within each comment section.
Fluent message key naming convention: use kebab-case, prefixed by feature area. Usesettings-<category>-<description>for settings labels,settings-<category>-<description>-inputfor input fields, andnotification-<description>for notifications.
Files:
crates/core/i18n/en-GB/cadmus_core.ftl
🧠 Learnings (2)
📚 Learning: 2026-05-31T07:53:12.579Z
Learnt from: OGKevin
Repo: OGKevin/cadmus PR: 553
File: docs/src/installation/migration.md:87-88
Timestamp: 2026-05-31T07:53:12.579Z
Learning: For markdown files under docs/src/ in the cadmus (OGKevin/cadmus) repo, validate mdBook admonition syntax using the allowed types: NOTE, TIP, WARNING, IMPORTANT, and CAUTION. The correct format is a blockquote prefix like `> [!NOTE]`, `> [!TIP]`, `> [!WARNING]`, `> [!IMPORTANT]`, or `> [!CAUTION]`. Do not flag `[!CAUTION]` or `[!IMPORTANT]` as non-standard in this repo.
Applied to files:
docs/src/auto-frontlight.mddocs/src/SUMMARY.mddocs/src/settings/index.md
📚 Learning: 2026-05-23T14:57:43.820Z
Learnt from: OGKevin
Repo: OGKevin/cadmus PR: 478
File: crates/core/src/view/settings_editor/refresh_rate_by_kind_editor.rs:91-91
Timestamp: 2026-05-23T14:57:43.820Z
Learning: When reviewing Rust code that calls `ToggleableKeyboard::new(parent_rect: Rectangle, number_mode: bool)` (from `crates/core/src/view/toggleable_keyboard.rs`), treat the second argument as `number_mode` (numeric/number-layout mode), not as an initial visibility flag. In the constructor implementation, `visible` is initialized to `false` and the keyboard starts hidden; only the numeric layout changes based on `number_mode` (e.g., for numeric inputs like `refresh rate u8`). Therefore, do not flag `ToggleableKeyboard::new(rect, true)` as “making the keyboard start visible.”
Applied to files:
crates/core/src/task/time_sync.rscrates/core/src/view/settings_editor/kinds/mod.rscrates/core/src/lib.rscrates/core/src/view/settings_editor/category.rscrates/core/src/view/settings_editor/kinds/identity.rscrates/core/src/view/home/mod.rscrates/core/src/time_manager.rscrates/core/src/task/auto_frontlight.rscrates/core/src/view/mod.rscrates/core/src/frontlight/natural.rscrates/core/src/geolocation.rscrates/core/src/context.rscrates/core/src/frontlight/auto.rscrates/core/src/view/settings_editor/kinds/general.rscrates/core/src/frontlight/premixed.rscrates/core/src/settings/mod.rscrates/core/src/frontlight/standard.rscrates/core/src/task/mod.rscrates/core/src/frontlight/mod.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/view/frontlight.rs
🪛 GitHub Actions: PR `#590` / 2_Analyze (rust).txt
crates/cadmus/src/app.rs
[warning] 124-206: CodeQL (Rust autobuild/indexing) reported "macro expansion failed" warnings for macros including 'format_err', 'debug', and 'tracing::error'.
🪛 GitHub Actions: PR `#590` / Analyze (rust)
crates/cadmus/src/app.rs
[warning] 124-206: CodeQL rust autobuild WARN: macro expansion failed for multiple macros (e.g., format_err, debug, tracing::error) during extraction.
🔇 Additional comments (16)
docs/src/SUMMARY.md (1)
20-20: LGTM!docs/src/auto-frontlight.md (2)
8-10: 💤 Low valueVerify timing of the first automatic adjustment.
Line 9 states "The first adjustment happens as soon as the feature starts, and then repeats on every 5-minute mark." The provided context confirms the task runs every 5 minutes, but the AutoFrontlightTask code itself isn't included in this review. Can you confirm that the initial adjustment truly fires immediately when the feature is activated, rather than waiting for the next 5-minute interval?
1-81: Documentation is well-written, accurate, and properly formatted.Feature explanation is clear and conversational; all technical claims (5-minute cycle, 1.5-hour ramp windows, brightness/warmth behavior, ipapi.co location source, coordinate priority, default night brightness) align with the implementation details. Cross-references to the settings guide and time-sync guide are in place. Admonition syntax is correct per the repo's standard blockquote format.
Source: Coding guidelines
docs/src/settings/index.md (1)
62-110: Settings documentation is accurate, well-organized, and consistent with implementation.All four auto-frontlight settings (toggle, night brightness, manual coordinates, last coordinates) are documented with correct indicators, clear descriptions, accurate default behavior, proper ranges, and corresponding TOML examples. The priority rule (manual > auto-detected) and auto-management semantics are clearly explained. Integration with the feature documentation (cross-link at line 31 of auto-frontlight.md) is in place.
Source: Coding guidelines
crates/core/src/settings/mod.rs (1)
7-8: LGTM!Also applies to: 261-282, 1023-1026, 1055-1063
crates/core/src/time_manager.rs (1)
27-35: LGTM!Also applies to: 82-94
crates/core/src/frontlight/auto.rs (1)
29-39: No changes needed—sunrise::SolarDay::event_time()returnsDateTime<Utc>directly, notOption. The code correctly calls.with_timezone()on the result.> Likely an incorrect or invalid review comment.crates/emulator/src/main.rs (1)
387-387: LGTM!crates/core/src/view/settings_editor/kinds/mod.rs (1)
40-41: LGTM!crates/core/src/view/settings_editor/kinds/identity.rs (1)
24-26: LGTM!crates/core/src/view/settings_editor/kinds/general.rs (1)
422-654: LGTM!crates/core/src/task/mod.rs (1)
39-40: LGTM!Also applies to: 103-105, 129-130, 285-286, 351-352, 449-452, 539-559, 673-683
crates/core/src/view/mod.rs (1)
67-67: LGTM!Also applies to: 491-493, 512-513, 646-647, 833-834
crates/core/src/context.rs (1)
45-45: LGTM!Also applies to: 213-219, 223-247
crates/cadmus/src/app.rs (1)
201-201: LGTM!Also applies to: 366-367, 721-721, 1094-1097
crates/core/src/view/home/mod.rs (1)
2366-2376: LGTM!
3489b8b to
3574fa1
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
crates/core/i18n/en-GB/cadmus_core.ftl (1)
52-56:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAlphabetical ordering violation: move auto-frontlight keys before auto-suspend.
The five
settings-general-auto-frontlight*keys (lines 52-56) are currently placed afterauto-suspendand beforeauto-time, but alphabetically"frontlight"comes before"suspend". Move all five keys to appear immediately afterauto-power-off-input(line 49) and beforeauto-suspend(line 50).📝 Suggested reorder
settings-general-auto-power-off = Auto Power Off (days) settings-general-auto-power-off-input = Auto Power Off (days, 0 = never) +settings-general-auto-frontlight = Automatic Frontlight +settings-general-auto-frontlight-brightness = Auto Night Brightness +settings-general-auto-frontlight-brightness-input = Night Brightness (% 0-100) +settings-general-auto-frontlight-manual-coordinates = Manual Coordinates +settings-general-auto-frontlight-manual-coordinates-input = lat,lon | coordinates settings-general-auto-suspend = Auto Suspend (minutes) settings-general-auto-suspend-input = Auto Suspend (minutes, 0 = never) -settings-general-auto-frontlight = Automatic Frontlight -settings-general-auto-frontlight-brightness = Auto Night Brightness -settings-general-auto-frontlight-brightness-input = Night Brightness (% 0-100) -settings-general-auto-frontlight-manual-coordinates = Manual Coordinates -settings-general-auto-frontlight-manual-coordinates-input = lat,lon | coordinates settings-general-auto-time = Automatic Time Sync🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/core/i18n/en-GB/cadmus_core.ftl` around lines 52 - 56, The five settings-general-auto-frontlight* keys (settings-general-auto-frontlight, settings-general-auto-frontlight-brightness, settings-general-auto-frontlight-brightness-input, settings-general-auto-frontlight-manual-coordinates, and settings-general-auto-frontlight-manual-coordinates-input) are currently placed after auto-suspend, but alphabetically "frontlight" should come before "suspend". Move all five auto-frontlight keys to appear immediately after the auto-power-off-input key and before the auto-suspend key to restore proper alphabetical ordering.Source: Coding guidelines
🧹 Nitpick comments (1)
crates/core/src/view/reader/mod.rs (1)
4036-4039: ⚡ Quick winUse the imported
error!macro instead oftracing::error!.Line 4036 and Line 4039 should use
error!(...)(already imported) to match the project logging style rule and keep instrumentation context clean.Suggested patch
- if let Err(error) = context.frontlight.set_intensity(intensity) { - tracing::error!(error = %error, "failed to set frontlight intensity"); + if let Err(error) = context.frontlight.set_intensity(intensity) { + error!(error = %error, "failed to set frontlight intensity"); } if let Err(error) = context.frontlight.set_warmth(warmth) { - tracing::error!(error = %error, "failed to set frontlight warmth"); + error!(error = %error, "failed to set frontlight warmth"); }As per coding guidelines, “Do not use module prefixes in logs — instrumentation scope provides context.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/core/src/view/reader/mod.rs` around lines 4036 - 4039, Replace the module-prefixed `tracing::error!` calls with the imported `error!` macro in the frontlight intensity and warmth error logging statements. The macro is already imported in the file, so remove the `tracing::` prefix from both error! invocations that log "failed to set frontlight intensity" and "failed to set frontlight warmth" to match the project's logging style guidelines and keep instrumentation context clean.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/core/src/task/auto_frontlight.rs`:
- Around line 21-23: When hub.send(Event::UpdateAutoFrontlight) fails with an
error, the loop continues indefinitely trying to resend the event even though
the receiver is permanently gone and the channel won't recover. Add a break
statement after logging the error in the error handling block to exit the loop
cleanly when the send fails, allowing the task manager to observe and handle the
failure instead of wasting CPU cycles on futile retries.
---
Duplicate comments:
In `@crates/core/i18n/en-GB/cadmus_core.ftl`:
- Around line 52-56: The five settings-general-auto-frontlight* keys
(settings-general-auto-frontlight, settings-general-auto-frontlight-brightness,
settings-general-auto-frontlight-brightness-input,
settings-general-auto-frontlight-manual-coordinates, and
settings-general-auto-frontlight-manual-coordinates-input) are currently placed
after auto-suspend, but alphabetically "frontlight" should come before
"suspend". Move all five auto-frontlight keys to appear immediately after the
auto-power-off-input key and before the auto-suspend key to restore proper
alphabetical ordering.
---
Nitpick comments:
In `@crates/core/src/view/reader/mod.rs`:
- Around line 4036-4039: Replace the module-prefixed `tracing::error!` calls
with the imported `error!` macro in the frontlight intensity and warmth error
logging statements. The macro is already imported in the file, so remove the
`tracing::` prefix from both error! invocations that log "failed to set
frontlight intensity" and "failed to set frontlight warmth" to match the
project's logging style guidelines and keep instrumentation context clean.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 4e68a0c3-fb88-4a34-9602-43653f0210dc
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (30)
contrib/Settings-sample.tomlcrates/cadmus/src/app.rscrates/core/Cargo.tomlcrates/core/i18n/en-GB/cadmus_core.ftlcrates/core/src/context.rscrates/core/src/frontlight/auto.rscrates/core/src/frontlight/mod.rscrates/core/src/frontlight/natural.rscrates/core/src/frontlight/premixed.rscrates/core/src/frontlight/standard.rscrates/core/src/geolocation.rscrates/core/src/lib.rscrates/core/src/settings/mod.rscrates/core/src/task/auto_frontlight.rscrates/core/src/task/mod.rscrates/core/src/task/time_sync.rscrates/core/src/time_manager.rscrates/core/src/view/frontlight.rscrates/core/src/view/home/mod.rscrates/core/src/view/mod.rscrates/core/src/view/reader/mod.rscrates/core/src/view/settings_editor/category.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/view/settings_editor/kinds/general.rscrates/core/src/view/settings_editor/kinds/identity.rscrates/core/src/view/settings_editor/kinds/mod.rscrates/emulator/src/main.rsdocs/src/SUMMARY.mddocs/src/auto-frontlight.mddocs/src/settings/index.md
✅ Files skipped from review due to trivial changes (3)
- docs/src/auto-frontlight.md
- docs/src/settings/index.md
- docs/src/SUMMARY.md
🚧 Files skipped from review as they are similar to previous changes (19)
- contrib/Settings-sample.toml
- crates/core/src/lib.rs
- crates/emulator/src/main.rs
- crates/core/src/view/settings_editor/category.rs
- crates/core/Cargo.toml
- crates/core/src/view/settings_editor/kinds/mod.rs
- crates/core/src/view/settings_editor/kinds/identity.rs
- crates/core/src/view/home/mod.rs
- crates/core/src/frontlight/premixed.rs
- crates/core/src/task/mod.rs
- crates/core/src/context.rs
- crates/core/src/view/mod.rs
- crates/core/src/frontlight/auto.rs
- crates/core/src/time_manager.rs
- crates/core/src/geolocation.rs
- crates/cadmus/src/app.rs
- crates/core/src/view/settings_editor/kinds/general.rs
- crates/core/src/frontlight/mod.rs
- crates/core/src/settings/mod.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (40)
- GitHub Check: test (test + tracing, ubuntu-latest)
- GitHub Check: test (kobo + profiling, ubuntu-latest)
- GitHub Check: test (kobo + test, ubuntu-latest)
- GitHub Check: test (emulator + kobo + profiling, ubuntu-latest)
- GitHub Check: clippy (test + tracing, ubuntu-latest)
- GitHub Check: test (default, ubuntu-latest)
- GitHub Check: test (kobo, ubuntu-latest)
- GitHub Check: clippy (kobo + test + tracing, ubuntu-latest)
- GitHub Check: clippy (kobo + profiling + test + tracing, ubuntu-latest)
- GitHub Check: clippy (emulator + kobo + test + tracing, ubuntu-latest)
- GitHub Check: clippy (emulator + kobo + profiling + tracing, ubuntu-latest)
- GitHub Check: clippy (emulator + kobo + profiling + test + tracing, ubuntu-latest)
- GitHub Check: clippy (emulator + profiling + test + tracing, ubuntu-latest)
- GitHub Check: clippy (profiling + test + tracing, ubuntu-latest)
- GitHub Check: clippy (emulator + test + tracing, ubuntu-latest)
- GitHub Check: clippy (profiling + tracing, ubuntu-latest)
- GitHub Check: clippy (kobo + profiling + tracing, ubuntu-latest)
- GitHub Check: clippy (kobo + tracing, ubuntu-latest)
- GitHub Check: clippy (emulator + profiling + tracing, ubuntu-latest)
- GitHub Check: clippy (emulator + kobo + tracing, ubuntu-latest)
- GitHub Check: clippy (kobo + profiling, ubuntu-latest)
- GitHub Check: clippy (kobo + profiling + test, ubuntu-latest)
- GitHub Check: clippy (profiling + test, ubuntu-latest)
- GitHub Check: clippy (emulator + tracing, ubuntu-latest)
- GitHub Check: clippy (tracing, ubuntu-latest)
- GitHub Check: clippy (emulator + kobo + profiling, ubuntu-latest)
- GitHub Check: clippy (emulator + profiling + test, ubuntu-latest)
- GitHub Check: clippy (emulator + test, ubuntu-latest)
- GitHub Check: clippy (emulator + kobo + test, ubuntu-latest)
- GitHub Check: clippy (emulator + profiling, ubuntu-latest)
- GitHub Check: clippy (profiling, ubuntu-latest)
- GitHub Check: clippy (kobo + test, ubuntu-latest)
- GitHub Check: clippy (test, ubuntu-latest)
- GitHub Check: clippy (emulator + kobo, ubuntu-latest)
- GitHub Check: clippy (emulator, ubuntu-latest)
- GitHub Check: clippy (default, ubuntu-latest)
- GitHub Check: clippy (kobo, ubuntu-latest)
- GitHub Check: build-kobo
- GitHub Check: build-kobo-test
- GitHub Check: build
🧰 Additional context used
📓 Path-based instructions (5)
crates/core/**/*.{ftl,rs}
📄 CodeRabbit inference engine (crates/core/AGENTS.md)
Every user-visible string needs a Fluent message ID in
crates/core/i18n/en-GB/cadmus_core.ftl. Usefl!("message-id")at the call site. For parameterised strings, use Fluent variables ({ $var }) in the.ftlfile and pass values viafl!("id", var = value).
Files:
crates/core/i18n/en-GB/cadmus_core.ftlcrates/core/src/view/reader/mod.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/task/auto_frontlight.rscrates/core/src/task/time_sync.rscrates/core/src/frontlight/natural.rscrates/core/src/frontlight/standard.rscrates/core/src/view/frontlight.rs
crates/core/**/*.ftl
📄 CodeRabbit inference engine (crates/core/AGENTS.md)
crates/core/**/*.ftl: Keep Fluent message keys (.ftlfile keys) sorted alphabetically within each comment section.
Fluent message key naming convention: use kebab-case, prefixed by feature area. Usesettings-<category>-<description>for settings labels,settings-<category>-<description>-inputfor input fields, andnotification-<description>for notifications.
Files:
crates/core/i18n/en-GB/cadmus_core.ftl
crates/core/**/*.rs
📄 CodeRabbit inference engine (crates/core/AGENTS.md)
crates/core/**/*.rs: Rustdoc examples should follow this preference order: fully compilable >no_run>ignore. Useno_runwhen the example compiles but cannot execute (file I/O, network, database). Useignoreonly for private/pub(crate)items unreachable from the test harness with a comment explaining why. Use#to hide boilerplate setup lines. Verify withcargo test --doc.
Use typed SQL macros (sqlx::query!,sqlx::query_as!,sqlx::query_scalar!) in Rust code. Never use untypedsqlx::query()/sqlx::query_as()/sqlx::query_scalar(). Use.flatten()onquery_scalar!results for nullable columns (Option<Option<T>>→Option<T>).
Untyped SQL queries are allowed only for dynamic SQL (e.g. runtimeORDER BYcolumn) if and only if the function has unit tests covering every dynamic path, with a comment explaining why the typed macro cannot be used.
All user-visible strings must use thefl!macro (use crate::fl;). Never hardcode string literals for labels, buttons, placeholders, or notifications. User-visible strings include:label()implementations onSettingKindtraits, input fieldlabelstrings inEvent::OpenNamedInput, menu entry text (EntryKind::Command,EntryKind::RadioButton, etc.), and button labels, notification text.
Files:
crates/core/src/view/reader/mod.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/task/auto_frontlight.rscrates/core/src/task/time_sync.rscrates/core/src/frontlight/natural.rscrates/core/src/frontlight/standard.rscrates/core/src/view/frontlight.rs
crates/core/**/*.{sql,rs}
📄 CodeRabbit inference engine (crates/core/AGENTS.md)
All SQL queries must list explicit column names. Do not use
SELECT *.
Files:
crates/core/src/view/reader/mod.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/task/auto_frontlight.rscrates/core/src/task/time_sync.rscrates/core/src/frontlight/natural.rscrates/core/src/frontlight/standard.rscrates/core/src/view/frontlight.rs
**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.rs: Prefer?operator overunwrap()/expect()in library and app code
Usethiserrorfor custom error types andanyhowfor ad-hoc errors in Rust
Use iterators over index-based loops in Rust
Use&stroverStringin function parameters when ownership is not needed
Prefer borrowing over cloning in Rust
Inline expressions directly into struct fields — avoid intermediate bindings solely to pass them into a struct literal
Avoidunsafeunless required and documented in Rust
Avoid prematurecollect()— keep iterators lazy in Rust
Ensure Rust code compiles without warnings
Prefer newtype wrappers over raw primitives for domain concepts (e.g.,Fingerprint(String)instead of bareString)
WrapString,i64, and similar primitives when the value represents a specific domain concept (fingerprints, file kinds, identifiers, etc.)
ImplementDisplay,FromStr, and other standard traits on newtype wrappers to keep them ergonomic
Match on enum variants instead of string comparisons — the compiler catches missing arms
Comment why, not what. Avoid inline comments — extract code into well-named, documented functions instead
Avoid dead-code comments (commented-out code) in Rust
Avoid changelog comments (Modified by X on date) in Rust
Avoid divider comments (//=====) in Rust
Annotations (TODO,FIXME,HACK,NOTE) are acceptable with context in Rust
Use structured fields with thetracingcrate — never use string formatting for log data
Use only structured fields for logging — data goes in fields, not format strings
Do not use module prefixes in logs — instrumentation scope provides context
Do not mix structured fields with format arguments in logging
Usedebuglog level for development and troubleshooting detail
Useinfolog level for important runtime events
Usewarnlog level for recoverable issues (retries, fallbacks)
Useerrorlog level for failures requiring attention
Return domain types directly from sqlx queries instead of parsin...
Files:
crates/core/src/view/reader/mod.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/task/auto_frontlight.rscrates/core/src/task/time_sync.rscrates/core/src/frontlight/natural.rscrates/core/src/frontlight/standard.rscrates/core/src/view/frontlight.rs
🧠 Learnings (1)
📚 Learning: 2026-05-23T14:57:43.820Z
Learnt from: OGKevin
Repo: OGKevin/cadmus PR: 478
File: crates/core/src/view/settings_editor/refresh_rate_by_kind_editor.rs:91-91
Timestamp: 2026-05-23T14:57:43.820Z
Learning: When reviewing Rust code that calls `ToggleableKeyboard::new(parent_rect: Rectangle, number_mode: bool)` (from `crates/core/src/view/toggleable_keyboard.rs`), treat the second argument as `number_mode` (numeric/number-layout mode), not as an initial visibility flag. In the constructor implementation, `visible` is initialized to `false` and the keyboard starts hidden; only the numeric layout changes based on `number_mode` (e.g., for numeric inputs like `refresh rate u8`). Therefore, do not flag `ToggleableKeyboard::new(rect, true)` as “making the keyboard start visible.”
Applied to files:
crates/core/src/view/reader/mod.rscrates/core/src/view/settings_editor/category_editor.rscrates/core/src/task/auto_frontlight.rscrates/core/src/task/time_sync.rscrates/core/src/frontlight/natural.rscrates/core/src/frontlight/standard.rscrates/core/src/view/frontlight.rs
🔇 Additional comments (10)
crates/core/src/view/frontlight.rs (3)
29-29: LGTM!Also applies to: 217-222, 259-271, 294-306
144-144: LGTM!Also applies to: 162-162, 283-284, 397-398
371-390: LGTM!crates/core/src/view/settings_editor/category_editor.rs (4)
800-802: LGTM!
837-838: LGTM!Also applies to: 940-941
1016-1021: LGTM!
1566-1615: LGTM!crates/core/src/task/time_sync.rs (1)
3-5: LGTM!Also applies to: 31-53
crates/core/src/task/auto_frontlight.rs (2)
1-7: LGTM!
9-12: LGTM!
3574fa1 to
c80c05a
Compare
Change-Id: 64d89c204d8bed70af57523eb93546ad Change-Id-Short: tvmrqnxzvmro
c80c05a to
dac8e06
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
Change-Id: 64d89c204d8bed70af57523eb93546ad
Change-Id-Short: tvmrqnxzvmro
Closes: #486
Closes: CAD-78
Automatic Frontlight
Adds an automatic frontlight feature that adjusts warmth and brightness based on the sun's position at the device's location.
How it works
A background task runs every 5 minutes and emits an
UpdateAutoFrontlightevent. The main loop handles this event by computing new frontlight levels viacompute_auto_frontlight_levels, which uses thesunrisecrate to determine local sunrise and sunset times.auto-frontlight-night-brightnessafter sunset.Making a manual frontlight adjustment while the task is running stops the background task so the chosen level is preserved until the next app start.
Location
Coordinates are resolved from
auto-frontlight-manual-coordinatesif set, otherwise fromauto-frontlight-last-coordinates, which is written automatically during each time sync. The geolocation fetch that was previously embedded inTimeManagerhas been extracted into a dedicatedgeolocationmodule and reused by the time sync task, which now forwards the discovered coordinates to the home view viaAutoFrontlightCoordinates.LightLeveltypeintensityandwarmthfields onLightLevelsare now a newtypeLightLevelwrappingf32and clamped to0.0–100.0. Conversion helpers (as_fraction,as_10_base,as_10_base_inverted,from_fraction) replace the ad-hoc arithmetic that was previously scattered across the frontlight backends. Aturn_offdefault method on theFrontlighttrait replaces repeatedset_intensity(0.0); set_warmth(0.0)call sites.Settings
Three new settings are introduced:
auto-frontlightfalseauto-frontlight-night-brightness1.0auto-frontlight-manual-coordinates[lat, lon]auto-frontlight-last-coordinatesis written automatically and should not be edited by hand.All three user-facing settings are exposed in Settings → General and documented in a new
auto-frontlight.mdpage.