Skip to content

Commit

Permalink
added Action settings menu
Browse files Browse the repository at this point in the history
  • Loading branch information
rdefeo committed Mar 24, 2024
1 parent d43f3e1 commit bdb3aa9
Show file tree
Hide file tree
Showing 19 changed files with 621 additions and 79 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: "FAP: Build for multiple SDK sources"
# This will build your app for dev and release channels on GitHub.
# It will also build your app every day to make sure it's up to date with the latest SDK changes.
# See https://github.com/marketplace/actions/build-flipper-application-package-fap for more information

on:
push:
## put your main branch name under "branches"
#branches:
# - master
pull_request:
schedule:
# do a build every day
- cron: "1 1 * * *"

jobs:
ufbt-build:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- name: dev channel
sdk-channel: dev
- name: release channel
sdk-channel: release
# You can add unofficial channels here. See ufbt action docs for more info.
name: 'ufbt: Build for ${{ matrix.name }}'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build with ufbt
uses: flipperdevices/flipperzero-ufbt-action@v0.1
id: build-app
with:
sdk-channel: ${{ matrix.sdk-channel }}
- name: Upload app artifacts
uses: actions/upload-artifact@v3
with:
# See ufbt action docs for other output variables
name: ${{ github.event.repository.name }}-${{ steps.build-app.outputs.suffix }}
path: ${{ steps.build-app.outputs.fap-artifacts }}
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dist/*
.vscode
.clang-format
.editorconfig
.env
.ufbt
2 changes: 2 additions & 0 deletions actions/action.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#define EMPTY_ACTION_INDEX -1

struct Item;

void action_tx(void* context, Item* item, FuriString* error);
18 changes: 9 additions & 9 deletions actions/action_rfid.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@
#include "action_i.h"
#include "quac.h"

#define RFID_FILE_TYPE "Flipper RFID key"
#define RFID_FILE_VERSION 1

// lifted from flipperzero-firmware/applications/main/lfrfid/lfrfid_cli.c
void action_rfid_tx(void* context, const FuriString* action_path, FuriString* error) {
UNUSED(error);

App* app = context;
const FuriString* file_name = action_path;
const char* file_name = furi_string_get_cstr(action_path);

FlipperFormat* fff_data_file = flipper_format_file_alloc(app->storage);
FuriString* temp_str;
Expand All @@ -32,22 +35,20 @@ void action_rfid_tx(void* context, const FuriString* action_path, FuriString* er
// FURI_LOG_I(TAG, "Max dict data size is %d", data_size);
bool successful_read = false;
do {
if(!flipper_format_file_open_existing(fff_data_file, furi_string_get_cstr(file_name))) {
ACTION_SET_ERROR("RFID: Error opening %s", furi_string_get_cstr(file_name));
if(!flipper_format_file_open_existing(fff_data_file, file_name)) {
ACTION_SET_ERROR("RFID: Error opening %s", file_name);
break;
}
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
ACTION_SET_ERROR("RFID: Missing or incorrect header");
break;
}
// FURI_LOG_I(TAG, "Read file headers");
// TODO: add better header checks here...
if(!strcmp(furi_string_get_cstr(temp_str), "Flipper RFID key")) {
if(!strcmp(furi_string_get_cstr(temp_str), RFID_FILE_TYPE) &&
temp_data32 == RFID_FILE_VERSION) {
} else {
ACTION_SET_ERROR("RFID: Type or version mismatch");
break;
}

// read and check the protocol field
if(!flipper_format_read_string(fff_data_file, "Key type", temp_str)) {
ACTION_SET_ERROR("RFID: Error reading protocol");
Expand Down Expand Up @@ -90,8 +91,7 @@ void action_rfid_tx(void* context, const FuriString* action_path, FuriString* er
lfrfid_worker_emulate_start(worker, protocol);

int16_t time_ms = app->settings.rfid_duration;
FURI_LOG_I(
TAG, "RFID: Emulating RFID (%s) for %d ms", furi_string_get_cstr(file_name), time_ms);
FURI_LOG_I(TAG, "RFID: Emulating RFID (%s) for %d ms", file_name, time_ms);
int16_t interval_ms = 100;
while(time_ms > 0) {
furi_delay_ms(interval_ms);
Expand Down
2 changes: 2 additions & 0 deletions item.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <m-array.h>

// Max length of a filename, final path element only
#define MAX_NAME_LEN 64
#define MAX_EXT_LEN 6

/** Defines an individual item action or item group. Each object contains
Expand Down
47 changes: 27 additions & 20 deletions quac.c
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
#include <furi.h>

#include <gui/gui.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <gui/modules/dialog_ex.h>
#include <gui/modules/variable_item_list.h>

#include <storage/storage.h>
#include <notification/notification_messages.h>
#include "quac.h"
#include "quac_settings.h"

#include "item.h"
#include "scenes/scenes.h"
#include "scenes/scene_items.h"

#include "quac.h"
#include "quac_settings.h"

/* generated by fbt from .png files in images folder */
#include <quac_icons.h>

