From 50f6d2fcf9623a3162e69fff8ebdfa9b617d9a66 Mon Sep 17 00:00:00 2001 From: ESurge Date: Thu, 9 Feb 2023 12:51:18 -0800 Subject: [PATCH 1/5] Small fix to function of NameChanger Srv Small fix to function of NameChanger App --- applications/plugins/namechanger/namechanger.c | 3 ++- applications/services/namechangersrv/namechangersrv.c | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/applications/plugins/namechanger/namechanger.c b/applications/plugins/namechanger/namechanger.c index 17abcea720b..e5a371b2cae 100644 --- a/applications/plugins/namechanger/namechanger.c +++ b/applications/plugins/namechanger/namechanger.c @@ -88,7 +88,8 @@ void namechanger_text_store_set(NameChanger* namechanger, const char* text, ...) va_end(args); } -int32_t namechanger_app() { +int32_t namechanger_app(void* p) { + UNUSED(p); NameChanger* namechanger = namechanger_alloc(); view_dispatcher_attach_to_gui( diff --git a/applications/services/namechangersrv/namechangersrv.c b/applications/services/namechangersrv/namechangersrv.c index 6f80f204dd1..26bd0cfe4a8 100644 --- a/applications/services/namechangersrv/namechangersrv.c +++ b/applications/services/namechangersrv/namechangersrv.c @@ -3,7 +3,8 @@ #include #include -void namechanger_on_system_start() { +int32_t namechanger_on_system_start(void* p) { + UNUSED(p); if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) { FURI_LOG_W(TAG, "NameChangerSRV load skipped. Device is in special startup mode."); } else { @@ -164,4 +165,6 @@ void namechanger_on_system_start() { furi_string_free(filepath); furi_record_close(RECORD_STORAGE); } + + return 0; } \ No newline at end of file From 3381a6b53b8e190c9057b14622376f467be84c1a Mon Sep 17 00:00:00 2001 From: ESurge Date: Thu, 9 Feb 2023 12:53:23 -0800 Subject: [PATCH 2/5] Fix build error for subghz_cli.c regarding "chat" command --- applications/main/subghz/subghz_cli.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 36cd7b9f841..803d3da2a81 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -602,7 +602,8 @@ static void subghz_cli_command_encrypt_raw(Cli* cli, FuriString* args) { furi_string_free(source); } -static void subghz_cli_command_chat(Cli* cli, FuriString* args) { +static void subghz_cli_command_chat(Cli* cli, FuriString* args, void* context) { + UNUSED(context); uint32_t frequency = 433920000; if(furi_string_size(args)) { @@ -791,7 +792,7 @@ static void subghz_cli_command(Cli* cli, FuriString* args, void* context) { } if(furi_string_cmp_str(cmd, "chat") == 0) { - subghz_cli_command_chat(cli, args); + subghz_cli_command_chat(cli, args, context); break; } From ffce2dd938b11d4beb3c1526e3dd469ce45d7e2d Mon Sep 17 00:00:00 2001 From: ESurge Date: Thu, 9 Feb 2023 13:04:10 -0800 Subject: [PATCH 3/5] Cleaned up the XP levels Progression is more consistent --- .../services/dolphin/helpers/dolphin_deed.c | 68 ++++++++-------- .../services/dolphin/helpers/dolphin_state.c | 78 ++++++++++++++----- .../services/dolphin/helpers/dolphin_state.h | 2 + 3 files changed, 96 insertions(+), 52 deletions(-) diff --git a/applications/services/dolphin/helpers/dolphin_deed.c b/applications/services/dolphin/helpers/dolphin_deed.c index 05758d445c7..89fc0416ced 100644 --- a/applications/services/dolphin/helpers/dolphin_deed.c +++ b/applications/services/dolphin/helpers/dolphin_deed.c @@ -2,46 +2,46 @@ #include static const DolphinDeedWeight dolphin_deed_weights[] = { - {1, DolphinAppSubGhz}, // DolphinDeedSubGhzReceiverInfo - {3, DolphinAppSubGhz}, // DolphinDeedSubGhzSave - {1, DolphinAppSubGhz}, // DolphinDeedSubGhzRawRec - {2, DolphinAppSubGhz}, // DolphinDeedSubGhzAddManually - {2, DolphinAppSubGhz}, // DolphinDeedSubGhzSend - {1, DolphinAppSubGhz}, // DolphinDeedSubGhzFrequencyAnalyzer + {5, DolphinAppSubGhz}, // DolphinDeedSubGhzReceiverInfo + {15, DolphinAppSubGhz}, // DolphinDeedSubGhzSave + {5, DolphinAppSubGhz}, // DolphinDeedSubGhzRawRec + {10, DolphinAppSubGhz}, // DolphinDeedSubGhzAddManually + {10, DolphinAppSubGhz}, // DolphinDeedSubGhzSend + {5, DolphinAppSubGhz}, // DolphinDeedSubGhzFrequencyAnalyzer - {1, DolphinAppRfid}, // DolphinDeedRfidRead - {3, DolphinAppRfid}, // DolphinDeedRfidReadSuccess - {3, DolphinAppRfid}, // DolphinDeedRfidSave - {2, DolphinAppRfid}, // DolphinDeedRfidEmulate - {2, DolphinAppRfid}, // DolphinDeedRfidAdd + {5, DolphinAppRfid}, // DolphinDeedRfidRead + {15, DolphinAppRfid}, // DolphinDeedRfidReadSuccess + {15, DolphinAppRfid}, // DolphinDeedRfidSave + {10, DolphinAppRfid}, // DolphinDeedRfidEmulate + {10, DolphinAppRfid}, // DolphinDeedRfidAdd - {1, DolphinAppNfc}, // DolphinDeedNfcRead - {3, DolphinAppNfc}, // DolphinDeedNfcReadSuccess - {3, DolphinAppNfc}, // DolphinDeedNfcSave - {1, DolphinAppNfc}, // DolphinDeedNfcDetectReader - {2, DolphinAppNfc}, // DolphinDeedNfcEmulate - {2, DolphinAppNfc}, // DolphinDeedNfcMfcAdd - {1, DolphinAppNfc}, // DolphinDeedNfcAddSave - {1, DolphinAppNfc}, // DolphinDeedNfcAddEmulate + {5, DolphinAppNfc}, // DolphinDeedNfcRead + {15, DolphinAppNfc}, // DolphinDeedNfcReadSuccess + {5, DolphinAppNfc}, // DolphinDeedNfcSave + {5, DolphinAppNfc}, // DolphinDeedNfcDetectReader + {10, DolphinAppNfc}, // DolphinDeedNfcEmulate + {10, DolphinAppNfc}, // DolphinDeedNfcMfcAdd + {5, DolphinAppNfc}, // DolphinDeedNfcAddSave + {5, DolphinAppNfc}, // DolphinDeedNfcAddEmulate - {1, DolphinAppIr}, // DolphinDeedIrSend - {3, DolphinAppIr}, // DolphinDeedIrLearnSuccess - {3, DolphinAppIr}, // DolphinDeedIrSave + {5, DolphinAppIr}, // DolphinDeedIrSend + {15, DolphinAppIr}, // DolphinDeedIrLearnSuccess + {15, DolphinAppIr}, // DolphinDeedIrSave - {1, DolphinAppIbutton}, // DolphinDeedIbuttonRead - {3, DolphinAppIbutton}, // DolphinDeedIbuttonReadSuccess - {3, DolphinAppIbutton}, // DolphinDeedIbuttonSave - {2, DolphinAppIbutton}, // DolphinDeedIbuttonEmulate - {2, DolphinAppIbutton}, // DolphinDeedIbuttonAdd + {5, DolphinAppIbutton}, // DolphinDeedIbuttonRead + {15, DolphinAppIbutton}, // DolphinDeedIbuttonReadSuccess + {15, DolphinAppIbutton}, // DolphinDeedIbuttonSave + {10, DolphinAppIbutton}, // DolphinDeedIbuttonEmulate + {10, DolphinAppIbutton}, // DolphinDeedIbuttonAdd - {3, DolphinAppBadusb}, // DolphinDeedBadUsbPlayScript - {3, DolphinAppPlugin}, // DolphinDeedU2fAuthorized + {15, DolphinAppBadusb}, // DolphinDeedBadUsbPlayScript + {15, DolphinAppPlugin}, // DolphinDeedU2fAuthorized - {1, DolphinAppPlugin}, // DolphinDeedGpioUartBridge + {5, DolphinAppPlugin}, // DolphinDeedGpioUartBridge - {1, DolphinAppPlugin}, // DolphinDeedPluginStart - {1, DolphinAppPlugin}, // DolphinDeedPluginGameStart - {10, DolphinAppPlugin}, // DolphinDeedPluginGameWin + {5, DolphinAppPlugin}, // DolphinDeedPluginStart + {5, DolphinAppPlugin}, // DolphinDeedPluginGameStart + {20, DolphinAppPlugin}, // DolphinDeedPluginGameWin }; static uint8_t dolphin_deed_limits[] = { @@ -53,7 +53,7 @@ static uint8_t dolphin_deed_limits[] = { 100, // DolphinAppBadusb // 100, // DolphinAppU2f // 100, // DolphinAppGpio - 100, // DolphinAppPlugin + 200, // DolphinAppPlugin }; _Static_assert(COUNT_OF(dolphin_deed_weights) == DolphinDeedMAX, "dolphin_deed_weights size error"); diff --git a/applications/services/dolphin/helpers/dolphin_state.c b/applications/services/dolphin/helpers/dolphin_state.c index f683a6d731c..1c36319f2bd 100644 --- a/applications/services/dolphin/helpers/dolphin_state.c +++ b/applications/services/dolphin/helpers/dolphin_state.c @@ -14,9 +14,38 @@ #define DOLPHIN_STATE_PATH INT_PATH(DOLPHIN_STATE_FILE_NAME) #define DOLPHIN_STATE_HEADER_MAGIC 0xD0 #define DOLPHIN_STATE_HEADER_VERSION 0x01 -int level_array[30] = {450, 700, 1100, 1800, 2300, 2900, 3900, 5000, 5900, 7200, - 8400, 10000, 11500, 13000, 15000, 18000, 20000, 22000, 25000, 33000, - 41000, 50000, 62000, 75000, 90000, 105000, 120000, 135000, 155000}; + +/* +The way the math works: + +Current xp (icounter) is subtracted from the threshold (xp requirement for next level up) + +The array values in level_array result in the following XP requirements per level below: + +500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, +3000, 3250, 3500, 3750, 4000, 4250, 4500, 4750, 5000, 6000, +7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000, 15000 + +To change the level requirement, add the last level's value with the desired next level's value. +Ex: Level 1 is 0 - 500. Level 2 needs to be Level 1 + next desired XP value. + +Level 2 is calculated: +Previous Level's Required XP: 500 ++ +Desired Level XP: 750 += +Value in level_array: 1250 +*/ + +uint32_t level_array[29] = {500, 1250, 2250, 3500, 5000, 6750, 8750, 11000, + 13500, 16250, 19250, 22500, 26000, 29750, 33750, 38000, + 42500, 47250, 52250, 58250, 65250, 73250, 82250, 92250, + 103250, 115250, 128250, 142250, 157250}; + +/* +This calculates the size of an array. This is good as it's used for dynamic for loops below. Therefore, you can just add more values to level_array for more levels. +*/ +#define NUM(a) (sizeof(a) / sizeof(*a)) #define BUTTHURT_MAX 14 #define BUTTHURT_MIN 0 @@ -25,6 +54,10 @@ DolphinState* dolphin_state_alloc() { return malloc(sizeof(DolphinState)); } +int dolphin_state_max_level() { + return NUM(level_array) + 1; +} + void dolphin_state_free(DolphinState* dolphin_state) { free(dolphin_state); } @@ -82,41 +115,50 @@ uint64_t dolphin_state_timestamp() { } bool dolphin_state_is_levelup(uint32_t icounter) { - for(int i = 0; i < 30; ++i) { + for(int i = 0; i < NUM(level_array); i++) { if((icounter == level_array[i])) { - return true; + return (icounter == level_array[i]); } - }; - return false; + } + return NUM(level_array) + 1; } uint8_t dolphin_get_level(uint32_t icounter) { - for(int i = 0; i < 29; ++i) { + for(int i = 0; i < NUM(level_array); i++) { if(icounter <= level_array[i]) { return i + 1; } } - return 30; + return NUM(level_array) + 1; } uint32_t dolphin_state_xp_above_last_levelup(uint32_t icounter) { - if(level_array[0] > icounter) { - for(int i = 1; i < 29; ++i) { - if(icounter <= level_array[i]) { - return level_array[i] - icounter + 1; - } + uint32_t threshold = 0; + for(int i = 0; i < NUM(level_array); i++) { + if(icounter <= level_array[0]) { + threshold = 0; + break; + } else if(icounter <= level_array[i]) { + threshold = level_array[i - 1]; + break; + } else { + threshold = level_array[NUM(level_array) - 1]; } } - return icounter; + return icounter - threshold; } uint32_t dolphin_state_xp_to_levelup(uint32_t icounter) { - for(int i = 0; i < 29; ++i) { + uint32_t threshold = 0; + for(int i = 0; i < NUM(level_array); i++) { if(icounter <= level_array[i]) { - return level_array[i] - icounter; + threshold = level_array[i]; + break; + } else { + threshold = (uint32_t)-1; } } - return (uint32_t)-1 - icounter; + return threshold - icounter; } void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) { diff --git a/applications/services/dolphin/helpers/dolphin_state.h b/applications/services/dolphin/helpers/dolphin_state.h index 3e02fb87201..18ca9a49c95 100644 --- a/applications/services/dolphin/helpers/dolphin_state.h +++ b/applications/services/dolphin/helpers/dolphin_state.h @@ -33,6 +33,8 @@ void dolphin_state_clear_limits(DolphinState* dolphin_state); uint64_t dolphin_state_timestamp(); +int dolphin_state_max_level(); + void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed); void dolphin_state_butthurted(DolphinState* dolphin_state); From c8c4a0022cda6491ca62b0db6f6ed0f48a77bda8 Mon Sep 17 00:00:00 2001 From: ESurge Date: Thu, 9 Feb 2023 13:09:16 -0800 Subject: [PATCH 4/5] Desktop Changes for Dynamic Icon support Passport as a FAP with Multiple Page support, Dynamic Icon support New Passport Settings app Old Passport moved, made as a redundancy Updates to BT, Desktop, GUI, Power, and Storage services to support above changes Updates to Desktop Settings app to support above changes --- applications/services/bt/bt_service/bt.c | 17 +- applications/services/bt/bt_settings.h | 1 + applications/services/desktop/desktop.c | 61 ++ applications/services/desktop/desktop_i.h | 3 + .../services/desktop/desktop_settings.h | 3 + .../desktop/scenes/desktop_scene_main.c | 90 ++- .../desktop/views/desktop_view_lock_menu.c | 4 +- applications/services/gui/gui.c | 119 ++- applications/services/gui/gui.h | 1 + .../services/power/power_service/power.c | 29 +- applications/services/storage/storage.c | 6 +- applications/services/storage/storage_i.h | 1 + applications/settings/application.fam | 2 +- .../desktop_settings/desktop_settings_app.c | 2 + .../desktop_settings/desktop_settings_app.h | 2 + .../scenes/desktop_settings_scene_start.c | 112 ++- .../settings/dolphin_passport/passport.c | 328 --------- .../application.fam | 7 +- .../assets_images/DrMario_backdrop_128x64.png | Bin 0 -> 2920 bytes .../DrMario_blue_virus_25x25/frame_01.png | Bin 0 -> 1933 bytes .../DrMario_blue_virus_25x25/frame_02.png | Bin 0 -> 1947 bytes .../DrMario_blue_virus_25x25/frame_03.png | Bin 0 -> 1933 bytes .../DrMario_blue_virus_25x25/frame_04.png | Bin 0 -> 1944 bytes .../DrMario_blue_virus_25x25/frame_rate | 1 + .../DrMario_red_virus_25x25/frame_01.png | Bin 0 -> 1972 bytes .../DrMario_red_virus_25x25/frame_02.png | Bin 0 -> 1769 bytes .../DrMario_red_virus_25x25/frame_03.png | Bin 0 -> 1972 bytes .../DrMario_red_virus_25x25/frame_04.png | Bin 0 -> 1985 bytes .../DrMario_red_virus_25x25/frame_rate | 1 + .../DrMario_yellow_virus_25x25/frame_01.png | Bin 0 -> 1939 bytes .../DrMario_yellow_virus_25x25/frame_02.png | Bin 0 -> 1939 bytes .../DrMario_yellow_virus_25x25/frame_03.png | Bin 0 -> 1939 bytes .../DrMario_yellow_virus_25x25/frame_04.png | Bin 0 -> 1937 bytes .../DrMario_yellow_virus_25x25/frame_rate | 1 + .../passport_app/assets_images/G0ku.png | Bin 0 -> 1844 bytes .../passport_app/assets_images/g0ku_1.png | Bin 0 -> 1761 bytes .../passport_app/assets_images/g0ku_2.png | Bin 0 -> 1700 bytes .../passport_app/assets_images/g0ku_3.png | Bin 0 -> 1971 bytes .../assets_images/passport_background.png | Bin 0 -> 4425 bytes .../assets_images/passport_happy1_46x49.png | Bin 0 -> 1237 bytes .../assets_images/passport_happy2_46x49.png | Bin 0 -> 1263 bytes .../assets_images/passport_happy3_46x49.png | Bin 0 -> 1283 bytes .../passport_app/desktop/desktop_settings.h | 70 ++ .../desktop/desktop_settings_filename.h | 3 + .../dolphin/helpers/dolphin_deed.c | 75 ++ .../dolphin/helpers/dolphin_deed.h | 84 +++ .../dolphin/helpers/dolphin_state.c | 245 +++++++ .../dolphin/helpers/dolphin_state.h | 50 ++ .../dolphin/helpers/dolphin_state_filename.h | 3 + applications/settings/passport_app/passport.c | 690 ++++++++++++++++++ applications/settings/passport_app/passport.h | 107 +++ .../settings/passport_app/passport_10px.png | Bin 0 -> 1811 bytes .../passport_settings/passport_settings.c | 33 + .../passport_settings/passport_settings.h | 35 + .../passport_settings_filename.h | 3 + .../passport_settings/application.fam | 12 + .../passport_settings/passport_settings.c | 33 + .../passport_settings/passport_settings.h | 35 + .../passport_settings/passport_settings_app.c | 84 +++ .../passport_settings/passport_settings_app.h | 25 + .../passport_settings_filename.h | 3 + .../scenes/passport_settings_scene.c | 30 + .../scenes/passport_settings_scene.h | 29 + .../scenes/passport_settings_scene_config.h | 1 + .../scenes/passport_settings_scene_start.c | 261 +++++++ applications/system/application.fam | 1 + .../system/dolphin_passport/application.fam | 13 + .../dolphin_passport/dolphin_passport.c | 275 +++++++ 68 files changed, 2577 insertions(+), 414 deletions(-) delete mode 100644 applications/settings/dolphin_passport/passport.c rename applications/settings/{dolphin_passport => passport_app}/application.fam (54%) create mode 100644 applications/settings/passport_app/assets_images/DrMario_backdrop_128x64.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_01.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_02.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_03.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_04.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_rate create mode 100644 applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_01.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_02.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_03.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_04.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_rate create mode 100644 applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_01.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_02.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_03.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_04.png create mode 100644 applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_rate create mode 100644 applications/settings/passport_app/assets_images/G0ku.png create mode 100644 applications/settings/passport_app/assets_images/g0ku_1.png create mode 100644 applications/settings/passport_app/assets_images/g0ku_2.png create mode 100644 applications/settings/passport_app/assets_images/g0ku_3.png create mode 100644 applications/settings/passport_app/assets_images/passport_background.png create mode 100644 applications/settings/passport_app/assets_images/passport_happy1_46x49.png create mode 100644 applications/settings/passport_app/assets_images/passport_happy2_46x49.png create mode 100644 applications/settings/passport_app/assets_images/passport_happy3_46x49.png create mode 100644 applications/settings/passport_app/desktop/desktop_settings.h create mode 100644 applications/settings/passport_app/desktop/desktop_settings_filename.h create mode 100644 applications/settings/passport_app/dolphin/helpers/dolphin_deed.c create mode 100644 applications/settings/passport_app/dolphin/helpers/dolphin_deed.h create mode 100644 applications/settings/passport_app/dolphin/helpers/dolphin_state.c create mode 100644 applications/settings/passport_app/dolphin/helpers/dolphin_state.h create mode 100644 applications/settings/passport_app/dolphin/helpers/dolphin_state_filename.h create mode 100644 applications/settings/passport_app/passport.c create mode 100644 applications/settings/passport_app/passport.h create mode 100644 applications/settings/passport_app/passport_10px.png create mode 100644 applications/settings/passport_app/passport_settings/passport_settings.c create mode 100644 applications/settings/passport_app/passport_settings/passport_settings.h create mode 100644 applications/settings/passport_app/passport_settings/passport_settings_filename.h create mode 100644 applications/settings/passport_settings/application.fam create mode 100644 applications/settings/passport_settings/passport_settings.c create mode 100644 applications/settings/passport_settings/passport_settings.h create mode 100644 applications/settings/passport_settings/passport_settings_app.c create mode 100644 applications/settings/passport_settings/passport_settings_app.h create mode 100644 applications/settings/passport_settings/passport_settings_filename.h create mode 100644 applications/settings/passport_settings/scenes/passport_settings_scene.c create mode 100644 applications/settings/passport_settings/scenes/passport_settings_scene.h create mode 100644 applications/settings/passport_settings/scenes/passport_settings_scene_config.h create mode 100644 applications/settings/passport_settings/scenes/passport_settings_scene_start.c create mode 100644 applications/system/dolphin_passport/application.fam create mode 100644 applications/system/dolphin_passport/dolphin_passport.c diff --git a/applications/services/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c index 9e578269034..8e33d93281b 100644 --- a/applications/services/bt/bt_service/bt.c +++ b/applications/services/bt/bt_service/bt.c @@ -296,12 +296,17 @@ static void bt_on_key_storage_change_callback(uint8_t* addr, uint16_t size, void } static void bt_statusbar_update(Bt* bt) { - if(bt->status == BtStatusAdvertising) { - view_port_set_width(bt->statusbar_view_port, icon_get_width(&I_Bluetooth_Idle_5x8)); - view_port_enabled_set(bt->statusbar_view_port, true); - } else if(bt->status == BtStatusConnected) { - view_port_set_width(bt->statusbar_view_port, icon_get_width(&I_Bluetooth_Connected_16x8)); - view_port_enabled_set(bt->statusbar_view_port, true); + if(bt->bt_settings.iconshow == true) { + if(bt->status == BtStatusAdvertising) { + view_port_set_width(bt->statusbar_view_port, icon_get_width(&I_Bluetooth_Idle_5x8)); + view_port_enabled_set(bt->statusbar_view_port, true); + } else if(bt->status == BtStatusConnected) { + view_port_set_width( + bt->statusbar_view_port, icon_get_width(&I_Bluetooth_Connected_16x8)); + view_port_enabled_set(bt->statusbar_view_port, true); + } else { + view_port_enabled_set(bt->statusbar_view_port, false); + } } else { view_port_enabled_set(bt->statusbar_view_port, false); } diff --git a/applications/services/bt/bt_settings.h b/applications/services/bt/bt_settings.h index 9ed8be89c4a..f310ea87cc0 100644 --- a/applications/services/bt/bt_settings.h +++ b/applications/services/bt/bt_settings.h @@ -11,6 +11,7 @@ extern "C" { typedef struct { bool enabled; + bool iconshow; } BtSettings; bool bt_settings_load(BtSettings* bt_settings); diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index db1201e2b3a..b5694b89e46 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -32,6 +32,22 @@ static void desktop_loader_callback(const void* message, void* context) { view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAfterAppFinished); } } + +static void storage_Desktop_status_callback(const void* message, void* context) { + furi_assert(context); + Desktop* desktop = context; + const StorageEvent* storage_event = message; + + if((storage_event->type == StorageEventTypeCardUnmount) || + (storage_event->type == StorageEventTypeCardMountError)) { + view_port_enabled_set(desktop->sdcard_icon_viewport, false); + } + + if(storage_event->type == StorageEventTypeCardMount) { + view_port_enabled_set(desktop->sdcard_icon_viewport, desktop->settings.sdcard); + } +} + static void desktop_lock_icon_draw_callback(Canvas* canvas, void* context) { UNUSED(context); furi_assert(canvas); @@ -44,6 +60,22 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); } +static void desktop_topbar_icon_draw_callback(Canvas* canvas, void* context) { + UNUSED(context); + furi_assert(canvas); + + canvas_set_bitmap_mode(canvas, 1); + canvas_draw_icon(canvas, 0, 0, &I_Background_128x11); + canvas_set_bitmap_mode(canvas, 0); +} + +static void desktop_sdcard_icon_draw_callback(Canvas* canvas, void* context) { + UNUSED(context); + furi_assert(canvas); + + canvas_draw_icon(canvas, 0, 0, &I_SDcardMounted_11x8); +} + static bool desktop_custom_event_callback(void* context, uint32_t event) { furi_assert(context); Desktop* desktop = (Desktop*)context; @@ -245,6 +277,22 @@ Desktop* desktop_alloc() { view_port_enabled_set(desktop->dummy_mode_icon_viewport, false); gui_add_view_port(desktop->gui, desktop->dummy_mode_icon_viewport, GuiLayerStatusBarLeft); + // Top bar icon + desktop->topbar_icon_viewport = view_port_alloc(); + view_port_set_width(desktop->topbar_icon_viewport, icon_get_width(&I_Background_128x11)); + view_port_draw_callback_set( + desktop->topbar_icon_viewport, desktop_topbar_icon_draw_callback, desktop); + view_port_enabled_set(desktop->topbar_icon_viewport, false); + gui_add_view_port(desktop->gui, desktop->topbar_icon_viewport, GuiLayerStatusBarTop); + + // SD card icon hack + desktop->sdcard_icon_viewport = view_port_alloc(); + view_port_set_width(desktop->sdcard_icon_viewport, icon_get_width(&I_SDcardMounted_11x8)); + view_port_draw_callback_set( + desktop->sdcard_icon_viewport, desktop_sdcard_icon_draw_callback, desktop); + view_port_enabled_set(desktop->sdcard_icon_viewport, false); + gui_add_view_port(desktop->gui, desktop->sdcard_icon_viewport, GuiLayerStatusBarLeft); + // Special case: autostart application is already running desktop->loader = furi_record_open(RECORD_LOADER); if(loader_is_locked(desktop->loader) && @@ -262,6 +310,11 @@ Desktop* desktop_alloc() { desktop->auto_lock_timer = furi_timer_alloc(desktop_auto_lock_timer_callback, FuriTimerTypeOnce, desktop); + Storage* storage = furi_record_open(RECORD_STORAGE); + desktop->sub = furi_pubsub_subscribe( + storage_get_pubsub(storage), storage_Desktop_status_callback, desktop); + furi_record_close(RECORD_STORAGE); + return desktop; } @@ -276,6 +329,10 @@ void desktop_free(Desktop* desktop) { desktop->input_events_subscription = NULL; } + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_pubsub_unsubscribe(storage_get_pubsub(storage), desktop->sub); + furi_record_close(RECORD_STORAGE); + desktop->loader = NULL; desktop->input_events_pubsub = NULL; furi_record_close(RECORD_LOADER); @@ -338,6 +395,10 @@ int32_t desktop_srv(void* p) { DESKTOP_SETTINGS_SAVE(&desktop->settings); } + view_port_enabled_set(desktop->topbar_icon_viewport, desktop->settings.top_bar); + + view_port_enabled_set(desktop->sdcard_icon_viewport, desktop->settings.sdcard); + view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode); desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode); animation_manager_set_dummy_mode_state( diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index 8034bbc3ac0..cd7cd25d88d 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -59,6 +59,8 @@ struct Desktop { ViewPort* lock_icon_viewport; ViewPort* dummy_mode_icon_viewport; + ViewPort* topbar_icon_viewport; + ViewPort* sdcard_icon_viewport; AnimationManager* animation_manager; @@ -68,6 +70,7 @@ struct Desktop { FuriPubSubSubscription* app_start_stop_subscription; FuriPubSub* input_events_pubsub; FuriPubSubSubscription* input_events_subscription; + FuriPubSubSubscription* sub; FuriTimer* auto_lock_timer; }; diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 1623c5722c5..5524ab9f8ad 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -42,6 +42,7 @@ #define DISPLAY_BATTERY_RETRO_3 3 #define DISPLAY_BATTERY_RETRO_5 4 #define DISPLAY_BATTERY_BAR_PERCENT 5 +#define DISPLAY_BATTERY_NONE 6 #define FAP_LOADER_APP_NAME "Applications" @@ -64,4 +65,6 @@ typedef struct { uint8_t displayBatteryPercentage; bool is_dumbmode; uint8_t dummy_mode; + bool top_bar; + bool sdcard; } DesktopSettings; diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index 0f1999f7789..a81ddaa6db5 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -2,6 +2,7 @@ #include #include "applications/services/applications.h" #include +#include #include #include "../desktop_i.h" @@ -13,7 +14,17 @@ #define TAG "DesktopSrv" -#define CLOCK_APP EXT_PATH("/apps/Main/Clock.fap") +#define CLOCK_APP EXT_PATH("apps/Main/Clock.fap") +#define PASSPORT_APP EXT_PATH("apps/Main/Passport.fap") +#define SNAKE_APP EXT_PATH("apps/Games/Snake.fap") +#define IMPROVED_2048_APP EXT_PATH("apps/Games/2048_improved.fap") +#define ZOMBIEZ_APP EXT_PATH("apps/Games/Zombiez.fap") +#define TETRIS_APP EXT_PATH("apps/Games/Tetris.fap") +#define DOOM_APP EXT_PATH("apps/Games/DOOM.fap") +#define DICE_APP EXT_PATH("apps/Games/Dice.fap") +#define ARKANOID_APP EXT_PATH("apps/Games/Arkanoid.fap") +#define HEAP_DEFENCE_APP EXT_PATH("apps/Games/Heap_Defence.fap") +#define SUBGHZ_REMOTE_APP EXT_PATH("apps/Main/SubGHz_Remote.fap") static void desktop_scene_main_new_idle_animation_callback(void* context) { furi_assert(context); @@ -69,9 +80,21 @@ static void desktop_scene_main_open_app_or_profile(Desktop* desktop, const char* if(status == LoaderStatusOk) break; FURI_LOG_E(TAG, "loader_start failed: %d", status); - status = loader_start(desktop->loader, "Passport", NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); + Storage* storage = furi_record_open(RECORD_STORAGE); + if(storage_file_exists(storage, PASSPORT_APP)) { + furi_record_close(RECORD_STORAGE); + LoaderStatus status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, PASSPORT_APP); + + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } + } else { + furi_record_close(RECORD_STORAGE); + LoaderStatus status = loader_start(desktop->loader, "Passport", NULL); + + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } } } while(false); } @@ -193,57 +216,80 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { break; case DesktopAnimationEventInteractAnimation: if(!animation_manager_interact_process(desktop->animation_manager)) { - LoaderStatus status = loader_start(desktop->loader, "Passport", NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); + Storage* storage = furi_record_open(RECORD_STORAGE); + if(storage_file_exists(storage, PASSPORT_APP)) { + furi_record_close(RECORD_STORAGE); + LoaderStatus status = + loader_start(desktop->loader, FAP_LOADER_APP_NAME, PASSPORT_APP); + + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } + } else { + furi_record_close(RECORD_STORAGE); + LoaderStatus status = loader_start(desktop->loader, "Passport", NULL); + + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } } } consumed = true; break; case DesktopMainEventOpenPassport: { - LoaderStatus status = loader_start(desktop->loader, "Passport", NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); + Storage* storage = furi_record_open(RECORD_STORAGE); + if(storage_file_exists(storage, PASSPORT_APP)) { + furi_record_close(RECORD_STORAGE); + LoaderStatus status = + loader_start(desktop->loader, FAP_LOADER_APP_NAME, PASSPORT_APP); + + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } + } else { + furi_record_close(RECORD_STORAGE); + LoaderStatus status = loader_start(desktop->loader, "Passport", NULL); + + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } } break; } case DesktopMainEventOpenSnake: { - desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Snake.fap")); + desktop_scene_main_open_app_or_profile(desktop, SNAKE_APP); break; } case DesktopMainEventOpen2048: { - desktop_scene_main_open_app_or_profile( - desktop, EXT_PATH("/apps/Games/2048_improved.fap")); + desktop_scene_main_open_app_or_profile(desktop, IMPROVED_2048_APP); break; } case DesktopMainEventOpenZombiez: { - desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Zombiez.fap")); + desktop_scene_main_open_app_or_profile(desktop, ZOMBIEZ_APP); break; } case DesktopMainEventOpenTetris: { - desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Tetris.fap")); + desktop_scene_main_open_app_or_profile(desktop, TETRIS_APP); break; } case DesktopMainEventOpenDOOM: { - desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/DOOM.fap")); + desktop_scene_main_open_app_or_profile(desktop, DOOM_APP); break; } case DesktopMainEventOpenDice: { - desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Dice.fap")); + desktop_scene_main_open_app_or_profile(desktop, DICE_APP); break; } case DesktopMainEventOpenArkanoid: { - desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Arkanoid.fap")); + desktop_scene_main_open_app_or_profile(desktop, ARKANOID_APP); break; } case DesktopMainEventOpenHeap: { - desktop_scene_main_open_app_or_profile( - desktop, EXT_PATH("/apps/Games/Heap_Defence.fap")); + desktop_scene_main_open_app_or_profile(desktop, HEAP_DEFENCE_APP); break; } case DesktopMainEventOpenSubRemote: { - desktop_scene_main_open_app_or_profile( - desktop, EXT_PATH("/apps/Main/SubGHz_Remote.fap")); + desktop_scene_main_open_app_or_profile(desktop, SUBGHZ_REMOTE_APP); break; } case DesktopMainEventOpenClock: { diff --git a/applications/services/desktop/views/desktop_view_lock_menu.c b/applications/services/desktop/views/desktop_view_lock_menu.c index e729e48bbab..7705143cb9b 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.c +++ b/applications/services/desktop/views/desktop_view_lock_menu.c @@ -9,12 +9,12 @@ #define LOCK_MENU_ITEMS_NB 5 -static void desktop_view_lock_menu_dumbmode_changed(bool isThisGameMode) { +/*static void desktop_view_lock_menu_dumbmode_changed(bool isThisGameMode) { DesktopSettingsApp* app = malloc(sizeof(DesktopSettingsApp)); DESKTOP_SETTINGS_LOAD(&app->settings); app->settings.is_dumbmode = isThisGameMode; DESKTOP_SETTINGS_SAVE(&app->settings); -} +}*/ typedef enum { DesktopLockMenuIndexLock, diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 1fc613d0a56..961a38ac5e3 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -49,26 +49,59 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { ViewPortArray_it_t it; uint8_t left_used = 0; uint8_t right_used = 0; + uint8_t top_used = 0; uint8_t width; canvas_set_orientation(gui->canvas, CanvasOrientationHorizontal); canvas_frame_set( - gui->canvas, GUI_STATUS_BAR_X, GUI_STATUS_BAR_Y, GUI_DISPLAY_WIDTH, GUI_STATUS_BAR_HEIGHT); + gui->canvas, + GUI_STATUS_BAR_X, + GUI_STATUS_BAR_Y, + GUI_STATUS_BAR_WIDTH, + GUI_STATUS_BAR_HEIGHT); /* for support black theme - paint white area and * draw icon with transparent white color */ - canvas_set_color(gui->canvas, ColorWhite); - // canvas_draw_box(gui->canvas, 1, 1, 9, 7); - // canvas_draw_box(gui->canvas, 7, 3, 58, 6); - // canvas_draw_box(gui->canvas, 61, 1, 32, 7); - // canvas_draw_box(gui->canvas, 89, 3, 38, 6); - canvas_set_color(gui->canvas, ColorBlack); - canvas_set_bitmap_mode(gui->canvas, 1); - // canvas_draw_icon(gui->canvas, 0, 0, &I_Background_128x11); - canvas_set_bitmap_mode(gui->canvas, 0); + //canvas_set_color(gui->canvas, ColorWhite); + //canvas_draw_box(gui->canvas, 1, 1, 9, 7); + //canvas_draw_box(gui->canvas, 7, 3, 58, 6); + //canvas_draw_box(gui->canvas, 61, 1, 32, 7); + //canvas_draw_box(gui->canvas, 89, 3, 38, 6); + //canvas_set_color(gui->canvas, ColorBlack); + //canvas_set_bitmap_mode(gui->canvas, 1); + //canvas_draw_icon(gui->canvas, 0, 0, &I_Background_128x11); + //canvas_set_bitmap_mode(gui->canvas, 0); + + // Top bar + ViewPortArray_it(it, gui->layers[GuiLayerStatusBarTop]); + while(!ViewPortArray_end_p(it) && top_used <= GUI_STATUS_BAR_WIDTH) { + ViewPort* view_port = *ViewPortArray_ref(it); + if(view_port_is_enabled(view_port)) { + width = view_port_get_width(view_port); + if(!width) width = GUI_DISPLAY_WIDTH; + // Prepare work area background + canvas_frame_set( + gui->canvas, + GUI_STATUS_BAR_X, + GUI_STATUS_BAR_Y, + GUI_STATUS_BAR_WIDTH, + GUI_STATUS_BAR_HEIGHT); + canvas_set_color(gui->canvas, ColorWhite); + canvas_draw_box(gui->canvas, 1, 1, 9, 7); + canvas_draw_box(gui->canvas, 7, 3, 58, 6); + canvas_draw_box(gui->canvas, 61, 1, 32, 7); + canvas_draw_box(gui->canvas, 89, 3, 38, 6); + canvas_set_color(gui->canvas, ColorBlack); + // ViewPort draw + canvas_frame_set( + gui->canvas, GUI_STATUS_BAR_X, GUI_STATUS_BAR_Y, width, GUI_STATUS_BAR_HEIGHT); + view_port_draw(view_port, gui->canvas); + } + ViewPortArray_next(it); + } // Right side - uint8_t x = GUI_DISPLAY_WIDTH - 1; + uint8_t x = GUI_DISPLAY_WIDTH; ViewPortArray_it(it, gui->layers[GuiLayerStatusBarRight]); while(!ViewPortArray_end_p(it) && right_used < GUI_STATUS_BAR_WIDTH) { ViewPort* view_port = *ViewPortArray_ref(it); @@ -80,43 +113,47 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { x -= (width + 2); // Prepare work area background canvas_frame_set( - gui->canvas, - x - 1, - GUI_STATUS_BAR_Y + 1, - width + 2, - GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); + gui->canvas, x, GUI_STATUS_BAR_Y, width + 2, GUI_STATUS_BAR_WORKAREA_HEIGHT + 3); canvas_set_color(gui->canvas, ColorWhite); canvas_draw_box( gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); canvas_set_color(gui->canvas, ColorBlack); // ViewPort draw canvas_frame_set( - gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); + gui->canvas, x + 1, GUI_STATUS_BAR_Y + 1, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); view_port_draw(view_port, gui->canvas); } ViewPortArray_next(it); } + /* // Draw frame around icons on the right if(right_used) { canvas_frame_set( gui->canvas, GUI_DISPLAY_WIDTH - 3 - right_used, GUI_STATUS_BAR_Y, - right_used + 2, + right_used + 3, GUI_STATUS_BAR_HEIGHT); canvas_set_color(gui->canvas, ColorBlack); canvas_draw_rframe( - gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas) - 1, 1); + gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); canvas_draw_line( gui->canvas, - canvas_width(gui->canvas) - 1, - 2, - canvas_width(gui->canvas) - 1, - canvas_height(gui->canvas) - 4); + canvas_width(gui->canvas) - 2, + 1, + canvas_width(gui->canvas) - 2, + canvas_height(gui->canvas) - 2); + canvas_draw_line( + gui->canvas, + 1, + canvas_height(gui->canvas) - 2, + canvas_width(gui->canvas) - 2, + canvas_height(gui->canvas) - 2); } + */ // Left side - x = 2; + x = 0; ViewPortArray_it(it, gui->layers[GuiLayerStatusBarLeft]); while(!ViewPortArray_end_p(it) && (right_used + left_used) < GUI_STATUS_BAR_WIDTH) { ViewPort* view_port = *ViewPortArray_ref(it); @@ -125,24 +162,14 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { if(!width) width = 8; // Prepare work area background canvas_frame_set( - gui->canvas, - x - 1, - // SASQUACH SAYS : This is the white box behind the left bar, move it 64 to hide it - GUI_STATUS_BAR_Y + 64, - width + 2, - GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); + gui->canvas, x, GUI_STATUS_BAR_Y, width + 2, GUI_STATUS_BAR_WORKAREA_HEIGHT + 3); canvas_set_color(gui->canvas, ColorWhite); canvas_draw_box( gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); canvas_set_color(gui->canvas, ColorBlack); // ViewPort draw canvas_frame_set( - // SASQUACH SAYS : This is where you move the Icons for the left bar, 64 to hide it - gui->canvas, - x, - GUI_STATUS_BAR_Y + 64, - width, - GUI_STATUS_BAR_WORKAREA_HEIGHT); + gui->canvas, x + 1, GUI_STATUS_BAR_Y + 1, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); view_port_draw(view_port, gui->canvas); // Recalculate next position left_used += (width + 2); @@ -171,7 +198,25 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { left_used += (width + 2); x += (width + 2); } - // Draw frame around icons on the left + /* + // Draw frame around icons on the left + if(left_used) { + canvas_frame_set(gui->canvas, 0, 0, left_used + 3, GUI_STATUS_BAR_HEIGHT); + canvas_draw_rframe( + gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); + canvas_draw_line( + gui->canvas, + canvas_width(gui->canvas) - 2, + 1, + canvas_width(gui->canvas) - 2, + canvas_height(gui->canvas) - 2); + canvas_draw_line( + gui->canvas, + 1, + canvas_height(gui->canvas) - 2, + canvas_width(gui->canvas) - 2, + canvas_height(gui->canvas) - 2); + }*/ } static bool gui_redraw_window(Gui* gui) { diff --git a/applications/services/gui/gui.h b/applications/services/gui/gui.h index 4e7fc2e4d87..07a13147e4c 100644 --- a/applications/services/gui/gui.h +++ b/applications/services/gui/gui.h @@ -18,6 +18,7 @@ typedef enum { GuiLayerWindow, /**< Window layer, status bar is shown */ + GuiLayerStatusBarTop, /**< Status bar top side layer */ GuiLayerStatusBarLeft, /**< Status bar left-side layer, auto-layout */ GuiLayerStatusBarRight, /**< Status bar right-side layer, auto-layout */ diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index e7cbeb2605c..af6c09fac2b 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -512,7 +512,15 @@ int32_t power_srv(void* p) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - power->displayBatteryPercentage = settings->displayBatteryPercentage; + + if(settings->displayBatteryPercentage != DISPLAY_BATTERY_NONE) { + power->displayBatteryPercentage = settings->displayBatteryPercentage; + view_port_enabled_set(power->battery_view_port, true); + } else { + power->displayBatteryPercentage = settings->displayBatteryPercentage; + view_port_enabled_set(power->battery_view_port, false); + } + free(settings); while(1) { @@ -532,9 +540,24 @@ int32_t power_srv(void* p) { if(need_refresh) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - power->displayBatteryPercentage = settings->displayBatteryPercentage; + + if(power->displayBatteryPercentage == DISPLAY_BATTERY_NONE) { + if(settings->displayBatteryPercentage != DISPLAY_BATTERY_NONE) { + power->displayBatteryPercentage = settings->displayBatteryPercentage; + view_port_enabled_set(power->battery_view_port, true); + view_port_update(power->battery_view_port); + } + } else { + if(settings->displayBatteryPercentage == DISPLAY_BATTERY_NONE) { + power->displayBatteryPercentage = settings->displayBatteryPercentage; + view_port_enabled_set(power->battery_view_port, false); + } else { + power->displayBatteryPercentage = settings->displayBatteryPercentage; + view_port_update(power->battery_view_port); + } + } + free(settings); - view_port_update(power->battery_view_port); } // Check OTG status and disable it in case of fault diff --git a/applications/services/storage/storage.c b/applications/services/storage/storage.c index 1816bf921cc..d1564c8dbc5 100644 --- a/applications/services/storage/storage.c +++ b/applications/services/storage/storage.c @@ -6,6 +6,7 @@ #include "storages/storage_int.h" #include "storages/storage_ext.h" #include +#include #define STORAGE_TICK 1000 @@ -58,6 +59,9 @@ Storage* storage_app_alloc() { gui_add_view_port(gui, app->sd_gui.view_port, GuiLayerStatusBarLeft); furi_record_close(RECORD_GUI); + //Show Icon on Desktop + app->sd_gui.iconshow = false; + return app; } @@ -87,7 +91,7 @@ void storage_tick(Storage* app) { app->storage[ST_EXT].status == StorageStatusErrorInternal) && app->sd_gui.enabled == false) { app->sd_gui.enabled = true; - view_port_enabled_set(app->sd_gui.view_port, true); + view_port_enabled_set(app->sd_gui.view_port, app->sd_gui.iconshow); if(app->storage[ST_EXT].status == StorageStatusOK) { FURI_LOG_I(TAG, "SD card mount"); diff --git a/applications/services/storage/storage_i.h b/applications/services/storage/storage_i.h index 406fc921ef9..32e21a2df39 100644 --- a/applications/services/storage/storage_i.h +++ b/applications/services/storage/storage_i.h @@ -15,6 +15,7 @@ extern "C" { typedef struct { ViewPort* view_port; bool enabled; + bool iconshow; } StorageSDGui; struct Storage { diff --git a/applications/settings/application.fam b/applications/settings/application.fam index cc4b9703dcb..0d18c9d92ed 100644 --- a/applications/settings/application.fam +++ b/applications/settings/application.fam @@ -3,7 +3,7 @@ App( name="Basic settings apps bundle", apptype=FlipperAppType.METAPACKAGE, provides=[ - "passport", + "passport_settings", "system_settings", "about", ], diff --git a/applications/settings/desktop_settings/desktop_settings_app.c b/applications/settings/desktop_settings/desktop_settings_app.c index afb5d59ec69..965a16b1170 100644 --- a/applications/settings/desktop_settings/desktop_settings_app.c +++ b/applications/settings/desktop_settings/desktop_settings_app.c @@ -92,6 +92,8 @@ void desktop_settings_app_free(DesktopSettingsApp* app) { extern int32_t desktop_settings_app(void* p) { DesktopSettingsApp* app = desktop_settings_app_alloc(); DESKTOP_SETTINGS_LOAD(&app->settings); + bt_settings_load(&app->bt_settings); + if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) { scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); } else { diff --git a/applications/settings/desktop_settings/desktop_settings_app.h b/applications/settings/desktop_settings/desktop_settings_app.h index 6f97564c94d..baf718454e8 100644 --- a/applications/settings/desktop_settings/desktop_settings_app.h +++ b/applications/settings/desktop_settings/desktop_settings_app.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include "views/desktop_settings_view_pin_setup_howto.h" @@ -25,6 +26,7 @@ typedef enum { typedef struct { DesktopSettings settings; + BtSettings bt_settings; Gui* gui; DialogsApp* dialogs; diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 692b5f4fdef..120b14a6833 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -9,7 +9,10 @@ #define SCENE_EVENT_SELECT_PIN_SETUP 2 #define SCENE_EVENT_SELECT_AUTO_LOCK_DELAY 3 #define SCENE_EVENT_SELECT_BATTERY_DISPLAY 4 -#define SCENE_EVENT_SELECT_DUMBMODE 5 +#define SCENE_EVENT_SELECT_BT_ICON 5 +#define SCENE_EVENT_SELECT_SDCARD_ICON 6 +#define SCENE_EVENT_SELECT_TOP_BAR 7 +#define SCENE_EVENT_SELECT_DUMBMODE 8 #define AUTO_LOCK_DELAY_COUNT 9 const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { @@ -26,10 +29,10 @@ const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] = {0, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000}; -#define BATTERY_VIEW_COUNT 6 +#define BATTERY_VIEW_COUNT 7 const char* const battery_view_count_text[BATTERY_VIEW_COUNT] = - {"Bar", "%", "Inv. %", "Retro 3", "Retro 5", "Bar %"}; + {"Bar", "%", "Inv. %", "Retro 3", "Retro 5", "Bar %", "None"}; const uint32_t displayBatteryPercentage_value[BATTERY_VIEW_COUNT] = { DISPLAY_BATTERY_BAR, @@ -37,17 +40,28 @@ const uint32_t displayBatteryPercentage_value[BATTERY_VIEW_COUNT] = { DISPLAY_BATTERY_INVERTED_PERCENT, DISPLAY_BATTERY_RETRO_3, DISPLAY_BATTERY_RETRO_5, - DISPLAY_BATTERY_BAR_PERCENT}; + DISPLAY_BATTERY_BAR_PERCENT, + DISPLAY_BATTERY_NONE}; uint8_t origBattDisp_value = 0; -#define DUMBMODE_COUNT 2 -const char* const dumbmode_text[DUMBMODE_COUNT] = { +#define DESKTOP_ON_OFF_COUNT 2 + +const char* const desktop_on_off_text[DESKTOP_ON_OFF_COUNT] = { "OFF", "ON", }; -const uint32_t dumbmode_value[DUMBMODE_COUNT] = {0, 1}; +const uint32_t bticon_value[DESKTOP_ON_OFF_COUNT] = {false, true}; +uint8_t origBTIcon_value = true; + +const uint32_t sdcard_value[DESKTOP_ON_OFF_COUNT] = {false, true}; +uint8_t origSDCard_value = true; + +const uint32_t topbar_value[DESKTOP_ON_OFF_COUNT] = {false, true}; +uint8_t origTopBar_value = true; + +const uint32_t dumbmode_value[DESKTOP_ON_OFF_COUNT] = {false, true}; static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; @@ -70,11 +84,35 @@ static void desktop_settings_scene_start_battery_view_changed(VariableItem* item app->settings.displayBatteryPercentage = index; } +static void desktop_settings_scene_start_bticon_changed(VariableItem* item) { + DesktopSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, desktop_on_off_text[index]); + app->bt_settings.iconshow = bticon_value[index]; +} + +static void desktop_settings_scene_start_sdcard_changed(VariableItem* item) { + DesktopSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, desktop_on_off_text[index]); + app->settings.sdcard = sdcard_value[index]; +} + +static void desktop_settings_scene_start_topbar_changed(VariableItem* item) { + DesktopSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, desktop_on_off_text[index]); + app->settings.top_bar = topbar_value[index]; +} + static void desktop_settings_scene_start_dumbmode_changed(VariableItem* item) { DesktopSettingsApp* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, dumbmode_text[index]); + variable_item_set_current_value_text(item, desktop_on_off_text[index]); app->settings.is_dumbmode = dumbmode_value[index]; } @@ -82,6 +120,9 @@ void desktop_settings_scene_start_on_enter(void* context) { DesktopSettingsApp* app = context; VariableItemList* variable_item_list = app->variable_item_list; origBattDisp_value = app->settings.displayBatteryPercentage; + origBTIcon_value = app->bt_settings.iconshow; + origTopBar_value = app->settings.top_bar; + origSDCard_value = app->settings.sdcard; VariableItem* item; uint8_t value_index; @@ -120,16 +161,51 @@ void desktop_settings_scene_start_on_enter(void* context) { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, battery_view_count_text[value_index]); + item = variable_item_list_add( + variable_item_list, + "BT Icon", + DESKTOP_ON_OFF_COUNT, + desktop_settings_scene_start_bticon_changed, + app); + + value_index = + value_index_uint32(app->bt_settings.iconshow, bticon_value, DESKTOP_ON_OFF_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, desktop_on_off_text[value_index]); + + item = variable_item_list_add( + variable_item_list, + "SD Card Icon", + DESKTOP_ON_OFF_COUNT, + desktop_settings_scene_start_sdcard_changed, + app); + + value_index = value_index_uint32(app->settings.sdcard, sdcard_value, DESKTOP_ON_OFF_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, desktop_on_off_text[value_index]); + + item = variable_item_list_add( + variable_item_list, + "Top Bar", + DESKTOP_ON_OFF_COUNT, + desktop_settings_scene_start_topbar_changed, + app); + + value_index = value_index_uint32(app->settings.top_bar, topbar_value, DESKTOP_ON_OFF_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, desktop_on_off_text[value_index]); + item = variable_item_list_add( variable_item_list, "Games Only", - DUMBMODE_COUNT, + DESKTOP_ON_OFF_COUNT, desktop_settings_scene_start_dumbmode_changed, app); - value_index = value_index_uint32(app->settings.is_dumbmode, dumbmode_value, DUMBMODE_COUNT); + value_index = + value_index_uint32(app->settings.is_dumbmode, dumbmode_value, DESKTOP_ON_OFF_COUNT); variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, dumbmode_text[value_index]); + variable_item_set_current_value_text(item, desktop_on_off_text[value_index]); variable_item_list_set_enter_callback( variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app); @@ -167,6 +243,15 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent sme) case SCENE_EVENT_SELECT_BATTERY_DISPLAY: consumed = true; break; + case SCENE_EVENT_SELECT_BT_ICON: + consumed = true; + break; + case SCENE_EVENT_SELECT_SDCARD_ICON: + consumed = true; + break; + case SCENE_EVENT_SELECT_TOP_BAR: + consumed = true; + break; case SCENE_EVENT_SELECT_DUMBMODE: consumed = true; break; @@ -179,8 +264,11 @@ void desktop_settings_scene_start_on_exit(void* context) { DesktopSettingsApp* app = context; variable_item_list_reset(app->variable_item_list); DESKTOP_SETTINGS_SAVE(&app->settings); + bt_settings_save(&app->bt_settings); - if(app->settings.displayBatteryPercentage != origBattDisp_value) { + if((app->settings.displayBatteryPercentage != origBattDisp_value) || + (app->bt_settings.iconshow != origBTIcon_value) || + (app->settings.sdcard != origSDCard_value) || (app->settings.top_bar != origTopBar_value)) { furi_hal_power_reset(); } } diff --git a/applications/settings/dolphin_passport/passport.c b/applications/settings/dolphin_passport/passport.c deleted file mode 100644 index de9009a5ed1..00000000000 --- a/applications/settings/dolphin_passport/passport.c +++ /dev/null @@ -1,328 +0,0 @@ -#include "assets_icons.h" -#include "dolphin/helpers/dolphin_state.h" -#include -#include -#include -#include -#include -#include "dolphin/dolphin.h" -#include "../desktop_settings/desktop_settings_app.h" -#include "math.h" - -#define MOODS_TOTAL 1 -#define BUTTHURT_MAX 14 - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef struct { - FuriMessageQueue* event_queue; - - Dolphin* dolphin; - DolphinStats stats; - - DesktopSettings* desktop_settings; - - uint8_t counter; -} Passport; - -static const Icon* const portrait_happy[7] = { - &I_passport_happy1_46x49, - &I_passport_happy2_46x49, - &I_passport_happy3_46x49, - &I_G0ku, - &I_g0ku_1, - &I_g0ku_2, - &I_g0ku_3}; -// static const Icon* const portrait_ok[MOODS_TOTAL] = { -// &I_passport_okay1_46x49, -// &I_passport_okay2_46x49, -// &I_passport_okay3_46x49}; -// static const Icon* const portrait_bad[MOODS_TOTAL] = { -// &I_passport_bad1_46x49, -// &I_passport_bad2_46x49, -// &I_passport_bad3_46x49}; - -// static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy, portrait_ok, portrait_bad}; -static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy}; - -static const char* const moods[16] = { - "Stoned", - "Baked", - "Ripped", - "Joyful", - "Happy", - "Satisfied", - "Relaxed", - "Nostalgic", - "Okay", - "Tired", - "Bored", - "Sad", - "Annoyed", - "Upset", - "Angry", - "Furious"}; - -static void input_callback(InputEvent* input, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeKey, .input = *input}; - furi_message_queue_put(event_queue, &event, 0); -} - -static void render_callback(Canvas* canvas, void* ctx) { - Passport* passport = ctx; - DolphinStats* stats = &passport->stats; - DesktopSettings* desktop_settings = passport->desktop_settings; - - char level_str[12]; - char xp_str[14]; - char mood_str[20]; - uint8_t mood = 0; - uint8_t moodStrIndex = stats->butthurt; - if(desktop_settings->is_dumbmode) moodStrIndex = moodStrIndex + 4; - snprintf(mood_str, 20, "Mood: %s", moods[moodStrIndex]); - mood = 0; // DONT NEED DIFFERENT PICS BASED ON MOOD - - // UNUSED(mood); - // UNUSED(portraits); - - //process XP values - double xp_progress; - int xp_fill; - uint32_t xp_to_levelup = dolphin_state_xp_to_levelup(stats->icounter); - uint32_t xp_above_last_levelup = dolphin_state_xp_above_last_levelup(stats->icounter); - uint32_t xp_for_current_level = xp_to_levelup + xp_above_last_levelup; - - //get percentage from remaining XP - if(stats->level == 30) { - xp_progress = 100; - } else { - xp_progress = round(((xp_above_last_levelup * 100) / xp_for_current_level)); - } - - //calc bar fill ratio - //default bar is 65px wide - xp_fill = (int)round((xp_progress / 100) * 65); - - // multipass - canvas_draw_icon(canvas, 0, 0, &I_passport_DB); - - // portrait - furi_assert((stats->level > 0) && (stats->level <= 30)); - uint16_t tmpLvl = 0; - if(stats->level > 10) tmpLvl = 1; - if(stats->level > 15) tmpLvl = 2; - if(stats->level > 18) tmpLvl = 3; - if(stats->level > 21) tmpLvl = 4; - if(stats->level > 24) tmpLvl = 5; - if(stats->level > 27) tmpLvl = 6; - canvas_draw_icon(canvas, 11, 2, portraits[mood][tmpLvl]); - - /*//Rabbit - if((passport->counter >= 1) && (passport->counter < 5)) - { - canvas_draw_icon(canvas, 11, 2, &I_rabbit_00); - } - else if((passport->counter >= 5) && (passport->counter < 10)) - { - canvas_draw_icon(canvas, 11, 2, &I_rabbit_01); - } - else if((passport->counter >= 10) && (passport->counter < 15)) - { - canvas_draw_icon(canvas, 11, 2, &I_rabbit_02); - } - else if((passport->counter >= 15) && (passport->counter < 20)) - { - canvas_draw_icon(canvas, 11, 2, &I_rabbit_03); - } - else if((passport->counter >= 20) && (passport->counter < 25)) - { - canvas_draw_icon(canvas, 11, 2, &I_rabbit_04); - } - else if((passport->counter >= 25) && (passport->counter < 30)) - { - canvas_draw_icon(canvas, 11, 2, &I_rabbit_05); - } - else if((passport->counter >= 30) && (passport->counter < 35)) - { - canvas_draw_icon(canvas, 11, 2, &I_rabbit_06); - } - else if((passport->counter >= 35) && (passport->counter < 40)) - { - canvas_draw_icon(canvas, 11, 2, &I_rabbit_07); - } - - passport->counter++; - - if(passport->counter == 41) - { - passport->counter = 1; - } - //Sonic - if((passport->counter >= 1) && (passport->counter < 2)) - { - canvas_draw_icon(canvas, 11, 2, &I_sonic_00); - } - else if((passport->counter >= 2) && (passport->counter < 3)) - { - canvas_draw_icon(canvas, 11, 2, &I_sonic_01); - } - else if((passport->counter >= 3) && (passport->counter < 4)) - { - canvas_draw_icon(canvas, 11, 2, &I_sonic_02); - } - else if((passport->counter >= 4) && (passport->counter < 5)) - { - canvas_draw_icon(canvas, 11, 2, &I_sonic_03); - } - else if((passport->counter >= 5) && (passport->counter < 6)) - { - canvas_draw_icon(canvas, 11, 2, &I_sonic_04); - } - else if((passport->counter >= 6) && (passport->counter < 7)) - { - canvas_draw_icon(canvas, 11, 2, &I_sonic_05); - } - else if((passport->counter >= 7) && (passport->counter < 8)) - { - canvas_draw_icon(canvas, 11, 2, &I_sonic_06); - } - else if((passport->counter >= 8) && (passport->counter < 9)) - { - canvas_draw_icon(canvas, 11, 2, &I_sonic_07); - } - - passport->counter++; - - if(passport->counter == 10) - { - passport->counter = 1; - } - - */ - - const char* my_name = furi_hal_version_get_name_ptr(); - snprintf(level_str, 12, "Level: %hu", stats->level); - snprintf(xp_str, 14, "%lu/%lu", xp_above_last_levelup, xp_for_current_level); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 58, 10, my_name ? my_name : "Unknown"); - canvas_draw_str(canvas, 58, 22, mood_str); - canvas_set_color(canvas, ColorBlack); - canvas_draw_str(canvas, 58, 34, level_str); - canvas_set_font(canvas, FontBatteryPercent); - - if(stats->level == 30) { - canvas_draw_str(canvas, 58, 42, "Max Level"); - } else { - canvas_draw_str(canvas, 58, 42, xp_str); - } - - canvas_set_font(canvas, FontSecondary); - - //old code - /* - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 123 - xp_progress, 45, xp_progress + 1, 5); - canvas_set_color(canvas, ColorBlack); - canvas_draw_line(canvas, 123, 45, 123, 49); - */ - - //Round Edge - - //blank out background - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 58, 44, 67, 7); - - //draw black xp bar which will be used as outline but also for full bar - canvas_set_color(canvas, ColorBlack); - canvas_draw_rbox(canvas, 58, 45, 67, 6, 1); - - //hollow out xp bar with white "empty" space - canvas_set_color(canvas, ColorWhite); - canvas_draw_rbox(canvas, 59, 46, 65, 4, 1); - - //fill bar according to xp percentage - canvas_set_color(canvas, ColorBlack); - canvas_draw_rbox(canvas, 59, 46, xp_fill, 4, 1); -} - -Passport* passport_alloc() { - Passport* app = malloc(sizeof(Passport)); - - app->event_queue = furi_message_queue_alloc(10, sizeof(PluginEvent)); - app->counter = 0; - - return app; -} - -int32_t passport_app(void* p) { - UNUSED(p); - Passport* passport = passport_alloc(); - - ViewPort* view_port = view_port_alloc(); - - passport->dolphin = furi_record_open(RECORD_DOLPHIN); - passport->stats = dolphin_stats(passport->dolphin); - furi_record_close(RECORD_DOLPHIN); - - passport->desktop_settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(passport->desktop_settings); - - view_port_draw_callback_set(view_port, render_callback, passport); - view_port_input_callback_set(view_port, input_callback, passport->event_queue); - - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - view_port_update(view_port); - - PluginEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(passport->event_queue, &event, 10); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: - break; - case InputKeyLeft: - break; - case InputKeyOk: - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } - } - - view_port_update(view_port); - } - - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - view_port_free(view_port); - furi_message_queue_free(passport->event_queue); - furi_record_close(RECORD_GUI); - //furi_semaphore_free(semaphore); - free(passport); - - return 0; -} \ No newline at end of file diff --git a/applications/settings/dolphin_passport/application.fam b/applications/settings/passport_app/application.fam similarity index 54% rename from applications/settings/dolphin_passport/application.fam rename to applications/settings/passport_app/application.fam index 4167e9dcd59..716ab41d817 100644 --- a/applications/settings/dolphin_passport/application.fam +++ b/applications/settings/passport_app/application.fam @@ -1,7 +1,7 @@ App( - appid="passport", + appid="Passport", name="Passport", - apptype=FlipperAppType.SETTINGS, + apptype=FlipperAppType.EXTERNAL, entry_point="passport_app", cdefines=["APP_PASSPORT"], requires=[ @@ -10,4 +10,7 @@ App( ], stack_size=1 * 1024, order=60, + fap_icon="passport_10px.png", + fap_category="Main", + fap_icon_assets="assets_images", ) diff --git a/applications/settings/passport_app/assets_images/DrMario_backdrop_128x64.png b/applications/settings/passport_app/assets_images/DrMario_backdrop_128x64.png new file mode 100644 index 0000000000000000000000000000000000000000..486259b2596a5cd610219a0372fc2c813472f814 GIT binary patch literal 2920 zcmcImYitxn9N+Sg%CmwA2GlHDjbNPH_wDVpHG-`rMi~%)3Li`|tk3>I+h=zBJ4GEHyuwI7_DPj9!nt&jT*Gi6qI)-l_6+(Eyc zwlk}P)#>F1B83<U2BX zLOjfBF%cj^5Liu*VG~MO*?NGL1WDvY`cr@?8M0s~5?ehu>drGQqa(Gf>Wsc6xm*yq z2G19Z#aK~}5wD9EbzSELiI*fm5y0am3&Ieq18@okILXnL%Rmr;q+}$?P~(Ow0wG}t zLIs+pEHYsLuK}wWK{lkgA!&aD6VtZ(t_wAhVG*wYX^HIu?83b3bd|lO(?*-)2hc&d zEtTYGs4?3%4Fzd}oDfBzV;l#Hti%C?au#G|#Y%{Aq$5$QjZYEO6ShAbUzrLfLDWW6 zH$&5O4JnkFD%KIOpke|jnUGr3RY^<4u_{$^r_rqRY&siZeyG(jDwA52Oi4~a$pSPo z8EBe<0gPugV98=uLo&w5v^e&v-xiW5UYeM+=5ja{%9J!(ZJ)NTuR6Ip@y6;?-e$`z zG$0BmN|Hlild;KFKik99X>1Wy%ocN)8Xcwi6_`(~pa?zO+(m18U2^dw1@FV&(L+~N z$%^X<4d^n`08A(dKv_TlYoaR1koGtv_ z*{akA)BR8Q81201OSE^x4pk11?#w=$(|J3?)GcUBHD^jk2akO>{aLnQV*BMQZw_`2 z&U|g-i;EBLU75cBv9t9#0c;7yYI?dbsN4F@0+yqo4a=JicffX z^XKm$8f@tQ;_M8%vwgeqINx~c7iR7BGbb7AmOU499hWX_ewz8}x6;0M>T33fx$m5J z!29yVu`~8dz>t^r& UecKyNM?*VpOIM_JEm=SC7e@fE!2kdN literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_01.png b/applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_01.png new file mode 100644 index 0000000000000000000000000000000000000000..cb818233a3cce6cec258dadc624e4e7939370f7d GIT binary patch literal 1933 zcmcIlU1%Id9Nz{jHIfIb4{0A{*@7rIw=;XYz1?lE@sf+)p_j(=FexZFJ2QK?y9eq=YZN{iPP<78S@onR542?-mWWq!P? zYmAcK+F&NEwLGOnWi?h8ut*3)JySuI$2_X?b^Pdk?s*f~BO${v56hg_x|tg9vdCIG zh2(oDJ)iPMbYG&Vvw-Ds%(9BeS{gtEG@}eP8zLK;0Gc+0ZD>gp0>v@@H&_=K8)g0h z=G1fNHUlk{?4lpV*e9%*&niMx%JZo0!i+_txvMmEU%rPN=hHe7O(h0ycVKb47j5MYiL0z`}p(nNuu3gWX zsG@=~?Gj>8gn;29Ccp$#3R45WqR4-%8R0b^ zmN*qLPbbwZ*o7AbFA}Mn>+FvM>`-S^^W;|1*_b4?o>fSaWJZq+o&=@ zxSf=G7lWA_( z_5VeBC#fk%Gn=d8_407TzPgz_tnG}NoR{qiQ*SK3*0<}4YN2pmOnH6 H_K^y literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_02.png b/applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_02.png new file mode 100644 index 0000000000000000000000000000000000000000..f8811b57742007b05b723142510a6db691ed35f1 GIT binary patch literal 1947 zcmcIlU1%Id9KTkoZ9)+0gVm>Xn+J>T?e6UE?d_Vgq`BC{bkmTWZHkD_?#$k8?rvw@ z-Q+G&FjNbc2nE4DXs}fZf=vsBKG<4NAEZKsLLX9n@ImO4rD`jv=tKSQeOYS~L&0S~ zW@dl$`~UtQGjn)sbazkJqg|;~s%Lm8KMvnVl4tWqc#kY>RpGNG7&;K8Qr!+yw#)R24U9Sd!PNn*G)&uO6Y0TNQ==nMRr%ylQIgjM{{hB3N z!2m6JLvtaWm>VrPb7jXM{LZJjzPbqnRT^WiUak0%SF8I;*Hbb69PUr=($9yhf#5S9bb390G z`cMrzw0_iz6GTj`<3N#1UzQRsj})Fu7wYD6yDDCANwmo!=dA0&^gwIA&piu}V8rV{H}= zDQTH|e81-tR*QBdidqwB9>+AtL)H{Qk_Ds{BxEAZRH2(SC8-Iupb!X-@xQ?;U`#3V z4=^L1JG&mJWtqc%6l33^!}%N!qSBs6OjpllYy*-nXOJVPu1W;#Xu6=QhL%ODOJvn; z=z{rq=1eEyOXfH0mM{l6IuSB81S}bh1x3ynLRL|A!KN8oAXJm6Dk-{~G1_cCt&a)%a;sJGxJJ>L*hy+V$2&=qDdAhg-b&G1m(C__ ztwe!zjpR3B5p&}j4rzZ8BK@DmC9Wnu!ZT}2r&)>GF3t#ux|(1ZDiUzUCIT`LAxLx8 zEY;ht|1Z*8VRcH_FH+b!MgHEMSzi^emWR96)xG3lWoN`>zid{Rcz5wN{@t;+LLwVO zuwf_7&QSrK&S67+h*Jnh$;8ss&u|Q#9M1O_vX@T1)4z3I+I-)ixA$KEV&uIyHtjz5 z?FS>r=db^9dHE@(&>J89c;@xr$97yUzO{5UQ>6W8yLxXPU8tRZ_^~J6T>AKY&!vTp zM>ZWFdu87Pb4T9a_MDzO_Ulylt(h%{{POL?+ShV#q37bOyOf1vedBY>C%#1G2T}3R z&9~29{pQ;8neG?Azm@iW+c5v^3m1Or-Lq)@aAoS`Cm()(@GJGo>F&k)1+?(mfm7e% X6NPKfUqm;O<8yd$G=F;6O9%e~-gy9eq=YZN{iPP<78S@onR542?-mWWq!P? zYmAcK+F&NEwLGOnWi?h8ut*3)JySuI$2_X?b^Pdk?s*f~BO${v56hg_x|tg9vdCIG zh2(oDJ)iPMbYG&Vvw-Ds%(9BeS{gtEG@}eP8zLK;0Gc+0ZD>gp0>v@@H&_=K8)g0h z=G1fNHUlk{?4lpV*e9%*&niMx%JZo0!i+_txvMmEU%rPN=hHe7O(h0ycVKb47j5MYiL0z`}p(nNuu3gWX zsG@=~?Gj>8gn;29Ccp$#3R45WqR4-%8R0b^ zmN*qLPbbwZ*o7AbFA}Mn>+FvM>`-S^^W;|1*_b4?o>fSaWJZq+o&=@ zxSf=G7lWA_( z_5VeBC#fk%Gn=d8_407TzPgz_tnG}NoR{qiQ*SK3*0<}4YN2pmOnH6 H_K^y literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_04.png b/applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_04.png new file mode 100644 index 0000000000000000000000000000000000000000..b6d1fc78473d600d062634ad35eccdd5d8f04ff3 GIT binary patch literal 1944 zcmcIlTZr6L7>*aju5BN-XjOa&DR_aN$vra(GrO!aYj;?)uG4|tt%#nSoXo_Xvkm970gR7-^ei6 z9CXXG@vM2bfryuaHnDK3GJqk|jI4SxJyYUZj5oh>{@-h9a@OA4koFwqukEclC_Xw;WfEC@dmZh)4L{dRBi{DFX4#PLxjg0*pGMhjoE0h zHmHZSj;A)_aSeME7Exj1z*JBrF^Q^V9X|%22i^omKEyC4VVRIxKU33v7FLo|B76Ic z>)WIm-H|BjEx-jB;~Yn`CIdkPl3EsM)>K1KfRHf+p$j!>A=og6{|3v3svD~G4=}M^ zr@a}dX&Oa8ilL8iv5@1asFds426V8hC}{;CD+7U`D;c1R5(buxBqU^11O=<3i>@ya zR8PW}tnb#XO%UZ6M98q9B}g!%08O*fAfqZ8$OyIuY$uJ8Vk1q{#Xj3Tp-Z<8tX<5S zsIn=eB0HLjB?n~EiUZ_~A_7ZMRiKJkRYlQ}kV1KEWH==BAgvSEgB8pNeuZQIR+A?+ z5}L%OF_)8SrtH*<2{)ptYxnlYUi@%xRCC!*(HRgWwVvZpl4NXiy=ixi=xt7Cm$q5O zlyrmScVQ86;wB97ScOLVKZ}cBPkaO$8%xKUmWB|?K({Ov=vWbe?$86kffm$kRaR96 z^`c)E zI~fjI1$`Mb8|>3Kg|wAiP){DCZRl{ZFjmf-e)GA>;YD_9{@p)cuYa?6ly~o)6Srm$ zTv-13ME#Td_wjSTmA-mq6r4YI>*+1$zkee5edL!PKb+(ntE-P4eKpv>=l#-)?ve7B zkKQu$?8!r8!8_&U?DniPy|Vb4KeEdHI@LaN-}2j^Kl#x^!$+1D&+JZp{N7n*?%bgR z-|f83eE!r8Pt{d)^{J(3<%bVGeP;Xh4>U&3eyzJZW*&*ZICxd#jhR1Q*!h-L{&wlJ R;=ZJJ7RRRwD|bHl_+Qgrc=7-M literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_rate b/applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_rate new file mode 100644 index 00000000000..7813681f5b4 --- /dev/null +++ b/applications/settings/passport_app/assets_images/DrMario_blue_virus_25x25/frame_rate @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_01.png b/applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_01.png new file mode 100644 index 0000000000000000000000000000000000000000..6649b1b40a5be340bfe783397a758f3389c65fe5 GIT binary patch literal 1972 zcmcIlU1%Id96yWNniz!?N^PO6Tai{ew_mq+yX#$R%taIGB_Ta*QnYql!_&^)CW-z5ycc0MQpJD+{J z>E+s~N4P{(0!S1^E}=&WhO((xyEs{tB|&0$3`nw}h(=82Y8TJUdDt@g(vQ@Pv0jSL z2Z3t{La9`WmXs*eK0t4!0DJ|49)mvxb zWF;zbJNDZSrX_!8sHir9q+vi(Jj_I$7{Gsn6+>lU z@gHD{ZEIvL&`ieYa{K@~h;*e>JQEeQZEO(L#FE7X>84}>8OI1P3F}G{ic44{rV3F- z7n`4^XebO{IKNuAm?Fl}h>&5)s%9dh15H;HpplpfG*ux0nn<@aY{rqK)!BMHn=Kt! zxSlmsg&CumkaS2C8N^gE0rW&n1~86Hpr~v(9!rSWOz<2=hDE(1WOZT}VU7r{ljFI+ z)wI(B^)eK*m@8p5Gj`@hr|q-Ujnvl1K61F$D%f15=nRO$T2JvPOftcIZP;EWdTY~J zr7h(NBV8r=RhUn$paebAmSd6r&*BnR67R#|)uk&M(c*Ff0TRb1u;MWbm=LN!kqFYT ztf{5~>#qMV(raNwdFbQ_+c^dP=ABtv6|a!F|lxwNxujk%>`p4(aO^qkVb{{&s)cWR3a*RLy!o-6-%lUELG`fYY*a)e-n zUz*N6bZIuXu=T$AZ!cZ`^WfD5{ezi#W4-lE-*n-L0#17Q|gt(p1F-Gr7#AGsnhdcW3KPZPx8}+zUR~GbblAVJ0~- z$!un(AXv80(h6#A3u_hUMIXGr_)u3+&?2&ERRl{ZXpue?p#$E)hk_?_30imC(qWRE zoP7WHU%o$o4oy!z(cd@J$1qHPb}}Sw49$ z!`!xFi1&(b&ypqC=1`gSIb($R~ z4raGSB_4^Q$ZktVu?FRQOn;P>MOhLg`j7LH3}PaP%WUVzQFo4}gPF{Zjx&0va7E9v zfgt$4AN6BV;uHiaolXm)EXXoX5xiToJXqx|cWaj+gI(kpwr3EF4H#jbR6K>Fp|*1{ z?U2@TJ9VNJ6ROY_q^KC=)BKo2V%RV~Jg5-%rmB2`TWafugGKor|hl{SI~J@|ic3?$M( zPW}f>G()dl7pftk6UT(KN`?swSg@@^%bTi#tmS&pLO7dII2vlyFf@>oQ%FooF<#f9 z$m2v@=ks)fM@cOS6A;DaRHAF2A*d24*tOTFJ;E@d$2CMv^(3Db1N&4u&8HG_UW`FG zsbko+f66iFD+J3o&l4&H#z~ntD$!__V?qD6`Up%KE)}cRc_a4V=Q^vh!M0ilKooSh z!l6J`tZ|)fV~xt(SY~ZnzlbU6HRNu?T%vnEbns|_R`I&+B&-*_3m2~)`i+UYUg%df z-_3;HDJv>MtAOdO6u2N6As8xcQG~1YYCZec0P4c&R122jJf%0`M8+1ScIdo)5B>HB zoz*{NGo!iGi^qis@_uT__{&e=OfnMKh3~#`n-9M|} zHE`-B{plTNF7LiH)NH)#$-Vw1Zg)gFVpP5=DA-?q{>%E#w@?4Q@2_{7b>V2?LeIr3 zZhz##gOx^n?tF7_>Fd|~1|RzNwDaq^$6jtMA1Hn2pF6d1;*)2;8Qx`^XZOAGv)+7I nEKM){vU2>#BWHe(U%2DM-Y=GV9ylC)yO`|6RObD$z5D+GMrA}< literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_03.png b/applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_03.png new file mode 100644 index 0000000000000000000000000000000000000000..6649b1b40a5be340bfe783397a758f3389c65fe5 GIT binary patch literal 1972 zcmcIlU1%Id96yWNniz!?N^PO6Tai{ew_mq+yX#$R%taIGB_Ta*QnYql!_&^)CW-z5ycc0MQpJD+{J z>E+s~N4P{(0!S1^E}=&WhO((xyEs{tB|&0$3`nw}h(=82Y8TJUdDt@g(vQ@Pv0jSL z2Z3t{La9`WmXs*eK0t4!0DJ|49)mvxb zWF;zbJNDZSrX_!8sHir9q+vi(Jj_I$7{Gsn6+>lU z@gHD{ZEIvL&`ieYa{K@~h;*e>JQEeQZEO(L#FE7X>84}>8OI1P3F}G{ic44{rV3F- z7n`4^XebO{IKNuAm?Fl}h>&5)s%9dh15H;HpplpfG*ux0nn<@aY{rqK)!BMHn=Kt! zxSlmsg&CumkaS2C8N^gE0rW&n1~86Hpr~v(9!rSWOz<2=hDE(1WOZT}VU7r{ljFI+ z)wI(B^)eK*m@8p5Gj`@hr|q-Ujnvl1K61F$D%f15=nRO$T2JvPOftcIZP;EWdTY~J zr7h(NBV8r=RhUn$paebAmSd6r&*BnR67R#|)uk&M(c*Ff0TRb1u;MWbm=LN!kqFYT ztf{5~>#qMV(raNwdFbQ_+c^dP=ABtv6|a!F|lxwNxujk%>`p4(aO^qkVb{{&s)cWR3a*RLy!o-6-%lUELG`fYY*a)e-n zUz*N6bZIuXu=T$AZ!cZ`^WfD5{ezi#W4-lE7Vg;UC(}q(Ne*s=t!hvZOMgb3Pun6-uxfhh0-{Y#u6YB8WmB2)db)SPEp+F*KJ)fjzC zvbi8|HJ&dPi_u~%O1vyDsH(~XkrzddA~=8231EqH{I(iH8vDqz-M}Ue6EZ@Bj0Z`U zO0D=%aO<>=UyT!u7+-=eFGNA;QyFNYI?f&U@@3;D;&C1quoL(cE7Y+xOuAl&FG^b| z)X{#>JwX*!eOnamXC__D4`QE;dkA+=P>XFfVQ!8D#Ltl>{HTAfd*f;;55s_X8A9^4 zObygn7%>(VnEN-`j!BAsduXM)0H7 ziUc`T79nQ<%K%V7zz{3GQ#FrxHr-G#e>rQY%A|}4!?-1xh{JJ9=2ReAoS~>Hr^H1A z#Goi!7_!Vic2guzJe`;{=CQDv%T=ZI*gj3&WOaWG;U}u2yv>vgNrNb?^(2eJBx94U zPTPyb>G~8^Xp1>aNw1Rp3d|=~P=p@t%+i=%v$*)B#QSjK>e2;ln2H>WbHI=#PC*jj z6lh7Dh!iXVHKu|Ds=2u0tO~ zS&{nV=Y`4Smz}N1?wCGx$BC}dEs?|h%NnE;%JE}cw=X~X7Cg{2It@PNR+M z1_Jx|_UWcWXOHSL8{Ti&_vzP{7}jdO$k<=@#PEzbvipsL-~D*;2Y%1y z*IVx!I(ESO{PuG@=CZ-7jY+5i9m literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_rate b/applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_rate new file mode 100644 index 00000000000..7813681f5b4 --- /dev/null +++ b/applications/settings/passport_app/assets_images/DrMario_red_virus_25x25/frame_rate @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_01.png b/applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_01.png new file mode 100644 index 0000000000000000000000000000000000000000..9e5f1a69cb514e14b6dbf9bc224b321eaef779c9 GIT binary patch literal 1939 zcmb_dU1%Id9A6bn(~yWQNLyOjZXj03-pfWsJXNrE(Pc zNKvZQYNDD zOaBYZEXS_j5o!@+v%tkXOOA_6RPnu1!2-S=S9+F51M_k~YB_)Z6QGjLgOgw%1#HJxFPWrrVkf(!h{yTT96pLLgHcrgeZd zY^k)p{)xchTL@P+&eKr{4Y3LfOlI*cC*%5U)DaqWLM~RlwIe3!bFERu5gVn0Fo~-> zE0I`MYDukWXN}CnZL#!9^@v zScfvOG*#9i2684tr~zzS)u7!DeNERhh)dY2)Qz~_N-HU2uSEG-sYn|S=I$zVJsob@ zN&jCkN_;{#D@?hy_!{5-ahh@=8&mv$`*xU}Q*L+`B29NT*K!};Tne2~9*vZt@FOU-{%KezPtpRXR8 z`ttnqKc&Aq|J`bT@xf=_fBWWc^V+I*N&oe&`}+5MaqRj?+&0IC^SRTHKl}3E;Ztw3 literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_02.png b/applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_02.png new file mode 100644 index 0000000000000000000000000000000000000000..1a76b3a0191b60c83f07782fb33c9cba19080749 GIT binary patch literal 1939 zcmcIlZD<@t7+wX%rp6yBR3loJjY4ZX`@Pu@d#!0Mnxk%v$w5>6z}cDEyES(^+ucp> z5=5*BVx>}o2#Qrv3R-IXAyP^ZBZ!LrQJbn@&{9zRS48}w6zlALS!)tQ!Q*y!cJ`U) zecq3m_nFa=d%C-B?&3JEyD*#|W6$2~y6$Rr-}`Kj&K?`0;r$86ZQPVyS8*@Bd=tlA z`$ABhNGIHT9Ym`l#MC2Vy&5qz$L-u*k06>PDesX|5axvQ3m*u4fOEn=!H)o=Y$5Y!^YXPB=8MLI++s&GK2htJIW8z znDC~k03^#YZ`vZkQ1vu_2d~PiA}Q>z14VT-+0j+L^%I!682ipx{_d7B_LdXMX&O0_ zRIAm*nkLe?Bq_FSOR_4dDqskZ%!DbdgD~l9GvrBv;vh-`8uA$<^ypNY6PVPd57nqc z8z!wdv4}}^7)gpKXFj!ouDdq0TJ4~dbZDAcY3W^&I4RCVL>eOror)0|nkHe|*EWVx zXKgeUR~nvTB#{cKGFZZdDIHT$nWi);(^dTFeC~J?IfF5QDUFMiR@#{wZL{#ICMx{a zeL;w6E!mbSYAqmnn39~pvZeu90jg1yRY$Q|;(%;9vfPBatPn6v;lIH;!>|B?&zEN}zL|Lup1e7J2V4*b~tPs8R>1@*0%7l@w zk^Cksp?+F}F&QYaNdISXNvnxZ;Pl$kRk`0+HO~iLzhVRE=_X)j3TCPDZ4DvY*G#YN z`u`%m6;@P+VTrJlQxdM+ne|oiYI(S9UtLKaR(3|p&dX+nNtYL2p9IfBfAa;t!wu)L8iP{)c|* zS=j$rU+>XBpTBK>$M^%^EC*W-Z=PRzefj9YU$=a9;fWsJXNrE(Pc zNKvZQYNDD zOaBYZEXS_j5o!@+v%tkXOOA_6RPnu1!2-S=S9+F51M_k~YB_)Z6QGjLgOgw%1#HJxFPWrrVkf(!h{yTT96pLLgHcrgeZd zY^k)p{)xchTL@P+&eKr{4Y3LfOlI*cC*%5U)DaqWLM~RlwIe3!bFERu5gVn0Fo~-> zE0I`MYDukWXN}CnZL#!9^@v zScfvOG*#9i2684tr~zzS)u7!DeNERhh)dY2)Qz~_N-HU2uSEG-sYn|S=I$zVJsob@ zN&jCkN_;{#D@?hy_!{5-ahh@=8&mv$`*xU}Q*L+`B29NT*K!};Tne2~9*vZt@FOU-{%KezPtpRXR8 z`ttnqKc&Aq|J`bT@xf=_fBWWc^V+I*N&oe&`}+5MaqRj?+&0IC^SRTHKl}3E;Ztw3 literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_04.png b/applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_04.png new file mode 100644 index 0000000000000000000000000000000000000000..ccd585f874ed615368dd9735ad571f69e5b0cbe1 GIT binary patch literal 1937 zcmcIlOKjXk7~T>UK_O73qO=Gh%e?^YtjDjl$IUiMvnkoq4Ix?41TM_Z%Ziky9XR<6cz z;3!I?(MUJ+G!H9^iV#wurf3=v2oNp!F>V4s+S6sov516j5WC!$5=LC&b8%J{QrkXw zL66ptI&l&aQ<^wX)HFH-UejiH{`Lr3xGys*;IyC!i|TnLyl$s#@%5;i)|{CH2- z7$v>6!CY8xc}j`G>dX_cNC;DVrh+Puc~s@=_|f~^^CoacLWW}=7CEnXGd0m=ku*K6 zN)I1(eaairBZ;EU0+z!u%gQ2aI)EzB%pw$7GabzU&~_kfLkpr1D30;J!G^$yEdK+{ zsasyy475;i@_rO!pRjx`D+^I+*QHLzwltDa%K#z-K}I)hfRMp}k)dT9LX(vA+wOK3mGNbCV*&02_Pe50%TF9mQ8}8rOFZ|PML=u7Ior!xWbgcugKEhYDRdS zhXqbW%=M(21-tNK%#B3q7CQT5ip_RLbysQ?or6hI>sgs3NoG{;OuK7DZ*w}^w2dkg zq#Go^4U2d=Zs3p&S45=$v$&M?#7B63W9djWOxrLSuvA1qiMB$_2+&{|=~j|@-Ripj zzew+dl~l1`VdCUe- zwF>dlYc|XmaSBB%xmTS$DcaCm`P^{PKJ|SO-SYyxd*#oe{(-(nKa(f!A3U4+a{R%= zvse38m$#m+pWd0?zVgzymwv9z$UEN7KQm>$QM~S5AA5Db@y&%p=rsJ}#MaD1?_aGP zzH;Tnckk^3^=l)w=Lasdg80;nx>0FD+l&wJ>|`tK~EAoH=&6@7(cANz=@aj_2Mz I`0Vk&0CgX26aWAK literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_rate b/applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_rate new file mode 100644 index 00000000000..7813681f5b4 --- /dev/null +++ b/applications/settings/passport_app/assets_images/DrMario_yellow_virus_25x25/frame_rate @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/applications/settings/passport_app/assets_images/G0ku.png b/applications/settings/passport_app/assets_images/G0ku.png new file mode 100644 index 0000000000000000000000000000000000000000..84389c4f4947f8df4841a39c8d2b48977bf37a19 GIT binary patch literal 1844 zcmcIle@xs|94`_QV4w-=n7W0gID=xZ?Ys8wTDg(q4&iVI3@#gPX!hE^yKA^>yS8u# zngy5ehZ51Ki3T+ilIb5Ti_t$e$D(l)r=Vsdj;L`l8e+^e8jYF8`Rnz#I~TJd|Jd}$ zd#|7O`F_4X`t75=-5s^nw^kDbQ5)@y^x>xmUtHyN_+uL{Vf|zyLsF1Z|J%4$RTI-B@IZAX~9C)6oo_bQz&+3_C#z zD_wITW0q)jyAUQEFeV30hV!tlOGRKTwmvkIDWPqreFR%6=)Eej9UnCj(}!$h*iumY z2-2O#qA^t|?KOw3bly`{VNe=nFwDlnxRNO|WjKbNGOpoA>2=8)Qwm!MI))WDjC3(k zy+sxh01rnt?a_4A$l7pIHC9A7S#f+S)szAV6fCw>}%=>B4%dxaykwHM<6cGsmMXHLFFsuy3b)scp5;3Np zq{x5NgpIUe#S9h4-0M~|X2)K1YBo;YXyNp@C!lZ;fVu&iAr zdK=TZMw?9`OuA0;*I>4haI(-sp(KvXGUw!+@If5vwi$+56fz#)o3)L-< zmEkx3I(#|%;%@Hi#?aEK_A@K~vhx1_Gi1Ge6%j**h5h zV6wJ}yuJ;lF8036?=FA)>?b4Kp(d(Q?0R$I)4i*6AlUPL^XiYQe^xGbZN9zgl-%;m zab|Jp(!pN`pWk|6=#E9c{_&dT{>g=%6{~Gi%g-*Q_MN-w%s0EH$%nr@&4-Q!H&xu$ zBUF!Ut9tC)hAn%imILXpUai|T@zO2vrr%Rk1isU7v$bRKqN)rPx#1ZP1_K>z@;j|==^1poj7%}`8KMgEE`>VGKPcP8e2C>{_6CKLx;G7zm^9`}YT zTQU#;001=|39nxsy=Nf;0RRO90gOx-4hRAW1Od`=B*ttay=EcQb0tV83}Q7AyJjFD z5e5tf0%tf9*>)y-Llp-E0o-^d@`Ng1GY}XJ1ixq@gGU#WP#OG*EN?v%1Ofp`C=DnU z2l|LBJ|YY1e<|^UDwR3%5SdMDO&C2~F# z^MopqPZ>WV3mOgt6AA+-6$g+`866M>P%94YfhkBQ4Ky4H0|5a2i7cR396lin0RaGC zG!P>b24gl6$800GWFSi^4FduJVKou?hb#SxEPzE84F>`S0|5{S19d+X^@S?qd?z;^ z3WZ1)2?YWS2Lf0y5AJ~};d&=VCJg6(C=dw)vtb{BMi$+8CRs5L91jI57YF!nAPUQFBWO7iEf@%&Rvgc8B)VlFS1%8ZO&E$x7`|sA4hI4j z3Z!Ps9PP(ZzI)oCG3DHu3sM2b0xfHAm@E3^n@y*SRAHW9o~2*$!#ObZX<$6 z7o}Pqp;sKyaU}49DkT&Kw__l=Wgu!g65@L&mr@#YKNK4e1;uM3hDjHhQyQvV9kpT~ z3I+mgI};NN18zJMwqqdcfGHOY1S=N@&Tu3$8wrn2859cy5()zq3VGd00W&#L_t(YOO2KN zLsL~4$Dd>>J%Gr__i&QH8cq1(BAi7~l{H6ERS+1Ya7N#)}{-X{;;= z(KI3`&1octilEsW6)9>je}m_o`wX^mmwtY@=RD8%!`<1v=L{IaBg1I&aJVRjj~MAn z#Y6BYBD%R#@nAegG2e4ERS(9C>8SLk$|;YH88eoTHQ&r0a5 zFiPZkio5~BXHz1>99;xigXk%9Br>hrrePQWZ1HB5rsopOo|P@ z;grenEI^DphD0l|OOzBl5*Ht@z~|x<63HZ;v`&(I4Q*BVK%Avq&+9U}XK z@Bqxp&UqcD`9N+irZatg<{KVlS=o@s?-RXIlkd3+--H63n+k=S^P{)$HlkvyFNs7^ z<~GE)bmQLMj#v!EDJ2k~+A$(xCzsuJsmZdzb@w}HDt)(b&wG1Ii$|yJd%tXBPQebu z@`_3_9M~UQRjofzQ|TXg@X+eRwI*%Uh7Xh`Eu}IXIr?Fp`J?KOj~V?60LJ>U1Nlh= zWkc~-qT*8*m-@6?C=1Ck#KAwX(S3-z4yRco`lEfK!{2F_GKYspz^%Te>~Ig2*wwB@|V1pwU? zZ#bnsX0gcaE_P0r<0$6>qjFdA3g{E0-) zS@X|aX6Wa)^M>(a#xEux_B>na*p3WkL6%u3RK{*`XTiGS1x1Ct*Z3>D{MJ-&Hejz5 zDKF3A0kp?Swcz(y(Sz0^e*GhtwFb`kpC|Zh>$5xan$4a3$+flt)b?q3=P%Lcc$Kq% zV7Jivc@mzt^ZWbnjPJiYRg`uaz&)BdA#U*I4DhgBxeO_GIsDB(&hQVFL+HIJ)=%_; z7?v5tAj`ir3MAbbhX2?%r#WM#Rk!>41F)`L;Dz@AV?*_!)J6g900000NkvXXu0mjf Ds9?RY literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/g0ku_2.png b/applications/settings/passport_app/assets_images/g0ku_2.png new file mode 100644 index 0000000000000000000000000000000000000000..202353bb9ef5d2be128a083c5dd120418452fa21 GIT binary patch literal 1700 zcmV;V23z@wP)Px#1ZP1_K>z@;j|==^1poj6+E7eXMgEE`8V&^giY(}UC>RX{_=hV1008!eEBuKp z(sCpx6$jCABs?Gr>wqZ+0|68Z0}~4a?0_i@1_I@LC?FCB0s#QRY9iWpCLj?8C>95| zWFQ$11SAs%;(I4OAq(n%Dd&DD^@S=l90>#h0rG?@VGKrhAa7pE7o)+*>)x`83@X5Bj$Z5<9jFJdM6MG z1JrXR_Ju1e7Y92a3Lg;#+IJ?)ZX^4ME3#o9-gzd$X(IWEE6;EwE*S^|0suH33czR~ z$ZaDn7zoX8Bg1MU#A+fB2m|ebDHjX`1p)yc5CsDP0Iy#j;Cd%XC=E_34F?1P-gqVz z3j`?_2N4Ma91jKih%8Jg4Zmn1!f7JqeJBG00SpHM000SaNLh0L01m?d01m?e z$8V@)000D2Nkl~_I>V>z6*?QWAzEGkw^x4CKMh=jDD zun{toinJ0eh@_ITOtG>b6#cI~@40ufw4o0l?z#7Uzn^p7bIyC-GwQ5>-#(Utp{`KS ze}4>xnOXDScbC4Wn`kfakfHmg4hn|DL_HCc!cQ|c}S-_ce z4oy0rKEgvpN7G&W3_Y7|!-GjY2H75dj-P*Fq(Conz@e9Dl#4{ih6^Kw;p6s5$z!3U zj9QQ|*p--i5dfO9;03Nwh1vE|(TQq}PM+eIomT{ZHE^2iDd1!L+W3$STu;588czq# z__*|Fdy@mMVGvVHNi`mDNQX~C_N4HNOYX#d+-=7vBd*ql*Db**Z@pnzhddlht?1%e zyq+`Z&EgTuvcyhgi9_a;l9+tFEXD*z_LajY(Oc%=RF8O0nJ3~s^|;^r^i;1H*?b%1 zI|rt!=4f;#j!d=B+bJ8tFuyCEq_J!T(oMEKBVyNwT$}Ay>}oh!_lCR_xr`^ia&0l% zJ2BC0?7bP9gU60txDcCfj?PTRJ zJhhMsYGBZi>}sq3V9w-^<`+Na%egC!T%JBD9}shTvBvx}si6S}NrgPPB|} zv}I&!!qzn8433oOT82Y(jX&4E$Y7vM#y5L&Le@&YXLfKRJA`0TT+rd&+11L*$|`@! z(}Gvm4)a%taP2zjYxAYGG7s_U3e2rgl)QxmF1w1}!)hUQFRvkg|64l4S?!>ND0n7A zLwKxn=4+U<{EenPP@;mRi^gT?=G$_)JW(=kpxG#u&hfIbQJVFk{|d)OrrIt!O`VjV zSwG6_O`WW+=69Z{Zx! zBy)GvxoM1YOz?3K@yTcfkcZ#TB~>^ChaxbmDwYMYvmM1^@rLpjS8F#d(v7*=c`L%! z55*rcAgD*M18ya2xV{ESR zr^5Xd^XfjX;WlaNmVjB+6Q!+b%7^OW{Hw5cOAm$q-d2UT%Ktb+h3$H1dTRpZV0+BN uRdV=cNhL6$EJ2d6%=if*dF|hPME?Q>XQb?U962oj0000Px#1ZP1_K>z@;j|==^1poj77Enx7MgEE`@`Ne?008`nECd1p?0_i-0|EGlEAWCU z8V&>q1OfAeDi#a`4hRCmY9c)$3fguiLL>_&6bBOu1J`vW=Y1&Xekc?R1U4NB-gqYa zi7eQ5CHaRd9}xv976&C11_1#8(sCs3fhqQeE987A0s#R1i7W>M0T2lT?SU!9Ya&M{ z483O|Arc1TdnfydE5m9cMkWjq2?Hz`2)!4dnYy?2^VI9S{ZSekjy)B|RYv@`EbXbS2hwCChFj z5()!29tt}k3btb)D;Eb(D-P;^C>sw2&2J+p76&gH2o47V+IJ==6$klNGA=% zY9c`-3(#>SIv@%z83-a11{n?n6$=F5dMDFzB*|?f_l7G&Bn%S^1IlhAF&hc*f+@sn zBCuc|MI{U*69xkT0Pcb*#%m(mcP7?#B{CZcI3EhlZzR)mCC6+cuU{VJeJDO63nUZ< z&v7I(90|T>Axg!OW&i zh+NEWe0i9>>?5~`{USFxpeH~_Fcf}h4JHpq)^-NhMWT^MnAQh3(8jLlrpV@~8Qs#& zJ&~AZ0|7SWZ{r*!N^lZC&?OQ}=1H6m7>e2(i^cjlWu^LKj|%-Uew??)Q(IEoC>`7W z1jqwBcDlJQo)Na!>v1sXVWk~kyS%&`wy$H)Zix4Y?L$KK5@*#J3OS(@<@NEtmW_Z3 z5BMOX!jr=zSdW^tm%7J_qnM8u(uKlP6C=a>3iPyM@7&Lm!~4e$gmDDtA+VzAYAy?d z(&(oUCuAas%4s3WGUlaFEGDy_$S8XF7#}x!4gAJvy8OIppP-C!vP?K7k2@)-8@d&}wN7#z;i$+l>ZVFl zowE28&uryc8uD)v@e9d~N$bU=NwKLko$j>#Tuy2=fQwQXgOVJ1hJWQyS+{tly8(8T~gMS-3#p-F=SHGC0k?>so^`ccQ%3nD+S)AKj z%+=qp7Z&U{v%MnXsQDI`O!JgwSz@p%52sk*U-4~9uM`vo5EtZRB6P>52hhXe@Nw>L zHobP%R_ZTRtJPVX-nQSV_VLKOyoYO=*^3RW-N_}TT>u9=C0v1iojW?J;mf}Fe3eBk z=UVhF{JtFug@$-$$-KgccnAx%mL%|i*&o2=t|l}+Fc?5o`vQT$RZ3hFfr9$dbOlKQ z*;EUs$kc6=F$wMW@MRjkeq$2Qe&n9X4v1Uy4R`TifYGu1EQkQ7sS4VcI@6;;IpX2KWU-`a2T1oy$3vBs8KkvVp)N;uSjsIy^37nHxLZV8#VFMYoU*j0qw>ke4{Y-ae zXYWu){+wODYy6U*Df=}2SN)o4?9%$Tm9EgeT<#uqpzWjk-^*R4lA-AG0<=-m^wx{0 zQGqe-*SXc>ew&~R6Y0@zP5*stegY7$Ox)k!Nh@P#HGNQ#+dWcwtPLMFEEk5Hcv$Fw z=L`lspy#}sB{rIA;0aZ|2IC&jvNvjBb;2WIx*uPr{uHmFJ9d;-{z&zJKEER_xNF0p zKVuu?J5VSzozhWN&xD++uF_EY6@&z+e-#`=X85nJUb@uRWm3VuG(s1n8zP5={CD_r zSJzzdpRO^k3iAS;##qD-92`_dsoqry-zubaIH~5Re*rCs*W?kt)OG*>002ovPDHLk FV1jdIP6+@2 literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/passport_background.png b/applications/settings/passport_app/assets_images/passport_background.png new file mode 100644 index 0000000000000000000000000000000000000000..16b96ced910713421ba237acf1bdbb2e0be75f22 GIT binary patch literal 4425 zcmc&&4R91!9luCJ%SUh=Wuy>fIVjT@_HOsR{Wb^QCrRNT4QI)lo>mt(*mVf2ZX_fwoZ#uVilbhOSRUPG8SR#z}P86e0yJ9XYvJp z^k(li@4f%~f4%?z_y50qt99kFx~a3LdOV)GmgYzsd4H39zj)gu^85B}TjS(aW4A2} zdG?>GKTig?bOhr;kLT&F)2^agGX7-iibRyWhlhtRUAiCB5FQ3T~YLBOBX+DRvF6>Y$?l7_e@5Q6f zdMQH>c-Qc8CY}r9PNR99g;%dznb6jCX|nEJx}>K9kPcN+6L+)9UcEvMl=<;0J&v6tvx!bx@wp+6#(I zN^Bz7)+{6E7-p7o*&@~Kb^>0aanY1auEINOm;6OM=g*^@pY<`WX$3-EtI*}Tt#m;H zUGw8K&fu(L6I!-HOS~12SI9?Xo5@tDZ7148G%6W5BDJ09%VB>Tw#{x!!_gihaY0!z z+iAns{WF2>guJpj*J(PY-D!^Egv#S9& zCD2J5R3WPsq!mrm-0;S_w=`{x5Frygiz3_JPE4FQM%Wk0Y%}HbA`1sQi08*oEB^!x zu~E<1W@s{xWx&cb17v}gIF6x_fJw;nFvVb;LV!bMH;iNkgbL4>v-hUVC~nd^QMLn< z(nfIhzhfA~%M1%yVw23%DZoKm0vt~x32OjB0Hsvrd@F{HhBW_2!!$G7gRQFI%OMMq zs*No>;7wU(hC;bq+RzG_>F>$vr6O3#dde}WDvXYn+0B!!+ekn2BVM*3StxrfR8dU zK@5dLB7|dZmLjo`$bldmlo&1|i7*(0EJJ=HVOa>mu_cev3aD6Su&C0U${?EM+*W|p za2m=`g0cX421sM-G&0+XobOGr6(NUptO8oVSf^#kkpPkqQC>$W0dhQMWONg35sOrf zB~2hE4GS&ur0A$B5Q!5+RT2a&t4O{HwmL_g$4CM#K#XZkCQX~lBcA4MPndzBTV=kU{d5;ols5w@iVcwtLg?; z$f)8hx!#cxLALVU(j8Uqr#MS0w?%HBO*x3k1^FK>kzk@Td|~^yAAOFR9__w7{A`~+ zujYw;_uhVHAUUIM{``dvOMDyuE+5GK`u3BPuhx35)UVin`NN^fr@p#J9XfvUM{i!8 zxB1}u;nxO}b&2=nT_3>5h9}+q$BRqnNKf`Z9JuwL=K4*2Cziil+e5#VyR!GCCk~#S z@?CTK=U;db>=dvwDY19Q#-AtflZdNp|J|lvdHQ0naQ6=gOQt@*FL?U7X!>Wh$px=8 z?jL;r)}Bj`Z#~kVX}xxO#yfQ<=j;-HYfoA_z_h$r_xfMcpB44Imy11-wo1}U-;Ia2Y+gv znRaA%;Mn(n{ATm}o_l5(^b literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/passport_happy1_46x49.png b/applications/settings/passport_app/assets_images/passport_happy1_46x49.png new file mode 100644 index 0000000000000000000000000000000000000000..7e5648364c1f6c9a23d4ca1b56519fb7a4de995d GIT binary patch literal 1237 zcmV;`1S00004XF*Lt006O% z3;baP0000WV@Og>004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv00G^K6QlqD00(qQO+^Rh2onYl3IxtstpET5x_VStbW&k=AaHVTW@&6?Aar?f zWgvKMZ~y=}jg?hVvfD5S{MRXZ1Q`&>$8jR-uQUDZ@wWm)M7gxV{3zO>N&BIsUb%^Zqa=A#+qK zo5p5)GshDFRpBI}Q+KI)jjmgChocWB^F=Cu`_=bQt`%kg8uLjUx*ZFT?TO?o3~U#A z*uz6=>o!^~LU1$Eq#?U5GJvP@qD5EP;k3A9@!}#^*hTq|M0gtROTlBL+omW7cY~$A zU2-c>5YlyPVrKqYT)8c>z#fJRAyLqb{F6Pf3z&#Gm>J1%B@)41a373O-0`A;4v~}S zC=406{)z$+&@8k3AaGxcBWTxP~<~DmE)L+@KH!5Z4o;6M}aDDzO_^4^<&~it^9B1dtxM|${U(w9H7!z{q*bUaHu%0W^U4at2y(U zU9EznBTs{4w6Ldmm-R7Muk^N@D@RuRz&nLfpLD(X6A|TGCL9Raev+Sa4qn7P-;5+s z1UwDUwNydC%`;0)mQaHGO$5&f{vrZuygZKB+;kv`6F*p2Gz4|BUwHSFB}X)Q9!-9XVF+AG7lGHACIUcPr%h z5S2gZ2AbSQJM%68008nyL_t&-(>2gNPQySD1>kYSpF}}Apus8WXz3<5;0W;zprb%! zmWBo)I057Cf`BkrI9TLQ_e*xAS1MVVqhX|=O@Gvb7`A?w-;iHj`VKZJs3W_Tn6 z;FD|uzhsxF$Ud+vU8K{ooB%y$k&a9}T0fFWrFBJ0U6f-{XLIL7Z*ycKdS8bDxkJwk z`Uby4S~SB1+r(gHk#Gl*r=zV%r8kcFyebGXKa2!97W;XQN$u-A@m+)QBc3nc+u62@ zG^hOKr3<43(~3=3YhFdBAw;eNEYh2C_^aOLHq)$C3HntbYx+4WjbSWWnpw>05UK#GA%GTEipM%Fg7|dG&(RbD=;uRFfhMI z+_?Y%03~!qSaf7zbY(hiZ)9m^c>ppnGBPbNI4v00004XF*Lt006O% z3;baP0000WV@Og>004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv00G^K6QlqD00(qQO+^Rh2onYl3v$8jR-uQUDZ@w%= ztNh@vM=yHS89k~mu72?rCe_88hp)ct5ZUMDa+xBKuWppI&}Kucji{#B+kGw8V+$xY zjm`FEjyDXdLP=gWtj{ul1V<4l6vf?4e$8buPHx$X(K&3JI>DSZYP;p$%+@v|H+4GuJ zt%9Q?PlKbiu%~#J_0d229p4zKvYoJ6Tlyx#mN5#`%VI1sY@f`GHnkr#2#nK20@ z0Z#)|Em;sy^Yl_PO9;XJMuKMqe<1-mULHqmZaR>}DL+_O6a;ayUYL8*amm&iJf#YG zifJbekz_6h*$N4jh?PvnDJi#$K<1}2s(c+%@7s<8^&vgoBge}9GAmEF8R92gNN&`_42k`#}QNbeVq97)vT`aBk({m= zIUsfoh0FZM^`6C(BCx@a-+LNm?w$1ND1S^lDnae#@QM4Vb?+8J)OyWK2~i^&468Uw zqi$M9s3X!E;ng+=K=?ee1wh4|%L#SMW?jg5RubkcV<4uq;nACp`<+$CP+e%jREAA~ z0~r)7c0r#H%wy2x*z-PRzVVm_=xv^?X~%3|wsaP@>fuCa|1RkRZEGFpmdTM5je$6) zu5g;u;0rh~Dif4ZMjk`63U2}b|NH~s)0TZ~US19W001R)MObuXVRU6WV{&C-bY%cC zFfuYNFgPtSIaDweFfckWF!8=L%K!iX8FWQhbW?9;ba!ELWdK2BZ(?O2No`?g ZWm08fWO;GPWjp`?002ovPDHLkV1nWP8#e#| literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/assets_images/passport_happy3_46x49.png b/applications/settings/passport_app/assets_images/passport_happy3_46x49.png new file mode 100644 index 0000000000000000000000000000000000000000..a4c6a7612e4fb90bab899b459a4994e1890e2fab GIT binary patch literal 1283 zcmV+e1^oJnP)00004XF*Lt006O% z3;baP0000WV@Og>004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv00G^K6QlqD00(qQO+^Rh2onYl4DGG_m;e9*yLwbubW&k=AaHVTW@&6?Aar?f zWgvKMZ~y=}jg?hVvfCgG{O1%s0+v9+$8m!B>r6j;{O*c4&xzC5X*|JLfV7fUBK`jP zEB)ZFc}sfN;mxxxrgpRHMY4%ib6aiKF0zl??KVUpU#(D5U2Ex@OZQw9dz-DPG~XNt ztNK>^QWTg!5t|cgRKghatQR#wFp^c^(Stv7R>g5AXn46(fqJ2k!+*>tGrSNFiIW zp0z?&6OJl2D>z)i5GoMU3!)2xcK~T3Kq6>Is1?x!yR{Wm6bQJKilqh#Dw?|>1y^8J z@y#k1RJWuz%Os|fn#R1}@ zR3c9?ZKNTB%w;EAA>konWunm~<#7?n_|&7)SCe|*HXG_wdbvmD%5j;c(`^R7=e^}J zFQW7Z(oUMxkERT*0003WNkl7} z3s_i2um}>9T^sGh7f|mJd;<5%bjH>q7qIY}m;=RIl5@vNBwsPV>SKn10%r!(2sw7>E7ZnA6Vz(H+hiQ^iF$4dxXtyJ@n+YoAB9 zIDrDD^*g1*SUaX^Nsh^+jDbcbHB--I^bJ&u_+W$)X2|CzF0BIp|NH|jjg-SdPpU2e z001R)MObuXVRU6WV{&C-bY%cCFfuYNFgPtSIaDweFfckWF!8=L%K!iX8FWQh tbW?9;ba!ELWdK2BZ(?O2No`?gWm08fWO;GPWjp`?002ovPDHLkV1gGaB2fSU literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/desktop/desktop_settings.h b/applications/settings/passport_app/desktop/desktop_settings.h new file mode 100644 index 00000000000..5524ab9f8ad --- /dev/null +++ b/applications/settings/passport_app/desktop/desktop_settings.h @@ -0,0 +1,70 @@ +#pragma once + +#include "desktop_settings_filename.h" + +#include +#include +#include +#include +#include + +#define DESKTOP_SETTINGS_VER (6) + +#define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME) +#define DESKTOP_SETTINGS_MAGIC (0x17) +#define PIN_MAX_LENGTH 12 + +#define DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG "run_pin_setup" + +#define DESKTOP_SETTINGS_SAVE(x) \ + saved_struct_save( \ + DESKTOP_SETTINGS_PATH, \ + (x), \ + sizeof(DesktopSettings), \ + DESKTOP_SETTINGS_MAGIC, \ + DESKTOP_SETTINGS_VER) + +#define DESKTOP_SETTINGS_LOAD(x) \ + saved_struct_load( \ + DESKTOP_SETTINGS_PATH, \ + (x), \ + sizeof(DesktopSettings), \ + DESKTOP_SETTINGS_MAGIC, \ + DESKTOP_SETTINGS_VER) + +#define MAX_PIN_SIZE 10 +#define MIN_PIN_SIZE 4 +#define MAX_APP_LENGTH 128 + +#define DISPLAY_BATTERY_BAR 0 +#define DISPLAY_BATTERY_PERCENT 1 +#define DISPLAY_BATTERY_INVERTED_PERCENT 2 +#define DISPLAY_BATTERY_RETRO_3 3 +#define DISPLAY_BATTERY_RETRO_5 4 +#define DISPLAY_BATTERY_BAR_PERCENT 5 +#define DISPLAY_BATTERY_NONE 6 + +#define FAP_LOADER_APP_NAME "Applications" + +typedef struct { + InputKey data[MAX_PIN_SIZE]; + uint8_t length; +} PinCode; + +typedef struct { + bool is_external; + char name_or_path[MAX_APP_LENGTH]; +} FavoriteApp; + +typedef struct { + FavoriteApp favorite_primary; + FavoriteApp favorite_secondary; + PinCode pin_code; + uint8_t is_locked; + uint32_t auto_lock_delay_ms; + uint8_t displayBatteryPercentage; + bool is_dumbmode; + uint8_t dummy_mode; + bool top_bar; + bool sdcard; +} DesktopSettings; diff --git a/applications/settings/passport_app/desktop/desktop_settings_filename.h b/applications/settings/passport_app/desktop/desktop_settings_filename.h new file mode 100644 index 00000000000..b9140f24cfc --- /dev/null +++ b/applications/settings/passport_app/desktop/desktop_settings_filename.h @@ -0,0 +1,3 @@ +#pragma once + +#define DESKTOP_SETTINGS_FILE_NAME ".desktop.settings" diff --git a/applications/settings/passport_app/dolphin/helpers/dolphin_deed.c b/applications/settings/passport_app/dolphin/helpers/dolphin_deed.c new file mode 100644 index 00000000000..89fc0416ced --- /dev/null +++ b/applications/settings/passport_app/dolphin/helpers/dolphin_deed.c @@ -0,0 +1,75 @@ +#include "dolphin_deed.h" +#include + +static const DolphinDeedWeight dolphin_deed_weights[] = { + {5, DolphinAppSubGhz}, // DolphinDeedSubGhzReceiverInfo + {15, DolphinAppSubGhz}, // DolphinDeedSubGhzSave + {5, DolphinAppSubGhz}, // DolphinDeedSubGhzRawRec + {10, DolphinAppSubGhz}, // DolphinDeedSubGhzAddManually + {10, DolphinAppSubGhz}, // DolphinDeedSubGhzSend + {5, DolphinAppSubGhz}, // DolphinDeedSubGhzFrequencyAnalyzer + + {5, DolphinAppRfid}, // DolphinDeedRfidRead + {15, DolphinAppRfid}, // DolphinDeedRfidReadSuccess + {15, DolphinAppRfid}, // DolphinDeedRfidSave + {10, DolphinAppRfid}, // DolphinDeedRfidEmulate + {10, DolphinAppRfid}, // DolphinDeedRfidAdd + + {5, DolphinAppNfc}, // DolphinDeedNfcRead + {15, DolphinAppNfc}, // DolphinDeedNfcReadSuccess + {5, DolphinAppNfc}, // DolphinDeedNfcSave + {5, DolphinAppNfc}, // DolphinDeedNfcDetectReader + {10, DolphinAppNfc}, // DolphinDeedNfcEmulate + {10, DolphinAppNfc}, // DolphinDeedNfcMfcAdd + {5, DolphinAppNfc}, // DolphinDeedNfcAddSave + {5, DolphinAppNfc}, // DolphinDeedNfcAddEmulate + + {5, DolphinAppIr}, // DolphinDeedIrSend + {15, DolphinAppIr}, // DolphinDeedIrLearnSuccess + {15, DolphinAppIr}, // DolphinDeedIrSave + + {5, DolphinAppIbutton}, // DolphinDeedIbuttonRead + {15, DolphinAppIbutton}, // DolphinDeedIbuttonReadSuccess + {15, DolphinAppIbutton}, // DolphinDeedIbuttonSave + {10, DolphinAppIbutton}, // DolphinDeedIbuttonEmulate + {10, DolphinAppIbutton}, // DolphinDeedIbuttonAdd + + {15, DolphinAppBadusb}, // DolphinDeedBadUsbPlayScript + {15, DolphinAppPlugin}, // DolphinDeedU2fAuthorized + + {5, DolphinAppPlugin}, // DolphinDeedGpioUartBridge + + {5, DolphinAppPlugin}, // DolphinDeedPluginStart + {5, DolphinAppPlugin}, // DolphinDeedPluginGameStart + {20, DolphinAppPlugin}, // DolphinDeedPluginGameWin +}; + +static uint8_t dolphin_deed_limits[] = { + 100, // DolphinAppSubGhz + 100, // DolphinAppRfid + 100, // DolphinAppNfc + 100, // DolphinAppIr + 100, // DolphinAppIbutton + 100, // DolphinAppBadusb + // 100, // DolphinAppU2f + // 100, // DolphinAppGpio + 200, // DolphinAppPlugin +}; + +_Static_assert(COUNT_OF(dolphin_deed_weights) == DolphinDeedMAX, "dolphin_deed_weights size error"); +_Static_assert(COUNT_OF(dolphin_deed_limits) == DolphinAppMAX, "dolphin_deed_limits size error"); + +uint8_t dolphin_deed_get_weight(DolphinDeed deed) { + furi_check(deed < DolphinDeedMAX); + return dolphin_deed_weights[deed].icounter; +} + +DolphinApp dolphin_deed_get_app(DolphinDeed deed) { + furi_check(deed < DolphinDeedMAX); + return dolphin_deed_weights[deed].app; +} + +uint8_t dolphin_deed_get_app_limit(DolphinApp app) { + furi_check(app < DolphinAppMAX); + return dolphin_deed_limits[app]; +} diff --git a/applications/settings/passport_app/dolphin/helpers/dolphin_deed.h b/applications/settings/passport_app/dolphin/helpers/dolphin_deed.h new file mode 100644 index 00000000000..c9cd18f316f --- /dev/null +++ b/applications/settings/passport_app/dolphin/helpers/dolphin_deed.h @@ -0,0 +1,84 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + DolphinAppSubGhz, + DolphinAppRfid, + DolphinAppNfc, + DolphinAppIr, + DolphinAppIbutton, + DolphinAppBadusb, + DolphinAppPlugin, + DolphinAppMAX, +} DolphinApp; + +typedef enum { + DolphinDeedSubGhzReceiverInfo, + DolphinDeedSubGhzSave, + DolphinDeedSubGhzRawRec, + DolphinDeedSubGhzAddManually, + DolphinDeedSubGhzSend, + DolphinDeedSubGhzFrequencyAnalyzer, + + DolphinDeedRfidRead, + DolphinDeedRfidReadSuccess, + DolphinDeedRfidSave, + DolphinDeedRfidEmulate, + DolphinDeedRfidAdd, + + DolphinDeedNfcRead, + DolphinDeedNfcReadSuccess, + DolphinDeedNfcSave, + DolphinDeedNfcDetectReader, + DolphinDeedNfcEmulate, + DolphinDeedNfcMfcAdd, + DolphinDeedNfcAddSave, + DolphinDeedNfcAddEmulate, + + DolphinDeedIrSend, + DolphinDeedIrLearnSuccess, + DolphinDeedIrSave, + + DolphinDeedIbuttonRead, + DolphinDeedIbuttonReadSuccess, + DolphinDeedIbuttonSave, + DolphinDeedIbuttonEmulate, + DolphinDeedIbuttonAdd, + + DolphinDeedBadUsbPlayScript, + + DolphinDeedU2fAuthorized, + DolphinDeedGpioUartBridge, + + DolphinDeedPluginStart, + DolphinDeedPluginGameStart, + DolphinDeedPluginGameWin, + + DolphinDeedMAX, + + DolphinDeedTestLeft, + DolphinDeedTestRight, +} DolphinDeed; + +typedef struct { + uint8_t icounter; + DolphinApp app; +} DolphinDeedWeight; + +typedef struct { + DolphinApp app; + uint8_t icounter_limit; +} DolphinDeedLimits; + +DolphinApp dolphin_deed_get_app(DolphinDeed deed); +uint8_t dolphin_deed_get_app_limit(DolphinApp app); +uint8_t dolphin_deed_get_weight(DolphinDeed deed); + +#ifdef __cplusplus +} +#endif diff --git a/applications/settings/passport_app/dolphin/helpers/dolphin_state.c b/applications/settings/passport_app/dolphin/helpers/dolphin_state.c new file mode 100644 index 00000000000..1c36319f2bd --- /dev/null +++ b/applications/settings/passport_app/dolphin/helpers/dolphin_state.c @@ -0,0 +1,245 @@ +#include "dolphin_state.h" +#include "dolphin/helpers/dolphin_deed.h" +#include "dolphin_state_filename.h" + +#include +#include +#include +#include +#include +#include + +#define TAG "DolphinState" + +#define DOLPHIN_STATE_PATH INT_PATH(DOLPHIN_STATE_FILE_NAME) +#define DOLPHIN_STATE_HEADER_MAGIC 0xD0 +#define DOLPHIN_STATE_HEADER_VERSION 0x01 + +/* +The way the math works: + +Current xp (icounter) is subtracted from the threshold (xp requirement for next level up) + +The array values in level_array result in the following XP requirements per level below: + +500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, +3000, 3250, 3500, 3750, 4000, 4250, 4500, 4750, 5000, 6000, +7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000, 15000 + +To change the level requirement, add the last level's value with the desired next level's value. +Ex: Level 1 is 0 - 500. Level 2 needs to be Level 1 + next desired XP value. + +Level 2 is calculated: +Previous Level's Required XP: 500 ++ +Desired Level XP: 750 += +Value in level_array: 1250 +*/ + +uint32_t level_array[29] = {500, 1250, 2250, 3500, 5000, 6750, 8750, 11000, + 13500, 16250, 19250, 22500, 26000, 29750, 33750, 38000, + 42500, 47250, 52250, 58250, 65250, 73250, 82250, 92250, + 103250, 115250, 128250, 142250, 157250}; + +/* +This calculates the size of an array. This is good as it's used for dynamic for loops below. Therefore, you can just add more values to level_array for more levels. +*/ +#define NUM(a) (sizeof(a) / sizeof(*a)) + +#define BUTTHURT_MAX 14 +#define BUTTHURT_MIN 0 + +DolphinState* dolphin_state_alloc() { + return malloc(sizeof(DolphinState)); +} + +int dolphin_state_max_level() { + return NUM(level_array) + 1; +} + +void dolphin_state_free(DolphinState* dolphin_state) { + free(dolphin_state); +} + +bool dolphin_state_save(DolphinState* dolphin_state) { + if(!dolphin_state->dirty) { + return true; + } + + bool result = saved_struct_save( + DOLPHIN_STATE_PATH, + &dolphin_state->data, + sizeof(DolphinStoreData), + DOLPHIN_STATE_HEADER_MAGIC, + DOLPHIN_STATE_HEADER_VERSION); + + if(result) { + FURI_LOG_I(TAG, "State saved"); + dolphin_state->dirty = false; + } else { + FURI_LOG_E(TAG, "Failed to save state"); + } + + return result; +} + +bool dolphin_state_load(DolphinState* dolphin_state) { + bool success = saved_struct_load( + DOLPHIN_STATE_PATH, + &dolphin_state->data, + sizeof(DolphinStoreData), + DOLPHIN_STATE_HEADER_MAGIC, + DOLPHIN_STATE_HEADER_VERSION); + + if(success) { + if((dolphin_state->data.butthurt > BUTTHURT_MAX) || + (dolphin_state->data.butthurt < BUTTHURT_MIN)) { + success = false; + } + } + + if(!success) { + FURI_LOG_W(TAG, "Reset dolphin-state"); + memset(dolphin_state, 0, sizeof(*dolphin_state)); + dolphin_state->dirty = true; + } + + return success; +} + +uint64_t dolphin_state_timestamp() { + FuriHalRtcDateTime datetime; + furi_hal_rtc_get_datetime(&datetime); + return furi_hal_rtc_datetime_to_timestamp(&datetime); +} + +bool dolphin_state_is_levelup(uint32_t icounter) { + for(int i = 0; i < NUM(level_array); i++) { + if((icounter == level_array[i])) { + return (icounter == level_array[i]); + } + } + return NUM(level_array) + 1; +} + +uint8_t dolphin_get_level(uint32_t icounter) { + for(int i = 0; i < NUM(level_array); i++) { + if(icounter <= level_array[i]) { + return i + 1; + } + } + return NUM(level_array) + 1; +} + +uint32_t dolphin_state_xp_above_last_levelup(uint32_t icounter) { + uint32_t threshold = 0; + for(int i = 0; i < NUM(level_array); i++) { + if(icounter <= level_array[0]) { + threshold = 0; + break; + } else if(icounter <= level_array[i]) { + threshold = level_array[i - 1]; + break; + } else { + threshold = level_array[NUM(level_array) - 1]; + } + } + return icounter - threshold; +} + +uint32_t dolphin_state_xp_to_levelup(uint32_t icounter) { + uint32_t threshold = 0; + for(int i = 0; i < NUM(level_array); i++) { + if(icounter <= level_array[i]) { + threshold = level_array[i]; + break; + } else { + threshold = (uint32_t)-1; + } + } + return threshold - icounter; +} + +void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) { + // Special case for testing + if(deed > DolphinDeedMAX) { + if(deed == DolphinDeedTestLeft) { + dolphin_state->data.butthurt = + CLAMP(dolphin_state->data.butthurt + 1, BUTTHURT_MAX, BUTTHURT_MIN); + if(dolphin_state->data.icounter > 0) dolphin_state->data.icounter--; + dolphin_state->data.timestamp = dolphin_state_timestamp(); + dolphin_state->dirty = true; + } else if(deed == DolphinDeedTestRight) { + dolphin_state->data.butthurt = BUTTHURT_MIN; + if(dolphin_state->data.icounter < UINT32_MAX) dolphin_state->data.icounter++; + dolphin_state->data.timestamp = dolphin_state_timestamp(); + dolphin_state->dirty = true; + } + return; + } + + DolphinApp app = dolphin_deed_get_app(deed); + int8_t weight_limit = + dolphin_deed_get_app_limit(app) - dolphin_state->data.icounter_daily_limit[app]; + uint8_t deed_weight = CLAMP(dolphin_deed_get_weight(deed), weight_limit, 0); + + uint32_t xp_to_levelup = dolphin_state_xp_to_levelup(dolphin_state->data.icounter); + if(xp_to_levelup) { + deed_weight = MIN(xp_to_levelup, deed_weight); + dolphin_state->data.icounter += deed_weight; + dolphin_state->data.icounter_daily_limit[app] += deed_weight; + } + + /* decrease butthurt: + * 0 deeds accumulating --> 0 butthurt + * +1....+15 deeds accumulating --> -1 butthurt + * +16...+30 deeds accumulating --> -1 butthurt + * +31...+45 deeds accumulating --> -1 butthurt + * +46...... deeds accumulating --> -1 butthurt + * -4 butthurt per day is maximum + * */ + uint8_t butthurt_icounter_level_old = dolphin_state->data.butthurt_daily_limit / 15 + + !!(dolphin_state->data.butthurt_daily_limit % 15); + dolphin_state->data.butthurt_daily_limit = + CLAMP(dolphin_state->data.butthurt_daily_limit + deed_weight, 46, 0); + uint8_t butthurt_icounter_level_new = dolphin_state->data.butthurt_daily_limit / 15 + + !!(dolphin_state->data.butthurt_daily_limit % 15); + int32_t new_butthurt = ((int32_t)dolphin_state->data.butthurt) - + (butthurt_icounter_level_old != butthurt_icounter_level_new); + new_butthurt = CLAMP(new_butthurt, BUTTHURT_MAX, BUTTHURT_MIN); + if(new_butthurt >= 7) new_butthurt = BUTTHURT_MIN; // FLIPPER STAYS HAPPY + dolphin_state->data.butthurt = new_butthurt; + dolphin_state->data.timestamp = dolphin_state_timestamp(); + dolphin_state->dirty = true; + + FURI_LOG_D( + TAG, + "icounter %lu, butthurt %ld", + dolphin_state->data.icounter, + dolphin_state->data.butthurt); +} + +void dolphin_state_butthurted(DolphinState* dolphin_state) { + if(dolphin_state->data.butthurt < BUTTHURT_MAX) { + dolphin_state->data.butthurt++; + dolphin_state->data.timestamp = dolphin_state_timestamp(); + dolphin_state->dirty = true; + } +} + +void dolphin_state_increase_level(DolphinState* dolphin_state) { + furi_assert(dolphin_state_is_levelup(dolphin_state->data.icounter)); + ++dolphin_state->data.icounter; + dolphin_state->dirty = true; +} + +void dolphin_state_clear_limits(DolphinState* dolphin_state) { + furi_assert(dolphin_state); + + for(int i = 0; i < DolphinAppMAX; ++i) { + dolphin_state->data.icounter_daily_limit[i] = 0; + } + dolphin_state->data.butthurt_daily_limit = 0; + dolphin_state->dirty = true; +} \ No newline at end of file diff --git a/applications/settings/passport_app/dolphin/helpers/dolphin_state.h b/applications/settings/passport_app/dolphin/helpers/dolphin_state.h new file mode 100644 index 00000000000..18ca9a49c95 --- /dev/null +++ b/applications/settings/passport_app/dolphin/helpers/dolphin_state.h @@ -0,0 +1,50 @@ +#pragma once + +#include "dolphin_deed.h" +#include +#include +#include + +typedef struct DolphinState DolphinState; +typedef struct { + uint8_t icounter_daily_limit[DolphinAppMAX]; + uint8_t butthurt_daily_limit; + + uint32_t flags; + uint32_t icounter; + int32_t butthurt; + uint64_t timestamp; +} DolphinStoreData; + +struct DolphinState { + DolphinStoreData data; + bool dirty; +}; + +DolphinState* dolphin_state_alloc(); + +void dolphin_state_free(DolphinState* dolphin_state); + +bool dolphin_state_save(DolphinState* dolphin_state); + +bool dolphin_state_load(DolphinState* dolphin_state); + +void dolphin_state_clear_limits(DolphinState* dolphin_state); + +uint64_t dolphin_state_timestamp(); + +int dolphin_state_max_level(); + +void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed); + +void dolphin_state_butthurted(DolphinState* dolphin_state); + +uint32_t dolphin_state_xp_to_levelup(uint32_t icounter); + +uint32_t dolphin_state_xp_above_last_levelup(uint32_t icounter); + +bool dolphin_state_is_levelup(uint32_t icounter); + +void dolphin_state_increase_level(DolphinState* dolphin_state); + +uint8_t dolphin_get_level(uint32_t icounter); diff --git a/applications/settings/passport_app/dolphin/helpers/dolphin_state_filename.h b/applications/settings/passport_app/dolphin/helpers/dolphin_state_filename.h new file mode 100644 index 00000000000..86822c0ac70 --- /dev/null +++ b/applications/settings/passport_app/dolphin/helpers/dolphin_state_filename.h @@ -0,0 +1,3 @@ +#pragma once + +#define DOLPHIN_STATE_FILE_NAME ".dolphin.state" diff --git a/applications/settings/passport_app/passport.c b/applications/settings/passport_app/passport.c new file mode 100644 index 00000000000..da9539e86a6 --- /dev/null +++ b/applications/settings/passport_app/passport.c @@ -0,0 +1,690 @@ +#include "passport.h" + +void passport_alloc(Passport* passport) { + furi_assert(passport); + + // Load Passport Settings + if(!(passport_settings_load(&passport->settings))) { + passport->settings.background = true; + passport->settings.image = true; + passport->settings.name = true; + passport->settings.mood = true; + passport->settings.level = true; + passport->settings.xp_text = true; + passport->settings.xp_mode = 0; + passport->settings.multipage = true; + passport_settings_save(&passport->settings); + } + + // Load Desktop Settings + DESKTOP_SETTINGS_LOAD(&passport->desktop_settings); + + //animations + if(passport->settings.multipage) { + animations[AniRedVirus] = icon_animation_alloc(&A_DrMario_red_virus_25x25); + animations[AniYelVirus] = icon_animation_alloc(&A_DrMario_yellow_virus_25x25); + animations[AniBluVirus] = icon_animation_alloc(&A_DrMario_blue_virus_25x25); + + icon_animation_start(animations[AniRedVirus]); + icon_animation_start(animations[AniYelVirus]); + icon_animation_start(animations[AniBluVirus]); + } + + //stats, xp, levels + passport->dolphin = furi_record_open(RECORD_DOLPHIN); + passport->stats = dolphin_stats(passport->dolphin); + furi_record_close(RECORD_DOLPHIN); + + DolphinStats* stats = &passport->stats; + + passport->max_level = dolphin_state_max_level(); + passport->tmpLvl = 0; + + //get XP + passport->xp_to_levelup = dolphin_state_xp_to_levelup(stats->icounter); + passport->xp_above_last_levelup = dolphin_state_xp_above_last_levelup(stats->icounter); + passport->xp_for_current_level = passport->xp_to_levelup + passport->xp_above_last_levelup; + + //get percentage from remaining XP + if(stats->level == passport->max_level) { + passport->xp_progress = 100; + } else { + passport->xp_progress = + round(((passport->xp_above_last_levelup * 100) / passport->xp_for_current_level)); + } + + //mood + passport->mood = 0; // DONT NEED DIFFERENT PICS BASED ON MOOD + passport->moodStrIndex = stats->butthurt; + + // set mood to "Happy" if dumbmode is enabled + if(passport->desktop_settings.is_dumbmode) passport->moodStrIndex = passport->moodStrIndex + 4; + + // portrait + furi_assert((stats->level > 0) && (stats->level <= passport->max_level)); + if(stats->level > 10) passport->tmpLvl = 1; + if(stats->level > 15) passport->tmpLvl = 2; + if(stats->level > 18) passport->tmpLvl = 3; + if(stats->level > 21) passport->tmpLvl = 4; + if(stats->level > 24) passport->tmpLvl = 5; + if(stats->level > 27) passport->tmpLvl = 6; + + //string variables set + //name + snprintf(passport->my_name, 8, "%s", furi_hal_version_get_name_ptr()); + //mood + snprintf(passport->mood_str, 20, "Mood: %s", moods[passport->moodStrIndex]); + //level + snprintf(passport->level_str, 12, "Level: %hu", stats->level); + + if(passport->settings.multipage) { + snprintf(passport->level_str1, 12, "%hu", stats->level); + } + + //determine whether to display XP stats or max level + if(stats->level == passport->max_level) { + //xp display for main passport view + snprintf(passport->xp_str, 14, "Max Level"); + + if(passport->settings.multipage) { + //xp display for Dr. Mario view + snprintf(passport->xp_str1, 7, "Max"); + snprintf(passport->xp_str2, 7, "Level"); + } + } else { + //xp display for main passport view + snprintf( + passport->xp_str, + 14, + "%lu/%lu", + passport->xp_above_last_levelup, + passport->xp_for_current_level); + + if(passport->settings.multipage) { + //xp display for Dr. Mario view + snprintf(passport->xp_str1, 7, "%lu", passport->xp_above_last_levelup); + snprintf(passport->xp_str2, 7, "%lu", passport->xp_for_current_level); + } + } + + //set first page shown + passport->page = Main; + + free(stats); +} + +static void render_callback(Canvas* const canvas, void* mutex) { + furi_assert(mutex); + + Passport* passport = acquire_mutex((ValueMutex*)mutex, 25); + + if(passport->page == Main) { + //calc bar fill ratio + //default bar is 65px wide + passport->xp_fill = (int)round((passport->xp_progress / 100) * 65); + + // draw background + if(passport->settings.background) { + canvas_draw_icon(canvas, 0, 0, &I_passport_background); + } + + // draw portrait + if(passport->settings.image) { + canvas_draw_icon(canvas, 11, 2, portrait[passport->tmpLvl]); + } + + //draw flipper info + canvas_set_font(canvas, FontSecondary); + //name + if(passport->settings.name) { + canvas_draw_str(canvas, 58, 10, passport->my_name ? passport->my_name : "Unknown"); + } + //mood + if(passport->settings.mood) { + canvas_draw_str(canvas, 58, 22, passport->mood_str); + } + //level + if(passport->settings.level) { + canvas_draw_str(canvas, 58, 34, passport->level_str); + } + + canvas_set_font(canvas, FontBatteryPercent); + + //xp stats + if(passport->settings.xp_text) { + canvas_draw_str(canvas, 58, 42, passport->xp_str); + } + + canvas_set_font(canvas, FontSecondary); + + //blank out background + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, 58, 44, 67, 7); + canvas_set_color(canvas, ColorBlack); + + char percent[5]; + + switch(passport->settings.xp_mode) { + case 0: + //Bar + //draw black xp bar which will be used as outline but also for full bar + canvas_draw_rbox(canvas, 58, 45, 67, 6, 1); + + //hollow out xp bar with white "empty" space + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 59, 46, 65, 4, 1); + + //fill bar according to xp percentage + if(passport->xp_fill >= 2) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 59, 46, passport->xp_fill, 4, 1); + } + break; + case 1: + //Percent + //draw black xp bar which will be used as outline but also for full bar + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 58, 44, 67, 8, 1); + + //hollow out xp bar with white "empty" space + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 59, 45, 65, 6, 1); + + //fill bar fully + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 59, 45, 65, 6, 1); + + //put percentage text + canvas_set_font(canvas, FontBatteryPercent); + canvas_set_color(canvas, ColorWhite); + + snprintf(percent, 5, "%d%%", (int)passport->xp_progress); + canvas_draw_str_aligned(canvas, 90, 45, AlignCenter, AlignTop, percent); + + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + break; + case 2: + //Inverted Percent + //draw black xp bar which will be used as outline but also for full bar + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 58, 44, 67, 8, 1); + + //hollow out xp bar with white "empty" space + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 59, 45, 65, 6, 1); + + //put percentage text + canvas_set_font(canvas, FontBatteryPercent); + canvas_set_color(canvas, ColorBlack); + + snprintf(percent, 5, "%d%%", (int)passport->xp_progress); + canvas_draw_str_aligned(canvas, 90, 45, AlignCenter, AlignTop, percent); + + canvas_set_font(canvas, FontSecondary); + break; + case 3: + //Retro 3 + //draw black xp bar which will be used as outline but also for full bar + canvas_draw_rbox(canvas, 58, 45, 67, 6, 1); + + //hollow out xp bar with white "empty" space + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 59, 46, 65, 4, 1); + + //create retro x3 look - outline + canvas_set_color(canvas, ColorBlack); + //first section + //no start - drawing end curve + canvas_draw_dot(canvas, 77, 46); + canvas_draw_dot(canvas, 78, 47); + canvas_draw_dot(canvas, 78, 48); + canvas_draw_dot(canvas, 77, 49); + //second section + //start curve + canvas_draw_dot(canvas, 81, 46); + canvas_draw_dot(canvas, 80, 47); + canvas_draw_dot(canvas, 80, 48); + canvas_draw_dot(canvas, 81, 49); + //end curve + canvas_draw_dot(canvas, 99, 46); + canvas_draw_dot(canvas, 100, 47); + canvas_draw_dot(canvas, 100, 48); + canvas_draw_dot(canvas, 99, 49); + //third section + //start curve (no end curve) + canvas_draw_dot(canvas, 103, 46); + canvas_draw_dot(canvas, 102, 47); + canvas_draw_dot(canvas, 102, 48); + canvas_draw_dot(canvas, 103, 49); + + //fill bar according to xp percentage + if(passport->xp_fill >= 2) { + canvas_draw_rbox(canvas, 59, 46, passport->xp_fill, 4, 1); + } + + //create retro x3 look - white parts after fill + canvas_set_color(canvas, ColorWhite); + //between first and second sections + canvas_draw_dot(canvas, 77, 45); + canvas_draw_dot(canvas, 78, 45); + canvas_draw_dot(canvas, 79, 45); + canvas_draw_dot(canvas, 80, 45); + canvas_draw_dot(canvas, 81, 45); + + canvas_draw_dot(canvas, 78, 46); + canvas_draw_dot(canvas, 79, 46); + canvas_draw_dot(canvas, 80, 46); + + canvas_draw_dot(canvas, 79, 47); + + canvas_draw_dot(canvas, 79, 48); + + canvas_draw_dot(canvas, 78, 49); + canvas_draw_dot(canvas, 79, 49); + canvas_draw_dot(canvas, 80, 49); + + canvas_draw_dot(canvas, 77, 50); + canvas_draw_dot(canvas, 78, 50); + canvas_draw_dot(canvas, 79, 50); + canvas_draw_dot(canvas, 80, 50); + canvas_draw_dot(canvas, 81, 50); + //between second and third sections + canvas_draw_dot(canvas, 99, 45); + canvas_draw_dot(canvas, 100, 45); + canvas_draw_dot(canvas, 101, 45); + canvas_draw_dot(canvas, 102, 45); + canvas_draw_dot(canvas, 103, 45); + + canvas_draw_dot(canvas, 100, 46); + canvas_draw_dot(canvas, 101, 46); + canvas_draw_dot(canvas, 102, 46); + + canvas_draw_dot(canvas, 101, 47); + + canvas_draw_dot(canvas, 101, 48); + + canvas_draw_dot(canvas, 100, 49); + canvas_draw_dot(canvas, 101, 49); + canvas_draw_dot(canvas, 102, 49); + + canvas_draw_dot(canvas, 99, 50); + canvas_draw_dot(canvas, 100, 50); + canvas_draw_dot(canvas, 101, 50); + canvas_draw_dot(canvas, 102, 50); + canvas_draw_dot(canvas, 103, 50); + break; + case 4: + //Retro 5 + //draw black xp bar which will be used as outline but also for full bar + canvas_draw_rbox(canvas, 58, 45, 67, 6, 1); + + //hollow out xp bar with white "empty" space + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 59, 46, 65, 4, 1); + + //create retro x5 look - outline + canvas_set_color(canvas, ColorBlack); + //first section + //no start - drawing end curve + canvas_draw_dot(canvas, 71, 46); + canvas_draw_dot(canvas, 72, 47); + canvas_draw_dot(canvas, 72, 48); + canvas_draw_dot(canvas, 71, 49); + //second section + //start curve + canvas_draw_dot(canvas, 75, 46); + canvas_draw_dot(canvas, 74, 47); + canvas_draw_dot(canvas, 74, 48); + canvas_draw_dot(canvas, 75, 49); + //end curve + canvas_draw_dot(canvas, 83, 46); + canvas_draw_dot(canvas, 84, 47); + canvas_draw_dot(canvas, 84, 48); + canvas_draw_dot(canvas, 83, 49); + //third section + //start curve + canvas_draw_dot(canvas, 87, 46); + canvas_draw_dot(canvas, 86, 47); + canvas_draw_dot(canvas, 86, 48); + canvas_draw_dot(canvas, 87, 49); + //end curve + canvas_draw_dot(canvas, 95, 46); + canvas_draw_dot(canvas, 96, 47); + canvas_draw_dot(canvas, 96, 48); + canvas_draw_dot(canvas, 95, 49); + //fourth section + //start curve + canvas_draw_dot(canvas, 99, 46); + canvas_draw_dot(canvas, 98, 47); + canvas_draw_dot(canvas, 98, 48); + canvas_draw_dot(canvas, 99, 49); + //end curve + canvas_draw_dot(canvas, 107, 46); + canvas_draw_dot(canvas, 108, 47); + canvas_draw_dot(canvas, 108, 48); + canvas_draw_dot(canvas, 107, 49); + //fifth section + //start curve (no end curve) + canvas_draw_dot(canvas, 111, 46); + canvas_draw_dot(canvas, 110, 47); + canvas_draw_dot(canvas, 110, 48); + canvas_draw_dot(canvas, 111, 49); + + //fill bar according to xp percentage + if(passport->xp_fill >= 2) { + canvas_draw_rbox(canvas, 59, 46, passport->xp_fill, 4, 1); + } + + //create retro x3 look - white parts after fill + canvas_set_color(canvas, ColorWhite); + //between first and second sections + canvas_draw_dot(canvas, 71, 45); + canvas_draw_dot(canvas, 72, 45); + canvas_draw_dot(canvas, 73, 45); + canvas_draw_dot(canvas, 74, 45); + canvas_draw_dot(canvas, 75, 45); + + canvas_draw_dot(canvas, 72, 46); + canvas_draw_dot(canvas, 73, 46); + canvas_draw_dot(canvas, 74, 46); + + canvas_draw_dot(canvas, 73, 47); + + canvas_draw_dot(canvas, 73, 48); + + canvas_draw_dot(canvas, 72, 49); + canvas_draw_dot(canvas, 73, 49); + canvas_draw_dot(canvas, 74, 49); + + canvas_draw_dot(canvas, 71, 50); + canvas_draw_dot(canvas, 72, 50); + canvas_draw_dot(canvas, 73, 50); + canvas_draw_dot(canvas, 74, 50); + canvas_draw_dot(canvas, 75, 50); + //between second and third sections + canvas_draw_dot(canvas, 83, 45); + canvas_draw_dot(canvas, 84, 45); + canvas_draw_dot(canvas, 85, 45); + canvas_draw_dot(canvas, 86, 45); + canvas_draw_dot(canvas, 87, 45); + + canvas_draw_dot(canvas, 84, 46); + canvas_draw_dot(canvas, 85, 46); + canvas_draw_dot(canvas, 86, 46); + + canvas_draw_dot(canvas, 85, 47); + + canvas_draw_dot(canvas, 85, 48); + + canvas_draw_dot(canvas, 84, 49); + canvas_draw_dot(canvas, 85, 49); + canvas_draw_dot(canvas, 86, 49); + + canvas_draw_dot(canvas, 83, 50); + canvas_draw_dot(canvas, 84, 50); + canvas_draw_dot(canvas, 85, 50); + canvas_draw_dot(canvas, 86, 50); + canvas_draw_dot(canvas, 87, 50); + //between third and fourth sections + canvas_draw_dot(canvas, 95, 45); + canvas_draw_dot(canvas, 96, 45); + canvas_draw_dot(canvas, 97, 45); + canvas_draw_dot(canvas, 98, 45); + canvas_draw_dot(canvas, 99, 45); + + canvas_draw_dot(canvas, 96, 46); + canvas_draw_dot(canvas, 97, 46); + canvas_draw_dot(canvas, 98, 46); + + canvas_draw_dot(canvas, 97, 47); + + canvas_draw_dot(canvas, 97, 48); + + canvas_draw_dot(canvas, 96, 49); + canvas_draw_dot(canvas, 97, 49); + canvas_draw_dot(canvas, 98, 49); + + canvas_draw_dot(canvas, 95, 50); + canvas_draw_dot(canvas, 96, 50); + canvas_draw_dot(canvas, 97, 50); + canvas_draw_dot(canvas, 98, 50); + canvas_draw_dot(canvas, 99, 50); + //between fourth and fifth sections + canvas_draw_dot(canvas, 107, 45); + canvas_draw_dot(canvas, 108, 45); + canvas_draw_dot(canvas, 109, 45); + canvas_draw_dot(canvas, 110, 45); + canvas_draw_dot(canvas, 111, 45); + + canvas_draw_dot(canvas, 108, 46); + canvas_draw_dot(canvas, 109, 46); + canvas_draw_dot(canvas, 110, 46); + + canvas_draw_dot(canvas, 109, 47); + + canvas_draw_dot(canvas, 109, 48); + + canvas_draw_dot(canvas, 108, 49); + canvas_draw_dot(canvas, 109, 49); + canvas_draw_dot(canvas, 110, 49); + + canvas_draw_dot(canvas, 107, 50); + canvas_draw_dot(canvas, 108, 50); + canvas_draw_dot(canvas, 109, 50); + canvas_draw_dot(canvas, 110, 50); + canvas_draw_dot(canvas, 111, 50); + break; + case 5: + //Percent with Bar + //draw black xp bar which will be used as outline but also for full bar + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 58, 44, 67, 8, 1); + + //hollow out xp bar with white "empty" space + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 59, 45, 65, 6, 1); + + //fill bar according to xp percentage + if(passport->xp_fill >= 2) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 59, 45, passport->xp_fill, 6, 1); + } + + //put percentage text + canvas_set_font(canvas, FontBatteryPercent); + + if(((int)passport->xp_progress >= 0) && ((int)passport->xp_progress <= 40)) { + canvas_set_color(canvas, ColorBlack); + snprintf(percent, 5, "%d%%", (int)passport->xp_progress); + canvas_draw_str_aligned(canvas, 90, 45, AlignCenter, AlignTop, percent); + } else if(((int)passport->xp_progress > 40) && ((int)passport->xp_progress <= 60)) { + canvas_set_color(canvas, ColorBlack); + snprintf(percent, 5, "%d%%", (int)passport->xp_progress); + canvas_draw_str_aligned(canvas, 112, 45, AlignCenter, AlignTop, percent); + } else { + canvas_set_color(canvas, ColorWhite); + snprintf(percent, 5, "%d%%", (int)passport->xp_progress); + canvas_draw_str_aligned(canvas, 90, 45, AlignCenter, AlignTop, percent); + canvas_set_color(canvas, ColorBlack); + } + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + break; + case 6: + //None + + break; + default: + //draw black xp bar which will be used as outline but also for full bar + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 58, 45, 67, 6, 1); + + //hollow out xp bar with white "empty" space + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 59, 46, 65, 4, 1); + + //fill bar according to xp percentage + if(passport->xp_fill >= 2) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 59, 46, passport->xp_fill, 4, 1); + } + break; + } + } else if(passport->page == DrMario) { + //calc bar fill ratio + //dr mario pill jar fill area is 50px tall + passport->xp_fill = (int)round((passport->xp_progress / 100) * 50); + + //backdrop + canvas_draw_icon(canvas, 0, 0, &I_DrMario_backdrop_128x64); + + //fill in stats + canvas_set_font(canvas, FontSecondary); + + // level + canvas_draw_str(canvas, 89, 50, "Level:"); + canvas_draw_str(canvas, 110, 58, passport->level_str1); + // xp + canvas_draw_str(canvas, 40, 44, "XP:"); + + canvas_set_font(canvas, FontBatteryPercent); + + if(strcmp(passport->xp_str1, "Max") == 0) { + canvas_draw_str_aligned(canvas, 60, 45, AlignCenter, AlignTop, passport->xp_str1); + canvas_draw_str_aligned(canvas, 60, 54, AlignCenter, AlignTop, passport->xp_str2); + } else { + canvas_draw_str_aligned(canvas, 60, 45, AlignCenter, AlignTop, passport->xp_str1); + canvas_draw_line(canvas, 45, 52, 75, 52); + canvas_draw_str_aligned(canvas, 60, 54, AlignCenter, AlignTop, passport->xp_str2); + } + + canvas_set_font(canvas, FontSecondary); + + //fill bar black + canvas_set_color(canvas, ColorBlack); + canvas_draw_box(canvas, 5, 9, 28, 50); + + //use white bar to fill based on xp_fill value + if(passport->xp_fill < 50) { + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, 5, 9, 28, 50 - passport->xp_fill); + } + + canvas_set_color(canvas, ColorBlack); + + //draw sprites + canvas_draw_icon_animation(canvas, 41, 3, animations[AniRedVirus]); + canvas_draw_icon_animation(canvas, 70, 3, animations[AniYelVirus]); + canvas_draw_icon_animation(canvas, 99, 3, animations[AniBluVirus]); + } + + release_mutex((ValueMutex*)mutex, passport); +} + +static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { + furi_assert(event_queue); + PassportEvent event = {.type = EventKeyPress, .input = *input_event}; + furi_message_queue_put(event_queue, &event, FuriWaitForever); +} + +void passport_free(Passport* passport) { + furi_assert(passport); + + //stop and clear animations + if(passport->settings.multipage) { + icon_animation_stop(animations[AniRedVirus]); + icon_animation_free(animations[AniRedVirus]); + icon_animation_stop(animations[AniYelVirus]); + icon_animation_free(animations[AniYelVirus]); + icon_animation_stop(animations[AniBluVirus]); + icon_animation_free(animations[AniBluVirus]); + } + + free(passport); +} + +int32_t passport_app(void* p) { + UNUSED(p); + FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PassportEvent)); + + Passport* passport = malloc(sizeof(Passport)); + + ValueMutex state_mutex; + if(!init_mutex(&state_mutex, passport, sizeof(Passport))) { + passport_free(passport); + return 1; + } + + passport_alloc(passport); + + ViewPort* view_port = view_port_alloc(); + view_port_draw_callback_set(view_port, render_callback, &state_mutex); + view_port_input_callback_set(view_port, input_callback, event_queue); + + Gui* gui = furi_record_open("gui"); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + PassportEvent event = {0}; + + while(event.input.key != InputKeyBack) { + if(furi_message_queue_get(event_queue, &event, 10) != FuriStatusOk) { + continue; + } + + passport = (Passport*)acquire_mutex_block(&state_mutex); + + if(event.type == EventKeyPress) { + switch(event.input.key) { + case InputKeyUp: + break; + case InputKeyDown: + break; + case InputKeyRight: + if(passport->settings.multipage) { + switch(passport->page) { + case Main: + passport->page = DrMario; + break; + case DrMario: + passport->page = Main; + break; + default: + break; + } + } + break; + case InputKeyLeft: + if(passport->settings.multipage) { + switch(passport->page) { + case Main: + passport->page = DrMario; + break; + case DrMario: + passport->page = Main; + break; + default: + break; + } + } + break; + case InputKeyOk: + break; + default: + break; + } + } + release_mutex(&state_mutex, passport); + view_port_update(view_port); + } + + gui_remove_view_port(gui, view_port); + furi_record_close(RECORD_GUI); + view_port_free(view_port); + gui = NULL; + furi_message_queue_free(event_queue); + + passport_free(passport); + + return 0; +} \ No newline at end of file diff --git a/applications/settings/passport_app/passport.h b/applications/settings/passport_app/passport.h new file mode 100644 index 00000000000..def583f4734 --- /dev/null +++ b/applications/settings/passport_app/passport.h @@ -0,0 +1,107 @@ +#pragma once + +#include "Passport_icons.h" +#include +#include +#include +#include +#include +#include +#include +#include "dolphin/dolphin.h" +#include "dolphin/helpers/dolphin_state.h" +#include "desktop/desktop_settings.h" +#include "passport_settings/passport_settings.h" +#include "math.h" + +#define MOODS_TOTAL 1 +#define BUTTHURT_MAX 14 + +typedef enum { + AniRedVirus, + AniYelVirus, + AniBluVirus, +} Animations; + +static IconAnimation* animations[3]; + +typedef enum { EventGameTick, EventKeyPress } EventType; + +typedef struct { + EventType type; + InputEvent input; +} PassportEvent; + +typedef enum { + Main, + DrMario, +} Pages; + +static const Icon* const portrait[7] = { + &I_passport_happy1_46x49, + &I_passport_happy2_46x49, + &I_passport_happy3_46x49, + &I_G0ku, + &I_g0ku_1, + &I_g0ku_2, + &I_g0ku_3}; +// static const Icon* const portrait_ok[MOODS_TOTAL] = { +// &I_passport_okay1_46x49, +// &I_passport_okay2_46x49, +// &I_passport_okay3_46x49}; +// static const Icon* const portrait_bad[MOODS_TOTAL] = { +// &I_passport_bad1_46x49, +// &I_passport_bad2_46x49, +// &I_passport_bad3_46x49}; + +// static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy, portrait_ok, portrait_bad}; +//static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy}; + +static const char* const moods[16] = { + "Stoned", + "Baked", + "Ripped", + "Joyful", + "Happy", + "Satisfied", + "Relaxed", + "Nostalgic", + "Okay", + "Tired", + "Bored", + "Sad", + "Annoyed", + "Upset", + "Angry", + "Furious"}; + +typedef struct { + Dolphin* dolphin; + DolphinStats stats; + + DesktopSettings desktop_settings; + PassportSettings settings; + + Pages page; + + uint32_t xp_to_levelup; + uint32_t xp_above_last_levelup; + uint32_t xp_for_current_level; + char xp_str[14]; + char xp_str1[7]; + char xp_str2[7]; + double xp_progress; + int xp_fill; + + int max_level; + uint16_t tmpLvl; + char level_str[12]; + char level_str1[12]; + + char my_name[8]; + + char mood_str[20]; + uint8_t mood; + uint8_t moodStrIndex; + char dumbmode_mood[20]; +} Passport; \ No newline at end of file diff --git a/applications/settings/passport_app/passport_10px.png b/applications/settings/passport_app/passport_10px.png new file mode 100644 index 0000000000000000000000000000000000000000..9c5458ca126cb48827e8fb7d768cbf64a3cf1de3 GIT binary patch literal 1811 zcmb_dy^q{P6n7E{k&CVg6oDv`%2`G^G1E`RYKvbkbNEFcV?DZNFZ9a5j<+aD--}}AKdGCXr z;cM$_FRm$yvOd`E@4~ZMuRVJj?x%P5?!)73wtcHmlylEj|5M5*cP=Q(Gw;Wvy>c&j zoiLf`l*>@)^CSbbqFlK)&nVj$r5cKHoch}D_rBKDnETpIC%{3rDJJpuaV~Bg4@c~H zpLtxnc2&JHCqR&hlB)A$nigd4Yc(%{b+v71Y7Hs(eQl#ssO|+j>ZZ(v>gpz97-QA- zbit_=+R-bjg)P%C;p!mMA~q%+OKpA{sLOdocKfe3%HYk{CS{os!9y)I)2bJ6j7jweF5 zx0LToc2H$-DbGPZq{6XHParc4fyC&BewTqWHveG9G1oK@T5qy4$n6%bS$7(8rsR7dAbT+m4_84>Hl-as5<1L!iVo4+Wxp1=3g_xHcp|L(W^&X?zZSXa*e{p+QlFaG#hHMRy@!~W;j-+J#K D2Ff+C literal 0 HcmV?d00001 diff --git a/applications/settings/passport_app/passport_settings/passport_settings.c b/applications/settings/passport_app/passport_settings/passport_settings.c new file mode 100644 index 00000000000..88c96c1d703 --- /dev/null +++ b/applications/settings/passport_app/passport_settings/passport_settings.c @@ -0,0 +1,33 @@ +#include "passport_settings.h" + +#include "passport_settings_filename.h" + +#include +#include +#include + +#define PASSPORT_SETTINGS_PATH INT_PATH(PASSPORT_SETTINGS_FILE_NAME) +#define PASSPORT_SETTINGS_VERSION (4) +#define PASSPORT_SETTINGS_MAGIC (0x20) + +bool passport_settings_load(PassportSettings* passport_settings) { + furi_assert(passport_settings); + + return saved_struct_load( + PASSPORT_SETTINGS_PATH, + passport_settings, + sizeof(PassportSettings), + PASSPORT_SETTINGS_MAGIC, + PASSPORT_SETTINGS_VERSION); +} + +bool passport_settings_save(PassportSettings* passport_settings) { + furi_assert(passport_settings); + + return saved_struct_save( + PASSPORT_SETTINGS_PATH, + passport_settings, + sizeof(PassportSettings), + PASSPORT_SETTINGS_MAGIC, + PASSPORT_SETTINGS_VERSION); +} diff --git a/applications/settings/passport_app/passport_settings/passport_settings.h b/applications/settings/passport_app/passport_settings/passport_settings.h new file mode 100644 index 00000000000..27d7d162038 --- /dev/null +++ b/applications/settings/passport_app/passport_settings/passport_settings.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define XP_MODE_BAR 0 +#define XP_MODE_PERCENT 1 +#define XP_MODE_INVERTED_PERCENT 2 +#define XP_MODE_RETRO_3 3 +#define XP_MODE_RETRO_5 4 +#define XP_MODE_BAR_PERCENT 5 +#define XP_MODE_NONE 6 + +typedef struct { + bool background; + bool image; + bool name; + bool mood; + bool level; + bool xp_text; + uint8_t xp_mode; + bool multipage; +} PassportSettings; + +bool passport_settings_load(PassportSettings* passport_settings); + +bool passport_settings_save(PassportSettings* passport_settings); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/settings/passport_app/passport_settings/passport_settings_filename.h b/applications/settings/passport_app/passport_settings/passport_settings_filename.h new file mode 100644 index 00000000000..9cd0744b3ed --- /dev/null +++ b/applications/settings/passport_app/passport_settings/passport_settings_filename.h @@ -0,0 +1,3 @@ +#pragma once + +#define PASSPORT_SETTINGS_FILE_NAME ".passport.settings" diff --git a/applications/settings/passport_settings/application.fam b/applications/settings/passport_settings/application.fam new file mode 100644 index 00000000000..738e465dfa5 --- /dev/null +++ b/applications/settings/passport_settings/application.fam @@ -0,0 +1,12 @@ +App( + appid="passport_settings", + name="Passport Settings", + apptype=FlipperAppType.SETTINGS, + entry_point="passport_settings_app", + requires=[ + "desktop", + "gui", + ], + stack_size=1 * 1024, + order=50, +) diff --git a/applications/settings/passport_settings/passport_settings.c b/applications/settings/passport_settings/passport_settings.c new file mode 100644 index 00000000000..88c96c1d703 --- /dev/null +++ b/applications/settings/passport_settings/passport_settings.c @@ -0,0 +1,33 @@ +#include "passport_settings.h" + +#include "passport_settings_filename.h" + +#include +#include +#include + +#define PASSPORT_SETTINGS_PATH INT_PATH(PASSPORT_SETTINGS_FILE_NAME) +#define PASSPORT_SETTINGS_VERSION (4) +#define PASSPORT_SETTINGS_MAGIC (0x20) + +bool passport_settings_load(PassportSettings* passport_settings) { + furi_assert(passport_settings); + + return saved_struct_load( + PASSPORT_SETTINGS_PATH, + passport_settings, + sizeof(PassportSettings), + PASSPORT_SETTINGS_MAGIC, + PASSPORT_SETTINGS_VERSION); +} + +bool passport_settings_save(PassportSettings* passport_settings) { + furi_assert(passport_settings); + + return saved_struct_save( + PASSPORT_SETTINGS_PATH, + passport_settings, + sizeof(PassportSettings), + PASSPORT_SETTINGS_MAGIC, + PASSPORT_SETTINGS_VERSION); +} diff --git a/applications/settings/passport_settings/passport_settings.h b/applications/settings/passport_settings/passport_settings.h new file mode 100644 index 00000000000..27d7d162038 --- /dev/null +++ b/applications/settings/passport_settings/passport_settings.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define XP_MODE_BAR 0 +#define XP_MODE_PERCENT 1 +#define XP_MODE_INVERTED_PERCENT 2 +#define XP_MODE_RETRO_3 3 +#define XP_MODE_RETRO_5 4 +#define XP_MODE_BAR_PERCENT 5 +#define XP_MODE_NONE 6 + +typedef struct { + bool background; + bool image; + bool name; + bool mood; + bool level; + bool xp_text; + uint8_t xp_mode; + bool multipage; +} PassportSettings; + +bool passport_settings_load(PassportSettings* passport_settings); + +bool passport_settings_save(PassportSettings* passport_settings); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/settings/passport_settings/passport_settings_app.c b/applications/settings/passport_settings/passport_settings_app.c new file mode 100644 index 00000000000..3ec5f7f4207 --- /dev/null +++ b/applications/settings/passport_settings/passport_settings_app.c @@ -0,0 +1,84 @@ +#include +#include + +#include "passport_settings_app.h" +#include "scenes/passport_settings_scene.h" + +static bool passport_settings_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + PassportSettingsApp* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool passport_settings_back_event_callback(void* context) { + furi_assert(context); + PassportSettingsApp* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +PassportSettingsApp* passport_settings_app_alloc() { + PassportSettingsApp* app = malloc(sizeof(PassportSettingsApp)); + + app->gui = furi_record_open(RECORD_GUI); + app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&passport_settings_scene_handlers, app); + view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, passport_settings_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, passport_settings_back_event_callback); + + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + app->submenu = submenu_alloc(); + app->variable_item_list = variable_item_list_alloc(); + + view_dispatcher_add_view( + app->view_dispatcher, PassportSettingsAppViewMenu, submenu_get_view(app->submenu)); + view_dispatcher_add_view( + app->view_dispatcher, + PassportSettingsAppViewVarItemList, + variable_item_list_get_view(app->variable_item_list)); + return app; +} + +void passport_settings_app_free(PassportSettingsApp* app) { + furi_assert(app); + // Variable item list + view_dispatcher_remove_view(app->view_dispatcher, PassportSettingsAppViewMenu); + view_dispatcher_remove_view(app->view_dispatcher, PassportSettingsAppViewVarItemList); + variable_item_list_free(app->variable_item_list); + submenu_free(app->submenu); + // View dispatcher + view_dispatcher_free(app->view_dispatcher); + scene_manager_free(app->scene_manager); + // Records + furi_record_close(RECORD_GUI); + free(app); +} + +extern int32_t passport_settings_app(void* p) { + UNUSED(p); + PassportSettingsApp* app = passport_settings_app_alloc(); + + // Load Passport Settings + if(!(passport_settings_load(&app->settings))) { + app->settings.background = true; + app->settings.image = true; + app->settings.name = true; + app->settings.mood = true; + app->settings.level = true; + app->settings.xp_text = true; + app->settings.xp_mode = 0; + app->settings.multipage = true; + passport_settings_save(&app->settings); + } + + scene_manager_next_scene(app->scene_manager, PassportSettingsAppSceneStart); + + view_dispatcher_run(app->view_dispatcher); + passport_settings_app_free(app); + return 0; +} diff --git a/applications/settings/passport_settings/passport_settings_app.h b/applications/settings/passport_settings/passport_settings_app.h new file mode 100644 index 00000000000..e8cad1950f8 --- /dev/null +++ b/applications/settings/passport_settings/passport_settings_app.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "passport_settings.h" + +typedef enum { + PassportSettingsAppViewMenu, + PassportSettingsAppViewVarItemList, +} PassportSettingsAppView; + +typedef struct { + PassportSettings settings; + + Gui* gui; + SceneManager* scene_manager; + ViewDispatcher* view_dispatcher; + VariableItemList* variable_item_list; + Submenu* submenu; +} PassportSettingsApp; diff --git a/applications/settings/passport_settings/passport_settings_filename.h b/applications/settings/passport_settings/passport_settings_filename.h new file mode 100644 index 00000000000..9cd0744b3ed --- /dev/null +++ b/applications/settings/passport_settings/passport_settings_filename.h @@ -0,0 +1,3 @@ +#pragma once + +#define PASSPORT_SETTINGS_FILE_NAME ".passport.settings" diff --git a/applications/settings/passport_settings/scenes/passport_settings_scene.c b/applications/settings/passport_settings/scenes/passport_settings_scene.c new file mode 100644 index 00000000000..0bfd3bf33e3 --- /dev/null +++ b/applications/settings/passport_settings/scenes/passport_settings_scene.c @@ -0,0 +1,30 @@ +#include "passport_settings_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const passport_settings_on_enter_handlers[])(void*) = { +#include "passport_settings_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const passport_settings_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "passport_settings_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const passport_settings_on_exit_handlers[])(void* context) = { +#include "passport_settings_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers passport_settings_scene_handlers = { + .on_enter_handlers = passport_settings_on_enter_handlers, + .on_event_handlers = passport_settings_on_event_handlers, + .on_exit_handlers = passport_settings_on_exit_handlers, + .scene_num = PassportSettingsAppSceneNum, +}; diff --git a/applications/settings/passport_settings/scenes/passport_settings_scene.h b/applications/settings/passport_settings/scenes/passport_settings_scene.h new file mode 100644 index 00000000000..650e85d1be4 --- /dev/null +++ b/applications/settings/passport_settings/scenes/passport_settings_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) PassportSettingsAppScene##id, +typedef enum { +#include "passport_settings_scene_config.h" + PassportSettingsAppSceneNum, +} PassportSettingsAppScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers passport_settings_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "passport_settings_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "passport_settings_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "passport_settings_scene_config.h" +#undef ADD_SCENE diff --git a/applications/settings/passport_settings/scenes/passport_settings_scene_config.h b/applications/settings/passport_settings/scenes/passport_settings_scene_config.h new file mode 100644 index 00000000000..8bbc2d8e22e --- /dev/null +++ b/applications/settings/passport_settings/scenes/passport_settings_scene_config.h @@ -0,0 +1 @@ +ADD_SCENE(passport_settings, start, Start) diff --git a/applications/settings/passport_settings/scenes/passport_settings_scene_start.c b/applications/settings/passport_settings/scenes/passport_settings_scene_start.c new file mode 100644 index 00000000000..d553c319b95 --- /dev/null +++ b/applications/settings/passport_settings/scenes/passport_settings_scene_start.c @@ -0,0 +1,261 @@ +#include +#include + +#include "../passport_settings_app.h" +#include "passport_settings_scene.h" + +#define SCENE_EVENT_SELECT_BACKGROUND 0 +#define SCENE_EVENT_SELECT_IMAGE 1 +#define SCENE_EVENT_SELECT_NAME 2 +#define SCENE_EVENT_SELECT_MOOD 3 +#define SCENE_EVENT_SELECT_LEVEL 4 +#define SCENE_EVENT_SELECT_XP_TEXT 5 +#define SCENE_EVENT_SELECT_XP_MODE 6 +#define SCENE_EVENT_SELECT_MULTIPAGE 7 + +#define XP_MODE_COUNT 7 + +const char* const xp_mode_count_text[XP_MODE_COUNT] = + {"Bar", "%", "Inv. %", "Retro 3", "Retro 5", "Bar %", "None"}; + +const uint32_t xp_mode_value[XP_MODE_COUNT] = { + XP_MODE_BAR, + XP_MODE_PERCENT, + XP_MODE_INVERTED_PERCENT, + XP_MODE_RETRO_3, + XP_MODE_RETRO_5, + XP_MODE_BAR_PERCENT, + XP_MODE_NONE}; + +#define PASSPORT_ON_OFF_COUNT 2 + +const char* const passport_on_off_text[PASSPORT_ON_OFF_COUNT] = { + "OFF", + "ON", +}; + +const uint32_t background_value[PASSPORT_ON_OFF_COUNT] = {false, true}; + +const uint32_t image_value[PASSPORT_ON_OFF_COUNT] = {false, true}; + +const uint32_t name_value[PASSPORT_ON_OFF_COUNT] = {false, true}; + +const uint32_t mood_value[PASSPORT_ON_OFF_COUNT] = {false, true}; + +const uint32_t level_value[PASSPORT_ON_OFF_COUNT] = {false, true}; + +const uint32_t xp_text_value[PASSPORT_ON_OFF_COUNT] = {false, true}; + +const uint32_t multipage_value[PASSPORT_ON_OFF_COUNT] = {false, true}; + +static void passport_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) { + PassportSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +static void passport_settings_scene_start_background_changed(VariableItem* item) { + PassportSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, passport_on_off_text[index]); + app->settings.background = background_value[index]; +} + +static void passport_settings_scene_start_image_changed(VariableItem* item) { + PassportSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, passport_on_off_text[index]); + app->settings.image = image_value[index]; +} + +static void passport_settings_scene_start_name_changed(VariableItem* item) { + PassportSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, passport_on_off_text[index]); + app->settings.name = name_value[index]; +} + +static void passport_settings_scene_start_mood_changed(VariableItem* item) { + PassportSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, passport_on_off_text[index]); + app->settings.mood = mood_value[index]; +} + +static void passport_settings_scene_start_level_changed(VariableItem* item) { + PassportSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, passport_on_off_text[index]); + app->settings.level = level_value[index]; +} + +static void passport_settings_scene_start_xp_text_changed(VariableItem* item) { + PassportSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, passport_on_off_text[index]); + app->settings.xp_text = xp_text_value[index]; +} + +static void passport_settings_scene_start_xp_mode_changed(VariableItem* item) { + PassportSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, xp_mode_count_text[index]); + app->settings.xp_mode = index; +} + +static void passport_settings_scene_start_multipage_changed(VariableItem* item) { + PassportSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, passport_on_off_text[index]); + app->settings.multipage = multipage_value[index]; +} + +void passport_settings_scene_start_on_enter(void* context) { + PassportSettingsApp* app = context; + VariableItemList* variable_item_list = app->variable_item_list; + + VariableItem* item; + uint8_t value_index; + + item = variable_item_list_add( + variable_item_list, + "Background", + PASSPORT_ON_OFF_COUNT, + passport_settings_scene_start_background_changed, + app); + + value_index = + value_index_uint32(app->settings.background, background_value, PASSPORT_ON_OFF_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, passport_on_off_text[value_index]); + + item = variable_item_list_add( + variable_item_list, + "Image", + PASSPORT_ON_OFF_COUNT, + passport_settings_scene_start_image_changed, + app); + + value_index = value_index_uint32(app->settings.image, image_value, PASSPORT_ON_OFF_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, passport_on_off_text[value_index]); + + item = variable_item_list_add( + variable_item_list, + "Name", + PASSPORT_ON_OFF_COUNT, + passport_settings_scene_start_name_changed, + app); + + value_index = value_index_uint32(app->settings.name, name_value, PASSPORT_ON_OFF_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, passport_on_off_text[value_index]); + + item = variable_item_list_add( + variable_item_list, + "Mood", + PASSPORT_ON_OFF_COUNT, + passport_settings_scene_start_mood_changed, + app); + + value_index = value_index_uint32(app->settings.mood, mood_value, PASSPORT_ON_OFF_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, passport_on_off_text[value_index]); + + item = variable_item_list_add( + variable_item_list, + "Level", + PASSPORT_ON_OFF_COUNT, + passport_settings_scene_start_level_changed, + app); + + value_index = value_index_uint32(app->settings.level, level_value, PASSPORT_ON_OFF_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, passport_on_off_text[value_index]); + + item = variable_item_list_add( + variable_item_list, + "XP Text", + PASSPORT_ON_OFF_COUNT, + passport_settings_scene_start_xp_text_changed, + app); + + value_index = value_index_uint32(app->settings.xp_text, xp_text_value, PASSPORT_ON_OFF_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, passport_on_off_text[value_index]); + + item = variable_item_list_add( + variable_item_list, + "XP Mode", + XP_MODE_COUNT, + passport_settings_scene_start_xp_mode_changed, + app); + + value_index = value_index_uint32(app->settings.xp_mode, xp_mode_value, XP_MODE_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, xp_mode_count_text[value_index]); + + item = variable_item_list_add( + variable_item_list, + "Multiple Pages", + PASSPORT_ON_OFF_COUNT, + passport_settings_scene_start_multipage_changed, + app); + + value_index = + value_index_uint32(app->settings.multipage, multipage_value, PASSPORT_ON_OFF_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, passport_on_off_text[value_index]); + + variable_item_list_set_enter_callback( + variable_item_list, passport_settings_scene_start_var_list_enter_callback, app); + view_dispatcher_switch_to_view(app->view_dispatcher, PassportSettingsAppViewVarItemList); +} + +bool passport_settings_scene_start_on_event(void* context, SceneManagerEvent sme) { + PassportSettingsApp* app = context; + bool consumed = false; + + if(sme.type == SceneManagerEventTypeCustom) { + switch(sme.event) { + case SCENE_EVENT_SELECT_BACKGROUND: + consumed = true; + break; + case SCENE_EVENT_SELECT_IMAGE: + consumed = true; + break; + case SCENE_EVENT_SELECT_NAME: + consumed = true; + break; + case SCENE_EVENT_SELECT_MOOD: + consumed = true; + break; + case SCENE_EVENT_SELECT_LEVEL: + consumed = true; + break; + case SCENE_EVENT_SELECT_XP_TEXT: + consumed = true; + break; + case SCENE_EVENT_SELECT_XP_MODE: + consumed = true; + break; + case SCENE_EVENT_SELECT_MULTIPAGE: + consumed = true; + break; + } + } + return consumed; +} + +void passport_settings_scene_start_on_exit(void* context) { + PassportSettingsApp* app = context; + variable_item_list_reset(app->variable_item_list); + passport_settings_save(&app->settings); +} diff --git a/applications/system/application.fam b/applications/system/application.fam index a59f840e456..a39a7261206 100644 --- a/applications/system/application.fam +++ b/applications/system/application.fam @@ -3,6 +3,7 @@ App( name="Applications not shown in menus", apptype=FlipperAppType.METAPACKAGE, provides=[ + "dolphin_passport", "updater_app", "storage_move_to_sd", # "archive", diff --git a/applications/system/dolphin_passport/application.fam b/applications/system/dolphin_passport/application.fam new file mode 100644 index 00000000000..886e89bc0e9 --- /dev/null +++ b/applications/system/dolphin_passport/application.fam @@ -0,0 +1,13 @@ +App( + appid="dolphin_passport", + name="Passport", + apptype=FlipperAppType.SYSTEM, + entry_point="dolphin_passport_app", + cdefines=["APP_DOLPHIN_PASSPORT"], + requires=[ + "gui", + "dolphin", + ], + stack_size=1 * 1024, + order=60, +) diff --git a/applications/system/dolphin_passport/dolphin_passport.c b/applications/system/dolphin_passport/dolphin_passport.c new file mode 100644 index 00000000000..ac6396e81e1 --- /dev/null +++ b/applications/system/dolphin_passport/dolphin_passport.c @@ -0,0 +1,275 @@ +#include "assets_icons.h" +#include +#include +#include +#include +#include +#include +#include +#include "dolphin/dolphin.h" +#include "dolphin/helpers/dolphin_state.h" +#include "applications/settings/desktop_settings/desktop_settings_app.h" +#include "math.h" + +#define MOODS_TOTAL 1 +#define BUTTHURT_MAX 14 + +typedef enum { EventGameTick, EventKeyPress } EventType; + +typedef struct { + EventType type; + InputEvent input; +} PassportEvent; + +typedef struct { + Dolphin* dolphin; + DolphinStats stats; + + DesktopSettings* desktop_settings; + + uint32_t xp_to_levelup; + uint32_t xp_above_last_levelup; + uint32_t xp_for_current_level; + char xp_str[14]; + double xp_progress; + int xp_fill; + + int max_level; + uint16_t tmpLvl; + char level_str[12]; + + char my_name[8]; + + char mood_str[20]; + uint8_t mood; + uint8_t moodStrIndex; + char dumbmode_mood[20]; +} Passport; + +static const Icon* const portrait[7] = { + &I_passport_happy1_46x49, + &I_passport_happy2_46x49, + &I_passport_happy3_46x49, + &I_G0ku, + &I_g0ku_1, + &I_g0ku_2, + &I_g0ku_3}; +// static const Icon* const portrait_ok[MOODS_TOTAL] = { +// &I_passport_okay1_46x49, +// &I_passport_okay2_46x49, +// &I_passport_okay3_46x49}; +// static const Icon* const portrait_bad[MOODS_TOTAL] = { +// &I_passport_bad1_46x49, +// &I_passport_bad2_46x49, +// &I_passport_bad3_46x49}; + +// static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy, portrait_ok, portrait_bad}; +//static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy}; + +static const char* const moods[16] = { + "Stoned", + "Baked", + "Ripped", + "Joyful", + "Happy", + "Satisfied", + "Relaxed", + "Nostalgic", + "Okay", + "Tired", + "Bored", + "Sad", + "Annoyed", + "Upset", + "Angry", + "Furious"}; + +void passport_set_variables(Passport* passport) { + //stats, xp, levels + passport->dolphin = furi_record_open(RECORD_DOLPHIN); + passport->stats = dolphin_stats(passport->dolphin); + furi_record_close(RECORD_DOLPHIN); + + DolphinStats* stats = &passport->stats; + + passport->max_level = dolphin_state_max_level(); + passport->tmpLvl = 0; + + //get XP + passport->xp_to_levelup = dolphin_state_xp_to_levelup(stats->icounter); + passport->xp_above_last_levelup = dolphin_state_xp_above_last_levelup(stats->icounter); + passport->xp_for_current_level = passport->xp_to_levelup + passport->xp_above_last_levelup; + + //get percentage from remaining XP + if(stats->level == passport->max_level) { + passport->xp_progress = 100; + } else { + passport->xp_progress = + round(((passport->xp_above_last_levelup * 100) / passport->xp_for_current_level)); + } + + //mood + passport->desktop_settings = malloc(sizeof(DesktopSettings)); + DESKTOP_SETTINGS_LOAD(passport->desktop_settings); + DesktopSettings* desktop_settings = passport->desktop_settings; + + passport->mood = 0; // DONT NEED DIFFERENT PICS BASED ON MOOD + passport->moodStrIndex = stats->butthurt; + + // set mood to "Happy" if dumbmode is enabled + if(desktop_settings->is_dumbmode) passport->moodStrIndex = passport->moodStrIndex + 4; + + // portrait + furi_assert((stats->level > 0) && (stats->level <= passport->max_level)); + if(stats->level > 10) passport->tmpLvl = 1; + if(stats->level > 15) passport->tmpLvl = 2; + if(stats->level > 18) passport->tmpLvl = 3; + if(stats->level > 21) passport->tmpLvl = 4; + if(stats->level > 24) passport->tmpLvl = 5; + if(stats->level > 27) passport->tmpLvl = 6; + + //string variables set + //name + snprintf(passport->my_name, 8, "%s", furi_hal_version_get_name_ptr()); + //mood + snprintf(passport->mood_str, 20, "Mood: %s", moods[passport->moodStrIndex]); + //level + snprintf(passport->level_str, 12, "Level: %hu", stats->level); + + //determine whether to display XP stats or max level + if(stats->level == passport->max_level) { + //xp display for main passport view + snprintf(passport->xp_str, 14, "Max Level"); + } else { + //xp display for main passport view + snprintf( + passport->xp_str, + 14, + "%lu/%lu", + passport->xp_above_last_levelup, + passport->xp_for_current_level); + } + + free(stats); +} + +static void render_callback(Canvas* const canvas, void* mutex) { + furi_assert(mutex); + + Passport* passport = acquire_mutex((ValueMutex*)mutex, 25); + + //calc bar fill ratio + //default bar is 65px wide + passport->xp_fill = (int)round((passport->xp_progress / 100) * 65); + + // draw background + canvas_draw_icon(canvas, 0, 0, &I_passport_DB); + + // draw portrait + canvas_draw_icon(canvas, 11, 2, portrait[passport->tmpLvl]); + + //draw flipper info + canvas_set_font(canvas, FontSecondary); + //name + canvas_draw_str(canvas, 58, 10, passport->my_name ? passport->my_name : "Unknown"); + //mood + canvas_draw_str(canvas, 58, 22, passport->mood_str); + //level + canvas_draw_str(canvas, 58, 34, passport->level_str); + + canvas_set_font(canvas, FontBatteryPercent); + + //xp stats + canvas_draw_str(canvas, 58, 42, passport->xp_str); + + canvas_set_font(canvas, FontSecondary); + + //Round Edge XP Bar + + //blank out background + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, 58, 44, 67, 7); + + //draw black xp bar which will be used as outline but also for full bar + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 58, 45, 67, 6, 1); + + //hollow out xp bar with white "empty" space + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 59, 46, 65, 4, 1); + + //fill bar according to xp percentage + if(passport->xp_fill >= 2) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_rbox(canvas, 59, 46, passport->xp_fill, 4, 1); + } + + release_mutex((ValueMutex*)mutex, passport); +} + +static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { + furi_assert(event_queue); + PassportEvent event = {.type = EventKeyPress, .input = *input_event}; + furi_message_queue_put(event_queue, &event, FuriWaitForever); +} + +int32_t dolphin_passport_app(void* p) { + UNUSED(p); + FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PassportEvent)); + + Passport* passport = malloc(sizeof(Passport)); + + ValueMutex state_mutex; + if(!init_mutex(&state_mutex, passport, sizeof(Passport))) { + free(passport); + return 1; + } + + passport_set_variables(passport); + + ViewPort* view_port = view_port_alloc(); + view_port_draw_callback_set(view_port, render_callback, &state_mutex); + view_port_input_callback_set(view_port, input_callback, event_queue); + + Gui* gui = furi_record_open("gui"); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + PassportEvent event = {0}; + + while(event.input.key != InputKeyBack) { + if(furi_message_queue_get(event_queue, &event, 10) != FuriStatusOk) { + continue; + } + + passport = (Passport*)acquire_mutex_block(&state_mutex); + + if(event.type == EventKeyPress) { + switch(event.input.key) { + case InputKeyUp: + break; + case InputKeyDown: + break; + case InputKeyRight: + break; + case InputKeyLeft: + break; + case InputKeyOk: + break; + default: + break; + } + } + release_mutex(&state_mutex, passport); + view_port_update(view_port); + } + + gui_remove_view_port(gui, view_port); + furi_record_close(RECORD_GUI); + view_port_free(view_port); + gui = NULL; + furi_message_queue_free(event_queue); + + free(passport); + + return 0; +} \ No newline at end of file From 90fe45d5b2bd72d4126fc429e636fbaf413b1dbc Mon Sep 17 00:00:00 2001 From: ESurge Date: Thu, 9 Feb 2023 13:33:56 -0800 Subject: [PATCH 5/5] Small update to storage.c, removed a line that was part of my testing --- applications/services/storage/storage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/applications/services/storage/storage.c b/applications/services/storage/storage.c index d1564c8dbc5..d61bf834db2 100644 --- a/applications/services/storage/storage.c +++ b/applications/services/storage/storage.c @@ -6,7 +6,6 @@ #include "storages/storage_int.h" #include "storages/storage_ext.h" #include -#include #define STORAGE_TICK 1000