From 4a1966246512d48406f2f894b2cdb820dbcfb123 Mon Sep 17 00:00:00 2001 From: Mykhailo Shevchuk Date: Fri, 24 Jul 2026 17:30:52 +0300 Subject: [PATCH 1/2] Nightstand Clock: fix unreachable nightlight, 12h midnight, and notif use-after-close (closes #243) - Round the inherited system brightness and clamp it to 0-100 so the -5/+5 stepping always lands exactly on 0 (the LED nightlight) and 100. Several system brightness levels (e.g. 70%, 90%) truncated off the multiple-of-5 grid, so Down skipped 0 and the nightlight could never be switched on, and brightness could leave the valid range. - Show midnight as 12:xx AM instead of 00:xx AM in 12-hour locales. - Close RECORD_NOTIFICATION after the exit-time settings restore instead of before it, so notif is no longer dereferenced after its record is closed. Bump fap_version 1.0 -> 1.1 and add CHANGELOG.md. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../FlipperNightStand_clock/CHANGELOG.md | 11 +++++++++++ .../FlipperNightStand_clock/application.fam | 2 +- .../FlipperNightStand_clock/clock_app.c | 18 ++++++++---------- 3 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 non_catalog_apps/FlipperNightStand_clock/CHANGELOG.md diff --git a/non_catalog_apps/FlipperNightStand_clock/CHANGELOG.md b/non_catalog_apps/FlipperNightStand_clock/CHANGELOG.md new file mode 100644 index 00000000..b2bfd6ae --- /dev/null +++ b/non_catalog_apps/FlipperNightStand_clock/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +## 1.1 + +- Fix the 12-hour clock showing midnight as `00:xx AM` instead of `12:xx AM` +- Fix the brightness control so the red LED nightlight stays reachable from every starting brightness: round the inherited system brightness to the nearest step and clamp brightness to 0-100 (previously levels such as 35/45/65/70/90/95% started off-grid, so Down skipped 0 and the nightlight could never be switched on) +- Restore the notification settings before releasing the notification record when exiting + +## 1.0 + +- Initial release: overnight clock with screen-brightness control, red LED nightlight, and a stopwatch diff --git a/non_catalog_apps/FlipperNightStand_clock/application.fam b/non_catalog_apps/FlipperNightStand_clock/application.fam index 380c34b1..bc1b860f 100644 --- a/non_catalog_apps/FlipperNightStand_clock/application.fam +++ b/non_catalog_apps/FlipperNightStand_clock/application.fam @@ -9,6 +9,6 @@ App( fap_category="Tools", fap_author="@nymda & @Willy-JL", fap_weburl="https://github.com/nymda/FlipperNightStand", - fap_version="1.0", + fap_version="1.1", fap_description="Clock with screen brightness controls", ) diff --git a/non_catalog_apps/FlipperNightStand_clock/clock_app.c b/non_catalog_apps/FlipperNightStand_clock/clock_app.c index 124bef74..65740698 100644 --- a/non_catalog_apps/FlipperNightStand_clock/clock_app.c +++ b/non_catalog_apps/FlipperNightStand_clock/clock_app.c @@ -60,6 +60,7 @@ void handle_up() { led = false; notification_message(notif, &led_off); brightness += 5; + if(brightness > 100) brightness = 100; } set_backlight_brightness((float)(brightness / 100.f)); } @@ -68,6 +69,7 @@ void handle_down() { dspBrightnessBarFrames = dspBrightnessBarDisplayFrames; if(brightness > 0) { brightness -= 5; + if(brightness < 0) brightness = 0; if(brightness == 0) { //trigger only on the first brightness 5 -> 0 transition led = true; notification_message(notif, &led_on); @@ -150,15 +152,10 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) { snprintf( time_string, TIME_LEN, CLOCK_TIME_FORMAT, curr_dt.hour, curr_dt.minute, curr_dt.second); } else { - bool pm = curr_dt.hour > 12; bool pm12 = curr_dt.hour >= 12; - snprintf( - time_string, - TIME_LEN, - CLOCK_TIME_FORMAT, - pm ? curr_dt.hour - 12 : curr_dt.hour, - curr_dt.minute, - curr_dt.second); + uint8_t hour12 = curr_dt.hour % 12; + if(hour12 == 0) hour12 = 12; + snprintf(time_string, TIME_LEN, CLOCK_TIME_FORMAT, hour12, curr_dt.minute, curr_dt.second); snprintf( meridian_string, @@ -309,7 +306,7 @@ int32_t clock_app(void* p) { notif = furi_record_open(RECORD_NOTIFICATION); float SavedBrightness = notif->settings.display_brightness; - brightness = SavedBrightness * 100; // Keep current brightness by default + brightness = (int)roundf(SavedBrightness * 100.f); // Keep current brightness by default uint32_t Saved_display_off_delay_ms = notif->settings.display_off_delay_ms; notif->settings.display_off_delay_ms = 0; @@ -387,7 +384,6 @@ int32_t clock_app(void* p) { view_port_enabled_set(view_port, false); gui_remove_view_port(gui, view_port); furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); view_port_free(view_port); furi_message_queue_free(plugin_state->event_queue); furi_mutex_free(plugin_state->mutex); @@ -400,5 +396,7 @@ int32_t clock_app(void* p) { set_backlight_brightness(SavedBrightness); notification_message(notif, &led_reset); + furi_record_close(RECORD_NOTIFICATION); + return 0; } From ba2f5de16f0c61f55619593eca01e76637d20ff3 Mon Sep 17 00:00:00 2001 From: Mykhailo Shevchuk Date: Fri, 24 Jul 2026 17:44:04 +0300 Subject: [PATCH 2/2] Nightstand Clock: free view_port and notification record if timer alloc fails The timer == NULL startup path returned 255 after freeing only the mutex, event queue and plugin_state, leaking the already-opened RECORD_NOTIFICATION handle and the allocated view_port, and leaving the backlight forced on with display_off_delay_ms = 0. Restore the notification settings and release both resources on that path, mirroring the normal teardown. Co-Authored-By: Claude Opus 4.8 (1M context) --- non_catalog_apps/FlipperNightStand_clock/CHANGELOG.md | 1 + non_catalog_apps/FlipperNightStand_clock/clock_app.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/non_catalog_apps/FlipperNightStand_clock/CHANGELOG.md b/non_catalog_apps/FlipperNightStand_clock/CHANGELOG.md index b2bfd6ae..bb21d198 100644 --- a/non_catalog_apps/FlipperNightStand_clock/CHANGELOG.md +++ b/non_catalog_apps/FlipperNightStand_clock/CHANGELOG.md @@ -5,6 +5,7 @@ - Fix the 12-hour clock showing midnight as `00:xx AM` instead of `12:xx AM` - Fix the brightness control so the red LED nightlight stays reachable from every starting brightness: round the inherited system brightness to the nearest step and clamp brightness to 0-100 (previously levels such as 35/45/65/70/90/95% started off-grid, so Down skipped 0 and the nightlight could never be switched on) - Restore the notification settings before releasing the notification record when exiting +- Free the view_port and notification record (and restore the display settings) if the periodic timer fails to allocate on startup ## 1.0 diff --git a/non_catalog_apps/FlipperNightStand_clock/clock_app.c b/non_catalog_apps/FlipperNightStand_clock/clock_app.c index 65740698..0431fcff 100644 --- a/non_catalog_apps/FlipperNightStand_clock/clock_app.c +++ b/non_catalog_apps/FlipperNightStand_clock/clock_app.c @@ -324,6 +324,12 @@ int32_t clock_app(void* p) { if(timer == NULL) { FURI_LOG_E(TAG, "Cannot create timer"); + //restore the notification settings mutated above before bailing out + notif->settings.display_off_delay_ms = Saved_display_off_delay_ms; + notification_message(notif, &sequence_display_backlight_enforce_auto); + notification_message(notif, &led_reset); + furi_record_close(RECORD_NOTIFICATION); + view_port_free(view_port); furi_mutex_free(plugin_state->mutex); furi_message_queue_free(plugin_state->event_queue); free(plugin_state);