Expand All @@ -32,26 +23,36 @@ App* app_alloc() {
// Main interface
app->action_menu = action_menu_alloc();
view_dispatcher_add_view(
app->view_dispatcher, Q_ActionMenu, action_menu_get_view(app->action_menu));
app->view_dispatcher, QView_ActionMenu, action_menu_get_view(app->action_menu));

// App settings
app->vil_settings = variable_item_list_alloc();
view_dispatcher_add_view(
app->view_dispatcher, Q_Settings, variable_item_list_get_view(app->vil_settings));
app->view_dispatcher, QView_Settings, variable_item_list_get_view(app->vil_settings));

app->dialog = dialog_ex_alloc();
view_dispatcher_add_view(app->view_dispatcher, Q_Dialog, dialog_ex_get_view(app->dialog));
// Misc interfaces
app->sub_menu = submenu_alloc();
view_dispatcher_add_view(
app->view_dispatcher, QView_ActionSettings, submenu_get_view(app->sub_menu));

app->text_input = text_input_alloc();
view_dispatcher_add_view(
app->view_dispatcher, QView_ActionTextInput, text_input_get_view(app->text_input));

// Storage
app->storage = furi_record_open(RECORD_STORAGE);

// Notifications - for LED light access
app->notifications = furi_record_open(RECORD_NOTIFICATION);

app->dialog = furi_record_open(RECORD_DIALOGS);

// data member initialize
app->depth = 0;
app->selected_item = -1;

app->temp_str = furi_string_alloc();

return app;
}

