Change colors to match selected service

This commit is contained in:
2026-04-26 04:41:06 -04:00
parent bd388a5646
commit cfcf16a031
4 changed files with 79 additions and 33 deletions

View File

@@ -15,13 +15,3 @@ in settings and let your Pebble keep track!
# Contributing # Contributing
If you use a different streaming service with an accessible API, I'd love help supporting them! If you use a different streaming service with an accessible API, I'd love help supporting them!
PRs are welcome, or even just issues telling me "Hey, this thing I use has an API!". PRs are welcome, or even just issues telling me "Hey, this thing I use has an API!".
# Spring 2026 Developer Contest
This app was entered in the Spring 2026 Developer Contest on the official Pebble appstore.
I set out to make a unique app that isn't just "for" Pebble, but _needs_ Pebble. This app uses:
- Pebble health (sleep data)
- The timeline (history tracking)
- PKJS (API calls)
- Vector animations (it's gotta look cute, right?)
- Crazy good battery life (kinda hard to track sleep when your watch needs to charge)

View File

@@ -54,6 +54,15 @@
"chalk", "chalk",
"gabbro" "gabbro"
] ]
},
{
"type": "raw",
"name": "PIN_ROUND_PLEX_ICON",
"file": "pin_round_plex.pdc",
"targetPlatforms": [
"chalk",
"gabbro"
]
} }
] ]
}, },

Binary file not shown.

View File

