Half-baked timeline peak support

This commit is contained in:
2026-06-13 23:42:21 -04:00
parent df3ec1cc72
commit 57bcad1a0e
16 changed files with 196 additions and 23 deletions
+108 -22
View File
@@ -4,6 +4,7 @@
// window statics
static Window *s_main_window;
static Layer *s_window_layer;
static BitmapLayer *s_time_mg_layers[4];
static BitmapLayer *s_time_fg_layers[4];
static BitmapLayer *s_c_layer;
@@ -23,13 +24,13 @@ static const uint16_t s_fuel_guage_x_pos = PBL_DISPLAY_WIDTH - 23;
// settings statics
static ClaySettings settings;
static GColor s_applied_time_mg = GColorDarkGray;
static GColor s_applied_f = GColorWhite; // only foreground element to not change color for warnings, so it is used as the base fg color
static GColor s_applied_e = GColorWhite;
static GColor s_applied_e_f = GColorWhite;
static GColor s_applied_c_h = GColorWhite;
static GColor s_applied_time_date = GColorWhite;
// bitmap statics
static GBitmap *s_font_bitmaps[10];
static GBitmap *s_font_bitmaps_mini[10];
static GBitmap *s_time_mg_super8;
static GBitmap *s_c_icon;
static GBitmap *s_h_icon;
@@ -37,6 +38,7 @@ static GBitmap *s_e_icon;
static GBitmap *s_f_icon;
// tracking statics
static bool s_peek_active = false;
static bool s_first_settings_application = true;
static bool s_showing_date = false;
static AppTimer *s_date_timer = NULL;
@@ -56,13 +58,14 @@ static void toggle_fuel_warning_state(bool enable_warning, bool force) {
return;
}
GColor dst = enable_warning ? settings.ColorWarning : settings.ColorFG;
if (s_first_settings_application && !enable_warning && dst.argb == s_applied_e.argb) {
if (s_first_settings_application && !enable_warning && dst.argb == s_applied_e_f.argb) {
// at startup, s_applied_e.argb is GColorWhite
// for those using white fg, do not pointlessly replace white at startup if that is the destination anyway
return;
}
replace_gbitmap_color(s_applied_e, dst, s_e_icon, s_e_layer);
s_applied_e = dst;
replace_gbitmap_color(s_applied_e_f, dst, s_e_icon, s_e_layer);
replace_gbitmap_color(s_applied_e_f, dst, s_f_icon, s_f_layer);
s_applied_e_f = dst;
s_fuel_is_warning = enable_warning;
}
@@ -196,8 +199,15 @@ static void update_minute_1() {
s_time_digits[2] = minute / 10;
s_time_digits[3] = minute % 10;
for (int i = 0; i < 4; ++i) {
bitmap_layer_set_bitmap(s_time_fg_layers[i], s_font_bitmaps[s_time_digits[i]]);
if (!s_peek_active) {
for (int i = 0; i < 4; ++i) {
bitmap_layer_set_bitmap(s_time_fg_layers[i], s_font_bitmaps[s_time_digits[i]]);
}
} else {
bitmap_layer_set_bitmap(s_time_fg_layers[0], s_font_bitmaps[s_time_digits[0]]);
bitmap_layer_set_bitmap(s_time_fg_layers[1], s_font_bitmaps[s_time_digits[1]]);
bitmap_layer_set_bitmap(s_time_fg_layers[2], s_font_bitmaps_mini[s_time_digits[2]]);
bitmap_layer_set_bitmap(s_time_fg_layers[3], s_font_bitmaps_mini[s_time_digits[3]]);
}
}
@@ -232,6 +242,38 @@ static void accel_tap_handler(AccelAxisType axis, int32_t direction) {
s_date_timer = app_timer_register(settings.DateTimeoutSecs * 1000, date_timeout, NULL);
}
static void peek_will_change(GRect final_unobstructed_screen_area, void *context) {
// if obstructed, set s_peek_active and run update_minute_1 to use small minutes
GRect full_bounds = layer_get_bounds(s_window_layer);
if (!grect_equal(&full_bounds, &final_unobstructed_screen_area)) {
s_peek_active = true;
if (!s_showing_date) {
update_minute_1();
}
} else {
s_peek_active = false;
}
}
static void peek_change(AnimationProgress progress, void *context) {
// animate the moving of the minute layers depending on s_peek_active
if (!s_peek_active) {
layer_set_frame(bitmap_layer_get_layer(s_time_fg_layers[2]), s_time_grects[2]);
layer_set_frame(bitmap_layer_get_layer(s_time_fg_layers[3]), s_time_grects[3]);
} else {
uint8_t y = s_time_grects[2].origin.y - 1;
layer_set_frame(bitmap_layer_get_layer(s_time_fg_layers[2]), GRect(s_time_grects[2].origin.x, y, 69, 54));
layer_set_frame(bitmap_layer_get_layer(s_time_fg_layers[3]), GRect(s_time_grects[3].origin.x, y, 69, 54));
}
}
static void peek_did_change(void *context) {
// if not obstructed, run update_minute_1 to use large minutes
if (!s_peek_active && !s_showing_date) {
update_minute_1();
}
}
static void apply_settings() {
// LED&BG
if (settings.UseCustomLED) {
@@ -251,7 +293,7 @@ static void apply_settings() {
//// create and insert any mg layer that does not already exist
Layer *sibling_layer = NULL;
if (s_first_settings_application) {
sibling_layer = window_get_root_layer(s_main_window);
sibling_layer = s_window_layer;
} else {
sibling_layer = bitmap_layer_get_layer(s_time_fg_layers[0]);
}
@@ -308,10 +350,6 @@ static void apply_settings() {
// fuel (e icon)
toggle_fuel_warning_state(s_fuel_is_warning, true);
// f icon (always fg color, never a warning indicator)
replace_gbitmap_color(s_applied_f, settings.ColorFG, s_f_icon, s_f_layer);
s_applied_f = settings.ColorFG;
// changes to temperature range
update_temperature();
@@ -324,13 +362,50 @@ static void apply_settings() {
accel_tap_service_subscribe(accel_tap_handler);
}
// re-sub timeline peek and create/destroy resources as needed
// TODO add mg support, fix broken-ness when toggling peak support off while running
unobstructed_area_service_unsubscribe();
if (settings.EnablePeek) {
if (!s_font_bitmaps_mini[0]) {
s_font_bitmaps_mini[0] = gbitmap_create_with_resource(RESOURCE_ID_0_M);
s_font_bitmaps_mini[1] = gbitmap_create_with_resource(RESOURCE_ID_1_M);
s_font_bitmaps_mini[2] = gbitmap_create_with_resource(RESOURCE_ID_2_M);
s_font_bitmaps_mini[3] = gbitmap_create_with_resource(RESOURCE_ID_3_M);
s_font_bitmaps_mini[4] = gbitmap_create_with_resource(RESOURCE_ID_4_M);
s_font_bitmaps_mini[5] = gbitmap_create_with_resource(RESOURCE_ID_5_M);
s_font_bitmaps_mini[6] = gbitmap_create_with_resource(RESOURCE_ID_6_M);
s_font_bitmaps_mini[7] = gbitmap_create_with_resource(RESOURCE_ID_7_M);
s_font_bitmaps_mini[8] = gbitmap_create_with_resource(RESOURCE_ID_8_M);
s_font_bitmaps_mini[9] = gbitmap_create_with_resource(RESOURCE_ID_9_M);
}
peek_will_change(layer_get_unobstructed_bounds(s_window_layer), NULL);
peek_change(0, NULL);
peek_did_change(NULL);
UnobstructedAreaHandlers peek_handlers = {
.will_change = peek_will_change,
.change = peek_change,
.did_change = peek_did_change,
};
unobstructed_area_service_subscribe(peek_handlers, NULL);
} else {
peek_will_change(layer_get_bounds(s_window_layer), NULL);
peek_change(0, NULL);
peek_did_change(NULL);
if (s_font_bitmaps_mini[0]) {
for (int i = 0; i < 10; ++i) {
gbitmap_destroy(s_font_bitmaps_mini[i]);
s_font_bitmaps_mini[i] = NULL;
}
}
}
if (s_first_settings_application) {
s_first_settings_application = false;
}
}
static void main_window_load() {
Layer *window_layer = window_get_root_layer(s_main_window);
s_window_layer = window_get_root_layer(s_main_window);
s_temp_mg_layer = layer_create(GRect(s_temp_guage_x_pos - 1, 21, s_bar_width + 2, PBL_DISPLAY_HEIGHT - 43));
layer_set_update_proc(s_temp_mg_layer, temp_mg_update_proc);
@@ -353,19 +428,25 @@ static void main_window_load() {
apply_settings();
for (int i = 0; i < 4; ++i) {
layer_add_child(window_layer, bitmap_layer_get_layer(s_time_fg_layers[i]));
layer_add_child(s_window_layer, bitmap_layer_get_layer(s_time_fg_layers[i]));
}
layer_add_child(window_layer, bitmap_layer_get_layer(s_c_layer));
layer_add_child(window_layer, bitmap_layer_get_layer(s_h_layer));
layer_add_child(window_layer, bitmap_layer_get_layer(s_e_layer));
layer_add_child(window_layer, bitmap_layer_get_layer(s_f_layer));
layer_add_child(window_layer, s_temp_mg_layer);
layer_add_child(window_layer, s_temp_layer);
layer_add_child(window_layer, s_fuel_mg_layer);
layer_add_child(window_layer, s_fuel_layer);
layer_add_child(s_window_layer, bitmap_layer_get_layer(s_c_layer));
layer_add_child(s_window_layer, bitmap_layer_get_layer(s_h_layer));
layer_add_child(s_window_layer, bitmap_layer_get_layer(s_e_layer));
layer_add_child(s_window_layer, bitmap_layer_get_layer(s_f_layer));
layer_add_child(s_window_layer, s_temp_mg_layer);
layer_add_child(s_window_layer, s_temp_layer);
layer_add_child(s_window_layer, s_fuel_mg_layer);
layer_add_child(s_window_layer, s_fuel_layer);
}
static void main_window_unload() {
if (settings.EnablePeek) {
unobstructed_area_service_unsubscribe();
for (int i = 0; i < 10; ++i) {
gbitmap_destroy(s_font_bitmaps_mini[i]);
}
}
connection_service_unsubscribe();
accel_tap_service_unsubscribe();
layer_destroy(s_fuel_mg_layer);
@@ -405,6 +486,7 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) {
}
// CLAY SETTINGS
Tuple *enable_peek_tuple = dict_find(iter, MESSAGE_KEY_CLAY_ENABLE_PEEK);
Tuple *track_bt_tuple = dict_find(iter, MESSAGE_KEY_CLAY_BT_INDICATOR);
Tuple *show_time_mg_tuple = dict_find(iter, MESSAGE_KEY_CLAY_SHOW_TIME_MG);
Tuple *use_custom_led_tuple = dict_find(iter, MESSAGE_KEY_CLAY_USE_CUSTOM_LED);
@@ -418,6 +500,9 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) {
Tuple *color_mg_time_tuple = dict_find(iter, MESSAGE_KEY_CLAY_TIME_MG_COLOR);
Tuple *color_fg_tuple = dict_find(iter, MESSAGE_KEY_CLAY_FG_COLOR);
Tuple *color_warning_tuple = dict_find(iter, MESSAGE_KEY_CLAY_WARNING_COLOR);
if (enable_peek_tuple) {
settings.EnablePeek = enable_peek_tuple->value->uint8;
}
if (track_bt_tuple) {
settings.TrackBTStatus = track_bt_tuple->value->uint8;
}
@@ -466,6 +551,7 @@ static void init() {
if (persist_exists(STORAGE_KEY_SETTINGS)) {
persist_read_data(STORAGE_KEY_SETTINGS, &settings, sizeof(settings));
} else {
settings.EnablePeek = true;
settings.TrackBTStatus = false;
settings.ShowTimeMG = false;
settings.UseCustomLED = false;