New Locale Settings API & Fix for long filenames

This commit is contained in:
VerstreuteSeele
2022-12-19 01:01:05 +01:00
parent 4c509ba243
commit febc6d4284
13 changed files with 529 additions and 56 deletions

View File

@@ -0,0 +1,11 @@
App(
appid="locale_test",
name="Locale Test",
apptype=FlipperAppType.DEBUG,
entry_point="locale_test_app",
cdefines=["APP_LOCALE"],
requires=["gui", "locale"],
stack_size=2 * 1024,
order=70,
fap_category="Debug",
)

View File

@@ -0,0 +1,102 @@
#include <furi.h>
#include <gui/gui.h>
#include <gui/elements.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/dialog_ex.h>
#include <locale/locale.h>
typedef struct {
Gui* gui;
ViewDispatcher* view_dispatcher;
View* view;
} LocaleTestApp;
static void locale_test_view_draw_callback(Canvas* canvas, void* _model) {
UNUSED(_model);
// Prepare canvas
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
FuriString* tmp_string = furi_string_alloc();
float temp = 25.3f;
LocaleMeasurementUnit units = locale_get_measurement_unit();
if(units == LocaleMeasurementUnitMetric) {
furi_string_printf(tmp_string, "Temp: %5.1fC", (double)temp);
} else {
temp = locale_celsius_to_fahrenheit(temp);
furi_string_printf(tmp_string, "Temp: %5.1fF", (double)temp);
}
canvas_draw_str(canvas, 0, 10, furi_string_get_cstr(tmp_string));
FuriHalRtcDateTime datetime;
furi_hal_rtc_get_datetime(&datetime);
locale_format_time(tmp_string, &datetime, locale_get_time_format(), false);
canvas_draw_str(canvas, 0, 25, furi_string_get_cstr(tmp_string));
locale_format_date(tmp_string, &datetime, locale_get_date_format(), "/");
canvas_draw_str(canvas, 0, 40, furi_string_get_cstr(tmp_string));
furi_string_free(tmp_string);
}
static bool locale_test_view_input_callback(InputEvent* event, void* context) {
UNUSED(event);
UNUSED(context);
return false;
}
static uint32_t locale_test_exit(void* context) {
UNUSED(context);
return VIEW_NONE;
}
static LocaleTestApp* locale_test_alloc() {
LocaleTestApp* app = malloc(sizeof(LocaleTestApp));
// Gui
app->gui = furi_record_open(RECORD_GUI);
// View dispatcher
app->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(app->view_dispatcher);
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
// Views
app->view = view_alloc();
view_set_draw_callback(app->view, locale_test_view_draw_callback);
view_set_input_callback(app->view, locale_test_view_input_callback);
view_set_previous_callback(app->view, locale_test_exit);
view_dispatcher_add_view(app->view_dispatcher, 0, app->view);
view_dispatcher_switch_to_view(app->view_dispatcher, 0);
return app;
}
static void locale_test_free(LocaleTestApp* app) {
furi_assert(app);
// Free views
view_dispatcher_remove_view(app->view_dispatcher, 0);
view_free(app->view);
view_dispatcher_free(app->view_dispatcher);
// Close gui record
furi_record_close(RECORD_GUI);
app->gui = NULL;
// Free rest
free(app);
}
int32_t locale_test_app(void* p) {
UNUSED(p);
LocaleTestApp* app = locale_test_alloc();
view_dispatcher_run(app->view_dispatcher);
locale_test_free(app);
return 0;
}

View File

