diff --git a/custom_assets/pin_icon_alignment_fix.svg b/custom_assets/pin_icon_alignment_fix.svg deleted file mode 100644 index 0e9909e..0000000 --- a/custom_assets/pin_icon_alignment_fix.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/custom_assets/sleep_icon_no_aa_fix.svg b/custom_assets/sleep_icon_no_aa_fix.svg deleted file mode 100644 index 1af53c1..0000000 --- a/custom_assets/sleep_icon_no_aa_fix.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/package.json b/package.json index 3a19d6f..cb6cb24 100644 --- a/package.json +++ b/package.json @@ -38,20 +38,28 @@ "name": "LOGO_25", "spaceOptimization": "storage", "type": "bitmap", - "menuIcon": true, - "targetPlatforms": [ - "basalt", - "diorite", - "chalk", - "flint", - "emery", - "gabbro" - ] + "menuIcon": true }, { - "type": "raw", - "name": "PIN_ICON", - "file": "pin.pdc" + "file": "pin.png", + "memoryFormat": "Smallest", + "name": "PIN", + "spaceOptimization": "storage", + "type": "bitmap" + }, + { + "file": "prev.png", + "memoryFormat": "Smallest", + "name": "PREV", + "spaceOptimization": "storage", + "type": "bitmap" + }, + { + "file": "next.png", + "memoryFormat": "Smallest", + "name": "NEXT", + "spaceOptimization": "storage", + "type": "bitmap" } ] }, diff --git a/resources/next.png b/resources/next.png new file mode 100644 index 0000000..04584ec Binary files /dev/null and b/resources/next.png differ diff --git a/resources/next~168h.png b/resources/next~168h.png new file mode 100644 index 0000000..47819df Binary files /dev/null and b/resources/next~168h.png differ diff --git a/resources/pin.pdc b/resources/pin.pdc deleted file mode 100644 index f1627cf..0000000 Binary files a/resources/pin.pdc and /dev/null differ diff --git a/resources/pin.png b/resources/pin.png new file mode 100644 index 0000000..d36a194 Binary files /dev/null and b/resources/pin.png differ diff --git a/resources/pin~bw.png b/resources/pin~bw.png new file mode 100644 index 0000000..c09e993 Binary files /dev/null and b/resources/pin~bw.png differ diff --git a/resources/prev.png b/resources/prev.png new file mode 100644 index 0000000..edd4e86 Binary files /dev/null and b/resources/prev.png differ diff --git a/resources/prev~168h.png b/resources/prev~168h.png new file mode 100644 index 0000000..3e77231 Binary files /dev/null and b/resources/prev~168h.png differ diff --git a/src/c/gdraw_anim.c b/src/c/gdraw_anim.c deleted file mode 100644 index d20d5fd..0000000 --- a/src/c/gdraw_anim.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "gdraw_anim.h" - -static uint8_t s_pin_stroke_width = 1; -static Animation *s_pin_stroke_anim; -static Layer *s_pin_layer; - -static uint8_t get_stroke_width_for_progress(AnimationProgress progress) { - const uint8_t min_width = PBL_IF_ROUND_ELSE(1, 2); - const uint8_t max_width = PBL_IF_ROUND_ELSE(3, 4); - const uint8_t delta = max_width - min_width; - const AnimationProgress half = ANIMATION_NORMALIZED_MAX / 2; - - if (progress <= half) { - return min_width + (uint8_t)(delta * progress * 2 / ANIMATION_NORMALIZED_MAX); - } - return max_width - (uint8_t)(delta * (progress - half) * 2 / ANIMATION_NORMALIZED_MAX); -} - -static void pin_stroke_anim_update(Animation *animation, const AnimationProgress progress) { - s_pin_stroke_width = get_stroke_width_for_progress(progress); - if (s_pin_layer) { - layer_mark_dirty(s_pin_layer); - } -} - -static void pin_stroke_anim_stopped(Animation *animation, bool finished, void *context) { - s_pin_stroke_anim = NULL; - animation_destroy(animation); -} - -void pin_animation_init(Layer *pin_layer) { - s_pin_layer = pin_layer; - s_pin_stroke_width = PBL_IF_ROUND_ELSE(1, 2); -} - -void pin_animation_start(void) { - if (s_pin_stroke_anim) { - animation_unschedule(s_pin_stroke_anim); - animation_destroy(s_pin_stroke_anim); - s_pin_stroke_anim = NULL; - } - - static const AnimationImplementation s_pin_stroke_anim_impl = { - .update = pin_stroke_anim_update, - }; - - s_pin_stroke_anim = animation_create(); - animation_set_implementation(s_pin_stroke_anim, &s_pin_stroke_anim_impl); - animation_set_duration(s_pin_stroke_anim, 400); - animation_set_curve(s_pin_stroke_anim, AnimationCurveEaseInOut); - animation_set_handlers(s_pin_stroke_anim, (AnimationHandlers){.stopped = pin_stroke_anim_stopped}, NULL); - animation_schedule(s_pin_stroke_anim); -} - -void pin_animation_deinit(void) { - if (s_pin_stroke_anim) { - animation_unschedule(s_pin_stroke_anim); - animation_destroy(s_pin_stroke_anim); - s_pin_stroke_anim = NULL; - } - s_pin_layer = NULL; -} - -uint8_t pin_animation_get_stroke_width(void) { - return s_pin_stroke_width; -} diff --git a/src/c/gdraw_anim.h b/src/c/gdraw_anim.h deleted file mode 100644 index 32715a6..0000000 --- a/src/c/gdraw_anim.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include - -void pin_animation_init(Layer *pin_layer); -void pin_animation_deinit(void); -void pin_animation_start(void); -uint8_t pin_animation_get_stroke_width(void); diff --git a/src/c/main.c b/src/c/main.c index 170f191..026695d 100644 --- a/src/c/main.c +++ b/src/c/main.c @@ -1,29 +1,31 @@ -#include "gdraw_anim.h" #include #include #include -// #define DEBUG_MODE 1 +#define DEBUG_MODE 1 // declare settings-derived statics static uint8_t s_is_jellyfin; static GColor s_color_primary = GColorWhite; static GColor s_color_secondary = GColorWhite; +// declare bitmaps +static GBitmap *s_logo_icon; +static GBitmap *s_pin_icon; +static GBitmap *s_next_icon; +static GBitmap *s_prev_icon; + // declare window/layer statics static Window *s_main_window; static TextLayer *s_config_app_layer; static TextLayer *s_sleep_time_layer; static TextLayer *s_last_watched_layer; -static Layer *s_button_bar_layer; +static ActionBarLayer *s_action_bar_layer; static Layer *s_sleep_bar_layer; static BitmapLayer *s_logo_layer; -static Layer *s_pin_icon_layer; -static GBitmap *s_logo; -static GDrawCommandImage *s_pin_icon; -static const uint8_t s_icon_width = 25; +static const uint8_t s_logo_width = 25; #if PBL_ROUND -#if PBL_DISPLAY_WIDTH >= 200 +#if PBL_DISPLAY_WIDTH >= 260 static const uint8_t s_sleep_bar_drop = 54; #else static const uint8_t s_sleep_bar_drop = 50; @@ -39,7 +41,7 @@ static const uint8_t s_sleep_bar_drop = 34; // declare animation statics static GRect s_sleep_bar_start = GRect(0, 0, PBL_DISPLAY_WIDTH, PBL_DISPLAY_HEIGHT); -static GRect s_logo_start = GRect((PBL_DISPLAY_WIDTH / 2) - 13, (PBL_DISPLAY_HEIGHT / 2) - 17, s_icon_width, s_icon_width); +static GRect s_logo_start = GRect((PBL_DISPLAY_WIDTH / 2) - 13, (PBL_DISPLAY_HEIGHT / 2) - 17, s_logo_width, s_logo_width); // declare time tracking statics static time_t s_sleep_timestamp; @@ -67,10 +69,9 @@ static void write_last_watched(const char *text) { y = s_sleep_bar_drop - s_wasted_top_text_pixels + s_margin; } - layer_set_frame(text_layer_get_layer(s_last_watched_layer), GRect(PBL_IF_ROUND_ELSE(s_icon_width, 0) + s_margin, - y, - PBL_DISPLAY_WIDTH - (PBL_IF_ROUND_ELSE(s_icon_width * 2, s_icon_width) + (s_margin) * 2), - s_available_height)); + GRect last_watched_frame = layer_get_frame(text_layer_get_layer(s_last_watched_layer)); + last_watched_frame.origin.y = y; + layer_set_frame(text_layer_get_layer(s_last_watched_layer), last_watched_frame); // APP_LOG(APP_LOG_LEVEL_DEBUG, "height=%d rows=%d/%d", text_size.h, current_rows, s_max_rows); } @@ -95,25 +96,46 @@ static void sleep_bar_update_proc(Layer *layer, GContext *ctx) { graphics_fill_rect(ctx, layer_get_bounds(layer), 0, GCornerNone); } -static void draw_pin() { - GDrawCommandList *command_list = gdraw_command_image_get_command_list(s_pin_icon); - const uint32_t command_count = gdraw_command_list_get_num_commands(command_list); - for (uint32_t i = 0; i < command_count; ++i) { - GDrawCommand *command = gdraw_command_list_get_command(command_list, i); - if (command) { -#if PBL_ROUND - gdraw_command_set_fill_color(command, GColorClear); - gdraw_command_set_stroke_color(command, s_color_secondary); -#endif - gdraw_command_set_stroke_width(command, pin_animation_get_stroke_width()); - } +static void send_pin_to_pkjs() { + DictionaryIterator *out; + AppMessageResult result = app_message_outbox_begin(&out); + if (result != APP_MSG_OK) { + write_last_watched("outbox_begin failure"); + return; + } + if (s_sleep_session_found) { + dict_write_uint32(out, MESSAGE_KEY_PKJS_PIN_TIMESTAMP, s_sleep_timestamp); + } else { + dict_write_uint32(out, MESSAGE_KEY_PKJS_PIN_TIMESTAMP, time(NULL)); + } + dict_write_cstring(out, MESSAGE_KEY_PKJS_PIN_TITLE, text_layer_get_text(s_last_watched_layer)); + result = app_message_outbox_send(); + if (result != APP_MSG_OK) { + write_last_watched("outbox_send failure"); + return; } } -static void pin_icon_update_proc(Layer *layer, GContext *ctx) { - graphics_context_set_antialiased(ctx, false); - draw_pin(); - gdraw_command_image_draw(ctx, s_pin_icon, GPoint(0, 0)); +static void select_click_handler(ClickRecognizerRef recognizer, void *context) { + send_pin_to_pkjs(); + static const uint32_t segments[] = {60}; + VibePattern pattern = { + .durations = segments, + .num_segments = ARRAY_LENGTH(segments), + }; + vibes_enqueue_custom_pattern(pattern); +} + +void up_click_handler(ClickRecognizerRef recognizer, void *context) { +} + +void down_click_handler(ClickRecognizerRef recognizer, void *context) { +} + +void click_config_provider(void *context) { + window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler); + window_single_click_subscribe(BUTTON_ID_UP, up_click_handler); + window_single_click_subscribe(BUTTON_ID_DOWN, down_click_handler); } static void main_window_load(Window *window) { @@ -134,18 +156,23 @@ static void main_window_load(Window *window) { return; } + // action bar + s_action_bar_layer = action_bar_layer_create(); + action_bar_layer_set_click_config_provider(s_action_bar_layer, click_config_provider); + action_bar_layer_set_icon(s_action_bar_layer, BUTTON_ID_UP, s_prev_icon); + action_bar_layer_set_icon(s_action_bar_layer, BUTTON_ID_SELECT, s_pin_icon); + action_bar_layer_set_icon(s_action_bar_layer, BUTTON_ID_DOWN, s_next_icon); + action_bar_layer_set_background_color(s_action_bar_layer, s_color_secondary); + action_bar_layer_set_icon_press_animation(s_action_bar_layer, BUTTON_ID_SELECT, ActionBarLayerIconPressAnimationMoveLeft); + action_bar_layer_add_to_window(s_action_bar_layer, window); + // sleep bar and icon s_sleep_bar_layer = layer_create(s_sleep_bar_start); s_logo_layer = bitmap_layer_create(s_logo_start); bitmap_layer_set_compositing_mode(s_logo_layer, GCompOpSet); - bitmap_layer_set_bitmap(s_logo_layer, s_logo); + bitmap_layer_set_bitmap(s_logo_layer, s_logo_icon); - // pin icon - s_pin_icon_layer = layer_create(GRect(PBL_DISPLAY_WIDTH - PBL_IF_ROUND_ELSE(s_icon_width + 3, s_icon_width), (PBL_DISPLAY_HEIGHT / 2) - 13, s_icon_width, s_icon_width)); - layer_set_update_proc(s_pin_icon_layer, pin_icon_update_proc); - pin_animation_init(s_pin_icon_layer); - - s_last_watched_layer = text_layer_create(GRect(0, 0, 0, 0)); // placeholder, updated when layer is written to + s_last_watched_layer = text_layer_create(GRect(s_margin, 0, PBL_DISPLAY_WIDTH - (2 * s_margin) - ACTION_BAR_WIDTH, s_available_height)); // y position updated when layer is written to #if PBL_DISPLAY_WIDTH >= 200 s_sleep_time_layer = text_layer_create(GRect(0, PBL_IF_ROUND_ELSE(22, 2), PBL_DISPLAY_WIDTH, 30)); text_layer_set_font(s_sleep_time_layer, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD)); @@ -195,13 +222,6 @@ static void main_window_load(Window *window) { } // add layers as children to windows -#if PBL_RECT - // button bar - s_button_bar_layer = layer_create(GRect(PBL_DISPLAY_WIDTH - s_icon_width, 0, s_icon_width, PBL_DISPLAY_HEIGHT)); - layer_set_update_proc(s_button_bar_layer, button_bar_update_proc); - layer_add_child(window_layer, s_button_bar_layer); -#endif - layer_add_child(window_layer, s_pin_icon_layer); layer_add_child(window_layer, text_layer_get_layer(s_last_watched_layer)); layer_add_child(window_layer, s_sleep_bar_layer); layer_add_child(window_layer, bitmap_layer_get_layer(s_logo_layer)); @@ -212,13 +232,11 @@ static void main_window_unload(Window *window) { if (s_is_jellyfin == 0) { text_layer_destroy(s_config_app_layer); } else { - pin_animation_deinit(); text_layer_destroy(s_last_watched_layer); text_layer_destroy(s_sleep_time_layer); bitmap_layer_destroy(s_logo_layer); layer_destroy(s_sleep_bar_layer); - layer_destroy(s_pin_icon_layer); - layer_destroy(s_button_bar_layer); + action_bar_layer_destroy(s_action_bar_layer); } } @@ -245,41 +263,6 @@ static void send_sleep_time_to_pkjs() { } } -static void send_pin_to_pkjs() { - DictionaryIterator *out; - AppMessageResult result = app_message_outbox_begin(&out); - if (result != APP_MSG_OK) { - write_last_watched("outbox_begin failure"); - return; - } - if (s_sleep_session_found) { - dict_write_uint32(out, MESSAGE_KEY_PKJS_PIN_TIMESTAMP, s_sleep_timestamp); - } else { - dict_write_uint32(out, MESSAGE_KEY_PKJS_PIN_TIMESTAMP, time(NULL)); - } - dict_write_cstring(out, MESSAGE_KEY_PKJS_PIN_TITLE, text_layer_get_text(s_last_watched_layer)); - result = app_message_outbox_send(); - if (result != APP_MSG_OK) { - write_last_watched("outbox_send failure"); - return; - } -} - -static void select_single_click_handler(ClickRecognizerRef recognizer, void *context) { - pin_animation_start(); - send_pin_to_pkjs(); - static const uint32_t segments[] = {60}; - VibePattern pattern = { - .durations = segments, - .num_segments = ARRAY_LENGTH(segments), - }; - vibes_enqueue_custom_pattern(pattern); -} - -static void click_config_provider(Window *window) { - window_single_click_subscribe(BUTTON_ID_SELECT, select_single_click_handler); -} - static void soft_reload(bool first_load) { if (!first_load) { window_stack_remove(s_main_window, false); @@ -291,7 +274,6 @@ static void soft_reload(bool first_load) { s_main_window, (WindowHandlers){.load = main_window_load, .unload = main_window_unload}); window_stack_push(s_main_window, false); - window_set_click_config_provider(s_main_window, (ClickConfigProvider)click_config_provider); send_sleep_time_to_pkjs(); } @@ -322,11 +304,6 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) { s_color_secondary = GColorLightGray; } layer_mark_dirty(s_sleep_bar_layer); -#if PBL_ROUND - layer_mark_dirty(s_pin_icon_layer); -#else - layer_mark_dirty(s_button_bar_layer); -#endif soft_reload(false); // app needs "restarted" when settings are changed return; } @@ -337,7 +314,7 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) { PropertyAnimation *sleep_bar_prop = property_animation_create_layer_frame(s_sleep_bar_layer, &s_sleep_bar_start, &GRect(0, -PBL_DISPLAY_HEIGHT + s_sleep_bar_drop, PBL_DISPLAY_WIDTH, PBL_DISPLAY_HEIGHT)); Animation *sleep_bar_anim = property_animation_get_animation(sleep_bar_prop); animation_set_duration(sleep_bar_anim, 512); - PropertyAnimation *logo_prop = property_animation_create_layer_frame(bitmap_layer_get_layer(s_logo_layer), &s_logo_start, &GRect(PBL_IF_ROUND_ELSE((PBL_DISPLAY_WIDTH / 2) - 13, s_margin), 3, s_icon_width, s_icon_width)); + PropertyAnimation *logo_prop = property_animation_create_layer_frame(bitmap_layer_get_layer(s_logo_layer), &s_logo_start, &GRect(PBL_IF_ROUND_ELSE((PBL_DISPLAY_WIDTH / 2) - 13, s_margin), 3, s_logo_width, s_logo_width)); Animation *logo_anim = property_animation_get_animation(logo_prop); animation_set_duration(logo_anim, 512); Animation *load_spawn_anim = animation_spawn_create(sleep_bar_anim, logo_anim, NULL); @@ -370,8 +347,10 @@ static void init() { s_color_primary = GColorWhite; s_color_secondary = GColorWhite; #endif - s_pin_icon = gdraw_command_image_create_with_resource(RESOURCE_ID_PIN_ICON); - s_logo = gbitmap_create_with_resource(RESOURCE_ID_LOGO_25); + s_logo_icon = gbitmap_create_with_resource(RESOURCE_ID_LOGO_25); + s_pin_icon = gbitmap_create_with_resource(RESOURCE_ID_PIN); + s_next_icon = gbitmap_create_with_resource(RESOURCE_ID_NEXT); + s_prev_icon = gbitmap_create_with_resource(RESOURCE_ID_PREV); // initialize pkjs app_message_register_inbox_received(inbox_received_handler);