From 6f530fa222db7d71ea617573a56b08afdb4ed12f Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 5 Sep 2026 15:31:30 +0300 Subject: [PATCH] Fifth --- screenshots/pic2.png | Bin 6814 -> 7030 bytes src/c/config.c | 42 ++++++------- src/c/items.c | 8 +++ src/c/items.h | 4 +- src/c/percentage.c | 7 --- src/c/scrolllayer.c | 143 ++++++++++++------------------------------- src/pkjs/config.js | 42 ++++++------- 7 files changed, 88 insertions(+), 158 deletions(-) diff --git a/screenshots/pic2.png b/screenshots/pic2.png index 7a3e38a4337c560a86ac9e14c275bcb665be3137..f26f1c3cb8130843417fe931aca619b8023e1c92 100644 GIT binary patch literal 7030 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 diff --git a/src/c/config.c b/src/c/config.c index 98f7392..b3af3de 100644 --- a/src/c/config.c +++ b/src/c/config.c @@ -2,7 +2,6 @@ #include "config.h" #include "src/c/scrolllayer.h" -#include "src/c/settings.h" #include "src/c/items.h" @@ -39,6 +38,25 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) { bool show_percentage = tuple->value->int32 != 0; item.show_percentage = show_percentage; } + + // Get RED/ORANGE limits + tuple = dict_find(iter, MESSAGE_KEY_RED_LIMIT); + if (tuple) { + item.red_limit = tuple->value->int32; + if (item.red_limit < 1) { item.red_limit = 1; } + if (item.red_limit > 100) { item.red_limit = 100; } + } + tuple = dict_find(iter, MESSAGE_KEY_ORANGE_LIMIT); + if (tuple) { + item.orange_limit = tuple->value->int32; + if (item.orange_limit < 1) { item.orange_limit = 1; } + if (item.orange_limit > 100) { item.orange_limit = 100; } + } + + if (item.orange_limit < item.red_limit) { + item.orange_limit = item.red_limit; + } + // Add or remove tuple = dict_find(iter, MESSAGE_KEY_ITEM_REMOVE); if (tuple) { @@ -55,28 +73,6 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) { // Update the ScrollLayer scroll_layer_add_items(); scroll_layer_update_scrollbar(); - - - // SETTINGS - settings_t settings_buffer; - memset(&settings_buffer, 0, sizeof(settings_buffer)); - - // Get settings - tuple = dict_find(iter, MESSAGE_KEY_RED_LIMIT); - if (tuple) { - settings_buffer.red_limit = tuple->value->int32; - } - tuple = dict_find(iter, MESSAGE_KEY_ORANGE_LIMIT); - if (tuple) { - settings_buffer.orange_limit = tuple->value->int32; - } - - if (settings_buffer.orange_limit < settings_buffer.red_limit) { - settings_buffer.orange_limit = settings_buffer.red_limit; - } - - settings_set(&settings_buffer); - settings_nvm_save(); } void config_init() { diff --git a/src/c/items.c b/src/c/items.c index 179eeff..d12fd14 100644 --- a/src/c/items.c +++ b/src/c/items.c @@ -72,10 +72,16 @@ void update_items(const item_t *item, bool remove) { for (int i = 0; i < MAX_ITEMS; i++) { if (s_items.items[i].name[0] != '\0' && str_case_cmp(s_items.items[i].name, item->name, MAX_CHARACTERS) == 0) { if (remove) { + // Remove item memset(&s_items.items[i], 0, sizeof(s_items.items[i])); } else { + // Update existing item s_items.items[i].show_percentage = item->show_percentage; + s_items.items[i].red_limit = item->red_limit; + s_items.items[i].orange_limit = item->orange_limit; + if (item->fails > 0) { s_items.items[i].fails = item->fails; } + if (item->successes > 0) { s_items.items[i].successes = item->successes; } } return; } @@ -84,7 +90,9 @@ void update_items(const item_t *item, bool remove) { // Not found if (!remove) { for (int i = 0; i < MAX_ITEMS; i++) { + // Find next empty space if (s_items.items[i].name[0] == '\0') { + // Add item s_items.items[i] = *item; break; } diff --git a/src/c/items.h b/src/c/items.h index b9d07f2..33fdeb0 100644 --- a/src/c/items.h +++ b/src/c/items.h @@ -4,13 +4,15 @@ // NVM #define ITEMS_NVM_KEY 1 #define MAX_ITEMS 9 -#define MAX_CHARACTERS 32 +#define MAX_CHARACTERS 41 typedef struct { char name[MAX_CHARACTERS+1]; int successes; int fails; + int red_limit; + int orange_limit; bool show_percentage; } item_t; diff --git a/src/c/percentage.c b/src/c/percentage.c index e32826c..3086517 100644 --- a/src/c/percentage.c +++ b/src/c/percentage.c @@ -4,7 +4,6 @@ #include "src/c/time.h" #include "src/c/scrolllayer.h" #include "src/c/config.h" -#include "src/c/settings.h" static Window *s_main_window; @@ -64,9 +63,6 @@ static void init() { // Register app config config_init(); - // Settings load - settings_init(); - // MAIN WINDOW CREATE s_main_window = window_create(); window_set_background_color(s_main_window, GColorBlack); @@ -81,9 +77,6 @@ static void deinit() { // Config deinit config_deinit(); - // Settings deinit - settings_deinit(); - // MAIN WINDOW DESTROY window_destroy(s_main_window); } diff --git a/src/c/scrolllayer.c b/src/c/scrolllayer.c index bf96ff7..d87b122 100644 --- a/src/c/scrolllayer.c +++ b/src/c/scrolllayer.c @@ -2,7 +2,6 @@ #include "scrolllayer.h" #include "src/c/colors.h" -#include "src/c/settings.h" static ScrollLayer *s_scroll_layer; static Layer *s_scroll_bar_layer; @@ -31,9 +30,6 @@ static int s_scroll_y; static int s_scroll_page; static scroll_items_t s_scroll_items; -// SETTINGS -settings_t *app_settings; - // ------------ SCROLL ------------ static void scroll_up(ClickRecognizerRef recognizer, void *context) { @@ -102,14 +98,14 @@ static void click_config_provider(void *context) { } // ------------ HELPERS ------------ -static GColor get_color_float(float val) { +static GColor get_color_float(item_t *item, float val) { GColor color; int percentage = (int)(val * 100.0); - if (percentage < app_settings->red_limit) { + if (percentage < item->red_limit) { color = RED; } - else if (percentage < app_settings->orange_limit) { + else if (percentage < item->orange_limit) { color = ORANGE; } else { @@ -186,7 +182,7 @@ void scroll_layer_add_items() { // Add percentage int total = s_scroll_items.items->items[i].successes + s_scroll_items.items->items[i].fails; float percentage = (float)s_scroll_items.items->items[i].successes / total; - GColor color = get_color_float(percentage); + GColor color = get_color_float(&s_scroll_items.items->items[i], percentage); s_scroll_items.numbers[i] = text_layer_create(GRect(26, (i * ITEM_UI_HEIGHT) + 18, 124, 16)); fill_percentage_buffer(&s_scroll_items, i, total, percentage); text_layer_set_text(s_scroll_items.numbers[i], s_scroll_items.numbers_buffer[i]); @@ -269,6 +265,24 @@ void scroll_layer_update_scrollbar() { layer_mark_dirty(s_scroll_bar_layer); } +static void touch_update_element(scroll_items_t *items, int element, int *inc_value_ptr) { + // Update numbers + (*inc_value_ptr)++; + int total = items->items->items[element].successes + items->items->items[element].fails; + float percentage = (float)items->items->items[element].successes / total; + GColor color = get_color_float(&items->items->items[element], percentage); + fill_percentage_buffer(items, element, total, percentage); + text_layer_set_text_color(items->numbers[element], color); + text_layer_set_text(items->numbers[element], items->numbers_buffer[element]); + + // Update the percentage bar + int width = (PERCENTAGE_BAR_WIDTH) * percentage; + GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); + GColor *color_ptr = layer_get_data(items->success_bars[element]); + *color_ptr = color; + layer_set_frame(items->success_bars[element], bar); +} + // ------------ TOUCH ------------ static void touch_handler(const TouchEvent *event, void *context) { // Get touch point @@ -286,21 +300,8 @@ static void touch_handler(const TouchEvent *event, void *context) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_plus_pressed_bitmap); - // Update numbers - s_scroll_items.items->items[element].successes++; - int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; - float percentage = (float)s_scroll_items.items->items[element].successes / total; - GColor color = get_color_float(percentage); - fill_percentage_buffer(&s_scroll_items, element, total, percentage); - text_layer_set_text_color(s_scroll_items.numbers[element], color); - text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); - - // Update the percentage bar - int width = (PERCENTAGE_BAR_WIDTH) * percentage; - GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); - GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); - *color_ptr = color; - layer_set_frame(s_scroll_items.success_bars[element], bar); + // Update element + touch_update_element(&s_scroll_items, element, &s_scroll_items.items->items[element].successes); } else if (event->type == TouchEvent_Liftoff) { // Reset the background @@ -318,21 +319,9 @@ static void touch_handler(const TouchEvent *event, void *context) { if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_minus_pressed_bitmap); - - s_scroll_items.items->items[element].fails++; - int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; - float percentage = (float)s_scroll_items.items->items[element].successes / total; - GColor color = get_color_float(percentage); - fill_percentage_buffer(&s_scroll_items, element, total, percentage); - text_layer_set_text_color(s_scroll_items.numbers[element], color); - text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); - - // Update the percentage bar - int width = (PERCENTAGE_BAR_WIDTH) * percentage; - GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); - GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); - *color_ptr = color; - layer_set_frame(s_scroll_items.success_bars[element], bar); + + // Update element + touch_update_element(&s_scroll_items, element, &s_scroll_items.items->items[element].fails); } else if (event->type == TouchEvent_Liftoff) { // Reset the background @@ -351,21 +340,9 @@ static void touch_handler(const TouchEvent *event, void *context) { if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_plus_pressed_bitmap); - - s_scroll_items.items->items[element].successes++; - int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; - float percentage = (float)s_scroll_items.items->items[element].successes / total; - GColor color = get_color_float(percentage); - fill_percentage_buffer(&s_scroll_items, element, total, percentage); - text_layer_set_text_color(s_scroll_items.numbers[element], color); - text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); - - // Update the percentage bar - int width = (PERCENTAGE_BAR_WIDTH) * percentage; - GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); - GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); - *color_ptr = color; - layer_set_frame(s_scroll_items.success_bars[element], bar); + + // Update element + touch_update_element(&s_scroll_items, element, &s_scroll_items.items->items[element].successes); } else if (event->type == TouchEvent_Liftoff) { // Reset the background @@ -383,21 +360,9 @@ static void touch_handler(const TouchEvent *event, void *context) { if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_minus_pressed_bitmap); - - s_scroll_items.items->items[element].fails++; - int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; - float percentage = (float)s_scroll_items.items->items[element].successes / total; - GColor color = get_color_float(percentage); - fill_percentage_buffer(&s_scroll_items, element, total, percentage); - text_layer_set_text_color(s_scroll_items.numbers[element], color); - text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); - - // Update the percentage bar - int width = (PERCENTAGE_BAR_WIDTH) * percentage; - GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); - GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); - *color_ptr = color; - layer_set_frame(s_scroll_items.success_bars[element], bar); + + // Update element + touch_update_element(&s_scroll_items, element, &s_scroll_items.items->items[element].fails); } else if (event->type == TouchEvent_Liftoff) { // Reset the background @@ -416,21 +381,9 @@ static void touch_handler(const TouchEvent *event, void *context) { if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_plus_pressed_bitmap); - - s_scroll_items.items->items[element].successes++; - int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; - float percentage = (float)s_scroll_items.items->items[element].successes / total; - GColor color = get_color_float(percentage); - fill_percentage_buffer(&s_scroll_items, element, total, percentage); - text_layer_set_text_color(s_scroll_items.numbers[element], color); - text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); - - // Update the percentage bar - int width = (PERCENTAGE_BAR_WIDTH) * percentage; - GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); - GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); - *color_ptr = color; - layer_set_frame(s_scroll_items.success_bars[element], bar); + + // Update element + touch_update_element(&s_scroll_items, element, &s_scroll_items.items->items[element].successes); } else if (event->type == TouchEvent_Liftoff) { // Reset the background @@ -448,21 +401,9 @@ static void touch_handler(const TouchEvent *event, void *context) { if (event->type == TouchEvent_Touchdown) { // Change background to pressed bitmap_layer_set_bitmap(s_scroll_items.backgrounds[element], s_background_minus_pressed_bitmap); - - s_scroll_items.items->items[element].fails++; - int total = s_scroll_items.items->items[element].successes + s_scroll_items.items->items[element].fails; - float percentage = (float)s_scroll_items.items->items[element].successes / total; - GColor color = get_color_float(percentage); - fill_percentage_buffer(&s_scroll_items, element, total, percentage); - text_layer_set_text_color(s_scroll_items.numbers[element], color); - text_layer_set_text(s_scroll_items.numbers[element], s_scroll_items.numbers_buffer[element]); - - // Update the percentage bar - int width = (PERCENTAGE_BAR_WIDTH) * percentage; - GRect bar = GRect(31, (element * ITEM_UI_HEIGHT) + 40, width, 4); - GColor *color_ptr = layer_get_data(s_scroll_items.success_bars[element]); - *color_ptr = color; - layer_set_frame(s_scroll_items.success_bars[element], bar); + + // Update element + touch_update_element(&s_scroll_items, element, &s_scroll_items.items->items[element].fails); } else if (event->type == TouchEvent_Liftoff) { // Reset the background @@ -477,9 +418,6 @@ void scrolllayer_init(Layer *parent, Window *window) { s_scroll_page = 0; GRect bounds = SCROLLLAYER_FRAME_RECT; - // Load settings - app_settings = settings_get(); - // Load custom fonts s_scrolllayer_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_SLKSCR_16)); s_scrolllayer_font_small = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_SLKSCR_8)); @@ -549,9 +487,6 @@ void scrolllayer_init(Layer *parent, Window *window) { } void scrolllayer_deinit() { - // Destroy settings - app_settings = NULL; - // Unload fonts fonts_unload_custom_font(s_scrolllayer_font); fonts_unload_custom_font(s_scrolllayer_font_small); diff --git a/src/pkjs/config.js b/src/pkjs/config.js index ca22db1..62760ed 100644 --- a/src/pkjs/config.js +++ b/src/pkjs/config.js @@ -5,7 +5,7 @@ module.exports = [ }, { "type": "text", - "defaultValue": "Add/remove up to 9 items. Character limit is 10. If numbers go higher than 1000, use percentage." + "defaultValue": "Add/remove/update up to 9 items. Name character limit is 40. If more than 10 characters, font goes smaller. If numbers go higher than 1000, use percentage." }, { @@ -18,42 +18,24 @@ module.exports = [ { "type": "input", "messageKey": "ITEM_NAME", + "label": "Name", + "description": "Non-case sensitive. Use existing name to replace/remove", "defaultValue": "" }, { "type": "input", "messageKey": "ITEM_SUCCESS", "label": "Success", + "description": "Set success value. 0 keeps old value if available", "defaultValue": "0" }, { "type": "input", "messageKey": "ITEM_FAIL", "label": "Fail", + "description": "Set fail value. 0 keeps old value if available", "defaultValue": "0" }, - { - "type": "toggle", - "messageKey": "ITEM_PERCENTAGE", - "label": "Show percentage", - "defaultValue": false - }, - { - "type": "toggle", - "messageKey": "ITEM_REMOVE", - "label": "Remove item", - "defaultValue": false - } - ] - }, - - { - "type": "section", - "items": [ - { - "type": "heading", - "defaultValue": "Settings" - }, { "type": "slider", "messageKey": "RED_LIMIT", @@ -73,6 +55,20 @@ module.exports = [ "min": 1, "max": 100, "step": 1 + }, + { + "type": "toggle", + "messageKey": "ITEM_PERCENTAGE", + "label": "Show percentage", + "description": "Disabled shows success/total. Enabled shows percentage instead", + "defaultValue": false + }, + { + "type": "toggle", + "messageKey": "ITEM_REMOVE", + "label": "Remove item", + "description": "Disabled adds/updates item. Enabled removes item", + "defaultValue": false } ] },