Merge branch 'DarkFlippers:dev' into feat/subghz-save-hopping-state

This commit is contained in:
DerSkythe
2023-08-24 17:17:35 +04:00
committed by GitHub
208 changed files with 1349 additions and 1057 deletions

View File

@@ -174,7 +174,7 @@ bool WIEGAND::DoWiegandConversion() {
return false;
}
// TODO: Handle validation failure case!
// TODO FL-3490: Handle validation failure case!
} else if(4 == _bitCount) {
// 4-bit Wiegand codes have no data integrity check so we just
// read the LOW nibble.

View File

@@ -56,7 +56,6 @@ static void subghz_test_packet_rx_callback(bool level, uint32_t duration, void*
subghz_decoder_princeton_for_testing_parse(instance->decoder, level, duration);
}
//todo
static void subghz_test_packet_rx_pt_callback(SubGhzDecoderPrinceton* parser, void* context) {
UNUSED(parser);
furi_assert(context);

View File

@@ -26,7 +26,7 @@ void test_furi_memmgr() {
mu_assert_int_eq(66, ((uint8_t*)ptr)[i]);
}
// TODO: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized
// TODO FL-3492: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized
free(ptr);
// allocate and zero-initialize array (calloc)

View File

@@ -69,7 +69,7 @@ MU_TEST(mu_test_furi_string_mem) {
mu_check(string != NULL);
mu_check(!furi_string_empty(string));
// TODO: how to test furi_string_reserve?
// TODO FL-3493: how to test furi_string_reserve?
// test furi_string_reset
furi_string_reset(string);

View File

@@ -311,7 +311,7 @@ MU_TEST(test_bit_lib_test_parity) {
}
MU_TEST(test_bit_lib_remove_bit_every_nth) {
// TODO: more tests
// TODO FL-3494: more tests
uint8_t data_i[1] = {0b00001111};
uint8_t data_o[1] = {0b00011111};
size_t length;

View File

@@ -90,7 +90,7 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
Loader* loader = furi_record_open(RECORD_LOADER);
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
// TODO: lock device while test running
// TODO FL-3491: lock device while test running
if(loader_is_locked(loader)) {
printf("RPC: stop all applications to run tests\r\n");
notification_message(notification, &sequence_blink_magenta_100);

View File

@@ -19,7 +19,7 @@ void gpio_scene_usb_uart_on_enter(void* context) {
uint32_t prev_state = scene_manager_get_scene_state(app->scene_manager, GpioAppViewUsbUart);
if(prev_state == 0) {
scene_usb_uart = malloc(sizeof(SceneUsbUartBridge));
scene_usb_uart->cfg.vcp_ch = 0; // TODO: settings load
scene_usb_uart->cfg.vcp_ch = 0; // TODO FL-3495: settings load
scene_usb_uart->cfg.uart_ch = 0;
scene_usb_uart->cfg.flow_pins = 0;
scene_usb_uart->cfg.baudrate_mode = 0;

View File

@@ -85,7 +85,7 @@ static void infrared_cli_print_usage(void) {
printf("\tir decode <input_file> [<output_file>]\r\n");
printf("\tir universal <remote_name> <signal_name>\r\n");
printf("\tir universal list <remote_name>\r\n");
// TODO: Do not hardcode universal remote names
// TODO FL-3496: Do not hardcode universal remote names
printf("\tAvailable universal remotes: tv audio ac projector\r\n");
}
@@ -211,7 +211,7 @@ static bool infrared_cli_decode_raw_signal(
size_t i;
for(i = 0; i < raw_signal->timings_size; ++i) {
// TODO: Any infrared_check_decoder_ready() magic?
// TODO FL-3523: Any infrared_check_decoder_ready() magic?
const InfraredMessage* message = infrared_decode(decoder, level, raw_signal->timings[i]);
if(message) {

View File

@@ -1,6 +1,7 @@
#include "../infrared_i.h"
#include "common/infrared_scene_universal_common.h"
#include <furi_hal_rtc.h>
void infrared_scene_universal_ac_on_enter(void* context) {
infrared_scene_universal_common_on_enter(context);
@@ -18,24 +19,26 @@ void infrared_scene_universal_ac_on_enter(void* context) {
i,
0,
0,
3,
22,
&I_Off_25x27,
&I_Off_hvr_25x27,
6,
15,
&I_power_19x20,
&I_power_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 4, 37, &I_power_text_24x5);
infrared_brute_force_add_record(brute_force, i++, "Off");
button_panel_add_item(
button_panel,
i,
1,
0,
36,
22,
&I_Dehumidify_25x27,
&I_Dehumidify_hvr_25x27,
39,
15,
&I_dry_19x20,
&I_dry_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 41, 37, &I_dry_text_15x5);
infrared_brute_force_add_record(brute_force, i++, "Dh");
button_panel_add_item(
button_panel,
@@ -43,9 +46,9 @@ void infrared_scene_universal_ac_on_enter(void* context) {
0,
1,
3,
59,
&I_CoolHi_25x27,
&I_CoolHi_hvr_25x27,
49,
&I_max_24x23,
&I_max_hover_24x23,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Cool_hi");
@@ -54,39 +57,71 @@ void infrared_scene_universal_ac_on_enter(void* context) {
i,
1,
1,
36,
59,
&I_HeatHi_25x27,
&I_HeatHi_hvr_25x27,
37,
49,
&I_max_24x23,
&I_max_hover_24x23,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Heat_hi");
button_panel_add_item(
button_panel,
i,
0,
2,
3,
91,
&I_CoolLo_25x27,
&I_CoolLo_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
if(furi_hal_rtc_get_locale_units() == FuriHalRtcLocaleUnitsMetric) {
button_panel_add_item(
button_panel,
i,
0,
2,
3,
100,
&I_celsius_24x23,
&I_celsius_hover_24x23,
infrared_scene_universal_common_item_callback,
context);
} else {
button_panel_add_item(
button_panel,
i,
0,
2,
3,
100,
&I_fahren_24x23,
&I_fahren_hover_24x23,
infrared_scene_universal_common_item_callback,
context);
}
infrared_brute_force_add_record(brute_force, i++, "Cool_lo");
button_panel_add_item(
button_panel,
i,
1,
2,
36,
91,
&I_HeatLo_25x27,
&I_HeatLo_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
if(furi_hal_rtc_get_locale_units() == FuriHalRtcLocaleUnitsMetric) {
button_panel_add_item(
button_panel,
i,
1,
2,
37,
100,
&I_celsius_24x23,
&I_celsius_hover_24x23,
infrared_scene_universal_common_item_callback,
context);
} else {
button_panel_add_item(
button_panel,
i,
1,
2,
37,
100,
&I_fahren_24x23,
&I_fahren_hover_24x23,
infrared_scene_universal_common_item_callback,
context);
}
infrared_brute_force_add_record(brute_force, i++, "Heat_lo");
button_panel_add_label(button_panel, 6, 10, FontPrimary, "AC remote");
button_panel_add_icon(button_panel, 0, 60, &I_cool_30x51);
button_panel_add_icon(button_panel, 34, 60, &I_heat_30x51);
button_panel_add_label(button_panel, 4, 10, FontPrimary, "AC remote");
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);

View File

@@ -18,82 +18,88 @@ void infrared_scene_universal_audio_on_enter(void* context) {
i,
0,
0,
3,
11,
&I_Power_25x27,
&I_Power_hvr_25x27,
6,
13,
&I_power_19x20,
&I_power_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 4, 35, &I_power_text_24x5);
infrared_brute_force_add_record(brute_force, i++, "Power");
button_panel_add_item(
button_panel,
i,
1,
0,
36,
11,
&I_Mute_25x27,
&I_Mute_hvr_25x27,
39,
13,
&I_mute_19x20,
&I_mute_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 39, 35, &I_mute_text_19x5);
infrared_brute_force_add_record(brute_force, i++, "Mute");
button_panel_add_item(
button_panel,
i,
0,
1,
3,
41,
&I_Play_25x27,
&I_Play_hvr_25x27,
6,
42,
&I_play_19x20,
&I_play_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 6, 64, &I_play_text_19x5);
infrared_brute_force_add_record(brute_force, i++, "Play");
button_panel_add_item(
button_panel,
i,
1,
1,
36,
41,
&I_Pause_25x27,
&I_Pause_hvr_25x27,
0,
2,
6,
71,
&I_pause_19x20,
&I_pause_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 4, 93, &I_pause_text_23x5);
infrared_brute_force_add_record(brute_force, i++, "Pause");
button_panel_add_item(
button_panel,
i,
0,
2,
3,
71,
&I_TrackPrev_25x27,
&I_TrackPrev_hvr_25x27,
6,
101,
&I_prev_19x20,
&I_prev_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 6, 123, &I_prev_text_19x5);
infrared_brute_force_add_record(brute_force, i++, "Prev");
button_panel_add_item(
button_panel,
i,
1,
2,
36,
71,
&I_TrackNext_25x27,
&I_TrackNext_hvr_25x27,
3,
39,
101,
&I_next_19x20,
&I_next_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 39, 123, &I_next_text_19x6);
infrared_brute_force_add_record(brute_force, i++, "Next");
button_panel_add_item(
button_panel,
i,
0,
3,
3,
101,
&I_Vol_down_25x27,
&I_Vol_down_hvr_25x27,
1,
2,
37,
77,
&I_voldown_24x21,
&I_voldown_hover_24x21,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_dn");
@@ -101,16 +107,17 @@ void infrared_scene_universal_audio_on_enter(void* context) {
button_panel,
i,
1,
3,
36,
101,
&I_Vol_up_25x27,
&I_Vol_up_hvr_25x27,
1,
37,
43,
&I_volup_24x21,
&I_volup_hover_24x21,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
button_panel_add_label(button_panel, 1, 8, FontPrimary, "Mus. remote");
button_panel_add_label(button_panel, 1, 10, FontPrimary, "Mus. remote");
button_panel_add_icon(button_panel, 34, 56, &I_vol_ac_text_30x30);
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);

View File

@@ -19,34 +19,38 @@ void infrared_scene_universal_fan_on_enter(void* context) {
i,
0,
0,
3,
6,
24,
&I_Power_25x27,
&I_Power_hvr_25x27,
&I_power_19x20,
&I_power_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Power");
button_panel_add_icon(button_panel, 4, 46, &I_power_text_24x5);
button_panel_add_item(
button_panel,
i,
1,
0,
36,
39,
24,
&I_Mode_25x27,
&I_Mode_hvr_25x27,
&I_mode_19x20,
&I_mode_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Mode");
button_panel_add_icon(button_panel, 39, 46, &I_mode_text_20x5);
button_panel_add_item(
button_panel,
i,
0,
1,
3,
66,
&I_Vol_up_25x27,
&I_Vol_up_hvr_25x27,
1,
37,
55,
&I_volup_24x21,
&I_volup_hover_24x21,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Speed_up");
@@ -54,11 +58,11 @@ void infrared_scene_universal_fan_on_enter(void* context) {
button_panel,
i,
1,
1,
36,
66,
&I_Vol_down_25x27,
&I_Vol_down_hvr_25x27,
2,
37,
89,
&I_voldown_24x21,
&I_voldown_hover_24x21,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Speed_dn");
@@ -66,31 +70,32 @@ void infrared_scene_universal_fan_on_enter(void* context) {
button_panel,
i,
0,
2,
3,
98,
&I_Rotate_25x27,
&I_Rotate_hvr_25x27,
1,
6,
58,
&I_rotate_19x20,
&I_rotate_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Rotate");
button_panel_add_icon(button_panel, 4, 80, &I_rotate_text_24x5);
button_panel_add_item(
button_panel,
i,
1,
0,
2,
36,
98,
&I_Timer_25x27,
&I_Timer_hvr_25x27,
6,
87,
&I_timer_19x20,
&I_timer_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Timer");
button_panel_add_icon(button_panel, 4, 109, &I_timer_text_23x5);
button_panel_add_label(button_panel, 5, 11, FontPrimary, "Fan remote");
button_panel_add_label(button_panel, 20, 63, FontSecondary, "Speed");
button_panel_add_label(button_panel, 8, 23, FontSecondary, "Pwr");
button_panel_add_label(button_panel, 40, 23, FontSecondary, "Mod");
button_panel_add_icon(button_panel, 34, 68, &I_speed_text_30x30);
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);

View File

@@ -18,46 +18,49 @@ void infrared_scene_universal_projector_on_enter(void* context) {
i,
0,
0,
3,
19,
&I_Power_25x27,
&I_Power_hvr_25x27,
6,
24,
&I_power_19x20,
&I_power_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 4, 46, &I_power_text_24x5);
infrared_brute_force_add_record(brute_force, i++, "Power");
button_panel_add_item(
button_panel,
i,
1,
0,
36,
19,
&I_Mute_25x27,
&I_Mute_hvr_25x27,
39,
24,
&I_mute_19x20,
&I_mute_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 39, 46, &I_mute_text_19x5);
infrared_brute_force_add_record(brute_force, i++, "Mute");
button_panel_add_item(
button_panel,
i,
0,
1,
3,
64,
&I_Vol_up_25x27,
&I_Vol_up_hvr_25x27,
1,
37,
55,
&I_volup_24x21,
&I_volup_hover_24x21,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
button_panel_add_item(
button_panel,
i,
1,
1,
36,
64,
&I_Vol_down_25x27,
&I_Vol_down_hvr_25x27,
2,
37,
89,
&I_voldown_24x21,
&I_voldown_hover_24x21,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_dn");
@@ -65,29 +68,31 @@ void infrared_scene_universal_projector_on_enter(void* context) {
button_panel,
i,
0,
2,
3,
101,
&I_Play_25x27,
&I_Play_hvr_25x27,
1,
6,
58,
&I_play_19x20,
&I_play_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Play");
button_panel_add_icon(button_panel, 6, 80, &I_play_text_19x5);
button_panel_add_item(
button_panel,
i,
1,
0,
2,
36,
101,
&I_Pause_25x27,
&I_Pause_hvr_25x27,
6,
87,
&I_pause_19x20,
&I_pause_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Pause");
button_panel_add_icon(button_panel, 4, 109, &I_pause_text_23x5);
button_panel_add_label(button_panel, 10, 11, FontPrimary, "Projector");
button_panel_add_label(button_panel, 17, 60, FontSecondary, "Volume");
button_panel_add_label(button_panel, 3, 11, FontPrimary, "Proj. remote");
button_panel_add_icon(button_panel, 34, 68, &I_vol_ac_text_30x30);
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);

View File

@@ -18,77 +18,82 @@ void infrared_scene_universal_tv_on_enter(void* context) {
i,
0,
0,
3,
19,
&I_Power_25x27,
&I_Power_hvr_25x27,
6,
16,
&I_power_19x20,
&I_power_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 4, 38, &I_power_text_24x5);
infrared_brute_force_add_record(brute_force, i++, "Power");
button_panel_add_item(
button_panel,
i,
1,
0,
36,
19,
&I_Mute_25x27,
&I_Mute_hvr_25x27,
39,
16,
&I_mute_19x20,
&I_mute_hover_19x20,
infrared_scene_universal_common_item_callback,
context);
button_panel_add_icon(button_panel, 39, 38, &I_mute_text_19x5);
button_panel_add_icon(button_panel, 0, 66, &I_ch_text_31x34);
button_panel_add_icon(button_panel, 35, 66, &I_vol_tv_text_29x34);
infrared_brute_force_add_record(brute_force, i++, "Mute");
button_panel_add_item(
button_panel,
i,
1,
1,
38,
53,
&I_volup_24x21,
&I_volup_hover_24x21,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
button_panel_add_item(
button_panel,
i,
0,
1,
3,
66,
&I_Vol_up_25x27,
&I_Vol_up_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
button_panel_add_item(
button_panel,
i,
1,
1,
36,
66,
&I_Up_25x27,
&I_Up_hvr_25x27,
53,
&I_ch_up_24x21,
&I_ch_up_hover_24x21,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Ch_next");
button_panel_add_item(
button_panel,
i,
0,
1,
2,
3,
98,
&I_Vol_down_25x27,
&I_Vol_down_hvr_25x27,
38,
91,
&I_voldown_24x21,
&I_voldown_hover_24x21,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_dn");
button_panel_add_item(
button_panel,
i,
1,
0,
2,
36,
98,
&I_Down_25x27,
&I_Down_hvr_25x27,
3,
91,
&I_ch_down_24x21,
&I_ch_down_hover_24x21,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Ch_prev");
button_panel_add_label(button_panel, 6, 11, FontPrimary, "TV remote");
button_panel_add_label(button_panel, 9, 64, FontSecondary, "Vol");
button_panel_add_label(button_panel, 43, 64, FontSecondary, "Ch");
button_panel_add_label(button_panel, 5, 10, FontPrimary, "TV remote");
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);

View File

@@ -334,7 +334,6 @@ static void subghz_txrx_tx_stop(SubGhzTxRx* instance) {
}
subghz_txrx_idle(instance);
subghz_txrx_speaker_off(instance);
//Todo: Show message
}
FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) {

View File

@@ -30,7 +30,7 @@ bool subghz_txrx_gen_data_protocol(
subghz_receiver_search_decoder_base_by_name(instance->receiver, protocol_name);
if(instance->decoder_result == NULL) {
//TODO: Error
//TODO FL-3502: Error
// furi_string_set(error_str, "Protocol not\nfound!");
// scene_manager_next_scene(scene_manager, SubGhzSceneShowErrorSub);
FURI_LOG_E(TAG, "Protocol not found!");

View File

@@ -27,7 +27,7 @@ static bool subghz_scene_receiver_info_update_parser(void* context) {
if(subghz_txrx_load_decoder_by_name_protocol(
subghz->txrx,
subghz_history_get_protocol_name(subghz->history, subghz->idx_menu_chosen))) {
//todo we are trying to deserialize without checking for errors, since it is assumed that we just received this signal
// we are trying to deserialize without checking for errors, since it is assumed that we just received this chignal
subghz_protocol_decoder_base_deserialize(
subghz_txrx_get_decoder(subghz->txrx),
subghz_history_get_raw_data(subghz->history, subghz->idx_menu_chosen));

View File

@@ -126,7 +126,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) {
SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx);
if(!strcmp(furi_string_get_cstr(temp_str), "CUSTOM")) {
//Todo add Custom_preset_module
//TODO FL-3551: add Custom_preset_module
//delete preset if it already exists
subghz_setting_delete_custom_preset(setting, furi_string_get_cstr(temp_str));
//load custom preset from file

View File

@@ -13,5 +13,5 @@ App(
fap_libs=["assets",],
fap_icon="icon.png",
fap_description="SubGhz Remote, uses up to 5 .sub files",
fap_category="Sub-Ghz",
fap_category="Sub-GHz",
)

View File

@@ -51,6 +51,12 @@ extern const size_t FLIPPER_ON_SYSTEM_START_COUNT;
extern const FlipperInternalApplication FLIPPER_SYSTEM_APPS[];
extern const size_t FLIPPER_SYSTEM_APPS_COUNT;
/* Debug apps
* Can only be spawned by loader by name
*/
extern const FlipperInternalApplication FLIPPER_DEBUG_APPS[];
extern const size_t FLIPPER_DEBUG_APPS_COUNT;
extern const FlipperInternalApplication FLIPPER_ARCHIVE;
/* Settings list

View File

@@ -65,8 +65,8 @@ static bool one_shot_view_input(InputEvent* event, void* context) {
if(!consumed) {
if(event->key == InputKeyRight) {
/* Right button reserved for animation activation, so consume */
consumed = true;
if(event->type == InputTypeShort) {
consumed = true;
if(view->interact_callback) {
view->interact_callback(view->interact_callback_context);
}

View File

@@ -101,7 +101,7 @@ static void desktop_clock_draw_callback(Canvas* canvas, void* context) {
char buffer[20];
snprintf(buffer, sizeof(buffer), "%02u:%02u", hour, desktop->time_minute);
// ToDo: never do that, may cause visual glitches
// TODO FL-3515: never do that, may cause visual glitches
view_port_set_width(
desktop->clock_viewport,
canvas_string_width(canvas, buffer) - 1 + (desktop->time_minute % 10 == 1));
@@ -126,13 +126,14 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) {
return true;
case DesktopGlobalAfterAppFinished:
animation_manager_load_and_continue_animation(desktop->animation_manager);
// TODO: Implement a message mechanism for loading settings and (optionally)
// TODO FL-3497: Implement a message mechanism for loading settings and (optionally)
// locking and unlocking
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_clock_reconfigure(desktop);
desktop_auto_lock_arm(desktop);
if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
desktop_auto_lock_arm(desktop);
}
return true;
case DesktopGlobalAutoLock:
if(!loader_is_locked(desktop->loader)) {
@@ -223,7 +224,6 @@ void desktop_lock(Desktop* desktop) {
scene_manager_set_scene_state(
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
notification_message(desktop->notification, &sequence_display_backlight_off_delay_1000);
DesktopStatus status = {.locked = true};
furi_pubsub_publish(desktop->status_pubsub, &status);
@@ -381,12 +381,7 @@ Desktop* desktop_alloc() {
}
gui_add_view_port(desktop->gui, desktop->stealth_mode_icon_viewport, GuiLayerStatusBarLeft);
// Special case: autostart application is already running
desktop->loader = furi_record_open(RECORD_LOADER);
if(loader_is_locked(desktop->loader) &&
animation_manager_is_animation_loaded(desktop->animation_manager)) {
animation_manager_unload_and_stall_animation(desktop->animation_manager);
}
desktop->notification = furi_record_open(RECORD_NOTIFICATION);
desktop->app_start_stop_subscription = furi_pubsub_subscribe(
@@ -477,6 +472,12 @@ int32_t desktop_srv(void* p) {
scene_manager_next_scene(desktop->scene_manager, DesktopSceneFault);
}
// Special case: autostart application is already running
if(loader_is_locked(desktop->loader) &&
animation_manager_is_animation_loaded(desktop->animation_manager)) {
animation_manager_unload_and_stall_animation(desktop->animation_manager);
}
view_dispatcher_run(desktop->view_dispatcher);
furi_crash("That was unexpected");

View File

@@ -8,7 +8,7 @@
#include <toolbox/saved_struct.h>
#include <storage/storage.h>
#define DESKTOP_SETTINGS_VER (12)
#define DESKTOP_SETTINGS_VER (13)
#define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME)
#define DESKTOP_SETTINGS_MAGIC (0x17)
@@ -43,6 +43,29 @@
#define DISPLAY_BATTERY_RETRO_5 4
#define DISPLAY_BATTERY_BAR_PERCENT 5
typedef enum {
FavoriteAppLeftShort = 0,
FavoriteAppLeftLong,
FavoriteAppRightShort,
FavoriteAppRightLong,
FavoriteAppNumber,
} FavoriteAppShortcut;
typedef enum {
DummyAppLeft = 0,
DummyAppLeftLong,
DummyAppRight,
DummyAppRightLong,
DummyAppUpLong,
DummyAppDown,
DummyAppDownLong,
DummyAppOk,
DummyAppOkLong,
DummyAppNumber,
} DummyAppShortcut;
typedef struct {
InputKey data[MAX_PIN_SIZE];
uint8_t length;
@@ -53,12 +76,11 @@ typedef struct {
} FavoriteApp;
typedef struct {
FavoriteApp favorite_primary;
FavoriteApp favorite_secondary;
FavoriteApp favorite_tertiary;
PinCode pin_code;
uint32_t auto_lock_delay_ms;
uint8_t displayBatteryPercentage;
uint8_t dummy_mode;
uint8_t display_clock;
FavoriteApp favorite_apps[FavoriteAppNumber];
FavoriteApp dummy_apps[DummyAppNumber];
} DesktopSettings;

View File

@@ -87,6 +87,10 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) {
desktop_unlock(desktop);
consumed = true;
break;
case DesktopLockedEventDoorsClosed:
notification_message(desktop->notification, &sequence_display_backlight_off);
consumed = true;
break;
case DesktopLockedEventUpdate:
if(desktop_view_locked_is_locked_hint_visible(desktop->locked_view)) {
notification_message(desktop->notification, &sequence_display_backlight_off);

View File

@@ -61,17 +61,33 @@ static void
}
#endif
static void desktop_scene_main_open_app_or_profile(Desktop* desktop, const char* path) {
if(loader_start_with_gui_error(desktop->loader, path, NULL) != LoaderStatusOk) {
static inline bool desktop_scene_main_check_none(const char* str) {
return (str[1] == '\0' && str[0] == '?');
}
static void desktop_scene_main_open_app_or_profile(Desktop* desktop, FavoriteApp* application) {
bool load_ok = false;
if(strlen(application->name_or_path) > 0) {
if(desktop_scene_main_check_none(application->name_or_path)) {
// skip loading
load_ok = true;
} else if(
loader_start(desktop->loader, application->name_or_path, NULL, NULL) ==
LoaderStatusOk) {
load_ok = true;
}
}
if(!load_ok) {
loader_start(desktop->loader, "Passport", NULL, NULL);
}
}
static void desktop_scene_main_start_favorite(Desktop* desktop, FavoriteApp* application) {
if(strlen(application->name_or_path) > 2) {
loader_start_with_gui_error(desktop->loader, application->name_or_path, NULL);
} else if(
(strlen(application->name_or_path) < 2) && (strcmp(application->name_or_path, "d") != 0)) {
if(strlen(application->name_or_path) > 0) {
if(!desktop_scene_main_check_none(application->name_or_path)) {
loader_start_with_gui_error(desktop->loader, application->name_or_path, NULL);
}
} else {
loader_start(desktop->loader, LOADER_APPLICATIONS_NAME, NULL, NULL);
}
}
@@ -112,6 +128,12 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
consumed = true;
} break;
case DesktopMainEventLock:
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
desktop_lock(desktop);
consumed = true;
break;
case DesktopMainEventOpenLockMenu:
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLockMenu);
consumed = true;
@@ -122,12 +144,6 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
consumed = true;
break;
case DesktopMainEventLock:
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
desktop_lock(desktop);
consumed = true;
break;
case DesktopMainEventOpenArchive:
#ifdef APP_ARCHIVE
desktop_switch_to_app(desktop, &FLIPPER_ARCHIVE);
@@ -141,21 +157,31 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
break;
}
case DesktopMainEventOpenFavoritePrimary:
case DesktopMainEventOpenFavoriteLeftShort:
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_primary);
desktop_scene_main_start_favorite(
desktop, &desktop->settings.favorite_apps[FavoriteAppLeftShort]);
consumed = true;
break;
case DesktopMainEventOpenFavoriteSecondary:
case DesktopMainEventOpenFavoriteLeftLong:
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_secondary);
desktop_scene_main_start_favorite(
desktop, &desktop->settings.favorite_apps[FavoriteAppLeftLong]);
consumed = true;
break;
case DesktopMainEventOpenFavoriteTertiary:
case DesktopMainEventOpenFavoriteRightShort:
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_tertiary);
desktop_scene_main_start_favorite(
desktop, &desktop->settings.favorite_apps[FavoriteAppRightShort]);
consumed = true;
break;
case DesktopMainEventOpenFavoriteRightLong:
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_scene_main_start_favorite(
desktop, &desktop->settings.favorite_apps[FavoriteAppRightLong]);
consumed = true;
break;
case DesktopAnimationEventCheckAnimation:
animation_manager_check_blocking_process(desktop->animation_manager);
consumed = true;
@@ -166,39 +192,57 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
break;
case DesktopAnimationEventInteractAnimation:
if(!animation_manager_interact_process(desktop->animation_manager)) {
loader_start(desktop->loader, "Passport", NULL, NULL);
DESKTOP_SETTINGS_LOAD(&desktop->settings);
if(!desktop->settings.dummy_mode) {
desktop_scene_main_open_app_or_profile(
desktop, &desktop->settings.favorite_apps[FavoriteAppRightShort]);
} else {
desktop_scene_main_open_app_or_profile(
desktop, &desktop->settings.dummy_apps[DummyAppRight]);
}
}
consumed = true;
break;
case DesktopMainEventOpenPassport: {
loader_start(desktop->loader, "Passport", NULL, NULL);
break;
}
case DesktopMainEventOpenGameMenu: {
desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/snake.fap"));
break;
}
case DesktopMainEventOpenTetris: {
desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/tetris.fap"));
break;
}
case DesktopMainEventOpenArkanoid: {
desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/arkanoid.fap"));
break;
}
case DesktopMainEventOpenDOOM: {
desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/doom.fap"));
break;
}
case DesktopMainEventOpenZombiez: {
desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/zombiez.fap"));
break;
}
case DesktopMainEventOpenHeap: {
case DesktopDummyEventOpenLeft:
desktop_scene_main_open_app_or_profile(
desktop, EXT_PATH("/apps/Games/heap_defence.fap"));
desktop, &desktop->settings.dummy_apps[DummyAppLeft]);
break;
}
case DesktopDummyEventOpenDown:
desktop_scene_main_open_app_or_profile(
desktop, &desktop->settings.dummy_apps[DummyAppDown]);
break;
case DesktopDummyEventOpenOk:
desktop_scene_main_open_app_or_profile(
desktop, &desktop->settings.dummy_apps[DummyAppOk]);
break;
case DesktopDummyEventOpenUpLong:
if(!desktop_scene_main_check_none(
desktop->settings.dummy_apps[DummyAppUpLong].name_or_path)) {
desktop_scene_main_open_app_or_profile(
desktop, &desktop->settings.dummy_apps[DummyAppUpLong]);
} else {
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
desktop_lock(desktop);
}
break;
case DesktopDummyEventOpenDownLong:
desktop_scene_main_open_app_or_profile(
desktop, &desktop->settings.dummy_apps[DummyAppDownLong]);
break;
case DesktopDummyEventOpenLeftLong:
desktop_scene_main_open_app_or_profile(
desktop, &desktop->settings.dummy_apps[DummyAppLeftLong]);
break;
case DesktopDummyEventOpenRightLong:
desktop_scene_main_open_app_or_profile(
desktop, &desktop->settings.dummy_apps[DummyAppRightLong]);
break;
case DesktopDummyEventOpenOkLong:
desktop_scene_main_open_app_or_profile(
desktop, &desktop->settings.dummy_apps[DummyAppOkLong]);
break;
case DesktopLockedEventUpdate:
desktop_view_locked_update(desktop->locked_view);
consumed = true;

View File

@@ -1,27 +1,30 @@
#pragma once
typedef enum {
DesktopMainEventLock,
DesktopMainEventOpenLockMenu,
DesktopMainEventOpenArchive,
DesktopMainEventOpenFavoritePrimary,
DesktopMainEventOpenFavoriteSecondary,
DesktopMainEventOpenFavoriteTertiary,
DesktopMainEventOpenFavoriteLeftShort,
DesktopMainEventOpenFavoriteLeftLong,
DesktopMainEventOpenFavoriteRightShort,
DesktopMainEventOpenFavoriteRightLong,
DesktopMainEventOpenMenu,
DesktopMainEventOpenDebug,
DesktopMainEventOpenPassport,
DesktopMainEventOpenPowerOff,
DesktopMainEventLock,
DesktopMainEventOpenGameMenu,
DesktopMainEventOpenTetris,
DesktopMainEventOpenArkanoid,
DesktopMainEventOpenDOOM,
DesktopMainEventOpenZombiez,
DesktopMainEventOpenHeap,
DesktopDummyEventOpenLeft,
DesktopDummyEventOpenDown,
DesktopDummyEventOpenOk,
DesktopDummyEventOpenUpLong,
DesktopDummyEventOpenDownLong,
DesktopDummyEventOpenLeftLong,
DesktopDummyEventOpenRightLong,
DesktopDummyEventOpenOkLong,
DesktopLockedEventUnlocked,
DesktopLockedEventUpdate,
DesktopLockedEventShowPinInput,
DesktopLockedEventDoorsClosed,
DesktopPinInputEventResetWrongPinLabel,
DesktopPinInputEventUnlocked,

View File

@@ -99,6 +99,7 @@ void desktop_view_locked_update(DesktopViewLocked* locked_view) {
if(view_state == DesktopViewLockedStateDoorsClosing &&
!desktop_view_locked_doors_move(model)) {
locked_view->callback(DesktopLockedEventDoorsClosed, locked_view->context);
model->view_state = DesktopViewLockedStateLocked;
} else if(view_state == DesktopViewLockedStateLockedHintShown) {
model->view_state = DesktopViewLockedStateLocked;
@@ -223,8 +224,7 @@ void desktop_view_locked_close_doors(DesktopViewLocked* locked_view) {
void desktop_view_locked_lock(DesktopViewLocked* locked_view, bool pin_locked) {
DesktopViewLockedModel* model = view_get_model(locked_view->view);
// TODO: Fix!!!!!!!!!!!
//furi_assert(model->view_state == DesktopViewLockedStateUnlocked);
furi_assert(model->view_state == DesktopViewLockedStateUnlocked);
model->view_state = DesktopViewLockedStateLocked;
model->pin_locked = pin_locked;
view_commit_model(locked_view->view, true);

View File

@@ -59,18 +59,18 @@ bool desktop_main_input_callback(InputEvent* event, void* context) {
} else if(event->key == InputKeyDown) {
main_view->callback(DesktopMainEventOpenArchive, main_view->context);
} else if(event->key == InputKeyLeft) {
main_view->callback(DesktopMainEventOpenFavoritePrimary, main_view->context);
main_view->callback(DesktopMainEventOpenFavoriteLeftShort, main_view->context);
}
// Right key is handled by animation manager
// Right key short is handled by animation manager
} else if(event->type == InputTypeLong) {
if(event->key == InputKeyDown) {
if(event->key == InputKeyUp) {
main_view->callback(DesktopMainEventLock, main_view->context);
} else if(event->key == InputKeyDown) {
main_view->callback(DesktopMainEventOpenDebug, main_view->context);
} else if(event->key == InputKeyLeft) {
main_view->callback(DesktopMainEventOpenFavoriteSecondary, main_view->context);
main_view->callback(DesktopMainEventOpenFavoriteLeftLong, main_view->context);
} else if(event->key == InputKeyRight) {
main_view->callback(DesktopMainEventOpenFavoriteTertiary, main_view->context);
} else if(event->key == InputKeyUp) {
main_view->callback(DesktopMainEventLock, main_view->context);
main_view->callback(DesktopMainEventOpenFavoriteRightLong, main_view->context);
} else if(event->key == InputKeyOk) {
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
main_view->callback(DesktopAnimationEventNewIdleAnimation, main_view->context);
@@ -80,31 +80,30 @@ bool desktop_main_input_callback(InputEvent* event, void* context) {
} else {
if(event->type == InputTypeShort) {
if(event->key == InputKeyOk) {
main_view->callback(
DesktopMainEventOpenGameMenu, main_view->context); // OPENS Snake
main_view->callback(DesktopDummyEventOpenOk, main_view->context);
} else if(event->key == InputKeyUp) {
main_view->callback(DesktopMainEventOpenLockMenu, main_view->context);
} else if(event->key == InputKeyDown) {
main_view->callback(
DesktopMainEventOpenTetris, main_view->context); // OPENS Tetris
main_view->callback(DesktopDummyEventOpenDown, main_view->context);
} else if(event->key == InputKeyLeft) {
main_view->callback(
DesktopMainEventOpenArkanoid, main_view->context); // OPENS Arkanoid
main_view->callback(DesktopDummyEventOpenLeft, main_view->context);
}
// Right key is handled by animation manager
// Right key short is handled by animation manager
} else if(event->type == InputTypeLong) {
if(event->key == InputKeyOk) {
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
main_view->callback(DesktopAnimationEventNewIdleAnimation, main_view->context);
}
// Not working in DummyMode
// if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
// main_view->callback(DesktopAnimationEventNewIdleAnimation, main_view->context);
// }
main_view->callback(DesktopDummyEventOpenOkLong, main_view->context);
} else if(event->key == InputKeyUp) {
main_view->callback(DesktopMainEventOpenDOOM, main_view->context); // OPENS DOOM
main_view->callback(DesktopDummyEventOpenUpLong, main_view->context);
} else if(event->key == InputKeyDown) {
main_view->callback(
DesktopMainEventOpenZombiez, main_view->context); // OPENS Zombiez
main_view->callback(DesktopDummyEventOpenDownLong, main_view->context);
} else if(event->key == InputKeyLeft) {
main_view->callback(
DesktopMainEventOpenHeap, main_view->context); // OPENS Heap Defence
main_view->callback(DesktopDummyEventOpenLeftLong, main_view->context);
} else if(event->key == InputKeyRight) {
main_view->callback(DesktopDummyEventOpenRightLong, main_view->context);
}
}
}

View File

@@ -236,11 +236,11 @@ static size_t
}
if(len_px > px_left) {
uint8_t excess_symbols_approximately =
roundf((float)(len_px - px_left) / ((float)len_px / (float)text_size));
size_t excess_symbols_approximately =
ceilf((float)(len_px - px_left) / ((float)len_px / (float)text_size));
// reduce to 5 to be sure dash fit, and next line will be at least 5 symbols long
if(excess_symbols_approximately > 0) {
excess_symbols_approximately = MAX(excess_symbols_approximately, 5);
excess_symbols_approximately = MAX(excess_symbols_approximately, 5u);
result = text_size - excess_symbols_approximately - 1;
} else {
result = text_size;

View File

@@ -29,6 +29,9 @@ typedef struct {
const Icon* name_selected;
} IconElement;
LIST_DEF(IconList, IconElement, M_POD_OPLIST)
#define M_OPL_IconList_t() LIST_OPLIST(IconList)
typedef struct ButtonItem {
uint32_t index;
ButtonItemCallback callback;
@@ -47,6 +50,7 @@ struct ButtonPanel {
typedef struct {
ButtonMatrix_t button_matrix;
IconList_t icons;
LabelList_t labels;
uint16_t reserve_x;
uint16_t reserve_y;
@@ -114,7 +118,6 @@ void button_panel_reserve(ButtonPanel* button_panel, size_t reserve_x, size_t re
ButtonArray_t* array = ButtonMatrix_get(model->button_matrix, i);
ButtonArray_init(*array);
ButtonArray_reserve(*array, reserve_x);
// TODO: do we need to clear allocated memory of ptr-s to ButtonItem ??
}
LabelList_init(model->labels);
},
@@ -158,6 +161,7 @@ void button_panel_reset(ButtonPanel* button_panel) {
model->selected_item_x = 0;
model->selected_item_y = 0;
LabelList_reset(model->labels);
IconList_reset(model->icons);
ButtonMatrix_reset(model->button_matrix);
},
true);
@@ -220,9 +224,17 @@ static void button_panel_view_draw_callback(Canvas* canvas, void* _model) {
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
for
M_EACH(icon, model->icons, IconList_t) {
canvas_draw_icon(canvas, icon->x, icon->y, icon->name);
}
for(size_t x = 0; x < model->reserve_x; ++x) {
for(size_t y = 0; y < model->reserve_y; ++y) {
ButtonItem* button_item = *button_panel_get_item(model, x, y);
if(!button_item) {
continue;
}
const Icon* icon_name = button_item->icon.name;
if((model->selected_item_x == x) && (model->selected_item_y == y)) {
icon_name = button_item->icon.name_selected;
@@ -418,3 +430,24 @@ void button_panel_add_label(
},
true);
}
// Draw an icon but don't make it a button.
void button_panel_add_icon(
ButtonPanel* button_panel,
uint16_t x,
uint16_t y,
const Icon* icon_name) {
furi_assert(button_panel);
with_view_model( //-V773
button_panel->view,
ButtonPanelModel * model,
{
IconElement* icon = IconList_push_raw(model->icons);
icon->x = x;
icon->y = y;
icon->name = icon_name;
icon->name_selected = icon_name;
},
true);
}

View File

@@ -106,6 +106,19 @@ void button_panel_add_label(
Font font,
const char* label_str);
/** Add a non-button icon to button_panel module.
*
* @param button_panel ButtonPanel instance
* @param x x-coordinate to place icon
* @param y y-coordinate to place icon
* @param icon_name name of the icon to draw
*/
void button_panel_add_icon(
ButtonPanel* button_panel,
uint16_t x,
uint16_t y,
const Icon* icon_name);
#ifdef __cplusplus
}
#endif

View File

@@ -272,7 +272,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
} else if(view_dispatcher->navigation_event_callback) {
// Dispatch navigation event
if(!view_dispatcher->navigation_event_callback(view_dispatcher->event_context)) {
// TODO: should we allow view_dispatcher to stop without navigation_event_callback?
// TODO FL-3514: should we allow view_dispatcher to stop without navigation_event_callback?
view_dispatcher_stop(view_dispatcher);
return;
}

View File

@@ -7,7 +7,7 @@
#include "gui.h"
#include "gui_i.h"
// TODO add mutex to view_port ops
// TODO FL-3498: add mutex to view_port ops
_Static_assert(ViewPortOrientationMAX == 4, "Incorrect ViewPortOrientation count");
_Static_assert(

View File

@@ -1,4 +1,5 @@
#include "loader.h"
#include "core/core_defines.h"
#include "loader_i.h"
#include <applications.h>
#include <storage/storage.h>
@@ -61,7 +62,7 @@ LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const
dialog_message_free(message);
furi_record_close(RECORD_DIALOGS);
} else if(status == LoaderStatusErrorUnknownApp || status == LoaderStatusErrorInternal) {
// TODO: we have many places where we can emit a double start, ex: desktop, menu
// TODO FL-3522: we have many places where we can emit a double start, ex: desktop, menu
// so i prefer to not show LoaderStatusErrorAppStarted error message for now
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessage* message = dialog_message_alloc();
@@ -186,18 +187,25 @@ static FlipperInternalApplication const* loader_find_application_by_name_in_list
}
static const FlipperInternalApplication* loader_find_application_by_name(const char* name) {
const FlipperInternalApplication* application = NULL;
application = loader_find_application_by_name_in_list(name, FLIPPER_APPS, FLIPPER_APPS_COUNT);
if(!application) {
application = loader_find_application_by_name_in_list(
name, FLIPPER_SETTINGS_APPS, FLIPPER_SETTINGS_APPS_COUNT);
}
if(!application) {
application = loader_find_application_by_name_in_list(
name, FLIPPER_SYSTEM_APPS, FLIPPER_SYSTEM_APPS_COUNT);
const struct {
const FlipperInternalApplication* list;
const uint32_t count;
} lists[] = {
{FLIPPER_APPS, FLIPPER_APPS_COUNT},
{FLIPPER_SETTINGS_APPS, FLIPPER_SETTINGS_APPS_COUNT},
{FLIPPER_SYSTEM_APPS, FLIPPER_SYSTEM_APPS_COUNT},
{FLIPPER_DEBUG_APPS, FLIPPER_DEBUG_APPS_COUNT},
};
for(size_t i = 0; i < COUNT_OF(lists); i++) {
const FlipperInternalApplication* application =
loader_find_application_by_name_in_list(name, lists[i].list, lists[i].count);
if(application) {
return application;
}
}
return application;
return NULL;
}
static void loader_start_app_thread(Loader* loader, FlipperInternalApplicationFlag flags) {
@@ -253,9 +261,7 @@ static void loader_log_status_error(
furi_string_vprintf(error_message, format, args);
FURI_LOG_E(TAG, "Status [%d]: %s", status, furi_string_get_cstr(error_message));
} else {
FuriString* tmp = furi_string_alloc();
FURI_LOG_E(TAG, "Status [%d]: %s", status, furi_string_get_cstr(tmp));
furi_string_free(tmp);
FURI_LOG_E(TAG, "Status [%d]", status);
}
}
@@ -527,7 +533,9 @@ int32_t loader_srv(void* p) {
FLIPPER_ON_SYSTEM_START[i]();
}
if(FLIPPER_AUTORUN_APP_NAME && strlen(FLIPPER_AUTORUN_APP_NAME)) {
if((furi_hal_rtc_get_boot_mode() == FuriHalRtcBootModeNormal) && FLIPPER_AUTORUN_APP_NAME &&
strlen(FLIPPER_AUTORUN_APP_NAME)) {
FURI_LOG_I(TAG, "Starting autorun app: %s", FLIPPER_AUTORUN_APP_NAME);
loader_do_start_by_name(loader, FLIPPER_AUTORUN_APP_NAME, NULL, NULL);
}

View File

@@ -28,7 +28,7 @@ static void loader_cli_info(Loader* loader) {
if(!loader_is_locked(loader)) {
printf("No application is running\r\n");
} else {
// TODO: print application name ???
// TODO FL-3513: print application name ???
printf("Application is running\r\n");
}
}

View File

@@ -279,7 +279,7 @@ static void rpc_system_gui_start_virtual_display_process(const PB_Main* request,
return;
}
// TODO: consider refactoring
// TODO FL-3511: consider refactoring
// Using display framebuffer size as an XBM buffer size is like comparing apples and oranges
// Glad they both are 1024 for now
size_t buffer_size = canvas_get_buffer_size(rpc_gui->gui->canvas);

View File

@@ -399,7 +399,7 @@ static FS_Error storage_process_common_fs_info(
}
/****************** Raw SD API ******************/
// TODO think about implementing a custom storage API to split that kind of api linkage
// TODO FL-3521: think about implementing a custom storage API to split that kind of api linkage
#include "storages/storage_ext.h"
static FS_Error storage_process_sd_format(Storage* app) {

View File

@@ -100,7 +100,7 @@ FS_Error sd_unmount_card(StorageData* storage) {
storage->status = StorageStatusNotReady;
error = FR_DISK_ERR;
// TODO do i need to close the files?
// TODO FL-3522: do i need to close the files?
f_mount(0, sd_data->path, 0);
return storage_ext_parse_error(error);

View File

@@ -1,19 +1,25 @@
#include "../desktop_settings_app.h"
#include "applications.h"
#include "desktop_settings_scene.h"
#include "desktop_settings_scene_i.h"
#include <flipper_application/flipper_application.h>
#include <storage/storage.h>
#include <dialogs/dialogs.h>
#define APPS_COUNT (FLIPPER_APPS_COUNT + FLIPPER_EXTERNAL_APPS_COUNT)
#define EXTERNAL_BROWSER_NAME ("Apps")
#define EXTERNAL_BROWSER_INDEX (APPS_COUNT + 1)
#define DEFAULT_INDEX (0)
#define EXTERNAL_BROWSER_NAME ("Apps Menu (Default)")
#define PASSPORT_NAME ("Passport (Default)")
#define NONE_APPLICATION_INDEX (1)
#define NONE_APPLICATION_NAME "None (disable)"
#define LOCK_APPLICATION_NAME "Lock Flipper"
#define EXTERNAL_APPLICATION_INDEX (2)
#define EXTERNAL_APPLICATION_NAME ("[Select App]")
#define EXTERNAL_APPLICATION_INDEX (APPS_COUNT + 2)
#define NONE_APPLICATION_INDEX (APPS_COUNT + 3)
#define MAIN_LIST_APPLICATION_OFFSET (3)
#define PRESELECTED_SPECIAL 0xffffffff
@@ -57,40 +63,44 @@ void desktop_settings_scene_favorite_on_enter(void* context) {
Submenu* submenu = app->submenu;
submenu_reset(submenu);
uint32_t primary_favorite =
uint32_t favorite_id =
scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite);
uint32_t pre_select_item = PRESELECTED_SPECIAL;
FavoriteApp* curr_favorite_app = NULL;
if(primary_favorite == 0) {
curr_favorite_app = &app->settings.favorite_primary;
} else if(primary_favorite == 1) {
curr_favorite_app = &app->settings.favorite_secondary;
} else if(primary_favorite == 2) {
curr_favorite_app = &app->settings.favorite_tertiary;
bool is_dummy_app = false;
bool default_passport = false;
bool lock_if_none = false;
if((favorite_id & SCENE_STATE_SET_DUMMY_APP) == 0) {
furi_assert(favorite_id < FavoriteAppNumber);
curr_favorite_app = &app->settings.favorite_apps[favorite_id];
if(favorite_id == FavoriteAppRightShort) {
default_passport = true;
}
} else {
curr_favorite_app = &app->settings.favorite_primary;
}
if(curr_favorite_app == NULL) {
// This should not happen!
return;
}
for(size_t i = 0; i < APPS_COUNT; i++) {
const char* name = favorite_fap_get_app_name(i);
submenu_add_item(submenu, name, i, desktop_settings_scene_favorite_submenu_callback, app);
// Select favorite item in submenu
if(!strcmp(name, curr_favorite_app->name_or_path)) {
pre_select_item = i;
favorite_id &= ~(SCENE_STATE_SET_DUMMY_APP);
furi_assert(favorite_id < DummyAppNumber);
curr_favorite_app = &app->settings.dummy_apps[favorite_id];
is_dummy_app = true;
default_passport = true;
if(favorite_id == DummyAppUpLong) {
lock_if_none = true;
}
}
// Special case: Application browser
submenu_add_item(
submenu,
EXTERNAL_BROWSER_NAME,
EXTERNAL_BROWSER_INDEX,
default_passport ? (PASSPORT_NAME) : (EXTERNAL_BROWSER_NAME),
DEFAULT_INDEX,
desktop_settings_scene_favorite_submenu_callback,
app);
// Special case: None (disable) or Lock Flipper
submenu_add_item(
submenu,
lock_if_none ? (LOCK_APPLICATION_NAME) : (NONE_APPLICATION_NAME),
NONE_APPLICATION_INDEX,
desktop_settings_scene_favorite_submenu_callback,
app);
@@ -102,28 +112,37 @@ void desktop_settings_scene_favorite_on_enter(void* context) {
desktop_settings_scene_favorite_submenu_callback,
app);
if(!is_dummy_app) {
for(size_t i = 0; i < APPS_COUNT; i++) {
const char* name = favorite_fap_get_app_name(i);
submenu_add_item(
submenu,
name,
i + MAIN_LIST_APPLICATION_OFFSET,
desktop_settings_scene_favorite_submenu_callback,
app);
// Select favorite item in submenu
if(!strcmp(name, curr_favorite_app->name_or_path)) {
pre_select_item = i + MAIN_LIST_APPLICATION_OFFSET;
}
}
}
if(pre_select_item == PRESELECTED_SPECIAL) {
if(curr_favorite_app->name_or_path[0] == '\0') {
pre_select_item = EXTERNAL_BROWSER_INDEX;
pre_select_item = DEFAULT_INDEX;
} else if(
(curr_favorite_app->name_or_path[1] == '\0') &&
(curr_favorite_app->name_or_path[0] == '?')) {
pre_select_item = NONE_APPLICATION_INDEX;
} else {
pre_select_item = EXTERNAL_APPLICATION_INDEX;
}
}
submenu_add_item(
submenu,
"None (disable)",
NONE_APPLICATION_INDEX,
desktop_settings_scene_favorite_submenu_callback,
app);
if(primary_favorite == 0) {
submenu_set_header(submenu, "Primary favorite app:");
} else if(primary_favorite == 1) {
submenu_set_header(submenu, "Secondary favorite app:");
} else if(primary_favorite == 2) {
submenu_set_header(submenu, "Tertiary favorite app:");
}
submenu_set_header(submenu, is_dummy_app ? ("Dummy Mode app:") : ("Favorite app:"));
submenu_set_selected_item(submenu, pre_select_item); // If set during loop, visual glitch.
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
@@ -134,28 +153,26 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e
bool consumed = false;
FuriString* temp_path = furi_string_alloc_set_str(EXT_PATH("apps"));
uint32_t primary_favorite =
uint32_t favorite_id =
scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite);
FavoriteApp* curr_favorite_app = NULL;
if(primary_favorite == 0) {
curr_favorite_app = &app->settings.favorite_primary;
} else if(primary_favorite == 1) {
curr_favorite_app = &app->settings.favorite_secondary;
} else if(primary_favorite == 2) {
curr_favorite_app = &app->settings.favorite_tertiary;
if((favorite_id & SCENE_STATE_SET_DUMMY_APP) == 0) {
furi_assert(favorite_id < FavoriteAppNumber);
curr_favorite_app = &app->settings.favorite_apps[favorite_id];
} else {
curr_favorite_app = &app->settings.favorite_primary;
}
if(curr_favorite_app == NULL) {
// This should not happen!
furi_string_free(temp_path);
return consumed;
favorite_id &= ~(SCENE_STATE_SET_DUMMY_APP);
furi_assert(favorite_id < DummyAppNumber);
curr_favorite_app = &app->settings.dummy_apps[favorite_id];
}
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == EXTERNAL_BROWSER_INDEX) {
if(event.event == DEFAULT_INDEX) {
curr_favorite_app->name_or_path[0] = '\0';
consumed = true;
} else if(event.event == NONE_APPLICATION_INDEX) {
curr_favorite_app->name_or_path[0] = '?';
curr_favorite_app->name_or_path[1] = '\0';
consumed = true;
} else if(event.event == EXTERNAL_APPLICATION_INDEX) {
const DialogsFileBrowserOptions browser_options = {
.extension = ".fap",
@@ -180,13 +197,9 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e
MAX_APP_LENGTH);
consumed = true;
}
} else if(event.event == NONE_APPLICATION_INDEX) {
// Clear favorite app path and set it to "d" (disabled)
memset(curr_favorite_app->name_or_path, 0, strlen(curr_favorite_app->name_or_path));
strncpy(curr_favorite_app->name_or_path, "d", MAX_APP_LENGTH);
consumed = true;
} else {
const char* name = favorite_fap_get_app_name(event.event);
size_t app_index = event.event - MAIN_LIST_APPLICATION_OFFSET;
const char* name = favorite_fap_get_app_name(app_index);
if(name) strncpy(curr_favorite_app->name_or_path, name, MAX_APP_LENGTH);
consumed = true;
}

View File

@@ -5,3 +5,6 @@
#define SCENE_STATE_PIN_ERROR_MISMATCH (0)
#define SCENE_STATE_PIN_ERROR_WRONG (1)
#define SCENE_STATE_SET_FAVORITE_APP (0)
#define SCENE_STATE_SET_DUMMY_APP (1 << 8)

View File

@@ -3,16 +3,29 @@
#include "../desktop_settings_app.h"
#include "desktop_settings_scene.h"
#include "desktop_settings_scene_i.h"
#include <power/power_service/power.h>
#define SCENE_EVENT_SELECT_FAVORITE_PRIMARY 0
#define SCENE_EVENT_SELECT_FAVORITE_SECONDARY 1
#define SCENE_EVENT_SELECT_FAVORITE_TERTIARY 2
#define SCENE_EVENT_SELECT_PIN_SETUP 3
#define SCENE_EVENT_SELECT_AUTO_LOCK_DELAY 4
#define SCENE_EVENT_SELECT_BATTERY_DISPLAY 5
#define SCENE_EVENT_SELECT_CLOCK_DISPLAY 6
#define SCENE_EVENT_SELECT_CHANGE_NAME 7
typedef enum {
DesktopSettingsPinSetup = 0,
DesktopSettingsAutoLockDelay,
DesktopSettingsBatteryDisplay,
DesktopSettingsClockDisplay,
DesktopSettingsChangeName,
DesktopSettingsFavoriteLeftShort,
DesktopSettingsFavoriteLeftLong,
DesktopSettingsFavoriteRightShort,
DesktopSettingsFavoriteRightLong,
DesktopSettingsDummyLeft,
DesktopSettingsDummyLeftLong,
DesktopSettingsDummyRight,
DesktopSettingsDummyRightLong,
DesktopSettingsDummyUpLong,
DesktopSettingsDummyDown,
DesktopSettingsDummyDownLong,
DesktopSettingsDummyOk,
DesktopSettingsDummyOkLong,
} DesktopSettingsEntry;
#define AUTO_LOCK_DELAY_COUNT 9
const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = {
@@ -87,12 +100,6 @@ void desktop_settings_scene_start_on_enter(void* context) {
VariableItem* item;
uint8_t value_index;
variable_item_list_add(variable_item_list, "Primary Favorite App", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "Secondary Favorite App", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "Tertiary Favorite App", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "PIN Setup", 1, NULL, NULL);
item = variable_item_list_add(
@@ -102,8 +109,6 @@ void desktop_settings_scene_start_on_enter(void* context) {
desktop_settings_scene_start_auto_lock_delay_changed,
app);
variable_item_list_set_enter_callback(
variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app);
value_index = value_index_uint32(
app->settings.auto_lock_delay_ms, auto_lock_delay_value, AUTO_LOCK_DELAY_COUNT);
variable_item_set_current_value_index(item, value_index);
@@ -137,6 +142,24 @@ void desktop_settings_scene_start_on_enter(void* context) {
variable_item_list_add(variable_item_list, "Change Flipper Name", 0, NULL, app);
variable_item_list_add(variable_item_list, "Favorite App - Left Short", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "Favorite App - Left Long", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "Favorite App - Right Short", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "Favorite App - Right Long", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "DummyMode - Left", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "DummyMode - Left Long", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "DummyMode - Right", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "DummyMode - Right Long", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "DummyMode - Up Long", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "DummyMode - Down", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "DummyMode - Down Long", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "DummyMode - Ok", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "DummyMode - Ok Long", 1, NULL, NULL);
variable_item_list_set_enter_callback(
variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app);
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList);
}
@@ -146,35 +169,116 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even
if(event.type == SceneManagerEventTypeCustom) {
switch(event.event) {
case SCENE_EVENT_SELECT_FAVORITE_PRIMARY:
scene_manager_set_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite, 0);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
consumed = true;
break;
case SCENE_EVENT_SELECT_FAVORITE_SECONDARY:
scene_manager_set_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite, 1);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
consumed = true;
break;
case SCENE_EVENT_SELECT_FAVORITE_TERTIARY:
scene_manager_set_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite, 2);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
consumed = true;
break;
case SCENE_EVENT_SELECT_PIN_SETUP:
case DesktopSettingsPinSetup:
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinMenu);
consumed = true;
break;
case SCENE_EVENT_SELECT_AUTO_LOCK_DELAY:
case SCENE_EVENT_SELECT_CLOCK_DISPLAY:
case SCENE_EVENT_SELECT_BATTERY_DISPLAY:
consumed = true;
break;
case SCENE_EVENT_SELECT_CHANGE_NAME:
// case DesktopSettingsAutoLockDelay:
// case DesktopSettingsBatteryDisplay:
// case DesktopSettingsClockDisplay:
// Proces in default
case DesktopSettingsChangeName:
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneChangeName);
consumed = true;
break;
case DesktopSettingsFavoriteLeftShort:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_FAVORITE_APP | FavoriteAppLeftShort);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsFavoriteLeftLong:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_FAVORITE_APP | FavoriteAppLeftLong);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsFavoriteRightShort:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_FAVORITE_APP | FavoriteAppRightShort);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsFavoriteRightLong:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_FAVORITE_APP | FavoriteAppRightLong);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsDummyLeft:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_DUMMY_APP | DummyAppLeft);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsDummyLeftLong:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_DUMMY_APP | DummyAppLeftLong);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsDummyRight:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_DUMMY_APP | DummyAppRight);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsDummyRightLong:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_DUMMY_APP | DummyAppRightLong);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsDummyUpLong:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_DUMMY_APP | DummyAppUpLong);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsDummyDown:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_DUMMY_APP | DummyAppDown);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsDummyDownLong:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_DUMMY_APP | DummyAppDownLong);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsDummyOk:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_DUMMY_APP | DummyAppOk);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
case DesktopSettingsDummyOkLong:
scene_manager_set_scene_state(
app->scene_manager,
DesktopSettingsAppSceneFavorite,
SCENE_STATE_SET_DUMMY_APP | DummyAppOkLong);
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
break;
default:
break;
}
consumed = true;
}
return consumed;
}

View File

@@ -80,7 +80,7 @@ bool updater_scene_main_on_event(void* context, SceneManagerEvent event) {
break;
case UpdaterCustomEventSdUnmounted:
// TODO: error out, stop worker (it's probably dead actually)
// TODO FL-3499: error out, stop worker (it's probably dead actually)
break;
default:
break;