#include "../../plugins/FileManager.hpp" #include "../../include/FileAnalyzer.hpp" #include "../../include/ResourceLoader.hpp" #include "../../include/Theme.hpp" #include "../../include/Storage.hpp" #include "../../include/QuickMedia.hpp" namespace QuickMedia { static bool last_accessed_dir_loaded = false; static std::filesystem::path last_accessed_dir; static Path last_accessed_dir_path; static void set_last_accessed_dir(const std::filesystem::path &path) { //if(last_accessed_dir_path.data.empty()) // last_accessed_dir_path = get_storage_dir().join("file-manager").join("last_accessed_dir"); //file_overwrite_atomic(last_accessed_dir_path, path.string()); last_accessed_dir = path; } // Returns empty string if no extension static const char* get_ext(const std::filesystem::path &path) { const char *path_c = path.c_str(); int len = strlen(path_c); for(int i = len - 1; i >= 0; --i) { if(path_c[i] == '.') return path_c + i; } return ""; } PluginResult FileManagerPage::submit(const SubmitArgs &args, std::vector &result_tabs) { std::filesystem::path new_path; if(args.url == "..") new_path = current_dir.parent_path(); else new_path = current_dir / args.url; if(std::filesystem::is_regular_file(new_path)) { program->select_file(new_path); if(selection_handler) result_tabs = selection_handler(this, new_path); return PluginResult::OK; } if(!std::filesystem::is_directory(new_path)) return PluginResult::ERR; current_dir = std::move(new_path); BodyItems result_items; PluginResult result = get_files_in_directory(result_items); if(result != PluginResult::OK) return result; set_last_accessed_dir(current_dir); auto body = create_body(); body->set_items(std::move(result_items)); result_tabs.push_back(Tab{std::move(body), nullptr, nullptr}); return PluginResult::OK; } bool FileManagerPage::set_current_directory(const std::string &path) { current_dir = path; set_last_accessed_dir(current_dir); return true; } PluginResult FileManagerPage::get_files_in_directory(BodyItems &result_items) { std::vector> paths; try { for(auto &p : std::filesystem::directory_iterator(current_dir)) { time_t last_modified_time = 0; file_get_last_modified_time_seconds(p.path().c_str(), &last_modified_time); paths.push_back(std::make_pair(p, last_modified_time)); } } catch(const std::filesystem::filesystem_error &err) { fprintf(stderr, "Failed to list files in directory %s, error: %s\n", current_dir.c_str(), err.what()); return PluginResult::ERR; } std::sort(paths.begin(), paths.end(), [](const std::pair &path1, std::pair &path2) { return path1.second > path2.second; }); if(current_dir != "/") { auto parent_item = BodyItem::create("Go to parent directory"); parent_item->url = ".."; result_items.push_back(std::move(parent_item)); } char time_str[128] = {0}; for(auto &p : paths) { std::error_code regular_file_err; bool is_regular_file = p.first.is_regular_file(regular_file_err); if(regular_file_err) is_regular_file = true; // TODO: Check file magic number instead of extension? const char *ext = get_ext(p.first.path()); FileManagerMimeType file_mime_type = FILE_MANAGER_MIME_TYPE_OTHER; if(is_regular_file) { if(is_image_ext(ext)) file_mime_type = FILE_MANAGER_MIME_TYPE_IMAGE; else if(is_video_ext(ext)) file_mime_type = FILE_MANAGER_MIME_TYPE_VIDEO; } if(is_regular_file && !(mime_type & file_mime_type)) continue; auto body_item = BodyItem::create(p.first.path().filename().string()); body_item->url = body_item->get_title(); if(file_mime_type == FILE_MANAGER_MIME_TYPE_IMAGE || file_mime_type == FILE_MANAGER_MIME_TYPE_VIDEO) { body_item->thumbnail_is_local = true; body_item->thumbnail_url = p.first.path().string(); } else { body_item->thumbnail_is_local = true; if(is_regular_file) { body_item->thumbnail_url = get_resource_loader_root_path() + std::string("images/file.png"); body_item->thumbnail_size = mgl::vec2i(18, 24); } else { body_item->thumbnail_url = get_resource_loader_root_path() + std::string("images/folder.png"); body_item->thumbnail_size = mgl::vec2i(24, 22); } } struct tm last_modified_tm; localtime_r(&p.second, &last_modified_tm); strftime(time_str, sizeof(time_str) - 1, "%Y %b %d, %a %H:%M", &last_modified_tm); std::error_code file_size_err; int64_t file_size = p.first.file_size(file_size_err); if(file_size_err) file_size = 0; std::string description = "Modified: "; description += time_str; if(is_regular_file) { description += "\n"; description += "Size: " + file_size_to_human_readable_string(file_size); } else { description += "\nDirectory"; } body_item->set_description(std::move(description)); body_item->set_description_color(get_theme().faded_text_color); result_items.push_back(std::move(body_item)); } return PluginResult::OK; } // static std::filesystem::path& FileManagerPage::get_last_accessed_directory(std::filesystem::path &fallback) { //if(!last_accessed_dir_loaded) { // last_accessed_dir_loaded = true; // std::string last_accessed_dir_str; // file_get_content(get_storage_dir().join("file-manager").join("last_accessed_dir"), last_accessed_dir_str); // last_accessed_dir = std::move(last_accessed_dir_str); //} if(last_accessed_dir.empty()) return fallback; else return last_accessed_dir; } }