Files App - Copy, Cut, Paste Actions (#510)

This commit is contained in:
Shadowtrance
2026-02-27 05:11:05 +10:00
committed by GitHub
parent d2048e01b6
commit 33caf09856
7 changed files with 320 additions and 17 deletions
+48 -1
View File
@@ -2,7 +2,9 @@
#include <Tactility/RecursiveMutex.h>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include <dirent.h>
@@ -17,7 +19,8 @@ public:
ActionDelete,
ActionRename,
ActionCreateFile,
ActionCreateFolder
ActionCreateFolder,
ActionPaste
};
private:
@@ -27,6 +30,10 @@ private:
std::string current_path;
std::string selected_child_entry;
PendingAction action = ActionNone;
std::string pending_paste_dst;
std::string clipboard_path;
bool clipboard_is_cut = false;
bool clipboard_active = false;
public:
@@ -66,6 +73,46 @@ public:
PendingAction getPendingAction() const { return action; }
void setPendingAction(PendingAction newAction) { action = newAction; }
// These accessors intentionally omit mutex locking: both are only called
// from the UI thread (onPastePressed → onResult), so no concurrent access
// is possible. If that threading assumption changes, add mutex guards here
// to match the clipboard accessors above.
std::string getPendingPasteDst() const { return pending_paste_dst; }
void setPendingPasteDst(const std::string& dst) { pending_paste_dst = dst; }
void setClipboard(const std::string& path, bool is_cut) {
mutex.withLock([&] {
clipboard_path = path;
clipboard_is_cut = is_cut;
clipboard_active = true;
});
}
bool hasClipboard() const {
bool result = false;
mutex.withLock([&] { result = clipboard_active; });
return result;
}
/** Returns {path, is_cut} atomically, or nullopt if clipboard is empty. */
std::optional<std::pair<std::string, bool>> getClipboard() const {
std::optional<std::pair<std::string, bool>> result;
mutex.withLock([&] {
if (clipboard_active) {
result = { clipboard_path, clipboard_is_cut };
}
});
return result;
}
void clearClipboard() {
mutex.withLock([&] {
clipboard_active = false;
clipboard_path.clear();
clipboard_is_cut = false;
});
}
};
}
@@ -21,10 +21,12 @@ class View final {
lv_obj_t* navigate_up_button = nullptr;
lv_obj_t* new_file_button = nullptr;
lv_obj_t* new_folder_button = nullptr;
lv_obj_t* paste_button = nullptr;
std::string installAppPath = { 0 };
LaunchId installAppLaunchId = 0;
void showActions();
void showActionsForDirectory();
void showActionsForFile();
@@ -46,6 +48,9 @@ public:
void onDeletePressed();
void onNewFilePressed();
void onNewFolderPressed();
void onCopyPressed();
void onCutPressed();
void onPastePressed();
void onDirEntryListScrollBegin();
void onResult(LaunchId launchId, Result result, std::unique_ptr<Bundle> bundle);
void deinit(const AppContext& appContext);
@@ -53,6 +58,7 @@ public:
private:
bool resolveDirentFromListIndex(int32_t list_index, dirent& out_entry);
void doPaste(const std::string& src, bool is_cut, const std::string& dst);
};
}