mirror of
https://protopirate.net/ProtoPirate/ProtoPirate.git
synced 2026-10-23 14:52:21 +00:00
Merge pull request 'Sub Decoder Save Filename Dialog' (#45) from RalphWiggum/ProtoPirate:decode_save_dialog into main
FAP Build / ufbt: Build for Momentum dev (push) Canceled after 0s
FAP Build / ufbt: Build for Momentum release (push) Canceled after 0s
FAP Build / ufbt: Build for OFW dev channel (push) Canceled after 0s
FAP Build / ufbt: Build for OFW release channel (push) Canceled after 0s
FAP Build / ufbt: Build for Unleashed dev (push) Canceled after 0s
FAP Build / ufbt: Build for Unleashed release (push) Canceled after 0s
FAP Build / ufbt: Build for Momentum dev (push) Canceled after 0s
FAP Build / ufbt: Build for Momentum release (push) Canceled after 0s
FAP Build / ufbt: Build for OFW dev channel (push) Canceled after 0s
FAP Build / ufbt: Build for OFW release channel (push) Canceled after 0s
FAP Build / ufbt: Build for Unleashed dev (push) Canceled after 0s
FAP Build / ufbt: Build for Unleashed release (push) Canceled after 0s
Reviewed-on: http://protopirate.net/ProtoPirate/ProtoPirate/pulls/45 Reviewed-by: MMX <mmx@no-reply.protopirate.net>
This commit is contained in:
commit
39feb30b80
2 files changed
+87
-12
No files matched your search
@@ -44,6 +44,7 @@ typedef enum {
|
||||
ProtoPirateCustomEventSubDecodeEmulate,
|
||||
ProtoPirateCustomEventSubDecodeBruteforceStart,
|
||||
ProtoPirateCustomEventPsaBruteforceComplete,
|
||||
ProtoPirateCustomEventSubDecodeSaveConfirm,
|
||||
// File Browser
|
||||
ProtoPirateCustomEventSavedFileSelected,
|
||||
// Need saving confirmation
|
||||
|
||||
@@ -493,6 +493,12 @@ static bool protopirate_scene_sub_decode_open_browser_for_next_file(ProtoPirateA
|
||||
return true;
|
||||
}
|
||||
|
||||
static void protopirate_scene_sub_decode_text_input_callback(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSubDecodeSaveConfirm);
|
||||
}
|
||||
|
||||
void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
|
||||
@@ -621,9 +627,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
protopirate_history_get_raw_data(ctx->history, ctx->selected_history_index);
|
||||
|
||||
if(ff) {
|
||||
FuriString* saved_path = furi_string_alloc();
|
||||
FuriString* file_name_str = furi_string_alloc();
|
||||
|
||||
if(app->datetime_filenames) {
|
||||
//Get the date and time to save.
|
||||
DateTime date_time;
|
||||
@@ -638,6 +642,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
date_time.minute,
|
||||
date_time.second);
|
||||
}
|
||||
|
||||
// Extract protocol name
|
||||
FuriString* protocol = furi_string_alloc();
|
||||
protopirate_storage_get_capture_display_protocol(ff, protocol);
|
||||
@@ -650,18 +655,53 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
furi_string_replace_all(file_name_str, "/", "_");
|
||||
furi_string_replace_all(file_name_str, " ", "_");
|
||||
|
||||
if(protopirate_storage_save_capture(
|
||||
ff,
|
||||
furi_string_get_cstr(file_name_str),
|
||||
saved_path,
|
||||
app->datetime_filenames)) {
|
||||
notification_message(app->notifications, &sequence_success);
|
||||
} else {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
}
|
||||
// Get the next auto-generated filename (just the name part)
|
||||
FuriString* auto_path = furi_string_alloc();
|
||||
if(protopirate_storage_get_next_filename(
|
||||
furi_string_get_cstr(file_name_str), auto_path, app->datetime_filenames)) {
|
||||
// Extract just the filename without folder and extension
|
||||
const char* full = furi_string_get_cstr(auto_path);
|
||||
const char* slash = strrchr(full, '/');
|
||||
const char* name_start = slash ? slash + 1 : full;
|
||||
|
||||
// Copy without extension
|
||||
size_t name_len = strlen(name_start);
|
||||
const char* dot = strrchr(name_start, '.');
|
||||
if(dot) name_len = dot - name_start;
|
||||
if(name_len >= sizeof(app->save_filename))
|
||||
name_len = sizeof(app->save_filename) - 1;
|
||||
|
||||
memcpy(app->save_filename, name_start, name_len);
|
||||
app->save_filename[name_len] = '\0';
|
||||
} else {
|
||||
snprintf(app->save_filename, sizeof(app->save_filename), "capture");
|
||||
}
|
||||
furi_string_free(auto_path);
|
||||
|
||||
// Store context for when text input confirms
|
||||
app->save_history_idx = app->txrx->idx_menu_chosen;
|
||||
app->save_from_saved_info = false;
|
||||
|
||||
//Make sure we have a text input window.
|
||||
app->text_input = text_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
ProtoPirateViewTextInput,
|
||||
text_input_get_view(app->text_input));
|
||||
|
||||
// Configure and show text input
|
||||
text_input_reset(app->text_input);
|
||||
text_input_set_header_text(app->text_input, "Save filename:");
|
||||
text_input_set_result_callback(
|
||||
app->text_input,
|
||||
protopirate_scene_sub_decode_text_input_callback,
|
||||
app,
|
||||
app->save_filename,
|
||||
sizeof(app->save_filename),
|
||||
false); // don't clear default text
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewTextInput);
|
||||
furi_string_free(file_name_str);
|
||||
furi_string_free(saved_path);
|
||||
} else {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
@@ -670,6 +710,40 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == ProtoPirateCustomEventSubDecodeSaveConfirm) {
|
||||
// User confirmed the filename in text input
|
||||
FlipperFormat* ff =
|
||||
protopirate_history_get_raw_data(app->txrx->history, app->save_history_idx);
|
||||
if(ff) {
|
||||
// Build full path: folder/filename.psf
|
||||
FuriString* save_path = furi_string_alloc_printf(
|
||||
"%s/%s%s",
|
||||
PROTOPIRATE_APP_FOLDER,
|
||||
app->save_filename,
|
||||
PROTOPIRATE_APP_EXTENSION);
|
||||
|
||||
if(protopirate_storage_save_capture_to_path(ff, furi_string_get_cstr(save_path))) {
|
||||
notification_message(app->notifications, &sequence_success);
|
||||
FURI_LOG_I(TAG, "Saved to: %s", furi_string_get_cstr(save_path));
|
||||
} else {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
FURI_LOG_E(TAG, "Save failed");
|
||||
}
|
||||
furi_string_free(save_path);
|
||||
}
|
||||
|
||||
// Return to the receiver info widget
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewWidget);
|
||||
|
||||
//Kill the text_input view.
|
||||
if(app->text_input) {
|
||||
FURI_LOG_D(TAG, "Removing text_input view");
|
||||
view_dispatcher_remove_view(app->view_dispatcher, ProtoPirateViewTextInput);
|
||||
text_input_free(app->text_input);
|
||||
app->text_input = NULL;
|
||||
}
|
||||
consumed = true;
|
||||
|
||||
}
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
else if(
|
||||
|
||||
Reference in new issue
Block a user