Change colors to match selected service
This commit is contained in:
10
README.md
10
README.md
@@ -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)
|
|
||||||
|
|||||||
@@ -54,6 +54,15 @@
|
|||||||
"chalk",
|
"chalk",
|
||||||
"gabbro"
|
"gabbro"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "raw",
|
||||||
|
"name": "PIN_ROUND_PLEX_ICON",
|
||||||
|
"file": "pin_round_plex.pdc",
|
||||||
|
"targetPlatforms": [
|
||||||
|
"chalk",
|
||||||
|
"gabbro"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
BIN
resources/pin_round_plex.pdc
Normal file
BIN
resources/pin_round_plex.pdc
Normal file
Binary file not shown.
93
src/c/main.c
93
src/c/main.c
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user