@@ -532,21 +532,21 @@ void elements_bubble_str(
canvas_draw_line(canvas, x2, y2, x3, y3); canvas_draw_line(canvas, x2, y2, x3, y3);
} }
void elements_string_fit_width(Canvas* canvas, FuriString* string, uint8_t width) {
void elements_string_fit_width_trunc(Canvas* canvas, FuriString* string, uint8_t width) {
furi_assert(canvas); furi_assert(canvas);
furi_assert(string); furi_assert(string);
uint16_t len_px = canvas_string_width(canvas, furi_string_get_cstr(string)); uint16_t len_px = canvas_string_width(canvas, furi_string_get_cstr(string));
if(len_px > width) { if(len_px > width) {
width -= canvas_string_width(canvas, "...");
do { do {
furi_string_left(string, furi_string_size(string) - 1); furi_string_left(string, furi_string_size(string) - 1);
len_px = canvas_string_width(canvas, furi_string_get_cstr(string)); len_px = canvas_string_width(canvas, furi_string_get_cstr(string));
} while(len_px > width); } while(len_px > width);
furi_string_cat(string, "...");
} }
} }
void elements_text_box( void elements_text_box(
Canvas* canvas, Canvas* canvas,
uint8_t x, uint8_t x,

View File

@@ -192,6 +192,15 @@ void elements_bubble_str(
*/ */
void elements_string_fit_width(Canvas* canvas, FuriString* string, uint8_t width); void elements_string_fit_width(Canvas* canvas, FuriString* string, uint8_t width);
/** Trim string buffer to fit width in pixels. If the string is longer it truncates without ellipsis (...)
*
* @param canvas Canvas instance
* @param string string to trim
* @param width max width
*/
void elements_string_fit_width_trunc(Canvas* canvas, FuriString* string, uint8_t width);
/** Draw text box element /** Draw text box element
* *
* @param canvas Canvas instance * @param canvas Canvas instance

View File

@@ -5,8 +5,6 @@
#include <core/common_defines.h> #include <core/common_defines.h>
#include <core/log.h> #include <core/log.h>
#include "furi_hal_resources.h" #include "furi_hal_resources.h"
#include "m-string.h"
#include "m-algo.h"
#include <m-array.h> #include <m-array.h>
#include <gui/elements.h> #include <gui/elements.h>
#include <furi.h> #include <furi.h>
@@ -72,30 +70,14 @@ static void BrowserItem_t_clear(BrowserItem_t* obj) {
free(obj->custom_icon_data); free(obj->custom_icon_data);
} }
} }
ARRAY_DEF(
static int BrowserItem_t_cmp(const BrowserItem_t* a, const BrowserItem_t* b) { items_array,
// Back indicator comes before everything, then folders, then all other files. BrowserItem_t,
if((a->type == BrowserItemTypeBack) || (INIT(API_2(BrowserItem_t_init)),
(a->type == BrowserItemTypeFolder && b->type != BrowserItemTypeFolder && SET(API_6(BrowserItem_t_set)),
b->type != BrowserItemTypeBack)) { INIT_SET(API_6(BrowserItem_t_init_set)),
return -1; CLEAR(API_2(BrowserItem_t_clear))))
}
return furi_string_cmp(a->path, b->path);
}
#define M_OPL_BrowserItem_t() \
(INIT(API_2(BrowserItem_t_init)), \
SET(API_6(BrowserItem_t_set)), \
INIT_SET(API_6(BrowserItem_t_init_set)), \
CLEAR(API_2(BrowserItem_t_clear)), \
CMP(API_6(BrowserItem_t_cmp)), \
SWAP(M_SWAP_DEFAULT), \
EQUAL(API_6(M_EQUAL_DEFAULT)))
ARRAY_DEF(items_array, BrowserItem_t)
ALGO_DEF(items_array, ARRAY_OPLIST(items_array, M_OPL_BrowserItem_t()))
struct FileBrowser { struct FileBrowser {
View* view; View* view;
@@ -112,6 +94,8 @@ struct FileBrowser {
FileBrowserLoadItemCallback item_callback; FileBrowserLoadItemCallback item_callback;
void* item_context; void* item_context;
FuriTimer* timer;
FuriString* result_path; FuriString* result_path;
}; };
@@ -126,6 +110,8 @@ typedef struct {
int32_t array_offset; int32_t array_offset;
int32_t list_offset; int32_t list_offset;
FuriString* current_filename;
const Icon* file_icon; const Icon* file_icon;
bool hide_ext; bool hide_ext;
} FileBrowserModel; } FileBrowserModel;
@@ -139,6 +125,9 @@ static const Icon* BrowserItemIcons[] = {
static void file_browser_view_draw_callback(Canvas* canvas, void* _model); static void file_browser_view_draw_callback(Canvas* canvas, void* _model);
static bool file_browser_view_input_callback(InputEvent* event, void* context); static bool file_browser_view_input_callback(InputEvent* event, void* context);
static void file_browser_animate_filename_callback(void* context);
static const char* file_browser_get_selected_filename(FileBrowserModel* model);
static void static void
browser_folder_open_cb(void* context, uint32_t item_cnt, int32_t file_idx, bool is_root); browser_folder_open_cb(void* context, uint32_t item_cnt, int32_t file_idx, bool is_root);
@@ -157,9 +146,17 @@ FileBrowser* file_browser_alloc(FuriString* result_path) {
view_set_input_callback(browser->view, file_browser_view_input_callback); view_set_input_callback(browser->view, file_browser_view_input_callback);
browser->result_path = result_path; browser->result_path = result_path;
browser->timer =
furi_timer_alloc(file_browser_animate_filename_callback, FuriTimerTypePeriodic, browser);
with_view_model( with_view_model(
browser->view, FileBrowserModel * model, { items_array_init(model->items); }, false); browser->view,
FileBrowserModel * model,
{
items_array_init(model->items);
model->current_filename = furi_string_alloc();
},
false);
return browser; return browser;
} }
@@ -168,9 +165,16 @@ void file_browser_free(FileBrowser* browser) {
furi_assert(browser); furi_assert(browser);
with_view_model( with_view_model(
browser->view, FileBrowserModel * model, { items_array_clear(model->items); }, false); browser->view,
FileBrowserModel * model,
{
items_array_clear(model->items);
furi_string_free(model->current_filename);
},
false);
view_free(browser->view); view_free(browser->view);
furi_timer_free(browser->timer);
free(browser); free(browser);
} }
@@ -232,8 +236,10 @@ void file_browser_stop(FileBrowser* browser) {
model->item_idx = 0; model->item_idx = 0;
model->array_offset = 0; model->array_offset = 0;
model->list_offset = 0; model->list_offset = 0;
furi_string_set(model->current_filename, "");
}, },
false); false);
furi_timer_stop(browser->timer);
} }
void file_browser_set_callback(FileBrowser* browser, FileBrowserCallback callback, void* context) { void file_browser_set_callback(FileBrowser* browser, FileBrowserCallback callback, void* context) {
@@ -336,6 +342,7 @@ static void
model->is_root = is_root; model->is_root = is_root;
model->list_loading = true; model->list_loading = true;
model->folder_loading = false; model->folder_loading = false;
furi_string_set(model->current_filename, file_browser_get_selected_filename(model));
}, },
true); true);
browser_update_offset(browser); browser_update_offset(browser);
@@ -420,13 +427,7 @@ static void
} }
} else { } else {
with_view_model( with_view_model(
browser->view, browser->view, FileBrowserModel * model, { model->list_loading = false; }, true);
FileBrowserModel * model,
{
items_array_sort(model->items);
model->list_loading = false;
},
true);
} }
} }
@@ -492,8 +493,17 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) {
furi_string_set(filename, ". ."); furi_string_set(filename, ". .");
} }
elements_string_fit_width( uint8_t frame_width = (show_scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX);
canvas, filename, (show_scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX));
bool is_long_filename = canvas_string_width(canvas, furi_string_get_cstr(filename)) >
frame_width;
if(is_long_filename && model->item_idx == idx) {
furi_string_set(filename, model->current_filename);
elements_string_fit_width_trunc(canvas, filename, frame_width);
} else {
elements_string_fit_width(canvas, filename, frame_width);
}
if(model->item_idx == idx) { if(model->item_idx == idx) {
browser_draw_frame(canvas, i, show_scrollbar); browser_draw_frame(canvas, i, show_scrollbar);
@@ -538,6 +548,36 @@ static void file_browser_view_draw_callback(Canvas* canvas, void* _model) {
} }
} }
static void file_browser_animate_filename_callback(void* context) {
furi_assert(context);
FileBrowser* browser = context;
with_view_model(
browser->view,
FileBrowserModel * model,
{
FuriString* old_filename;
old_filename = furi_string_alloc();
furi_string_set(old_filename, model->current_filename);
furi_string_left(old_filename, 1);
furi_string_right(model->current_filename, 1);
furi_string_cat(model->current_filename, old_filename);
furi_string_free(old_filename);
},
true);
}
static const char* file_browser_get_selected_filename(FileBrowserModel* model) {
furi_assert(model);
BrowserItem_t* selected_item = NULL;
if(browser_is_item_in_array(model, model->item_idx)) {
selected_item = items_array_get(model->items, model->item_idx - model->array_offset);
return furi_string_get_cstr(selected_item->display_name);
}
return "";
}
static bool file_browser_view_input_callback(InputEvent* event, void* context) { static bool file_browser_view_input_callback(InputEvent* event, void* context) {
FileBrowser* browser = context; FileBrowser* browser = context;
furi_assert(browser); furi_assert(browser);
@@ -558,6 +598,10 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
if(event->key == InputKeyUp) { if(event->key == InputKeyUp) {
model->item_idx = model->item_idx =
((model->item_idx - 1) + model->item_cnt) % model->item_cnt; ((model->item_idx - 1) + model->item_cnt) % model->item_cnt;
furi_string_set(
model->current_filename, file_browser_get_selected_filename(model));
furi_string_cat(model->current_filename, " ");
furi_timer_start(browser->timer, 250);
if(browser_is_list_load_required(model)) { if(browser_is_list_load_required(model)) {
model->list_loading = true; model->list_loading = true;
int32_t load_offset = CLAMP( int32_t load_offset = CLAMP(
@@ -569,6 +613,10 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
} }
} else if(event->key == InputKeyDown) { } else if(event->key == InputKeyDown) {
model->item_idx = (model->item_idx + 1) % model->item_cnt; model->item_idx = (model->item_idx + 1) % model->item_cnt;
furi_string_set(
model->current_filename, file_browser_get_selected_filename(model));
furi_string_cat(model->current_filename, " ");
furi_timer_start(browser->timer, 250);
if(browser_is_list_load_required(model)) { if(browser_is_list_load_required(model)) {
model->list_loading = true; model->list_loading = true;
int32_t load_offset = CLAMP( int32_t load_offset = CLAMP(
@@ -644,4 +692,4 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
} }
return consumed; return consumed;
} }

View File

@@ -0,0 +1,9 @@
App(
appid="locale",
name="LocaleSrv",
apptype=FlipperAppType.STARTUP,
entry_point="locale_on_system_start",
cdefines=["SRV_LOCALE"],
order=90,
sdk_headers=["locale.h"],
)

View File

@@ -0,0 +1,109 @@
#include "locale.h"
#define TAG "LocaleSrv"
LocaleMeasurementUnit locale_get_measurement_unit(void) {
return furi_hal_rtc_get_locale_units();
}
void locale_set_measurement_unit(LocaleMeasurementUnit format) {
furi_hal_rtc_set_locale_units(format);
}
LocaleTimeFormat locale_get_time_format(void) {
return furi_hal_rtc_get_locale_timeformat();
}
void locale_set_time_format(LocaleTimeFormat format) {
furi_hal_rtc_set_locale_timeformat(format);
}
LocaleDateFormat locale_get_date_format(void) {
return furi_hal_rtc_get_locale_dateformat();
}
void locale_set_date_format(LocaleDateFormat format) {
furi_hal_rtc_set_locale_dateformat(format);
}
float locale_fahrenheit_to_celsius(float temp_f) {
return (temp_f - 32.f) / 1.8f;
}
float locale_celsius_to_fahrenheit(float temp_c) {
return (temp_c * 1.8f + 32.f);
}
void locale_format_time(
FuriString* out_str,
FuriHalRtcDateTime* datetime,
LocaleTimeFormat format,
bool show_seconds) {
furi_assert(out_str);
furi_assert(datetime);
uint8_t hours = datetime->hour;
uint8_t am_pm = 0;
if(format == LocaleTimeFormat12h) {
if(hours > 12) {
hours -= 12;
am_pm = 2;
} else {
am_pm = 1;
}
}
if(show_seconds) {
furi_string_printf(out_str, "%02u:%02u:%02u", hours, datetime->minute, datetime->second);
} else {
furi_string_printf(out_str, "%02u:%02u", hours, datetime->minute);
}
if(am_pm > 0) {
furi_string_cat_printf(out_str, " %s", (am_pm == 1) ? ("AM") : ("PM"));
}
}
void locale_format_date(
FuriString* out_str,
FuriHalRtcDateTime* datetime,
LocaleDateFormat format,
char* separator) {
furi_assert(out_str);
furi_assert(datetime);
furi_assert(separator);
if(format == LocaleDateFormatDMY) {
furi_string_printf(
out_str,
"%02u%s%02u%s%04u",
datetime->day,
separator,
datetime->month,
separator,
datetime->year);
} else if(format == LocaleDateFormatMDY) {
furi_string_printf(
out_str,
"%02u%s%02u%s%04u",
datetime->month,
separator,
datetime->day,
separator,
datetime->year);
} else {
furi_string_printf(
out_str,
"%04u%s%02u%s%02u",
datetime->year,
separator,
datetime->month,
separator,
datetime->day);
}
}
int32_t locale_on_system_start(void* p) {
UNUSED(p);
return 0;
}

View File

@@ -0,0 +1,53 @@
#pragma once
#include <stdbool.h>
#include <furi.h>
#include <furi_hal.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
LocaleMeasurementUnitMetric = 0, /**< Meric mesurement units */
LocaleMeasurementUnitImperial, /**< Imperial mesurement units */
} LocaleMeasurementUnit;
typedef enum {
LocaleTimeFormat24h = 0, /**< 24-hour format */
LocaleTimeFormat12h, /**< 12-hour format */
} LocaleTimeFormat;
typedef enum {
LocaleDateFormatDMY = 0, /**< Day/Month/Year */
LocaleDateFormatMDY, /**< Month/Day/Year */
LocaleDateFormatYMD, /**< Year/Month/Day */
} LocaleDateFormat;
LocaleMeasurementUnit locale_get_measurement_unit(void);
void locale_set_measurement_unit(LocaleMeasurementUnit format);
float locale_fahrenheit_to_celsius(float temp_f);
float locale_celsius_to_fahrenheit(float temp_c);
LocaleTimeFormat locale_get_time_format(void);
void locale_set_time_format(LocaleTimeFormat format);
void locale_format_time(
FuriString* out_str,
FuriHalRtcDateTime* datetime,
LocaleTimeFormat format,
bool show_seconds);
LocaleDateFormat locale_get_date_format(void);
void locale_set_date_format(LocaleDateFormat format);
void locale_format_date(
FuriString* out_str,
FuriHalRtcDateTime* datetime,
LocaleDateFormat format,
char* separator);
#ifdef __cplusplus
}
#endif

View File

@@ -3,7 +3,7 @@ App(
name="System", name="System",
apptype=FlipperAppType.SETTINGS, apptype=FlipperAppType.SETTINGS,
entry_point="system_settings_app", entry_point="system_settings_app",
requires=["gui"], requires=["gui", "locale"],
stack_size=1 * 1024, stack_size=1 * 1024,
order=70, order=70,
) )

