Skip to content

Commit b287cb4

Browse files
authored
Merge pull request #139 from askoriy/file-show-content
Browser: Context menu to show file content
2 parents 99ddb23 + dcf076b commit b287cb4

9 files changed

+198
-7
lines changed

applications/main/archive/application.fam

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ App(
55
entry_point="archive_app",
66
cdefines=["APP_ARCHIVE"],
77
requires=["gui"],
8-
stack_size=4 * 1024,
8+
stack_size=6 * 1024,
99
icon="A_FileManager_14",
1010
order=0,
1111
)

applications/main/archive/helpers/archive_files.c

+5
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder
3232
if(is_folder) {
3333
file->type = ArchiveFileTypeFolder;
3434
} else {
35+
char tmp_extension[MAX_EXT_LEN];
36+
path_extract_extension(file->path, tmp_extension, MAX_EXT_LEN);
37+
if((strcmp(tmp_extension, ".txt") == 0) || (strcmp(tmp_extension, ".md") == 0)) {
38+
file->is_text_file = true;
39+
}
3540
file->type = ArchiveFileTypeUnknown;
3641
}
3742
}

applications/main/archive/helpers/archive_files.h

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ typedef struct {
2929
FuriString* custom_name;
3030
bool fav;
3131
bool is_app;
32+
bool is_text_file;
3233
} ArchiveFile_t;
3334

