Просмотр исходного кода

Merge nfc_playlist from https://github.com/acegoal07/FlipperZero_NFC_Playlist

Willy-JL 1 год назад
Родитель
Сommit
831c7dc3e1

+ 2 - 1
nfc_playlist/README.md

@@ -26,8 +26,9 @@ As i know these firmwares are supported and working if you know any more please
 - Create PLaylist (Creates a new playlist with the given name)
 - Delete playlist (Deletes the selected playlist)
 - Rename playlist (Renames the selected playlist to the new name provided)
-- View playlist content (Allows you to view the contents of the playlist)
 - Add NFC Item (Adds the selected nfc item to the currently selected playlist)
+- Remove NFC Item (Opens a menu allowing you to select a line to remove from the playlist)
+- View playlist content (Allows you to view the contents of the playlist)
 ## Development plans/ideas:
 Things i would like to add:
 - Ability to remove cards from the playlist

+ 1 - 1
nfc_playlist/application.fam

@@ -8,7 +8,7 @@ App(
     fap_category="NFC",
     fap_author="@acegoal07",
     fap_weburl="https://github.com/acegoal07/FlipperZero_NFC_Playlist/tree/main",
-    fap_version="1.8",
+    fap_version="2.1",
     fap_icon="assets/icon.png",
     fap_private_libs=[
         Lib(

+ 2 - 2
nfc_playlist/nfc_playlist.c

@@ -22,7 +22,7 @@ static NfcPlaylist* nfc_playlist_alloc() {
     nfc_playlist->submenu = submenu_alloc();
     nfc_playlist->widget = widget_alloc();
 
-    nfc_playlist->settings.file_path = furi_string_alloc();
+    nfc_playlist->settings.playlist_path = furi_string_alloc();
     nfc_playlist->file_browser_output = furi_string_alloc();
     nfc_playlist->settings.playlist_selected = false;
     nfc_playlist->settings.emulate_timeout = default_emulate_timeout;
@@ -95,7 +95,7 @@ static void nfc_playlist_free(NfcPlaylist* nfc_playlist) {
     text_input_free(nfc_playlist->text_input);
     popup_free(nfc_playlist->popup);
 
-    furi_string_free(nfc_playlist->settings.file_path);
+    furi_string_free(nfc_playlist->settings.playlist_path);
     furi_string_free(nfc_playlist->file_browser_output);
     free(nfc_playlist);
 }

+ 2 - 2
nfc_playlist/nfc_playlist.h

@@ -38,7 +38,8 @@ typedef enum {
 } NfcPlaylistViews;
 
 typedef struct {
-    FuriString* file_path;
+    FuriString* playlist_path;
+    uint8_t playlist_length;
     bool playlist_selected;
     uint8_t emulate_timeout;
     uint8_t emulate_delay;
@@ -73,7 +74,6 @@ static const bool default_skip_error = false;
 
 #define PLAYLIST_LOCATION "/ext/apps_data/nfc_playlist/"
 #define PLAYLIST_DIR "/ext/apps_data/nfc_playlist"
-#define PLAYLIST_VIEW_MAX_SIZE 1000
 
 typedef enum NfcPlaylistLedState {
     NfcPlaylistLedState_Normal,

+ 4 - 3
nfc_playlist/scenes/nfc_playlist_scene_config.h

@@ -1,10 +1,11 @@
 ADD_SCENE(nfc_playlist, confirm_delete, ConfirmDelete)
 ADD_SCENE(nfc_playlist, emulation, Emulation)
-ADD_SCENE(nfc_playlist, file_edit, FileEdit)
-ADD_SCENE(nfc_playlist, file_rename, FileRename)
+ADD_SCENE(nfc_playlist, playlist_edit, PlaylistEdit)
+ADD_SCENE(nfc_playlist, playlist_rename, PlaylistRename)
 ADD_SCENE(nfc_playlist, main_menu, MainMenu)
-ADD_SCENE(nfc_playlist, name_new_file, NameNewFile)
+ADD_SCENE(nfc_playlist, name_new_playlist, NameNewPlaylist)
 ADD_SCENE(nfc_playlist, nfc_select, NfcSelect)
+ADD_SCENE(nfc_playlist, nfc_remove, NfcRemove)
 ADD_SCENE(nfc_playlist, playlist_select, PlaylistSelect)
 ADD_SCENE(nfc_playlist, settings, Settings)
 ADD_SCENE(nfc_playlist, view_playlist_content, ViewPlaylistContent)

+ 7 - 4
nfc_playlist/scenes/nfc_playlist_scene_confirm_delete.c

@@ -11,7 +11,7 @@ void nfc_playlist_confirm_delete_scene_on_enter(void* context) {
     NfcPlaylist* nfc_playlist = context;
 
     FuriString* temp_str = furi_string_alloc();
-    char* file_path = (char*)furi_string_get_cstr(nfc_playlist->settings.file_path);
+    char* file_path = (char*)furi_string_get_cstr(nfc_playlist->settings.playlist_path);
     furi_string_printf(
         temp_str,
         "\e#Delete %s?\e#",
@@ -53,16 +53,19 @@ bool nfc_playlist_confirm_delete_scene_on_event(void* context, SceneManagerEvent
         switch(event.event) {
         case GuiButtonTypeRight:
             Storage* storage = furi_record_open(RECORD_STORAGE);
-            storage_simply_remove(storage, furi_string_get_cstr(nfc_playlist->settings.file_path));
+            storage_simply_remove(
+                storage, furi_string_get_cstr(nfc_playlist->settings.playlist_path));
             nfc_playlist->settings.playlist_selected = false;
-            furi_string_reset(nfc_playlist->settings.file_path);
+            furi_string_reset(nfc_playlist->settings.playlist_path);
             furi_record_close(RECORD_STORAGE);
             consumed = true;
+            scene_manager_search_and_switch_to_previous_scene(
+                nfc_playlist->scene_manager, NfcPlaylistScene_MainMenu);
             break;
         default:
+            scene_manager_previous_scene(nfc_playlist->scene_manager);
             break;
         }
-        scene_manager_previous_scene(nfc_playlist->scene_manager);
     }
     return consumed;
 }

+ 2 - 2
nfc_playlist/scenes/nfc_playlist_scene_emulation.c

@@ -22,7 +22,7 @@ int32_t nfc_playlist_emulation_task(void* context) {
 
     if(file_stream_open(
            stream,
-           furi_string_get_cstr(nfc_playlist->settings.file_path),
+           furi_string_get_cstr(nfc_playlist->settings.playlist_path),
            FSAM_READ,
            FSOM_OPEN_EXISTING)) {
         EmulationState = NfcPlaylistEmulationState_Emulating;
@@ -36,7 +36,7 @@ int32_t nfc_playlist_emulation_task(void* context) {
               EmulationState == NfcPlaylistEmulationState_Emulating) {
             char* file_path = (char*)furi_string_get_cstr(line);
 
-            if(strlen(file_path) <= 1) {
+            if(strspn(file_path, " \t\n\r") == strlen(file_path)) {
                 continue;
             }
 

+ 2 - 2
nfc_playlist/scenes/nfc_playlist_scene_main_menu.c

@@ -38,7 +38,7 @@ void nfc_playlist_main_menu_scene_on_enter(void* context) {
         NfcPlaylistMenuSelection_Start,
         nfc_playlist_main_menu_menu_callback,
         nfc_playlist,
-        furi_string_empty(nfc_playlist->settings.file_path),
+        furi_string_empty(nfc_playlist->settings.playlist_path),
         "No\nplaylist\nselected");
 
     submenu_add_item(
@@ -79,7 +79,7 @@ bool nfc_playlist_main_menu_scene_on_event(void* context, SceneManagerEvent even
             consumed = true;
             break;
         case NfcPlaylistEvent_ShowFileEdit:
-            scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_FileEdit);
+            scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_PlaylistEdit);
             consumed = true;
             break;
         case NfcPlaylistEvent_ShowSettings:

+ 9 - 7
nfc_playlist/scenes/nfc_playlist_scene_name_new_file.c → nfc_playlist/scenes/nfc_playlist_scene_name_new_playlist.c

@@ -1,6 +1,6 @@
 #include "../nfc_playlist.h"
 
-void nfc_playlist_name_new_file_menu_callback(void* context) {
+void nfc_playlist_name_new_playlist_menu_callback(void* context) {
     NfcPlaylist* nfc_playlist = context;
     Storage* storage = furi_record_open(RECORD_STORAGE);
     FuriString* file_name = furi_string_alloc();
@@ -11,23 +11,25 @@ void nfc_playlist_name_new_file_menu_callback(void* context) {
     File* file = storage_file_alloc(storage);
     if(storage_file_open(file, furi_string_get_cstr(file_name), FSAM_READ_WRITE, FSOM_CREATE_NEW)) {
         storage_file_close(file);
-        furi_string_swap(nfc_playlist->settings.file_path, file_name);
+        furi_string_swap(nfc_playlist->settings.playlist_path, file_name);
     }
 
+    nfc_playlist->settings.playlist_length = 0;
+
     storage_file_free(file);
     furi_string_free(file_name);
     furi_record_close(RECORD_STORAGE);
     scene_manager_previous_scene(nfc_playlist->scene_manager);
 }
 
-void nfc_playlist_name_new_file_scene_on_enter(void* context) {
+void nfc_playlist_name_new_playlist_scene_on_enter(void* context) {
     NfcPlaylist* nfc_playlist = context;
     nfc_playlist->text_input_output = (char*)malloc(50);
     text_input_set_header_text(nfc_playlist->text_input, "Enter file name");
     text_input_set_minimum_length(nfc_playlist->text_input, 1);
     text_input_set_result_callback(
         nfc_playlist->text_input,
-        nfc_playlist_name_new_file_menu_callback,
+        nfc_playlist_name_new_playlist_menu_callback,
         nfc_playlist,
         nfc_playlist->text_input_output,
         50,
@@ -36,14 +38,14 @@ void nfc_playlist_name_new_file_scene_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_TextInput);
 }
 
-bool nfc_playlist_name_new_file_scene_on_event(void* context, SceneManagerEvent event) {
+bool nfc_playlist_name_new_playlist_scene_on_event(void* context, SceneManagerEvent event) {
     UNUSED(context);
     UNUSED(event);
     return false;
 }
 
-void nfc_playlist_name_new_file_scene_on_exit(void* context) {
+void nfc_playlist_name_new_playlist_scene_on_exit(void* context) {
     NfcPlaylist* nfc_playlist = context;
-    text_input_reset(nfc_playlist->text_input);
     free(nfc_playlist->text_input_output);
+    text_input_reset(nfc_playlist->text_input);
 }

+ 139 - 0
nfc_playlist/scenes/nfc_playlist_scene_nfc_remove.c

@@ -0,0 +1,139 @@
+#include "../nfc_playlist.h"
+
+typedef enum {
+    NfcPlaylistSettings_LineSelector,
+    NfcPlaylistSettings_RemoveLine
+} NfcPlaylistSettingsMenuSelection;
+
+uint8_t selected_line;
+
+void nfc_playlist_nfc_remove_menu_callback(void* context, uint32_t index) {
+    NfcPlaylist* nfc_playlist = context;
+    scene_manager_handle_custom_event(nfc_playlist->scene_manager, index);
+}
+
+void nfc_playlist_nfc_remove_options_change_callback(VariableItem* item) {
+    NfcPlaylist* nfc_playlist = variable_item_get_context(item);
+
+    uint8_t current_option =
+        variable_item_list_get_selected_item_index(nfc_playlist->variable_item_list);
+    uint8_t option_value_index = variable_item_get_current_value_index(item);
+    FuriString* tmp_str = furi_string_alloc();
+    switch(current_option) {
+    case NfcPlaylistSettings_LineSelector:
+        selected_line = option_value_index + 1;
+        furi_string_printf(tmp_str, "%d", selected_line);
+        variable_item_set_current_value_text(item, furi_string_get_cstr(tmp_str));
+        break;
+    default:
+        break;
+    }
+    furi_string_free(tmp_str);
+}
+
+void nfc_playlist_nfc_remove_scene_on_enter(void* context) {
+    NfcPlaylist* nfc_playlist = context;
+    FuriString* tmp_str = furi_string_alloc();
+
+    selected_line = nfc_playlist->settings.playlist_length;
+
+    variable_item_list_set_header(nfc_playlist->variable_item_list, "Settings");
+
+    VariableItem* Line_selector = variable_item_list_add(
+        nfc_playlist->variable_item_list,
+        "Select Line",
+        nfc_playlist->settings.playlist_length,
+        nfc_playlist_nfc_remove_options_change_callback,
+        nfc_playlist);
+    variable_item_set_current_value_index(
+        Line_selector, nfc_playlist->settings.playlist_length - 1);
+    furi_string_printf(tmp_str, "%d", selected_line);
+    variable_item_set_current_value_text(Line_selector, furi_string_get_cstr(tmp_str));
+    variable_item_set_locked(
+        Line_selector,
+        nfc_playlist->settings.playlist_length == 0 ? true : false,
+        "Playlist\nis empty");
+
+    variable_item_list_add(nfc_playlist->variable_item_list, "Remove Line", 0, NULL, NULL);
+    variable_item_set_locked(
+        variable_item_list_get(nfc_playlist->variable_item_list, NfcPlaylistSettings_RemoveLine),
+        nfc_playlist->settings.playlist_length == 0 ? true : false,
+        "Playlist\nis empty");
+
+    variable_item_list_set_enter_callback(
+        nfc_playlist->variable_item_list, nfc_playlist_nfc_remove_menu_callback, nfc_playlist);
+    furi_string_free(tmp_str);
+
+    view_dispatcher_switch_to_view(
+        nfc_playlist->view_dispatcher, NfcPlaylistView_VariableItemList);
+}
+
+bool nfc_playlist_nfc_remove_scene_on_event(void* context, SceneManagerEvent event) {
+    NfcPlaylist* nfc_playlist = context;
+    bool consumed = false;
+    if(event.type == SceneManagerEventTypeCustom) {
+        switch(event.event) {
+        case NfcPlaylistSettings_RemoveLine:
+            Storage* storage = furi_record_open(RECORD_STORAGE);
+            Stream* stream = file_stream_alloc(storage);
+
+            if(file_stream_open(
+                   stream,
+                   furi_string_get_cstr(nfc_playlist->settings.playlist_path),
+                   FSAM_READ_WRITE,
+                   FSOM_OPEN_EXISTING)) {
+                FuriString* line = furi_string_alloc();
+                FuriString* tmp_str = furi_string_alloc();
+                uint8_t current_line = 0;
+                while(stream_read_line(stream, line)) {
+                    current_line++;
+                    if(current_line != selected_line) {
+                        furi_string_replace_all(line, "\n", "");
+                        if(furi_string_empty(tmp_str)) {
+                            furi_string_cat_printf(tmp_str, "%s", furi_string_get_cstr(line));
+                        } else {
+                            furi_string_cat_printf(tmp_str, "\n%s", furi_string_get_cstr(line));
+                        }
+                    }
+                }
+
+                stream_clean(stream);
+                furi_string_free(line);
+                stream_write_string(stream, tmp_str);
+                furi_string_free(tmp_str);
+                file_stream_close(stream);
+                nfc_playlist->settings.playlist_length--;
+                selected_line = nfc_playlist->settings.playlist_length;
+            }
+            stream_free(stream);
+            furi_record_close(RECORD_STORAGE);
+
+            if(selected_line == 0) {
+                scene_manager_previous_scene(nfc_playlist->scene_manager);
+            } else {
+                FuriString* tmp_str = furi_string_alloc();
+
+                VariableItem* Line_selector = variable_item_list_get(
+                    nfc_playlist->variable_item_list, NfcPlaylistSettings_LineSelector);
+                variable_item_set_values_count(
+                    Line_selector, nfc_playlist->settings.playlist_length);
+                variable_item_set_current_value_index(Line_selector, selected_line - 1);
+                furi_string_printf(tmp_str, "%d", selected_line);
+                variable_item_set_current_value_text(Line_selector, furi_string_get_cstr(tmp_str));
+
+                furi_string_free(tmp_str);
+            }
+
+            consumed = true;
+            break;
+        default:
+            break;
+        }
+    }
+    return consumed;
+}
+
+void nfc_playlist_nfc_remove_scene_on_exit(void* context) {
+    NfcPlaylist* nfc_playlist = context;
+    variable_item_list_reset(nfc_playlist->variable_item_list);
+}

+ 19 - 22
nfc_playlist/scenes/nfc_playlist_scene_nfc_select.c

@@ -4,39 +4,36 @@ void nfc_playlist_nfc_select_menu_callback(void* context) {
     NfcPlaylist* nfc_playlist = context;
 
     Storage* storage = furi_record_open(RECORD_STORAGE);
-    File* file = storage_file_alloc(storage);
+    Stream* stream = file_stream_alloc(storage);
 
-    if(storage_file_open(
-           file,
-           furi_string_get_cstr(nfc_playlist->settings.file_path),
+    if(file_stream_open(
+           stream,
+           furi_string_get_cstr(nfc_playlist->settings.playlist_path),
            FSAM_READ_WRITE,
            FSOM_OPEN_EXISTING)) {
-        uint8_t buffer[PLAYLIST_VIEW_MAX_SIZE];
-        uint16_t read_count = storage_file_read(file, buffer, PLAYLIST_VIEW_MAX_SIZE);
-        FuriString* playlist_content = furi_string_alloc();
-
-        for(uint16_t i = 0; i < read_count; i++) {
-            furi_string_push_back(playlist_content, buffer[i]);
+        FuriString* line = furi_string_alloc();
+        FuriString* tmp_str = furi_string_alloc();
+        while(stream_read_line(stream, line)) {
+            furi_string_cat_printf(tmp_str, "%s", furi_string_get_cstr(line));
         }
 
-        if(read_count > 0) {
-            furi_string_printf(
-                playlist_content, "\n%s", furi_string_get_cstr(nfc_playlist->file_browser_output));
+        if(!furi_string_empty(tmp_str)) {
+            furi_string_cat_printf(
+                tmp_str, "\n%s", furi_string_get_cstr(nfc_playlist->file_browser_output));
         } else {
             furi_string_printf(
-                playlist_content, "%s", furi_string_get_cstr(nfc_playlist->file_browser_output));
+                tmp_str, "%s", furi_string_get_cstr(nfc_playlist->file_browser_output));
         }
 
-        storage_file_write(
-            file,
-            furi_string_get_cstr(playlist_content),
-            sizeof(char) * furi_string_utf8_length(playlist_content));
-
-        furi_string_free(playlist_content);
-        storage_file_close(file);
+        stream_clean(stream);
+        furi_string_free(line);
+        stream_write_string(stream, tmp_str);
+        file_stream_close(stream);
+        furi_string_free(tmp_str);
+        nfc_playlist->settings.playlist_length++;
     }
 
-    storage_file_free(file);
+    stream_free(stream);
     furi_record_close(RECORD_STORAGE);
     furi_string_reset(nfc_playlist->file_browser_output);
 

+ 40 - 25
nfc_playlist/scenes/nfc_playlist_scene_file_edit.c → nfc_playlist/scenes/nfc_playlist_scene_playlist_edit.c

@@ -4,16 +4,17 @@ typedef enum {
     NfcPlaylistMenuSelection_CreatePlaylist,
     NfcPlaylistMenuSelection_DeletePlaylist,
     NfcPlaylistMenuSelection_RenamePlaylist,
-    NfcPlaylistMenuSelection_ViewPlaylistContent,
-    NfcPlaylistMenuSelection_AddNfcItem
+    NfcPlaylistMenuSelection_AddNfcItem,
+    NfcPlaylistMenuSelection_RemoveNfcItem,
+    NfcPlaylistMenuSelection_ViewPlaylistContent
 } NfcPlaylistFileEditMenuSelection;
 
-void nfc_playlist_file_edit_menu_callback(void* context, uint32_t index) {
+void nfc_playlist_playlist_edit_menu_callback(void* context, uint32_t index) {
     NfcPlaylist* nfc_playlist = context;
     scene_manager_handle_custom_event(nfc_playlist->scene_manager, index);
 }
 
-void nfc_playlist_file_edit_scene_on_enter(void* context) {
+void nfc_playlist_playlist_edit_scene_on_enter(void* context) {
     NfcPlaylist* nfc_playlist = context;
 
     submenu_set_header(nfc_playlist->submenu, "Edit Playlist");
@@ -22,55 +23,65 @@ void nfc_playlist_file_edit_scene_on_enter(void* context) {
         nfc_playlist->submenu,
         "Create Playlist",
         NfcPlaylistMenuSelection_CreatePlaylist,
-        nfc_playlist_file_edit_menu_callback,
+        nfc_playlist_playlist_edit_menu_callback,
         nfc_playlist);
 
     submenu_add_lockable_item(
         nfc_playlist->submenu,
         "Delete Playlist",
         NfcPlaylistMenuSelection_DeletePlaylist,
-        nfc_playlist_file_edit_menu_callback,
+        nfc_playlist_playlist_edit_menu_callback,
         nfc_playlist,
-        furi_string_empty(nfc_playlist->settings.file_path),
+        furi_string_empty(nfc_playlist->settings.playlist_path),
         "No\nplaylist\nselected");
 
     submenu_add_lockable_item(
         nfc_playlist->submenu,
         "Rename Playlist",
         NfcPlaylistMenuSelection_RenamePlaylist,
-        nfc_playlist_file_edit_menu_callback,
+        nfc_playlist_playlist_edit_menu_callback,
         nfc_playlist,
-        furi_string_empty(nfc_playlist->settings.file_path),
+        furi_string_empty(nfc_playlist->settings.playlist_path),
         "No\nplaylist\nselected");
 
     submenu_add_lockable_item(
         nfc_playlist->submenu,
-        "View Playlist Content",
-        NfcPlaylistMenuSelection_ViewPlaylistContent,
-        nfc_playlist_file_edit_menu_callback,
+        "Add NFC Item",
+        NfcPlaylistMenuSelection_AddNfcItem,
+        nfc_playlist_playlist_edit_menu_callback,
         nfc_playlist,
-        furi_string_empty(nfc_playlist->settings.file_path),
+        furi_string_empty(nfc_playlist->settings.playlist_path),
         "No\nplaylist\nselected");
 
     submenu_add_lockable_item(
         nfc_playlist->submenu,
-        "Add NFC Item",
-        NfcPlaylistMenuSelection_AddNfcItem,
-        nfc_playlist_file_edit_menu_callback,
+        "Remove NFC Item",
+        NfcPlaylistMenuSelection_RemoveNfcItem,
+        nfc_playlist_playlist_edit_menu_callback,
+        nfc_playlist,
+        furi_string_empty(nfc_playlist->settings.playlist_path),
+        "No\nplaylist\nselected");
+
+    submenu_add_lockable_item(
+        nfc_playlist->submenu,
+        "View Playlist Content",
+        NfcPlaylistMenuSelection_ViewPlaylistContent,
+        nfc_playlist_playlist_edit_menu_callback,
         nfc_playlist,
-        furi_string_empty(nfc_playlist->settings.file_path),
+        furi_string_empty(nfc_playlist->settings.playlist_path),
         "No\nplaylist\nselected");
 
     view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Submenu);
 }
 
-bool nfc_playlist_file_edit_scene_on_event(void* context, SceneManagerEvent event) {
+bool nfc_playlist_playlist_edit_scene_on_event(void* context, SceneManagerEvent event) {
     NfcPlaylist* nfc_playlist = context;
     bool consumed = false;
     if(event.type == SceneManagerEventTypeCustom) {
         switch(event.event) {
         case NfcPlaylistMenuSelection_CreatePlaylist:
-            scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_NameNewFile);
+            scene_manager_next_scene(
+                nfc_playlist->scene_manager, NfcPlaylistScene_NameNewPlaylist);
             consumed = true;
             break;
         case NfcPlaylistMenuSelection_DeletePlaylist:
@@ -78,7 +89,15 @@ bool nfc_playlist_file_edit_scene_on_event(void* context, SceneManagerEvent even
             consumed = true;
             break;
         case NfcPlaylistMenuSelection_RenamePlaylist:
-            scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_FileRename);
+            scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_PlaylistRename);
+            consumed = true;
+            break;
+        case NfcPlaylistMenuSelection_AddNfcItem:
+            scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_NfcSelect);
+            consumed = true;
+            break;
+        case NfcPlaylistMenuSelection_RemoveNfcItem:
+            scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_NfcRemove);
             consumed = true;
             break;
         case NfcPlaylistMenuSelection_ViewPlaylistContent:
@@ -86,10 +105,6 @@ bool nfc_playlist_file_edit_scene_on_event(void* context, SceneManagerEvent even
                 nfc_playlist->scene_manager, NfcPlaylistScene_ViewPlaylistContent);
             consumed = true;
             break;
-        case NfcPlaylistMenuSelection_AddNfcItem:
-            scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_NfcSelect);
-            consumed = true;
-            break;
         default:
             break;
         }
@@ -97,7 +112,7 @@ bool nfc_playlist_file_edit_scene_on_event(void* context, SceneManagerEvent even
     return consumed;
 }
 
-void nfc_playlist_file_edit_scene_on_exit(void* context) {
+void nfc_playlist_playlist_edit_scene_on_exit(void* context) {
     NfcPlaylist* nfc_playlist = context;
     submenu_reset(nfc_playlist->submenu);
 }

+ 21 - 28
nfc_playlist/scenes/nfc_playlist_scene_file_rename.c → nfc_playlist/scenes/nfc_playlist_scene_playlist_rename.c

@@ -1,42 +1,34 @@
 #include "../nfc_playlist.h"
 
-void nfc_playlist_file_rename_menu_callback(void* context) {
+void nfc_playlist_playlist_rename_menu_callback(void* context) {
     NfcPlaylist* nfc_playlist = context;
     Storage* storage = furi_record_open(RECORD_STORAGE);
 
-    char const* old_file_path = (char*)furi_string_get_cstr(nfc_playlist->settings.file_path);
+    char const* old_file_path = (char*)furi_string_get_cstr(nfc_playlist->settings.playlist_path);
     char const* old_file_name =
         strchr(old_file_path, '/') != NULL ? &strrchr(old_file_path, '/')[1] : old_file_path;
 
-    FuriString* tmp_old_file_path = furi_string_alloc_set_str(old_file_path);
-    furi_string_replace(tmp_old_file_path, old_file_name, "");
+    FuriString* new_file_path = furi_string_alloc_set(nfc_playlist->settings.playlist_path);
+    furi_string_replace(new_file_path, old_file_name, nfc_playlist->text_input_output);
+    furi_string_cat_str(new_file_path, ".txt");
 
-    FuriString* tmp_new_file_path = furi_string_alloc();
-    furi_string_printf(
-        tmp_new_file_path,
-        "%s%s.txt",
-        furi_string_get_cstr(tmp_old_file_path),
-        nfc_playlist->text_input_output);
-
-    if(!storage_file_exists(storage, furi_string_get_cstr(tmp_new_file_path))) {
-        storage_common_rename_safe(
-            storage,
-            furi_string_get_cstr(nfc_playlist->settings.file_path),
-            furi_string_get_cstr(tmp_new_file_path));
-        nfc_playlist->settings.file_path =
-            furi_string_alloc_set_str(furi_string_get_cstr(tmp_new_file_path));
+    if(storage_common_rename_safe(storage, old_file_path, furi_string_get_cstr(new_file_path)) ==
+       0) {
+        furi_string_move(nfc_playlist->settings.playlist_path, new_file_path);
+    } else {
+        furi_string_free(new_file_path);
     }
+
     furi_record_close(RECORD_STORAGE);
-    furi_string_free(tmp_new_file_path);
-    furi_string_free(tmp_old_file_path);
 
-    scene_manager_previous_scene(nfc_playlist->scene_manager);
+    scene_manager_search_and_switch_to_previous_scene(
+        nfc_playlist->scene_manager, NfcPlaylistScene_MainMenu);
 }
 
-void nfc_playlist_file_rename_scene_on_enter(void* context) {
+void nfc_playlist_playlist_rename_scene_on_enter(void* context) {
     NfcPlaylist* nfc_playlist = context;
 
-    char const* tmp_file_path = (char*)furi_string_get_cstr(nfc_playlist->settings.file_path);
+    char const* tmp_file_path = furi_string_get_cstr(nfc_playlist->settings.playlist_path);
     char const* tmp_file_name =
         strchr(tmp_file_path, '/') != NULL ? &strrchr(tmp_file_path, '/')[1] : tmp_file_path;
 
@@ -45,27 +37,28 @@ void nfc_playlist_file_rename_scene_on_enter(void* context) {
 
     nfc_playlist->text_input_output = strdup(furi_string_get_cstr(tmp_file_name_furi));
     furi_string_free(tmp_file_name_furi);
+
     text_input_set_header_text(nfc_playlist->text_input, "Enter new file name");
     text_input_set_minimum_length(nfc_playlist->text_input, 1);
     text_input_set_result_callback(
         nfc_playlist->text_input,
-        nfc_playlist_file_rename_menu_callback,
+        nfc_playlist_playlist_rename_menu_callback,
         nfc_playlist,
         nfc_playlist->text_input_output,
-        50,
+        (50 + sizeof(nfc_playlist->text_input_output)),
         false);
 
     view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_TextInput);
 }
 
-bool nfc_playlist_file_rename_scene_on_event(void* context, SceneManagerEvent event) {
+bool nfc_playlist_playlist_rename_scene_on_event(void* context, SceneManagerEvent event) {
     UNUSED(context);
     UNUSED(event);
     return false;
 }
 
-void nfc_playlist_file_rename_scene_on_exit(void* context) {
+void nfc_playlist_playlist_rename_scene_on_exit(void* context) {
     NfcPlaylist* nfc_playlist = context;
-    text_input_reset(nfc_playlist->text_input);
     free(nfc_playlist->text_input_output);
+    text_input_reset(nfc_playlist->text_input);
 }

+ 22 - 1
nfc_playlist/scenes/nfc_playlist_scene_playlist_select.c

@@ -2,8 +2,29 @@
 
 void nfc_playlist_playlist_select_menu_callback(void* context) {
     NfcPlaylist* nfc_playlist = context;
-    furi_string_swap(nfc_playlist->settings.file_path, nfc_playlist->file_browser_output);
+    furi_string_swap(nfc_playlist->settings.playlist_path, nfc_playlist->file_browser_output);
     furi_string_reset(nfc_playlist->file_browser_output);
+
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+    Stream* stream = file_stream_alloc(storage);
+
+    if(file_stream_open(
+           stream,
+           furi_string_get_cstr(nfc_playlist->settings.playlist_path),
+           FSAM_READ,
+           FSOM_OPEN_EXISTING)) {
+        nfc_playlist->settings.playlist_length = 0;
+        FuriString* line = furi_string_alloc();
+        while(stream_read_line(stream, line)) {
+            nfc_playlist->settings.playlist_length++;
+        }
+        furi_string_free(line);
+        file_stream_close(stream);
+    }
+
+    stream_free(stream);
+    furi_record_close(RECORD_STORAGE);
+
     scene_manager_previous_scene(nfc_playlist->scene_manager);
 }
 

+ 15 - 13
nfc_playlist/scenes/nfc_playlist_scene_view_playlist_content.c

@@ -4,27 +4,29 @@ void nfc_playlist_view_playlist_content_scene_on_enter(void* context) {
     NfcPlaylist* nfc_playlist = context;
 
     Storage* storage = furi_record_open(RECORD_STORAGE);
-    File* file = storage_file_alloc(storage);
+    Stream* stream = file_stream_alloc(storage);
 
-    if(storage_file_open(
-           file,
-           furi_string_get_cstr(nfc_playlist->settings.file_path),
+    if(file_stream_open(
+           stream,
+           furi_string_get_cstr(nfc_playlist->settings.playlist_path),
            FSAM_READ,
            FSOM_OPEN_EXISTING)) {
-        uint8_t buffer[PLAYLIST_VIEW_MAX_SIZE];
-        uint16_t read_count = storage_file_read(file, buffer, PLAYLIST_VIEW_MAX_SIZE);
-        FuriString* playlist_content = furi_string_alloc();
+        FuriString* line = furi_string_alloc();
+        FuriString* tmp_str = furi_string_alloc();
 
-        for(uint16_t i = 0; i < read_count; i++) {
-            furi_string_push_back(playlist_content, buffer[i]);
+        while(stream_read_line(stream, line)) {
+            furi_string_cat_printf(tmp_str, "%s", furi_string_get_cstr(line));
         }
 
+        stream_clean(stream);
+        furi_string_free(line);
+        file_stream_close(stream);
+
         widget_add_text_scroll_element(
-            nfc_playlist->widget, 4, 4, 124, 60, furi_string_get_cstr(playlist_content));
+            nfc_playlist->widget, 4, 4, 124, 60, furi_string_get_cstr(tmp_str));
         widget_add_frame_element(nfc_playlist->widget, 0, 0, 128, 64, 0);
 
-        furi_string_free(playlist_content);
-        storage_file_close(file);
+        furi_string_free(tmp_str);
     } else {
         widget_add_text_box_element(
             nfc_playlist->widget,
@@ -38,7 +40,7 @@ void nfc_playlist_view_playlist_content_scene_on_enter(void* context) {
             false);
     }
 
-    storage_file_free(file);
+    stream_free(stream);
     furi_record_close(RECORD_STORAGE);
 
     view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Widget);