View File

@@ -1,6 +1,7 @@
#include "system_settings.h" #include "system_settings.h"
#include <loader/loader.h> #include <loader/loader.h>
#include <lib/toolbox/value_index.h> #include <lib/toolbox/value_index.h>
#include <locale/locale.h>
const char* const log_level_text[] = { const char* const log_level_text[] = {
"Default", "Default",
@@ -70,6 +71,59 @@ static void heap_trace_mode_changed(VariableItem* item) {
furi_hal_rtc_set_heap_track_mode(heap_trace_mode_value[index]); furi_hal_rtc_set_heap_track_mode(heap_trace_mode_value[index]);
} }
const char* const mesurement_units_text[] = {
"Metric",
"Imperial",
};
const uint32_t mesurement_units_value[] = {
LocaleMeasurementUnitMetric,
LocaleMeasurementUnitImperial,
};
static void mesurement_units_changed(VariableItem* item) {
// SystemSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, mesurement_units_text[index]);
locale_set_measurement_unit(mesurement_units_value[index]);
}
const char* const time_format_text[] = {
"24h",
"12h",
};
const uint32_t time_format_value[] = {
LocaleTimeFormat24h,
LocaleTimeFormat12h,
};
static void time_format_changed(VariableItem* item) {
// SystemSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, time_format_text[index]);
locale_set_time_format(time_format_value[index]);
}
const char* const date_format_text[] = {
"D/M/Y",
"M/D/Y",
"Y/M/D",
};
const uint32_t date_format_value[] = {
LocaleDateFormatDMY,
LocaleDateFormatMDY,
LocaleDateFormatYMD,
};
static void date_format_changed(VariableItem* item) {
// SystemSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, date_format_text[index]);
locale_set_date_format(date_format_value[index]);
}
static uint32_t system_settings_exit(void* context) { static uint32_t system_settings_exit(void* context) {
UNUSED(context); UNUSED(context);
return VIEW_NONE; return VIEW_NONE;
@@ -91,6 +145,31 @@ SystemSettings* system_settings_alloc() {
uint8_t value_index; uint8_t value_index;
app->var_item_list = variable_item_list_alloc(); app->var_item_list = variable_item_list_alloc();
item = variable_item_list_add(
app->var_item_list,
"Units",
COUNT_OF(mesurement_units_text),
mesurement_units_changed,
app);
value_index = value_index_uint32(
locale_get_measurement_unit(), mesurement_units_value, COUNT_OF(mesurement_units_value));
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, mesurement_units_text[value_index]);
item = variable_item_list_add(
app->var_item_list, "Time Format", COUNT_OF(time_format_text), time_format_changed, app);
value_index = value_index_uint32(
locale_get_time_format(), time_format_value, COUNT_OF(time_format_value));
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, time_format_text[value_index]);
item = variable_item_list_add(
app->var_item_list, "Date Format", COUNT_OF(date_format_text), date_format_changed, app);
value_index = value_index_uint32(
locale_get_date_format(), date_format_value, COUNT_OF(date_format_value));
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, date_format_text[value_index]);
item = variable_item_list_add( item = variable_item_list_add(
app->var_item_list, "Log Level", COUNT_OF(log_level_text), log_level_changed, app); app->var_item_list, "Log Level", COUNT_OF(log_level_text), log_level_changed, app);
value_index = value_index_uint32( value_index = value_index_uint32(

View File

@@ -14,7 +14,7 @@ DEBUG = 0
# Suffix to add to files when building distribution # Suffix to add to files when building distribution
# If OS environment has DIST_SUFFIX set, it will be used instead # If OS environment has DIST_SUFFIX set, it will be used instead
DIST_SUFFIX = "CC_CL-0011" DIST_SUFFIX = "CC_CL-0012"
# Coprocessor firmware # Coprocessor firmware
COPRO_OB_DATA = "scripts/ob.data" COPRO_OB_DATA = "scripts/ob.data"

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,11.0,, Version,+,12.0,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,, Header,+,applications/services/cli/cli_vcp.h,,
@@ -30,6 +30,7 @@ Header,+,applications/services/gui/view_dispatcher.h,,
Header,+,applications/services/gui/view_stack.h,, Header,+,applications/services/gui/view_stack.h,,
Header,+,applications/services/input/input.h,, Header,+,applications/services/input/input.h,,
Header,+,applications/services/loader/loader.h,, Header,+,applications/services/loader/loader.h,,
Header,+,applications/services/locale/locale.h,,
Header,+,applications/services/notification/notification.h,, Header,+,applications/services/notification/notification.h,,
Header,+,applications/services/notification/notification_messages.h,, Header,+,applications/services/notification/notification_messages.h,,
Header,+,applications/services/power/power_service/power.h,, Header,+,applications/services/power/power_service/power.h,,
@@ -784,6 +785,7 @@ Function,+,elements_scrollbar_pos,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint
Function,+,elements_slightly_rounded_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,elements_slightly_rounded_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t"
Function,+,elements_slightly_rounded_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" Function,+,elements_slightly_rounded_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t"
Function,+,elements_string_fit_width,void,"Canvas*, FuriString*, uint8_t" Function,+,elements_string_fit_width,void,"Canvas*, FuriString*, uint8_t"
Function,+,elements_string_fit_width_trunc,void,"Canvas*, FuriString*, uint8_t"
Function,+,elements_text_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, Align, Align, const char*, _Bool" Function,+,elements_text_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, Align, Align, const char*, _Bool"
Function,+,empty_screen_alloc,EmptyScreen*, Function,+,empty_screen_alloc,EmptyScreen*,
Function,+,empty_screen_free,void,EmptyScreen* Function,+,empty_screen_free,void,EmptyScreen*
@@ -1771,6 +1773,16 @@ Function,+,loader_update_menu,void,
Function,+,loading_alloc,Loading*, Function,+,loading_alloc,Loading*,
Function,+,loading_free,void,Loading* Function,+,loading_free,void,Loading*
Function,+,loading_get_view,View*,Loading* Function,+,loading_get_view,View*,Loading*
Function,+,locale_celsius_to_fahrenheit,float,float
Function,+,locale_fahrenheit_to_celsius,float,float
Function,+,locale_format_date,void,"FuriString*, FuriHalRtcDateTime*, LocaleDateFormat, char*"
Function,+,locale_format_time,void,"FuriString*, FuriHalRtcDateTime*, LocaleTimeFormat, _Bool"
Function,+,locale_get_date_format,LocaleDateFormat,
Function,+,locale_get_measurement_unit,LocaleMeasurementUnit,
Function,+,locale_get_time_format,LocaleTimeFormat,
Function,+,locale_set_date_format,void,LocaleDateFormat
Function,+,locale_set_measurement_unit,void,LocaleMeasurementUnit
Function,+,locale_set_time_format,void,LocaleTimeFormat
Function,-,localtime,tm*,const time_t* Function,-,localtime,tm*,const time_t*
Function,-,localtime_r,tm*,"const time_t*, tm*" Function,-,localtime_r,tm*,"const time_t*, tm*"
Function,-,log,double,double Function,-,log,double,double
1 entry status name type params
2 Version + 11.0 12.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
30 Header + applications/services/gui/view_stack.h
31 Header + applications/services/input/input.h
32 Header + applications/services/loader/loader.h
33 Header + applications/services/locale/locale.h
34 Header + applications/services/notification/notification.h
35 Header + applications/services/notification/notification_messages.h
36 Header + applications/services/power/power_service/power.h
785 Function + elements_slightly_rounded_box void Canvas*, uint8_t, uint8_t, uint8_t, uint8_t
786 Function + elements_slightly_rounded_frame void Canvas*, uint8_t, uint8_t, uint8_t, uint8_t
787 Function + elements_string_fit_width void Canvas*, FuriString*, uint8_t
788 Function + elements_string_fit_width_trunc void Canvas*, FuriString*, uint8_t
789 Function + elements_text_box void Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, Align, Align, const char*, _Bool
790 Function + empty_screen_alloc EmptyScreen*
791 Function + empty_screen_free void EmptyScreen*
1773 Function + loading_alloc Loading*
1774 Function + loading_free void Loading*
1775 Function + loading_get_view View* Loading*
1776 Function + locale_celsius_to_fahrenheit float float
1777 Function + locale_fahrenheit_to_celsius float float
1778 Function + locale_format_date void FuriString*, FuriHalRtcDateTime*, LocaleDateFormat, char*
1779 Function + locale_format_time void FuriString*, FuriHalRtcDateTime*, LocaleTimeFormat, _Bool
1780 Function + locale_get_date_format LocaleDateFormat
1781 Function + locale_get_measurement_unit LocaleMeasurementUnit
1782 Function + locale_get_time_format LocaleTimeFormat
1783 Function + locale_set_date_format void LocaleDateFormat
1784 Function + locale_set_measurement_unit void LocaleMeasurementUnit
1785 Function + locale_set_time_format void LocaleTimeFormat
1786 Function - localtime tm* const time_t*
1787 Function - localtime_r tm* const time_t*, tm*
1788 Function - log double double

View File

@@ -31,10 +31,13 @@ typedef struct {
uint8_t flags; uint8_t flags;
uint8_t boot_mode : 4; uint8_t boot_mode : 4;
uint8_t heap_track_mode : 2; uint8_t heap_track_mode : 2;
uint16_t reserved : 10; uint8_t locale_units : 1;
} DeveloperReg; uint8_t locale_timeformat : 1;
uint8_t locale_dateformat : 2;
uint8_t reserved : 6;
} SystemReg;
_Static_assert(sizeof(DeveloperReg) == 4, "DeveloperReg size mismatch"); _Static_assert(sizeof(SystemReg) == 4, "SystemReg size mismatch");
#define FURI_HAL_RTC_SECONDS_PER_MINUTE 60 #define FURI_HAL_RTC_SECONDS_PER_MINUTE 60
#define FURI_HAL_RTC_SECONDS_PER_HOUR (FURI_HAL_RTC_SECONDS_PER_MINUTE * 60) #define FURI_HAL_RTC_SECONDS_PER_HOUR (FURI_HAL_RTC_SECONDS_PER_MINUTE * 60)
@@ -172,7 +175,7 @@ void furi_hal_rtc_set_register(FuriHalRtcRegister reg, uint32_t value) {
void furi_hal_rtc_set_log_level(uint8_t level) { void furi_hal_rtc_set_log_level(uint8_t level) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem); uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg; SystemReg* data = (SystemReg*)&data_reg;
data->log_level = level; data->log_level = level;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
furi_log_set_level(level); furi_log_set_level(level);
@@ -180,13 +183,13 @@ void furi_hal_rtc_set_log_level(uint8_t level) {
uint8_t furi_hal_rtc_get_log_level() { uint8_t furi_hal_rtc_get_log_level() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem); uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg; SystemReg* data = (SystemReg*)&data_reg;
return data->log_level; return data->log_level;
} }
void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) { void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem); uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg; SystemReg* data = (SystemReg*)&data_reg;
data->flags |= flag; data->flags |= flag;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
@@ -197,7 +200,7 @@ void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) {
void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) { void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem); uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg; SystemReg* data = (SystemReg*)&data_reg;
data->flags &= ~flag; data->flags &= ~flag;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
@@ -208,36 +211,74 @@ void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) {
bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag) { bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem); uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg; SystemReg* data = (SystemReg*)&data_reg;
return data->flags & flag; return data->flags & flag;
} }
void furi_hal_rtc_set_boot_mode(FuriHalRtcBootMode mode) { void furi_hal_rtc_set_boot_mode(FuriHalRtcBootMode mode) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem); uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg; SystemReg* data = (SystemReg*)&data_reg;
data->boot_mode = mode; data->boot_mode = mode;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
} }
FuriHalRtcBootMode furi_hal_rtc_get_boot_mode() { FuriHalRtcBootMode furi_hal_rtc_get_boot_mode() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem); uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg; SystemReg* data = (SystemReg*)&data_reg;
return (FuriHalRtcBootMode)data->boot_mode; return (FuriHalRtcBootMode)data->boot_mode;
} }
void furi_hal_rtc_set_heap_track_mode(FuriHalRtcHeapTrackMode mode) { void furi_hal_rtc_set_heap_track_mode(FuriHalRtcHeapTrackMode mode) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem); uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg; SystemReg* data = (SystemReg*)&data_reg;
data->heap_track_mode = mode; data->heap_track_mode = mode;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
} }
FuriHalRtcHeapTrackMode furi_hal_rtc_get_heap_track_mode() { FuriHalRtcHeapTrackMode furi_hal_rtc_get_heap_track_mode() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem); uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg; SystemReg* data = (SystemReg*)&data_reg;
return (FuriHalRtcHeapTrackMode)data->heap_track_mode; return (FuriHalRtcHeapTrackMode)data->heap_track_mode;
} }
void furi_hal_rtc_set_locale_units(uint8_t mode) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
data->locale_units = mode;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
}
uint8_t furi_hal_rtc_get_locale_units() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
return (uint8_t)data->locale_units;
}
void furi_hal_rtc_set_locale_timeformat(uint8_t mode) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
data->locale_timeformat = mode;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
}
uint8_t furi_hal_rtc_get_locale_timeformat() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
return (uint8_t)data->locale_timeformat;
}
void furi_hal_rtc_set_locale_dateformat(uint8_t mode) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
data->locale_dateformat = mode;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
}
uint8_t furi_hal_rtc_get_locale_dateformat() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
return (uint8_t)data->locale_dateformat;
}
void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime) { void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime) {
furi_assert(datetime); furi_assert(datetime);
@@ -367,4 +408,4 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) {
timestamp += datetime->second; timestamp += datetime->second;
return timestamp; return timestamp;
} }