3435
static void ArchiveFile_t_init(ArchiveFile_t* obj) {
@@ -38,6 +39,7 @@ static void ArchiveFile_t_init(ArchiveFile_t* obj) {
3839
obj->custom_name = furi_string_alloc();
3940
obj->fav = false;
4041
obj->is_app = false;
42+
obj->is_text_file = false;
4143
}
4244

4345
static void ArchiveFile_t_init_set(ArchiveFile_t* obj, const ArchiveFile_t* src) {
@@ -52,6 +54,7 @@ static void ArchiveFile_t_init_set(ArchiveFile_t* obj, const ArchiveFile_t* src)
5254
obj->custom_name = furi_string_alloc_set(src->custom_name);
5355
obj->fav = src->fav;
5456
obj->is_app = src->is_app;
57+
obj->is_text_file = src->is_text_file;
5558
}
5659

5760
static void ArchiveFile_t_set(ArchiveFile_t* obj, const ArchiveFile_t* src) {
@@ -66,6 +69,7 @@ static void ArchiveFile_t_set(ArchiveFile_t* obj, const ArchiveFile_t* src) {
6669
furi_string_set(obj->custom_name, src->custom_name);
6770
obj->fav = src->fav;
6871
obj->is_app = src->is_app;
72+
obj->is_text_file = src->is_text_file;
6973
}
7074

7175
static void ArchiveFile_t_clear(ArchiveFile_t* obj) {

applications/main/archive/scenes/archive_scene_browser.c

+7
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
150150
scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneInfo);
151151
consumed = true;
152152
break;
153+
case ArchiveBrowserEventFileMenuShow:
154+
archive_show_file_menu(browser, false);
155+
scene_manager_set_scene_state(
156+
archive->scene_manager, ArchiveAppSceneBrowser, SCENE_STATE_DEFAULT);
157+
scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneShow);
158+
consumed = true;
159+
break;
153160
case ArchiveBrowserEventFileMenuDelete:
154161
if(archive_get_tab(browser) != ArchiveTabFavorites) {
155162
scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneDelete);

applications/main/archive/scenes/archive_scene_config.h

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ ADD_SCENE(archive, browser, Browser)
22
ADD_SCENE(archive, rename, Rename)
33
ADD_SCENE(archive, delete, Delete)
44
ADD_SCENE(archive, info, Info)
5+
ADD_SCENE(archive, show, Show)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#include "../archive_i.h"
2+
#include "../helpers/archive_browser.h"
3+
#include <storage/storage.h>
4+
5+
#define TAG "Archive"
6+
7+
#define SHOW_MAX_FILE_SIZE 5000
8+
9+
void archive_scene_show_widget_callback(GuiButtonType result, InputType type, void* context) {
10+
furi_assert(context);
11+
ArchiveApp* app = (ArchiveApp*)context;
12+
if(type == InputTypeShort) {
13+
view_dispatcher_send_custom_event(app->view_dispatcher, result);
14+
}
15+
}
16+
17+
static bool text_show_read_lines(File* file, FuriString* str_result) {
18+
//furi_string_reset(str_result);
19+
uint8_t buffer[SHOW_MAX_FILE_SIZE];
20+
21+
uint16_t read_count = storage_file_read(file, buffer, SHOW_MAX_FILE_SIZE);
22+
if(storage_file_get_error(file) != FSE_OK) {
23+
return false;
24+
}
25+
26+
for(uint16_t i = 0; i < read_count; i++) {
27+
furi_string_push_back(str_result, buffer[i]);
28+
}
29+
30+
return true;
31+
}
32+
33+
void archive_scene_show_on_enter(void* context) {
34+
furi_assert(context);
35+
ArchiveApp* instance = context;
36+
37+
FuriString* filename;
38+
filename = furi_string_alloc();
39+
40+
FuriString* buffer;
41+
buffer = furi_string_alloc();
42+
43+
ArchiveFile_t* current = archive_get_current_file(instance->browser);
44+
Storage* fs_api = furi_record_open(RECORD_STORAGE);
45+
File* file = storage_file_alloc(fs_api);
46+
47+
FileInfo fileinfo;
48+
FS_Error error = storage_common_stat(fs_api, furi_string_get_cstr(current->path), &fileinfo);
49+
if(error == FSE_OK) {
50+
if((fileinfo.size < SHOW_MAX_FILE_SIZE) && (fileinfo.size > 2)) {
51+
bool ok = storage_file_open(
52+
file, furi_string_get_cstr(current->path), FSAM_READ, FSOM_OPEN_EXISTING);
53+
if(ok) {
54+
if(!text_show_read_lines(file, buffer)) {
55+
goto text_file_read_err;
56+
}
57+
if(!furi_string_size(buffer)) {
58+
goto text_file_read_err;
59+
}
60+
61+
storage_file_seek(file, 0, true);
62+
63+
widget_add_text_scroll_element(
64+
instance->widget, 0, 0, 128, 64, furi_string_get_cstr(buffer));
65+
66+
} else {
67+
text_file_read_err:
68+
widget_add_text_box_element(
69+
instance->widget,
70+
0,
71+
0,
72+
128,
73+
64,
74+
AlignLeft,
75+
AlignCenter,
76+
"\e#Error:\nStorage file open error\e#",
77+
false);
78+
}
79+
storage_file_close(file);
80+
} else if(fileinfo.size < 2) {
81+
widget_add_text_box_element(
82+
instance->widget,
83+
0,
84+
0,
85+
128,
86+
64,
87+
AlignLeft,
88+
AlignCenter,
89+
"\e#Error:\nFile is too small\e#",
90+
false);
91+
} else {
92+
widget_add_text_box_element(
93+
instance->widget,
94+
0,
95+
0,
96+
128,
97+
64,
98+
AlignLeft,
99+
AlignCenter,
100+
"\e#Error:\nFile is too large to show\e#",
101+
false);
102+
}
103+
} else {
104+
widget_add_text_box_element(
105+
instance->widget,
106+
0,
107+
0,
108+
128,
109+
64,
110+
AlignLeft,
111+
AlignCenter,
112+
"\e#Error:\nFile system error\e#",
113+
false);
114+
}
115+
path_extract_filename(current->path, filename, false);
116+
117+
// This one to return and cursor select this file
118+
path_extract_filename_no_ext(furi_string_get_cstr(current->path), filename);
119+
strlcpy(instance->text_store, furi_string_get_cstr(filename), MAX_NAME_LEN);
120+
121+
furi_string_free(buffer);
122+
123+
storage_file_free(file);
124+
furi_record_close(RECORD_STORAGE);
125+
126+
furi_string_free(filename);
127+
128+
view_dispatcher_switch_to_view(instance->view_dispatcher, ArchiveViewWidget);
129+
}
130+
131+
bool archive_scene_show_on_event(void* context, SceneManagerEvent event) {
132+
furi_assert(context);
133+
ArchiveApp* app = (ArchiveApp*)context;
134+
135+
if(event.type == SceneManagerEventTypeCustom) {
136+
scene_manager_next_scene(app->scene_manager, ArchiveAppSceneBrowser);
137+
return true;
138+
}
139+
return false;
140+
}
141+
142+
void archive_scene_show_on_exit(void* context) {
143+
furi_assert(context);
144+
ArchiveApp* app = (ArchiveApp*)context;
145+
146+
widget_reset(app->widget);
147+
}

applications/main/archive/views/archive_browser_view.c

+30-4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
5151
FuriString* item_run = furi_string_alloc_set("Run In App");
5252
FuriString* item_pin = furi_string_alloc_set("Pin");
5353
FuriString* item_info = furi_string_alloc_set("Info");
54+
FuriString* item_show = furi_string_alloc_set("Show");
5455
FuriString* item_rename = furi_string_alloc_set("Rename");
5556
FuriString* item_delete = furi_string_alloc_set("Delete");
5657

@@ -79,6 +80,12 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
7980
menu_array_push_raw(model->context_menu),
8081
item_info,
8182
ArchiveBrowserEventFileMenuInfo);
83+
if(selected->is_text_file) {
84+
archive_menu_add_item(
85+
menu_array_push_raw(model->context_menu),
86+
item_show,
87+
ArchiveBrowserEventFileMenuShow);
88+
}
8289
archive_menu_add_item(
8390
menu_array_push_raw(model->context_menu),
8491
item_rename,
@@ -100,6 +107,12 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
100107
menu_array_push_raw(model->context_menu),
101108
item_pin,
102109
ArchiveBrowserEventFileMenuPin);
110+
if(selected->type <= ArchiveFileTypeBadUsb) {
111+
archive_menu_add_item(
112+
menu_array_push_raw(model->context_menu),
113+
item_show,
114+
ArchiveBrowserEventFileMenuShow);
115+
}
103116
archive_menu_add_item(
104117
menu_array_push_raw(model->context_menu),
105118
item_rename,
@@ -114,6 +127,12 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
114127
menu_array_push_raw(model->context_menu),
115128
item_info,
116129
ArchiveBrowserEventFileMenuInfo);
130+
if(selected->type <= ArchiveFileTypeBadUsb) {
131+
archive_menu_add_item(
132+
menu_array_push_raw(model->context_menu),
133+
item_show,
134+
ArchiveBrowserEventFileMenuShow);
135+
}
117136
archive_menu_add_item(
118137
menu_array_push_raw(model->context_menu),
119138
item_pin,
@@ -136,6 +155,12 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
136155
menu_array_push_raw(model->context_menu),
137156
item_info,
138157
ArchiveBrowserEventFileMenuInfo);
158+
if(selected->type <= ArchiveFileTypeBadUsb) {
159+
archive_menu_add_item(
160+
menu_array_push_raw(model->context_menu),
161+
item_show,
162+
ArchiveBrowserEventFileMenuShow);
163+
}
139164
archive_menu_add_item(
140165
menu_array_push_raw(model->context_menu),
141166
item_rename,
@@ -149,6 +174,7 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
149174
furi_string_free(item_run);
150175
furi_string_free(item_pin);
151176
furi_string_free(item_info);
177+
furi_string_free(item_show);
152178
furi_string_free(item_rename);
153179
furi_string_free(item_delete);
154180
} /*else {
@@ -160,9 +186,9 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
160186

161187
canvas_set_color(canvas, ColorWhite);
162188
uint8_t calc_height = menu_height - ((MENU_ITEMS - size_menu) * line_height);
163-
canvas_draw_box(canvas, 71, 11, 57, calc_height + 4);
189+
canvas_draw_box(canvas, 71, 1, 57, calc_height + 4);
164190
canvas_set_color(canvas, ColorBlack);
165-
elements_slightly_rounded_frame(canvas, 70, 12, 58, calc_height + 4);
191+
elements_slightly_rounded_frame(canvas, 70, 2, 58, calc_height + 4);
166192

167193
/*FURI_LOG_D(
168194
TAG,
@@ -172,10 +198,10 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
172198
model->menu_idx);*/
173199
for(size_t i = 0; i < size_menu; i++) {
174200
ArchiveContextMenuItem_t* current = menu_array_get(model->context_menu, i);
175-
canvas_draw_str(canvas, 82, 21 + i * line_height, furi_string_get_cstr(current->text));
201+
canvas_draw_str(canvas, 82, 11 + i * line_height, furi_string_get_cstr(current->text));
176202
}
177203

