archive_browser.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include "archive_browser.h"
  2. #include "math.h"
  3. void archive_update_offset(ArchiveBrowserView* browser) {
  4. furi_assert(browser);
  5. with_view_model(
  6. browser->view, (ArchiveBrowserViewModel * model) {
  7. size_t array_size = files_array_size(model->files);
  8. uint16_t bounds = array_size > 3 ? 2 : array_size;
  9. if(array_size > 3 && model->idx >= array_size - 1) {
  10. model->list_offset = model->idx - 3;
  11. } else if(model->list_offset < model->idx - bounds) {
  12. model->list_offset = CLAMP(model->idx - 2, array_size - bounds, 0);
  13. } else if(model->list_offset > model->idx - bounds) {
  14. model->list_offset = CLAMP(model->idx - 1, array_size - bounds, 0);
  15. }
  16. return true;
  17. });
  18. }
  19. void archive_update_focus(ArchiveBrowserView* browser, const char* target) {
  20. furi_assert(browser);
  21. furi_assert(target);
  22. archive_get_filenames(browser, string_get_cstr(browser->path));
  23. if(!archive_file_array_size(browser) && !archive_get_depth(browser)) {
  24. archive_switch_tab(browser, DEFAULT_TAB_DIR);
  25. } else {
  26. with_view_model(
  27. browser->view, (ArchiveBrowserViewModel * model) {
  28. uint16_t idx = 0;
  29. while(idx < files_array_size(model->files)) {
  30. ArchiveFile_t* current = files_array_get(model->files, idx);
  31. if(!string_search(current->name, target)) {
  32. model->idx = idx;
  33. break;
  34. }
  35. ++idx;
  36. }
  37. return false;
  38. });
  39. archive_update_offset(browser);
  40. }
  41. }
  42. size_t archive_file_array_size(ArchiveBrowserView* browser) {
  43. uint16_t size = 0;
  44. with_view_model(
  45. browser->view, (ArchiveBrowserViewModel * model) {
  46. size = files_array_size(model->files);
  47. return false;
  48. });
  49. return size;
  50. }
  51. void archive_file_array_rm_selected(ArchiveBrowserView* browser) {
  52. with_view_model(
  53. browser->view, (ArchiveBrowserViewModel * model) {
  54. files_array_remove_v(model->files, model->idx, model->idx + 1);
  55. model->idx = CLAMP(model->idx, files_array_size(model->files) - 1, 0);
  56. return false;
  57. });
  58. if(!archive_file_array_size(browser) && !archive_get_depth(browser)) {
  59. archive_switch_tab(browser, DEFAULT_TAB_DIR);
  60. }
  61. archive_update_offset(browser);
  62. }
  63. void archive_file_array_rm_all(ArchiveBrowserView* browser) {
  64. with_view_model(
  65. browser->view, (ArchiveBrowserViewModel * model) {
  66. files_array_clean(model->files);
  67. return false;
  68. });
  69. }
  70. ArchiveFile_t* archive_get_current_file(ArchiveBrowserView* browser) {
  71. ArchiveFile_t* selected;
  72. with_view_model(
  73. browser->view, (ArchiveBrowserViewModel * model) {
  74. selected = files_array_size(model->files) ? files_array_get(model->files, model->idx) :
  75. NULL;
  76. return false;
  77. });
  78. return selected;
  79. }
  80. ArchiveTabEnum archive_get_tab(ArchiveBrowserView* browser) {
  81. ArchiveTabEnum tab_id;
  82. with_view_model(
  83. browser->view, (ArchiveBrowserViewModel * model) {
  84. tab_id = model->tab_idx;
  85. return false;
  86. });
  87. return tab_id;
  88. }
  89. uint8_t archive_get_depth(ArchiveBrowserView* browser) {
  90. uint8_t depth;
  91. with_view_model(
  92. browser->view, (ArchiveBrowserViewModel * model) {
  93. depth = model->depth;
  94. return false;
  95. });
  96. return depth;
  97. }
  98. const char* archive_get_path(ArchiveBrowserView* browser) {
  99. return string_get_cstr(browser->path);
  100. }
  101. const char* archive_get_name(ArchiveBrowserView* browser) {
  102. ArchiveFile_t* selected = archive_get_current_file(browser);
  103. return string_get_cstr(selected->name);
  104. }
  105. void archive_set_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) {
  106. with_view_model(
  107. browser->view, (ArchiveBrowserViewModel * model) {
  108. model->tab_idx = tab;
  109. return false;
  110. });
  111. }
  112. void archive_set_last_tab(ArchiveBrowserView* browser, ArchiveTabEnum tab) {
  113. with_view_model(
  114. browser->view, (ArchiveBrowserViewModel * model) {
  115. model->last_tab = model->tab_idx;
  116. return false;
  117. });
  118. }
  119. void archive_add_item(ArchiveBrowserView* browser, FileInfo* file_info, const char* name) {
  120. furi_assert(browser);
  121. furi_assert(file_info);
  122. furi_assert(name);
  123. ArchiveFile_t item;
  124. if(filter_by_extension(file_info, get_tab_ext(archive_get_tab(browser)), name)) {
  125. ArchiveFile_t_init(&item);
  126. string_init_set_str(item.name, name);
  127. set_file_type(&item, file_info);
  128. with_view_model(
  129. browser->view, (ArchiveBrowserViewModel * model) {
  130. files_array_push_back(model->files, item);
  131. return false;
  132. });
  133. ArchiveFile_t_clear(&item);
  134. }
  135. }
  136. void archive_show_file_menu(ArchiveBrowserView* browser, bool show) {
  137. furi_assert(browser);
  138. with_view_model(
  139. browser->view, (ArchiveBrowserViewModel * model) {
  140. model->menu = show;
  141. model->menu_idx = 0;
  142. if(show) {
  143. ArchiveFile_t* selected = files_array_get(model->files, model->idx);
  144. selected->fav = archive_is_favorite(
  145. "%s/%s", string_get_cstr(browser->path), string_get_cstr(selected->name));
  146. }
  147. return true;
  148. });
  149. }
  150. void archive_switch_dir(ArchiveBrowserView* browser, const char* path) {
  151. furi_assert(browser);
  152. furi_assert(path);
  153. string_set(browser->path, path);
  154. archive_get_filenames(browser, string_get_cstr(browser->path));
  155. archive_update_offset(browser);
  156. }
  157. void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
  158. furi_assert(browser);
  159. ArchiveTabEnum tab = archive_get_tab(browser);
  160. if(key == InputKeyLeft) {
  161. tab = ((tab - 1) + ArchiveTabTotal) % ArchiveTabTotal;
  162. } else if(key == InputKeyRight) {
  163. tab = (tab + 1) % ArchiveTabTotal;
  164. }
  165. archive_set_tab(browser, tab);
  166. if((tab != ArchiveTabFavorites &&
  167. !archive_dir_empty(browser, archive_get_default_path(tab))) ||
  168. (tab == ArchiveTabFavorites && !archive_favorites_count(browser))) {
  169. archive_switch_tab(browser, key);
  170. } else {
  171. with_view_model(
  172. browser->view, (ArchiveBrowserViewModel * model) {
  173. if(model->last_tab != model->tab_idx) {
  174. model->idx = 0;
  175. model->depth = 0;
  176. }
  177. return false;
  178. });
  179. archive_switch_dir(browser, archive_get_default_path(tab));
  180. }
  181. archive_set_last_tab(browser, tab);
  182. }
  183. void archive_enter_dir(ArchiveBrowserView* browser, string_t name) {
  184. furi_assert(browser);
  185. furi_assert(name);
  186. // update last index
  187. with_view_model(
  188. browser->view, (ArchiveBrowserViewModel * model) {
  189. model->last_idx[model->depth] =
  190. CLAMP(model->idx, files_array_size(model->files) - 1, 0);
  191. model->idx = 0;
  192. model->depth = CLAMP(model->depth + 1, MAX_DEPTH, 0);
  193. return false;
  194. });
  195. string_cat(browser->path, "/");
  196. string_cat(browser->path, name);
  197. archive_switch_dir(browser, string_get_cstr(browser->path));
  198. }
  199. void archive_leave_dir(ArchiveBrowserView* browser) {
  200. furi_assert(browser);
  201. const char* path = archive_get_path(browser);
  202. char* last_char_ptr = strrchr(path, '/');
  203. if(last_char_ptr) {
  204. size_t pos = last_char_ptr - path;
  205. string_left(browser->path, pos);
  206. }
  207. with_view_model(
  208. browser->view, (ArchiveBrowserViewModel * model) {
  209. model->depth = CLAMP(model->depth - 1, MAX_DEPTH, 0);
  210. model->idx = model->last_idx[model->depth];
  211. return false;
  212. });
  213. archive_switch_dir(browser, path);
  214. }