Sync system apps --nobuild

This commit is contained in:
Willy-JL
2023-12-08 22:22:31 +00:00
parent 76534b04a4
commit efbcdc2a8b
38 changed files with 1490 additions and 413 deletions

View File

@@ -8,11 +8,10 @@ App(
"dialogs",
],
stack_size=2 * 1024,
order=20,
fap_icon="icons/hex_10px.png",
fap_icon="icons/hex_10px.bmp",
fap_icon_assets="icons",
fap_category="Tools",
fap_author="@QtRoS",
fap_version="2.0",
fap_description="App allows to view various files as HEX.",
fap_description="App allows to view various files as HEX",
)

View File

@@ -123,7 +123,7 @@ bool hex_viewer_open_file(void* context, const char* file_path) {
// TODO Separate function?
if(hex_viewer->model->stream) {
buffered_file_stream_close(hex_viewer->model->stream);
stream_free(hex_viewer->model->stream); // TODO Check
stream_free(hex_viewer->model->stream);
hex_viewer->model->file_offset = 0;
}

View File

@@ -87,7 +87,10 @@ HexViewer* hex_viewer_app_alloc() {
void hex_viewer_app_free(HexViewer* app) {
furi_assert(app);
if(app->model->stream) buffered_file_stream_close(app->model->stream);
if(app->model->stream) {
buffered_file_stream_close(app->model->stream);
stream_free(app->model->stream);
}
// Scene manager
scene_manager_free(app->scene_manager);

View File

@@ -43,7 +43,6 @@ typedef struct {
Stream* stream;
} HexViewerModel;
// TODO Clean
typedef struct {
HexViewerModel* model;

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

View File

@@ -13,7 +13,7 @@ void hex_viewer_scene_scroll_on_enter(void* context) {
TextInput* text_input = app->text_input;
text_input_set_header_text(text_input, "Scroll to percent (0..100)");
text_input_set_header_text(text_input, "Scroll to percentage (0..100)");
text_input_set_result_callback(
text_input,
hex_viewer_scene_scroll_callback,

View File

@@ -61,7 +61,7 @@ void hex_viewer_startscreen_draw(Canvas* canvas, HexViewerStartscreenModel* mode
width,
0,
ROW_HEIGHT * HEX_VIEWER_LINES_ON_SCREEN,
first_line_on_screen, // TODO
first_line_on_screen,
line_count - (HEX_VIEWER_LINES_ON_SCREEN - 1));
}
@@ -69,6 +69,9 @@ void hex_viewer_startscreen_draw(Canvas* canvas, HexViewerStartscreenModel* mode
uint32_t row_iters = model->file_read_bytes / HEX_VIEWER_BYTES_PER_LINE;
if(model->file_read_bytes % HEX_VIEWER_BYTES_PER_LINE != 0) row_iters += 1;
// For the rest of drawing.
canvas_set_font(canvas, FontKeyboard);
for(uint32_t i = 0; i < row_iters; ++i) {
uint32_t bytes_left_per_row = model->file_read_bytes - i * HEX_VIEWER_BYTES_PER_LINE;
bytes_left_per_row = MIN(bytes_left_per_row, HEX_VIEWER_BYTES_PER_LINE);
@@ -79,13 +82,13 @@ void hex_viewer_startscreen_draw(Canvas* canvas, HexViewerStartscreenModel* mode
for(uint32_t j = 0; j < bytes_left_per_row; ++j)
if(!isprint((int)temp_buf[j])) temp_buf[j] = '.';
canvas_set_font(canvas, FontKeyboard);
//canvas_set_font(canvas, FontKeyboard);
canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf);
} else {
uint32_t addr = model->file_offset + i * HEX_VIEWER_BYTES_PER_LINE;
snprintf(temp_buf, 32, "%04lX", addr);
canvas_set_font(canvas, FontKeyboard);
//canvas_set_font(canvas, FontKeyboard);
canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf);
}
@@ -93,7 +96,7 @@ void hex_viewer_startscreen_draw(Canvas* canvas, HexViewerStartscreenModel* mode
for(uint32_t j = 0; j < bytes_left_per_row; ++j)
p += snprintf(p, 32, "%02X ", model->file_bytes[i][j]);
canvas_set_font(canvas, FontKeyboard);
//canvas_set_font(canvas, FontKeyboard);
canvas_draw_str(canvas, LEFT_OFFSET + 41, TOP_OFFSET + i * ROW_HEIGHT, temp_buf);
}
@@ -125,7 +128,7 @@ bool hex_viewer_startscreen_input(InputEvent* event, void* context) {
furi_assert(context);
HexViewerStartscreen* instance = context;
HexViewer* app = instance->context; // TO so good, but works
// TODO InputTypeShort?
if(event->type == InputTypeRelease || event->type == InputTypeRepeat) {
switch(event->key) {
case InputKeyBack:

View File

@@ -4,8 +4,6 @@ App(
apptype=FlipperAppType.EXTERNAL,
entry_point="hid_usb_app",
stack_size=1 * 1024,
fap_description="Use Flipper as a HID remote control over USB",
fap_version="1.0",
fap_category="USB",
fap_icon="hid_usb_10px.png",
fap_icon_assets="assets",
@@ -19,8 +17,6 @@ App(
apptype=FlipperAppType.EXTERNAL,
entry_point="hid_ble_app",
stack_size=1 * 1024,
fap_description="Use Flipper as a HID remote control over Bluetooth",
fap_version="1.0",
fap_category="Bluetooth",
fap_icon="hid_ble_10px.png",
fap_icon_assets="assets",

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

View File

@@ -12,11 +12,11 @@ enum HidDebugSubmenuIndex {
HidSubmenuIndexNumpad,
HidSubmenuIndexMedia,
HidSubmenuIndexMovie,
HidSubmenuIndexTikTok,
HidSubmenuIndexTikShorts,
HidSubmenuIndexMouse,
HidSubmenuIndexMouseClicker,
HidSubmenuIndexMouseJiggler,
HidSubmenuIndexPtt,
HidSubmenuIndexPushToTalk,
};
static void hid_submenu_callback(void* context, uint32_t index) {
@@ -45,18 +45,18 @@ static void hid_submenu_callback(void* context, uint32_t index) {
} else if(index == HidSubmenuIndexMouse) {
app->view_id = HidViewMouse;
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouse);
} else if(index == HidSubmenuIndexTikTok) {
app->view_id = BtHidViewTikTok;
view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok);
} else if(index == HidSubmenuIndexTikShorts) {
app->view_id = BtHidViewTikShorts;
view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikShorts);
} else if(index == HidSubmenuIndexMouseClicker) {
app->view_id = HidViewMouseClicker;
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseClicker);
} else if(index == HidSubmenuIndexMouseJiggler) {
app->view_id = HidViewMouseJiggler;
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseJiggler);
} else if(index == HidSubmenuIndexPtt) {
app->view_id = HidViewPtt;
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewPtt);
} else if(index == HidSubmenuIndexPushToTalk) {
app->view_id = HidViewPushToTalkMenu;
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewPushToTalkMenu);
}
}
@@ -80,7 +80,7 @@ static void bt_hid_connection_status_changed_callback(BtStatus status, void* con
hid_mouse_clicker_set_connected_status(hid->hid_mouse_clicker, connected);
hid_mouse_jiggler_set_connected_status(hid->hid_mouse_jiggler, connected);
hid_ptt_set_connected_status(hid->hid_ptt, connected);
hid_tiktok_set_connected_status(hid->hid_tiktok, connected);
hid_tikshorts_set_connected_status(hid->hid_tikshorts, connected);
}
static uint32_t hid_menu_view(void* context) {
@@ -93,6 +93,11 @@ static uint32_t hid_exit(void* context) {
return VIEW_NONE;
}
static uint32_t hid_ptt_menu_view(void* context) {
UNUSED(context);
return HidViewPushToTalkMenu;
}
Hid* hid_alloc(HidTransport transport) {
Hid* app = malloc(sizeof(Hid));
app->transport = transport;
@@ -134,7 +139,7 @@ Hid* hid_alloc(HidTransport transport) {
submenu_add_item(
app->device_type_submenu,
"TikTok / YT Shorts",
HidSubmenuIndexTikTok,
HidSubmenuIndexTikShorts,
hid_submenu_callback,
app);
}
@@ -151,7 +156,11 @@ Hid* hid_alloc(HidTransport transport) {
hid_submenu_callback,
app);
submenu_add_item(
app->device_type_submenu, "PTT", HidSubmenuIndexPtt, hid_submenu_callback, app);
app->device_type_submenu,
"PushToTalk",
HidSubmenuIndexPushToTalk,
hid_submenu_callback,
app);
view_set_previous_callback(submenu_get_view(app->device_type_submenu), hid_exit);
view_dispatcher_add_view(
app->view_dispatcher, HidViewSubmenu, submenu_get_view(app->device_type_submenu));
@@ -163,7 +172,6 @@ Hid* hid_alloc(HidTransport transport) {
Hid* hid_app_alloc_view(void* context) {
furi_assert(context);
Hid* app = context;
// Dialog view
// Keynote view
app->hid_keynote = hid_keynote_alloc(app);
@@ -195,11 +203,11 @@ Hid* hid_app_alloc_view(void* context) {
view_dispatcher_add_view(
app->view_dispatcher, HidViewMovie, hid_movie_get_view(app->hid_movie));
// TikTok view
app->hid_tiktok = hid_tiktok_alloc(app);
view_set_previous_callback(hid_tiktok_get_view(app->hid_tiktok), hid_menu_view);
// TikTok / YT Shorts view
app->hid_tikshorts = hid_tikshorts_alloc(app);
view_set_previous_callback(hid_tikshorts_get_view(app->hid_tikshorts), hid_menu_view);
view_dispatcher_add_view(
app->view_dispatcher, BtHidViewTikTok, hid_tiktok_get_view(app->hid_tiktok));
app->view_dispatcher, BtHidViewTikShorts, hid_tikshorts_get_view(app->hid_tikshorts));
// Mouse view
app->hid_mouse = hid_mouse_alloc(app);
@@ -223,10 +231,15 @@ Hid* hid_app_alloc_view(void* context) {
HidViewMouseJiggler,
hid_mouse_jiggler_get_view(app->hid_mouse_jiggler));
// Ptt view
// PushToTalk view
app->hid_ptt_menu = hid_ptt_menu_alloc(app);
view_set_previous_callback(hid_ptt_menu_get_view(app->hid_ptt_menu), hid_menu_view);
view_dispatcher_add_view(
app->view_dispatcher, HidViewPushToTalkMenu, hid_ptt_menu_get_view(app->hid_ptt_menu));
app->hid_ptt = hid_ptt_alloc(app);
view_set_previous_callback(hid_ptt_get_view(app->hid_ptt), hid_menu_view);
view_dispatcher_add_view(app->view_dispatcher, HidViewPtt, hid_ptt_get_view(app->hid_ptt));
view_set_previous_callback(hid_ptt_get_view(app->hid_ptt), hid_ptt_menu_view);
view_dispatcher_add_view(
app->view_dispatcher, HidViewPushToTalk, hid_ptt_get_view(app->hid_ptt));
return app;
}
@@ -258,10 +271,12 @@ void hid_free(Hid* app) {
hid_mouse_clicker_free(app->hid_mouse_clicker);
view_dispatcher_remove_view(app->view_dispatcher, HidViewMouseJiggler);
hid_mouse_jiggler_free(app->hid_mouse_jiggler);
view_dispatcher_remove_view(app->view_dispatcher, HidViewPtt);
view_dispatcher_remove_view(app->view_dispatcher, HidViewPushToTalkMenu);
hid_ptt_menu_free(app->hid_ptt_menu);
view_dispatcher_remove_view(app->view_dispatcher, HidViewPushToTalk);
hid_ptt_free(app->hid_ptt);
view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok);
hid_tiktok_free(app->hid_tiktok);
view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikShorts);
hid_tikshorts_free(app->hid_tikshorts);
view_dispatcher_free(app->view_dispatcher);
// Close records

View File

@@ -23,8 +23,9 @@
#include "views/hid_mouse.h"
#include "views/hid_mouse_clicker.h"
#include "views/hid_mouse_jiggler.h"
#include "views/hid_tiktok.h"
#include "views/hid_tikshorts.h"
#include "views/hid_ptt.h"
#include "views/hid_ptt_menu.h"
#include <assets_icons.h>
@@ -51,8 +52,9 @@ struct Hid {
HidMouse* hid_mouse;
HidMouseClicker* hid_mouse_clicker;
HidMouseJiggler* hid_mouse_jiggler;
HidTikTok* hid_tiktok;
HidPtt* hid_ptt;
HidTikShorts* hid_tikshorts;
HidPushToTalk* hid_ptt;
HidPushToTalkMenu* hid_ptt_menu;
HidTransport transport;
uint32_t view_id;

View File

@@ -8,6 +8,8 @@ typedef enum {
HidViewMouse,
HidViewMouseClicker,
HidViewMouseJiggler,
BtHidViewTikTok,
HidViewPtt,
BtHidViewTikShorts,
HidViewPushToTalk,
HidViewPushToTalkMenu,
HidViewPushToTalkHelp,
} HidView;

View File

@@ -188,12 +188,15 @@ static bool hid_media_input_callback(InputEvent* event, void* context) {
HidMedia* hid_media = context;
bool consumed = false;
if(event->type == InputTypePress) {
hid_media_process_press(hid_media, event);
consumed = true;
} else if(event->type == InputTypeRelease) {
hid_media_process_release(hid_media, event);
if(event->type == InputTypeLong && event->key == InputKeyBack) {
hid_hal_keyboard_release_all(hid_media->hid);
} else {
consumed = true;
if(event->type == InputTypePress) {
hid_media_process_press(hid_media, event);
} else if(event->type == InputTypeRelease) {
hid_media_process_release(hid_media, event);
}
}
return consumed;
}

View File

@@ -186,13 +186,19 @@ static bool hid_movie_input_callback(InputEvent* event, void* context) {
HidMovie* hid_movie = context;
bool consumed = false;
if(event->type == InputTypePress) {
hid_movie_process_press(hid_movie, event);
consumed = true;
} else if(event->type == InputTypeRelease) {
hid_movie_process_release(hid_movie, event);
if(event->type == InputTypeLong && event->key == InputKeyBack) {
hid_hal_keyboard_release_all(hid_movie->hid);
} else {
consumed = true;
if(event->type == InputTypePress) {
hid_movie_process_press(hid_movie, event);
consumed = true;
} else if(event->type == InputTypeRelease) {
hid_movie_process_release(hid_movie, event);
consumed = true;
}
}
return consumed;
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,12 +3,17 @@
#include <gui/view.h>
typedef struct Hid Hid;
typedef struct HidPtt HidPtt;
typedef struct HidPushToTalk HidPushToTalk;
HidPtt* hid_ptt_alloc(Hid* bt_hid);
HidPushToTalk* hid_ptt_alloc(Hid* bt_hid);
void hid_ptt_free(HidPtt* hid_ptt);
void hid_ptt_free(HidPushToTalk* hid_ptt);
View* hid_ptt_get_view(HidPtt* hid_ptt);
View* hid_ptt_get_view(HidPushToTalk* hid_ptt);
void hid_ptt_set_connected_status(HidPtt* hid_ptt, bool connected);
void hid_ptt_set_connected_status(HidPushToTalk* hid_ptt, bool connected);
enum HidPushToTalkOSes {
HidPushToTalkMacOS,
HidPushToTalkLinux,
};

View File

@@ -0,0 +1,423 @@
#include "hid_ptt_menu.h"
#include "hid_ptt.h"
#include <gui/elements.h>
#include <m-array.h>
#include "../hid.h"
#include "../views.h"
#define TAG "HidPushToTalkMenu"
struct HidPushToTalkMenu {
View* view;
Hid* hid;
};
typedef struct {
FuriString* label;
uint32_t index;
PushToTalkMenuItemCallback callback;
void* callback_context;
} PushToTalkMenuItem;
// Menu item
static void PushToTalkMenuItem_init(PushToTalkMenuItem* item) {
item->label = furi_string_alloc();
item->index = 0;
}
static void PushToTalkMenuItem_init_set(PushToTalkMenuItem* item, const PushToTalkMenuItem* src) {
item->label = furi_string_alloc_set(src->label);
item->index = src->index;
}
static void PushToTalkMenuItem_set(PushToTalkMenuItem* item, const PushToTalkMenuItem* src) {
furi_string_set(item->label, src->label);
item->index = src->index;
}
static void PushToTalkMenuItem_clear(PushToTalkMenuItem* item) {
furi_string_free(item->label);
}
ARRAY_DEF(
PushToTalkMenuItemArray,
PushToTalkMenuItem,
(INIT(API_2(PushToTalkMenuItem_init)),
SET(API_6(PushToTalkMenuItem_set)),
INIT_SET(API_6(PushToTalkMenuItem_init_set)),
CLEAR(API_2(PushToTalkMenuItem_clear))))
// Menu list (horisontal, 2d array)
typedef struct {
FuriString* label;
uint32_t index;
PushToTalkMenuItemArray_t items;
} PushToTalkMenuList;
typedef struct {
size_t list_position;
size_t position;
size_t window_position;
PushToTalkMenuList* lists;
int lists_count;
} HidPushToTalkMenuModel;
static void
hid_ptt_menu_draw_list(Canvas* canvas, void* context, const PushToTalkMenuItemArray_t items) {
furi_assert(context);
HidPushToTalkMenuModel* model = context;
const uint8_t item_height = 16;
uint8_t item_width = canvas_width(canvas) - 5;
canvas_set_font(canvas, FontSecondary);
size_t position = 0;
PushToTalkMenuItemArray_it_t it;
for(PushToTalkMenuItemArray_it(it, items); !PushToTalkMenuItemArray_end_p(it);
PushToTalkMenuItemArray_next(it)) {
const size_t item_position = position - model->window_position;
const size_t items_on_screen = 3;
uint8_t y_offset = 16;
if(item_position < items_on_screen) {
if(position == model->position) {
canvas_set_color(canvas, ColorBlack);
elements_slightly_rounded_box(
canvas,
0,
y_offset + (item_position * item_height) + 1,
item_width,
item_height - 2);
canvas_set_color(canvas, ColorWhite);
} else {
canvas_set_color(canvas, ColorBlack);
}
FuriString* disp_str;
disp_str = furi_string_alloc_set(PushToTalkMenuItemArray_cref(it)->label);
elements_string_fit_width(canvas, disp_str, item_width - (6 * 2));
canvas_draw_str(
canvas,
6,
y_offset + (item_position * item_height) + item_height - 4,
furi_string_get_cstr(disp_str));
furi_string_free(disp_str);
}
position++;
}
elements_scrollbar_pos(
canvas, 128, 17, 46, model->position, PushToTalkMenuItemArray_size(items));
}
PushToTalkMenuList* hid_ptt_menu_get_list_at_index(void* context, uint32_t index) {
furi_assert(context);
HidPushToTalkMenuModel* model = context;
for(int i = 0; i < model->lists_count; i++) {
PushToTalkMenuList* list = &model->lists[i];
if(index == list->index) {
return list;
}
}
return NULL;
}
static void hid_ptt_menu_draw_callback(Canvas* canvas, void* context) {
furi_assert(context);
HidPushToTalkMenuModel* model = context;
if(model->lists_count == 0) {
return;
}
uint8_t item_width = canvas_width(canvas) - 5;
canvas_clear(canvas);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 4, 11, "<");
canvas_draw_str(canvas, 121, 11, ">");
PushToTalkMenuList* list = &model->lists[model->list_position];
FuriString* disp_str;
disp_str = furi_string_alloc_set(list->label);
elements_string_fit_width(canvas, disp_str, item_width - (6 * 2));
uint8_t x_pos =
(canvas_width(canvas) - canvas_string_width(canvas, furi_string_get_cstr(disp_str))) / 2;
canvas_draw_str(canvas, x_pos, 11, furi_string_get_cstr(disp_str));
furi_string_free(disp_str);
canvas_set_font(canvas, FontSecondary);
hid_ptt_menu_draw_list(canvas, context, list->items);
}
void ptt_menu_add_list(HidPushToTalkMenu* hid_ptt_menu, const char* label, uint32_t index) {
furi_assert(label);
furi_assert(hid_ptt_menu);
with_view_model(
hid_ptt_menu->view,
HidPushToTalkMenuModel * model,
{
if(model->lists_count == 0) {
model->lists = (PushToTalkMenuList*)malloc(sizeof(PushToTalkMenuList));
} else {
model->lists = (PushToTalkMenuList*)realloc(
model->lists, (model->lists_count + 1) * sizeof(PushToTalkMenuList));
}
if(model->lists == NULL) {
FURI_LOG_E(TAG, "Memory reallocation failed (%i)", model->lists_count);
return;
}
PushToTalkMenuList* list = &model->lists[model->lists_count];
PushToTalkMenuItemArray_init(list->items);
list->label = furi_string_alloc_set(label);
list->index = index;
model->lists_count += 1;
},
true);
}
void ptt_menu_add_item_to_list(
HidPushToTalkMenu* hid_ptt_menu,
uint32_t list_index,
const char* label,
uint32_t index,
PushToTalkMenuItemCallback callback,
void* callback_context) {
PushToTalkMenuItem* item = NULL;
furi_assert(label);
furi_assert(hid_ptt_menu);
UNUSED(list_index);
with_view_model(
hid_ptt_menu->view,
HidPushToTalkMenuModel * model,
{
PushToTalkMenuList* list = hid_ptt_menu_get_list_at_index(model, list_index);
if(list == NULL) {
FURI_LOG_E(TAG, "Adding item %s to unknown index %li", label, list_index);
return;
}
item = PushToTalkMenuItemArray_push_new(list->items);
furi_string_set_str(item->label, label);
item->index = index;
item->callback = callback;
item->callback_context = callback_context;
},
true);
}
void ptt_menu_shift_list(HidPushToTalkMenu* hid_ptt_menu, int shift) {
size_t new_position = 0;
uint32_t index = 0;
with_view_model(
hid_ptt_menu->view,
HidPushToTalkMenuModel * model,
{
int new_list_position = (short)model->list_position + shift;
if(new_list_position >= model->lists_count) {
new_list_position = 0;
} else if(new_list_position < 0) {
new_list_position = model->lists_count - 1;
}
PushToTalkMenuList* list = &model->lists[model->list_position];
PushToTalkMenuList* new_list = &model->lists[new_list_position];
size_t new_window_position = model->window_position;
const size_t items_size = PushToTalkMenuItemArray_size(new_list->items);
size_t position = 0;
// Find item index from current list
PushToTalkMenuItemArray_it_t it;
for(PushToTalkMenuItemArray_it(it, list->items); !PushToTalkMenuItemArray_end_p(it);
PushToTalkMenuItemArray_next(it)) {
if(position == model->position) {
index = PushToTalkMenuItemArray_cref(it)->index;
break;
}
position++;
}
// Try to find item with the same index in a new list
position = 0;
bool item_exists_in_new_list = false;
for(PushToTalkMenuItemArray_it(it, new_list->items);
!PushToTalkMenuItemArray_end_p(it);
PushToTalkMenuItemArray_next(it)) {
if(PushToTalkMenuItemArray_cref(it)->index == index) {
item_exists_in_new_list = true;
new_position = position;
break;
}
position++;
}
// This list item is not presented in a new list, let's try to keep position as is.
// If it's out of range for the new list set it to the end
if(!item_exists_in_new_list) {
new_position = items_size - 1 < model->position ? items_size - 1 : model->position;
}
// Tune window position. As we have 3 items on screen, keep focus centered
const size_t items_on_screen = 3;
if(new_position >= items_size - 1) {
if(items_size < items_on_screen + 1) {
new_window_position = 0;
} else {
new_window_position = items_size - items_on_screen;
}
} else if(new_position < items_on_screen - 1) {
new_window_position = 0;
} else {
new_window_position = new_position - 1;
}
model->list_position = new_list_position;
model->position = new_position;
model->window_position = new_window_position;
},
true);
}
void ptt_menu_process_up(HidPushToTalkMenu* hid_ptt_menu) {
with_view_model(
hid_ptt_menu->view,
HidPushToTalkMenuModel * model,
{
PushToTalkMenuList* list = &model->lists[model->list_position];
const size_t items_on_screen = 3;
const size_t items_size = PushToTalkMenuItemArray_size(list->items);
if(model->position > 0) {
model->position--;
if((model->position == model->window_position) && (model->window_position > 0)) {
model->window_position--;
}
} else {
model->position = items_size - 1;
if(model->position > items_on_screen - 1) {
model->window_position = model->position - (items_on_screen - 1);
}
}
},
true);
}
void ptt_menu_process_down(HidPushToTalkMenu* hid_ptt_menu) {
with_view_model(
hid_ptt_menu->view,
HidPushToTalkMenuModel * model,
{
PushToTalkMenuList* list = &model->lists[model->list_position];
const size_t items_on_screen = 3;
const size_t items_size = PushToTalkMenuItemArray_size(list->items);
if(model->position < items_size - 1) {
model->position++;
if((model->position - model->window_position > items_on_screen - 2) &&
(model->window_position < items_size - items_on_screen)) {
model->window_position++;
}
} else {
model->position = 0;
model->window_position = 0;
}
},
true);
}
void ptt_menu_process_ok(HidPushToTalkMenu* hid_ptt_menu) {
PushToTalkMenuList* list = NULL;
PushToTalkMenuItem* item = NULL;
with_view_model(
hid_ptt_menu->view,
HidPushToTalkMenuModel * model,
{
list = &model->lists[model->list_position];
const size_t items_size = PushToTalkMenuItemArray_size(list->items);
if(model->position < items_size) {
item = PushToTalkMenuItemArray_get(list->items, model->position);
}
},
true);
if(item && list && item->callback) {
item->callback(item->callback_context, list->index, list->label, item->index, item->label);
}
}
static bool hid_ptt_menu_input_callback(InputEvent* event, void* context) {
furi_assert(context);
HidPushToTalkMenu* hid_ptt_menu = context;
bool consumed = false;
if(event->type == InputTypeShort) {
switch(event->key) {
case InputKeyUp:
consumed = true;
ptt_menu_process_up(hid_ptt_menu);
break;
case InputKeyDown:
consumed = true;
ptt_menu_process_down(hid_ptt_menu);
break;
case InputKeyLeft:
consumed = true;
ptt_menu_shift_list(hid_ptt_menu, -1);
break;
case InputKeyRight:
consumed = true;
ptt_menu_shift_list(hid_ptt_menu, +1);
break;
case InputKeyOk:
consumed = true;
ptt_menu_process_ok(hid_ptt_menu);
break;
default:
break;
}
} else if(event->type == InputTypeRepeat) {
if(event->key == InputKeyUp) {
consumed = true;
ptt_menu_process_up(hid_ptt_menu);
} else if(event->key == InputKeyDown) {
consumed = true;
ptt_menu_process_down(hid_ptt_menu);
}
}
return consumed;
}
View* hid_ptt_menu_get_view(HidPushToTalkMenu* hid_ptt_menu) {
furi_assert(hid_ptt_menu);
return hid_ptt_menu->view;
}
HidPushToTalkMenu* hid_ptt_menu_alloc(Hid* hid) {
HidPushToTalkMenu* hid_ptt_menu = malloc(sizeof(HidPushToTalkMenu));
hid_ptt_menu->hid = hid;
hid_ptt_menu->view = view_alloc();
view_set_context(hid_ptt_menu->view, hid_ptt_menu);
view_allocate_model(hid_ptt_menu->view, ViewModelTypeLocking, sizeof(HidPushToTalkMenuModel));
view_set_draw_callback(hid_ptt_menu->view, hid_ptt_menu_draw_callback);
view_set_input_callback(hid_ptt_menu->view, hid_ptt_menu_input_callback);
with_view_model(
hid_ptt_menu->view,
HidPushToTalkMenuModel * model,
{
model->lists_count = 0;
model->position = 0;
model->window_position = 0;
},
true);
return hid_ptt_menu;
}
void hid_ptt_menu_free(HidPushToTalkMenu* hid_ptt_menu) {
furi_assert(hid_ptt_menu);
with_view_model(
hid_ptt_menu->view,
HidPushToTalkMenuModel * model,
{
for(int i = 0; i < model->lists_count; i++) {
PushToTalkMenuItemArray_clear(model->lists[i].items);
furi_string_free(model->lists[i].label);
}
free(model->lists);
},
true);
view_free(hid_ptt_menu->view);
free(hid_ptt_menu);
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include <gui/view.h>
typedef struct Hid Hid;
typedef struct HidPushToTalkMenu HidPushToTalkMenu;
typedef void (*PushToTalkMenuItemCallback)(
void* context,
uint32_t listIndex,
FuriString* listLabel,
uint32_t itemIndex,
FuriString* itemLabel);
HidPushToTalkMenu* hid_ptt_menu_alloc(Hid* bt_hid);
void hid_ptt_menu_free(HidPushToTalkMenu* hid_ptt_menu);
View* hid_ptt_menu_get_view(HidPushToTalkMenu* hid_ptt_menu);
void ptt_menu_add_item_to_list(
HidPushToTalkMenu* hid_ptt_menu,
uint32_t list_index,
const char* label,
uint32_t index,
PushToTalkMenuItemCallback callback,
void* callback_context);
void ptt_menu_add_list(HidPushToTalkMenu* hid_ptt_menu, const char* label, uint32_t index);

View File

@@ -1,12 +1,12 @@
#include "hid_tiktok.h"
#include "hid_tikshorts.h"
#include "../hid.h"
#include <gui/elements.h>
#include "hid_icons.h"
#define TAG "HidTikTok"
#define TAG "HidTikShorts"
struct HidTikTok {
struct HidTikShorts {
View* view;
Hid* hid;
};
@@ -21,11 +21,11 @@ typedef struct {
bool is_cursor_set;
bool back_mouse_pressed;
HidTransport transport;
} HidTikTokModel;
} HidTikShortsModel;
static void hid_tiktok_draw_callback(Canvas* canvas, void* context) {
static void hid_tikshorts_draw_callback(Canvas* canvas, void* context) {
furi_assert(context);
HidTikTokModel* model = context;
HidTikShortsModel* model = context;
// Header
if(model->transport == HidTransportBle) {
@@ -110,30 +110,32 @@ static void hid_tiktok_draw_callback(Canvas* canvas, void* context) {
elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit");
}
static void hid_tiktok_reset_cursor(HidTikTok* hid_tiktok) {
static void hid_tikshorts_reset_cursor(HidTikShorts* hid_tikshorts) {
// Set cursor to the phone's left up corner
// Delays to guarantee one packet per connection interval
for(size_t i = 0; i < 8; i++) {
hid_hal_mouse_move(hid_tiktok->hid, -127, -127);
hid_hal_mouse_move(hid_tikshorts->hid, -127, -127);
furi_delay_ms(50);
}
// Move cursor from the corner
hid_hal_mouse_move(hid_tiktok->hid, 20, 120);
hid_hal_mouse_move(hid_tikshorts->hid, 20, 120);
furi_delay_ms(50);
}
static void
hid_tiktok_process_press(HidTikTok* hid_tiktok, HidTikTokModel* model, InputEvent* event) {
static void hid_tikshorts_process_press(
HidTikShorts* hid_tikshorts,
HidTikShortsModel* model,
InputEvent* event) {
if(event->key == InputKeyUp) {
model->up_pressed = true;
} else if(event->key == InputKeyDown) {
model->down_pressed = true;
} else if(event->key == InputKeyLeft) {
model->left_pressed = true;
hid_hal_consumer_key_press(hid_tiktok->hid, HID_CONSUMER_VOLUME_DECREMENT);
hid_hal_consumer_key_press(hid_tikshorts->hid, HID_CONSUMER_VOLUME_DECREMENT);
} else if(event->key == InputKeyRight) {
model->right_pressed = true;
hid_hal_consumer_key_press(hid_tiktok->hid, HID_CONSUMER_VOLUME_INCREMENT);
hid_hal_consumer_key_press(hid_tikshorts->hid, HID_CONSUMER_VOLUME_INCREMENT);
} else if(event->key == InputKeyOk) {
model->ok_pressed = true;
} else if(event->key == InputKeyBack) {
@@ -141,18 +143,20 @@ static void
}
}
static void
hid_tiktok_process_release(HidTikTok* hid_tiktok, HidTikTokModel* model, InputEvent* event) {
static void hid_tikshorts_process_release(
HidTikShorts* hid_tikshorts,
HidTikShortsModel* model,
InputEvent* event) {
if(event->key == InputKeyUp) {
model->up_pressed = false;
} else if(event->key == InputKeyDown) {
model->down_pressed = false;
} else if(event->key == InputKeyLeft) {
model->left_pressed = false;
hid_hal_consumer_key_release(hid_tiktok->hid, HID_CONSUMER_VOLUME_DECREMENT);
hid_hal_consumer_key_release(hid_tikshorts->hid, HID_CONSUMER_VOLUME_DECREMENT);
} else if(event->key == InputKeyRight) {
model->right_pressed = false;
hid_hal_consumer_key_release(hid_tiktok->hid, HID_CONSUMER_VOLUME_INCREMENT);
hid_hal_consumer_key_release(hid_tikshorts->hid, HID_CONSUMER_VOLUME_INCREMENT);
} else if(event->key == InputKeyOk) {
model->ok_pressed = false;
} else if(event->key == InputKeyBack) {
@@ -160,61 +164,61 @@ static void
}
}
static bool hid_tiktok_input_callback(InputEvent* event, void* context) {
static bool hid_tikshorts_input_callback(InputEvent* event, void* context) {
furi_assert(context);
HidTikTok* hid_tiktok = context;
HidTikShorts* hid_tikshorts = context;
bool consumed = false;
with_view_model(
hid_tiktok->view,
HidTikTokModel * model,
hid_tikshorts->view,
HidTikShortsModel * model,
{
if(event->type == InputTypePress) {
hid_tiktok_process_press(hid_tiktok, model, event);
hid_tikshorts_process_press(hid_tikshorts, model, event);
if(model->connected && !model->is_cursor_set) {
hid_tiktok_reset_cursor(hid_tiktok);
hid_tikshorts_reset_cursor(hid_tikshorts);
model->is_cursor_set = true;
}
consumed = true;
} else if(event->type == InputTypeRelease) {
hid_tiktok_process_release(hid_tiktok, model, event);
hid_tikshorts_process_release(hid_tikshorts, model, event);
consumed = true;
} else if(event->type == InputTypeShort) {
if(event->key == InputKeyOk) {
hid_hal_mouse_press(hid_tiktok->hid, HID_MOUSE_BTN_LEFT);
hid_hal_mouse_press(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT);
furi_delay_ms(25);
hid_hal_mouse_release(hid_tiktok->hid, HID_MOUSE_BTN_LEFT);
hid_hal_mouse_release(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT);
furi_delay_ms(100);
hid_hal_mouse_press(hid_tiktok->hid, HID_MOUSE_BTN_LEFT);
hid_hal_mouse_press(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT);
furi_delay_ms(25);
hid_hal_mouse_release(hid_tiktok->hid, HID_MOUSE_BTN_LEFT);
consumed = true;
} else if(event->key == InputKeyUp) {
// Emulate up swipe
hid_hal_mouse_scroll(hid_tiktok->hid, -6);
hid_hal_mouse_scroll(hid_tiktok->hid, -8);
hid_hal_mouse_scroll(hid_tiktok->hid, -10);
hid_hal_mouse_scroll(hid_tiktok->hid, -8);
hid_hal_mouse_scroll(hid_tiktok->hid, -6);
hid_hal_mouse_release(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT);
consumed = true;
} else if(event->key == InputKeyDown) {
// Emulate down swipe
hid_hal_mouse_scroll(hid_tiktok->hid, 6);
hid_hal_mouse_scroll(hid_tiktok->hid, 8);
hid_hal_mouse_scroll(hid_tiktok->hid, 10);
hid_hal_mouse_scroll(hid_tiktok->hid, 8);
hid_hal_mouse_scroll(hid_tiktok->hid, 6);
// Swipe to next video
hid_hal_mouse_scroll(hid_tikshorts->hid, 6);
hid_hal_mouse_scroll(hid_tikshorts->hid, 8);
hid_hal_mouse_scroll(hid_tikshorts->hid, 10);
hid_hal_mouse_scroll(hid_tikshorts->hid, 8);
hid_hal_mouse_scroll(hid_tikshorts->hid, 6);
consumed = true;
} else if(event->key == InputKeyUp) {
// Swipe to previous video
hid_hal_mouse_scroll(hid_tikshorts->hid, -6);
hid_hal_mouse_scroll(hid_tikshorts->hid, -8);
hid_hal_mouse_scroll(hid_tikshorts->hid, -10);
hid_hal_mouse_scroll(hid_tikshorts->hid, -8);
hid_hal_mouse_scroll(hid_tikshorts->hid, -6);
consumed = true;
} else if(event->key == InputKeyBack) {
// Pause
hid_hal_mouse_press(hid_tiktok->hid, HID_MOUSE_BTN_LEFT);
hid_hal_mouse_press(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT);
furi_delay_ms(50);
hid_hal_mouse_release(hid_tiktok->hid, HID_MOUSE_BTN_LEFT);
hid_hal_mouse_release(hid_tikshorts->hid, HID_MOUSE_BTN_LEFT);
consumed = true;
}
} else if(event->type == InputTypeLong) {
if(event->key == InputKeyBack) {
hid_hal_consumer_key_release_all(hid_tiktok->hid);
hid_hal_consumer_key_release_all(hid_tikshorts->hid);
model->is_cursor_set = false;
consumed = false;
}
@@ -225,37 +229,40 @@ static bool hid_tiktok_input_callback(InputEvent* event, void* context) {
return consumed;
}
HidTikTok* hid_tiktok_alloc(Hid* bt_hid) {
HidTikTok* hid_tiktok = malloc(sizeof(HidTikTok));
hid_tiktok->hid = bt_hid;
hid_tiktok->view = view_alloc();
view_set_context(hid_tiktok->view, hid_tiktok);
view_allocate_model(hid_tiktok->view, ViewModelTypeLocking, sizeof(HidTikTokModel));
view_set_draw_callback(hid_tiktok->view, hid_tiktok_draw_callback);
view_set_input_callback(hid_tiktok->view, hid_tiktok_input_callback);
HidTikShorts* hid_tikshorts_alloc(Hid* bt_hid) {
HidTikShorts* hid_tikshorts = malloc(sizeof(HidTikShorts));
hid_tikshorts->hid = bt_hid;
hid_tikshorts->view = view_alloc();
view_set_context(hid_tikshorts->view, hid_tikshorts);
view_allocate_model(hid_tikshorts->view, ViewModelTypeLocking, sizeof(HidTikShortsModel));
view_set_draw_callback(hid_tikshorts->view, hid_tikshorts_draw_callback);
view_set_input_callback(hid_tikshorts->view, hid_tikshorts_input_callback);
with_view_model(
hid_tiktok->view, HidTikTokModel * model, { model->transport = bt_hid->transport; }, true);
hid_tikshorts->view,
HidTikShortsModel * model,
{ model->transport = bt_hid->transport; },
true);
return hid_tiktok;
return hid_tikshorts;
}
void hid_tiktok_free(HidTikTok* hid_tiktok) {
furi_assert(hid_tiktok);
view_free(hid_tiktok->view);
free(hid_tiktok);
void hid_tikshorts_free(HidTikShorts* hid_tikshorts) {
furi_assert(hid_tikshorts);
view_free(hid_tikshorts->view);
free(hid_tikshorts);
}
View* hid_tiktok_get_view(HidTikTok* hid_tiktok) {
furi_assert(hid_tiktok);
return hid_tiktok->view;
View* hid_tikshorts_get_view(HidTikShorts* hid_tikshorts) {
furi_assert(hid_tikshorts);
return hid_tikshorts->view;
}
void hid_tiktok_set_connected_status(HidTikTok* hid_tiktok, bool connected) {
furi_assert(hid_tiktok);
void hid_tikshorts_set_connected_status(HidTikShorts* hid_tikshorts, bool connected) {
furi_assert(hid_tikshorts);
with_view_model(
hid_tiktok->view,
HidTikTokModel * model,
hid_tikshorts->view,
HidTikShortsModel * model,
{
model->connected = connected;
model->is_cursor_set = false;

View File

@@ -0,0 +1,14 @@
#pragma once
#include <gui/view.h>
typedef struct Hid Hid;
typedef struct HidTikShorts HidTikShorts;
HidTikShorts* hid_tikshorts_alloc(Hid* bt_hid);
void hid_tikshorts_free(HidTikShorts* hid_tikshorts);
View* hid_tikshorts_get_view(HidTikShorts* hid_tikshorts);
void hid_tikshorts_set_connected_status(HidTikShorts* hid_tikshorts, bool connected);

View File

@@ -1,14 +0,0 @@
#pragma once
#include <gui/view.h>
typedef struct Hid Hid;
typedef struct HidTikTok HidTikTok;
HidTikTok* hid_tiktok_alloc(Hid* bt_hid);
void hid_tiktok_free(HidTikTok* hid_tiktok);
View* hid_tiktok_get_view(HidTikTok* hid_tiktok);
void hid_tiktok_set_connected_status(HidTikTok* hid_tiktok, bool connected);

View File

@@ -6,7 +6,7 @@
#include <gui/gui.h>
#include <input/input.h>
#include <dialogs/dialogs.h>
#include "ir_remote_icons.h"
#include <ir_remote_icons.h>
#include <assets_icons.h>
#include <notification/notification.h>

View File

@@ -5,6 +5,7 @@ App(
entry_point="playlist_app",
requires=["storage", "gui", "dialogs", "subghz"],
stack_size=2 * 1024,
order=14,
fap_icon="subplaylist_10px.png",
fap_category="Sub-GHz",
fap_icon_assets="images",

View File

@@ -6,7 +6,7 @@
#include <storage/storage.h>
#include <lib/toolbox/path.h>
#include "subghz_playlist_icons.h"
#include <subghz_playlist_icons.h>
#include <assets_icons.h>
#include <lib/subghz/protocols/protocol_items.h>

View File

@@ -239,7 +239,6 @@ bool subrem_view_remote_input(InputEvent* event, void* context) {
return true;
}
// BACK button processing end
if(event->key == InputKeyUp && event->type == InputTypePress) {

View File

@@ -8,6 +8,7 @@ App(
"dialogs",
],
stack_size=10 * 1024,
order=20,
fap_icon="icons/text_10px.png",
fap_category="Tools",
fap_icon_assets="icons",