178-
canvas_draw_icon(canvas, 74, 14 + model->menu_idx * line_height, &I_ButtonRight_4x7);
204+
canvas_draw_icon(canvas, 74, 4 + model->menu_idx * line_height, &I_ButtonRight_4x7);
179205
}
180206

181207
static void archive_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar, bool moving) {

applications/main/archive/views/archive_browser_view.h

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ typedef enum {
4040
ArchiveBrowserEventFileMenuRename,
4141
ArchiveBrowserEventFileMenuDelete,
4242
ArchiveBrowserEventFileMenuInfo,
43+
ArchiveBrowserEventFileMenuShow,
4344
ArchiveBrowserEventFileMenuClose,
4445

4546
ArchiveBrowserEventEnterDir,

applications/main/subghz/subghz_history.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ FuriString* subghz_history_generate_temp_filename(uint32_t index) {
6363

6464
bool subghz_history_is_tmp_dir_exists(SubGhzHistory* instance) {
6565
FileInfo file_info;
66-
storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &file_info);
66+
FS_Error error = storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &file_info);
6767

68-
if(storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &file_info) == FSE_OK) {
68+
if(error == FSE_OK) {
6969
if(file_info.flags & FSF_DIRECTORY) {
7070
return true;
7171
}

0 commit comments

Comments
 (0)