Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Documentation/ideas.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
- T-Deck: Use trackball as input device (with optional mouse functionality for LVGL)
- Show a warning screen if firmware encryption or secure boot are off when saving WiFi credentials.
- Remove flex_flow from app_container in Gui.cpp
- Files app: copy/cut/paste actions
- ElfAppManifest: change name (remove "manifest" as it's confusing), remove icon and title, publish snapshot SDK on CDN
- Bug: CYD 2432S032C screen rotation fails due to touch driver issue
- Calculator app should show regular text input field on non-touch devices that have a keyboard (Cardputer, T-Lora Pager)
Expand Down
7 changes: 7 additions & 0 deletions Modules/lvgl-module/source/symbols.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ const struct ModuleSymbol lvgl_module_symbols[] = {
DEFINE_MODULE_SYMBOL(lv_obj_class_init_obj),
DEFINE_MODULE_SYMBOL(lv_obj_move_foreground),
DEFINE_MODULE_SYMBOL(lv_obj_move_to_index),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_min_height),
DEFINE_MODULE_SYMBOL(lv_obj_set_style_max_height),
// lv_font
DEFINE_MODULE_SYMBOL(lv_font_get_default),
// lv_theme
Expand Down Expand Up @@ -385,6 +387,7 @@ const struct ModuleSymbol lvgl_module_symbols[] = {
DEFINE_MODULE_SYMBOL(lv_group_set_editing),
DEFINE_MODULE_SYMBOL(lv_group_create),
DEFINE_MODULE_SYMBOL(lv_group_delete),
DEFINE_MODULE_SYMBOL(lv_group_get_editing),
// lv_mem
DEFINE_MODULE_SYMBOL(lv_free),
DEFINE_MODULE_SYMBOL(lv_malloc),
Expand All @@ -407,5 +410,9 @@ const struct ModuleSymbol lvgl_module_symbols[] = {
DEFINE_MODULE_SYMBOL(lv_anim_start),
DEFINE_MODULE_SYMBOL(lv_anim_path_ease_in_out),
DEFINE_MODULE_SYMBOL(lv_anim_path_linear),
DEFINE_MODULE_SYMBOL(lv_anim_path_ease_in),
DEFINE_MODULE_SYMBOL(lv_anim_path_ease_out),
// lv_async
DEFINE_MODULE_SYMBOL(lv_async_call),
MODULE_SYMBOL_TERMINATOR
};
49 changes: 48 additions & 1 deletion Tactility/Private/Tactility/app/files/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

#include <Tactility/RecursiveMutex.h>

#include <optional>
#include <string>
#include <utility>
#include <vector>
#include <dirent.h>

Expand All @@ -17,7 +19,8 @@ class State final {
ActionDelete,
ActionRename,
ActionCreateFile,
ActionCreateFolder
ActionCreateFolder,
ActionPaste
};

private:
Expand All @@ -27,6 +30,10 @@ class State final {
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:

Expand Down Expand Up @@ -66,6 +73,46 @@ class State final {
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;
});
}
};

}
6 changes: 6 additions & 0 deletions Tactility/Private/Tactility/app/files/View.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -46,13 +48,17 @@ class View final {
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);

private:

bool resolveDirentFromListIndex(int32_t list_index, dirent& out_entry);
void doPaste(const std::string& src, bool is_cut, const std::string& dst);
};

}
Loading