@@ -2,6 +2,10 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
// declare settings-derived statics
static GColor s_color_primary = GColorWhite;
static GColor s_color_secondary = GColorWhite;
// declare window statics // declare window statics
static Window *s_main_window; static Window *s_main_window;
static TextLayer *s_sleep_time_layer; static TextLayer *s_sleep_time_layer;
@@ -32,20 +36,44 @@ static void send_sleep_time_to_pkjs() {
} }
} }
static void inbox_received_handler_watched(DictionaryIterator *iter, void *context) { static void inbox_received_handler(DictionaryIterator *iter, void *context) {
Tuple *watched_tuple = dict_find(iter, MESSAGE_KEY_PKJS_LAST_WATCHED);
if (watched_tuple) {
// APP_LOG(APP_LOG_LEVEL_INFO, "Received PKJS_LAST_WATCHED, displaying...");
text_layer_set_text(s_last_watched_layer, watched_tuple->value->cstring);
}
}
static void inbox_received_handler_ready(DictionaryIterator *iter, void *context) {
Tuple *ready_tuple = dict_find(iter, MESSAGE_KEY_PKJS_READY); Tuple *ready_tuple = dict_find(iter, MESSAGE_KEY_PKJS_READY);
if (ready_tuple) { if (ready_tuple) {
// APP_LOG(APP_LOG_LEVEL_INFO, "Received PKJS_READY, calling PKJS..."); APP_LOG(APP_LOG_LEVEL_INFO, "Received PKJS_READY, calling PKJS...");
send_sleep_time_to_pkjs(); send_sleep_time_to_pkjs();
app_message_register_inbox_received(inbox_received_handler_watched); }
Tuple *clay_tuple = dict_find(iter, MESSAGE_KEY_CLAY_API_IS_JELLYFIN);
if (clay_tuple) {
APP_LOG(APP_LOG_LEVEL_INFO, "Received CLAY_API_IS_JELLYFIN, updating UI...");
bool is_jellyfin = clay_tuple->value->int32 == 1;
if (is_jellyfin) {
persist_write_int(0, 1);
s_color_primary = GColorVividViolet;
s_color_secondary = GColorPictonBlue;
#if PBL_ROUND
s_pin_icon = gdraw_command_image_create_with_resource(RESOURCE_ID_PIN_ROUND_JELLYFIN_ICON);
#endif
} else {
persist_write_int(0, 2);
s_color_primary = GColorChromeYellow;
s_color_secondary = GColorLightGray;
#if PBL_ROUND
s_pin_icon = gdraw_command_image_create_with_resource(RESOURCE_ID_PIN_ROUND_PLEX_ICON);
#endif
}
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
}
Tuple *watched_tuple = dict_find(iter, MESSAGE_KEY_PKJS_LAST_WATCHED);
if (watched_tuple) {
APP_LOG(APP_LOG_LEVEL_INFO, "Received PKJS_LAST_WATCHED, displaying...");
text_layer_set_text(s_last_watched_layer, watched_tuple->value->cstring);
} }
} }
@@ -61,12 +89,12 @@ static void update_sleep_time(time_t start, time_t end) {
} }
static void button_bar_update_proc(Layer *layer, GContext *ctx) { static void button_bar_update_proc(Layer *layer, GContext *ctx) {
graphics_context_set_fill_color(ctx, GColorPictonBlue); graphics_context_set_fill_color(ctx, s_color_secondary);
graphics_fill_rect(ctx, layer_get_bounds(layer), 0, GCornerNone); graphics_fill_rect(ctx, layer_get_bounds(layer), 0, GCornerNone);
} }
static void sleep_bar_update_proc(Layer *layer, GContext *ctx) { static void sleep_bar_update_proc(Layer *layer, GContext *ctx) {
graphics_context_set_fill_color(ctx, GColorVividViolet); graphics_context_set_fill_color(ctx, s_color_primary);
graphics_fill_rect(ctx, layer_get_bounds(layer), 0, GCornerNone); graphics_fill_rect(ctx, layer_get_bounds(layer), 0, GCornerNone);
} }
@@ -161,9 +189,36 @@ static void init() {
s_main_window, s_main_window,
(WindowHandlers){.load = main_window_load, .unload = main_window_unload}); (WindowHandlers){.load = main_window_load, .unload = main_window_unload});
// set colors if is_jellyfin is locally set;
// if it has not yet been set, it will be once
// the user saves their settings
// TODO check if it is unset (0) and prompt user
// to configure the app!!
uint8_t is_jellyfin = persist_read_int(0);
switch (is_jellyfin) {
case 1:
s_color_primary = GColorVividViolet;
s_color_secondary = GColorPictonBlue;
#if PBL_ROUND
s_pin_icon = gdraw_command_image_create_with_resource(RESOURCE_ID_PIN_ROUND_JELLYFIN_ICON);
#endif
break;
case 2:
s_color_primary = GColorChromeYellow;
s_color_secondary = GColorLightGray;
#if PBL_ROUND
s_pin_icon = gdraw_command_image_create_with_resource(RESOURCE_ID_PIN_ROUND_PLEX_ICON);
#endif
break;
}
#if PBL_RECT
s_pin_icon = gdraw_command_image_create_with_resource(RESOURCE_ID_PIN_ICON);
#endif
s_sleep_icon = gdraw_command_image_create_with_resource(RESOURCE_ID_SLEEP_ICON);
// initialize pkjs // initialize pkjs
app_message_register_inbox_received(inbox_received_handler_ready); app_message_register_inbox_received(inbox_received_handler);
app_message_open(1024, 1024); app_message_open(1024, 64);
// get sleep time (UNIX timestamp) // get sleep time (UNIX timestamp)
time_t end = time(NULL); time_t end = time(NULL);
@@ -175,14 +230,6 @@ static void init() {
s_sleep_data_accessible = false; s_sleep_data_accessible = false;
} }
// load PDCs
s_sleep_icon = gdraw_command_image_create_with_resource(RESOURCE_ID_SLEEP_ICON);
#if PBL_ROUND
s_pin_icon = gdraw_command_image_create_with_resource(RESOURCE_ID_PIN_ROUND_JELLYFIN_ICON);
#else
s_pin_icon = gdraw_command_image_create_with_resource(RESOURCE_ID_PIN_ICON);
#endif
window_stack_push(s_main_window, true); window_stack_push(s_main_window, true);
} }