Expand All @@ -60,19 +61,24 @@ void app_free(App* app) {

item_items_view_free(app->items_view);

view_dispatcher_remove_view(app->view_dispatcher, Q_ActionMenu);
view_dispatcher_remove_view(app->view_dispatcher, Q_Settings);
view_dispatcher_remove_view(app->view_dispatcher, Q_Dialog);
view_dispatcher_remove_view(app->view_dispatcher, QView_ActionMenu);
view_dispatcher_remove_view(app->view_dispatcher, QView_Settings);
view_dispatcher_remove_view(app->view_dispatcher, QView_ActionSettings);
view_dispatcher_remove_view(app->view_dispatcher, QView_ActionTextInput);

action_menu_free(app->action_menu);
variable_item_list_free(app->vil_settings);
dialog_ex_free(app->dialog);
submenu_free(app->sub_menu);
text_input_free(app->text_input);

scene_manager_free(app->scene_manager);
view_dispatcher_free(app->view_dispatcher);

furi_string_free(app->temp_str);

furi_record_close(RECORD_STORAGE);
furi_record_close(RECORD_NOTIFICATION);
furi_record_close(RECORD_DIALOGS);

free(app);
}
Expand All @@ -83,6 +89,7 @@ int32_t quac_app(void* p) {
FURI_LOG_I(TAG, "QUAC! QUAC!");

size_t free_start = memmgr_get_free_heap();
furi_assert(0);

App* app = app_alloc();
quac_load_settings(app);
Expand All @@ -92,7 +99,7 @@ int32_t quac_app(void* p) {

Gui* gui = furi_record_open(RECORD_GUI);
view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
scene_manager_next_scene(app->scene_manager, Q_Scene_Items);
scene_manager_next_scene(app->scene_manager, QScene_Items);
view_dispatcher_run(app->view_dispatcher);

furi_record_close(RECORD_GUI);
Expand Down
16 changes: 14 additions & 2 deletions quac.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#pragma once

#include <gui/gui.h>
#include <gui/scene_manager.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/dialog_ex.h>
#include <gui/scene_manager.h>
#include <gui/modules/variable_item_list.h>
#include <gui/modules/submenu.h>
#include <gui/modules/text_input.h>
#include <dialogs/dialogs.h>

#include <storage/storage.h>
#include <notification/notification_messages.h>
Expand All @@ -12,6 +16,9 @@

#include "item.h"

// #pragma GCC push_options
// #pragma GCC optimize("O0")

#define QUAC_NAME "Quac!"
#define TAG "Quac" // log statement id

Expand All @@ -28,7 +35,9 @@ typedef struct App {

ActionMenu* action_menu;
VariableItemList* vil_settings;
DialogEx* dialog;
DialogsApp* dialog;
Submenu* sub_menu;
TextInput* text_input;

Storage* storage;
NotificationApp* notifications;
Expand All @@ -37,6 +46,9 @@ typedef struct App {
int depth;
int selected_item;

FuriString* temp_str; // used for renames/etc
char temp_cstr[MAX_NAME_LEN]; // used for renames/etc

struct {
QuacAppLayout layout; // Defaults to Portrait
bool show_icons; // Defaults to True
Expand Down
6 changes: 6 additions & 0 deletions scenes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dist/*
.vscode
.clang-format
.editorconfig
.env
.ufbt
86 changes: 86 additions & 0 deletions scenes/scene_action_create_group.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <furi.h>

#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <gui/modules/text_input.h>

#include "quac.h"
#include "scenes.h"
#include "scene_action_create_group.h"
#include "../actions/action.h"

#include <lib/toolbox/path.h>

enum {
SceneActionCreateGroupEvent,
};

void scene_action_create_group_callback(void* context) {
App* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, SceneActionCreateGroupEvent);
}

void scene_action_create_group_on_enter(void* context) {
App* app = context;
TextInput* text = app->text_input;

text_input_set_header_text(text, "Enter new group name:");

app->temp_cstr[0] = 0;
text_input_set_result_callback(
text, scene_action_create_group_callback, app, app->temp_cstr, MAX_NAME_LEN, false);

// TextInputValidatorCallback
// text_input_set_validator(text, validator_callback, context)

view_dispatcher_switch_to_view(app->view_dispatcher, QView_ActionTextInput);
}

bool scene_action_create_group_on_event(void* context, SceneManagerEvent event) {
App* app = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SceneActionCreateGroupEvent) {
// FURI_LOG_I(TAG, "Attempting to create group %s", app->temp_cstr);
if(!strcmp(app->temp_cstr, "")) {
return false;
}
Item* item = ItemArray_get(app->items_view->items, app->selected_item);
FuriString* current_path = furi_string_alloc();
path_extract_dirname(furi_string_get_cstr(item->path), current_path);

FuriString* new_group_path = furi_string_alloc();
furi_string_printf(
new_group_path, "%s/%s", furi_string_get_cstr(current_path), app->temp_cstr);
// FURI_LOG_I(TAG, "Full new path: %s", furi_string_get_cstr(new_group_path));

FS_Error fs_result =
storage_common_mkdir(app->storage, furi_string_get_cstr(new_group_path));
if(fs_result == FSE_OK) {
ItemsView* new_items = item_get_items_view_from_path(app, current_path);
item_items_view_free(app->items_view);
app->items_view = new_items;
} else {
FURI_LOG_E(
TAG, "Create Group failed! %s", filesystem_api_error_get_desc(fs_result));
FuriString* error_msg = furi_string_alloc_printf(
"Create Group failed!\nError: %s", filesystem_api_error_get_desc(fs_result));
dialog_message_show_storage_error(app->dialog, furi_string_get_cstr(error_msg));
furi_string_free(error_msg);
}

furi_string_free(current_path);
furi_string_free(new_group_path);

scene_manager_search_and_switch_to_previous_scene(app->scene_manager, QScene_Items);
consumed = true;
}
}

return consumed;
}

void scene_action_create_group_on_exit(void* context) {
App* app = context;
text_input_reset(app->text_input);
}
8 changes: 8 additions & 0 deletions scenes/scene_action_create_group.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include <gui/scene_manager.h>

// For each scene, implement handler callbacks
void scene_action_create_group_on_enter(void* context);
bool scene_action_create_group_on_event(void* context, SceneManagerEvent event);
void scene_action_create_group_on_exit(void* context);
Loading

0 comments on commit bdb3aa9

Please sign in to comment.