feat: add ".." go-up entry to directory picker

The folder picker had no visible way to navigate to a parent directory.
Add a ".." list item (shown when not at root) so users can go up by
selecting it, matching standard file-picker conventions.

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-02 15:28:29 -05:00
parent 7eaced602f
commit c09f7b4a22
2 changed files with 27 additions and 15 deletions

View File

@@ -63,6 +63,14 @@ void DirectoryPickerActivity::loadDirectories() {
StringUtils::sortFileList(directories); StringUtils::sortFileList(directories);
} }
void DirectoryPickerActivity::navigateToParent() {
auto slash = basepath.find_last_of('/');
basepath = (slash == 0) ? "/" : basepath.substr(0, slash);
selectorIndex = 0;
loadDirectories();
requestUpdate();
}
void DirectoryPickerActivity::loop() { void DirectoryPickerActivity::loop() {
// Absorb the Confirm release from the parent activity that launched us // Absorb the Confirm release from the parent activity that launched us
if (waitForConfirmRelease) { if (waitForConfirmRelease) {
@@ -72,14 +80,16 @@ void DirectoryPickerActivity::loop() {
return; return;
} }
// Index 0 = "Save Here", indices 1..N = directory entries const int offset = directoryOffset();
const int totalItems = 1 + static_cast<int>(directories.size()); const int totalItems = offset + static_cast<int>(directories.size());
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
if (selectorIndex == 0) { if (selectorIndex == 0) {
onSelect(basepath); onSelect(basepath);
} else if (showGoUp() && selectorIndex == 1) {
navigateToParent();
} else { } else {
const auto& dirName = directories[selectorIndex - 1]; const auto& dirName = directories[selectorIndex - offset];
// Strip trailing '/' // Strip trailing '/'
std::string folderName = dirName.substr(0, dirName.length() - 1); std::string folderName = dirName.substr(0, dirName.length() - 1);
basepath = (basepath.back() == '/' ? basepath : basepath + "/") + folderName; basepath = (basepath.back() == '/' ? basepath : basepath + "/") + folderName;
@@ -94,11 +104,7 @@ void DirectoryPickerActivity::loop() {
if (basepath == "/") { if (basepath == "/") {
onCancel(); onCancel();
} else { } else {
auto slash = basepath.find_last_of('/'); navigateToParent();
basepath = (slash == 0) ? "/" : basepath.substr(0, slash);
selectorIndex = 0;
loadDirectories();
requestUpdate();
} }
return; return;
} }
@@ -139,21 +145,24 @@ void DirectoryPickerActivity::render(Activity::RenderLock&&) {
const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing; const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing;
const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing; const int contentHeight = pageHeight - contentTop - metrics.buttonHintsHeight - metrics.verticalSpacing;
const int totalItems = 1 + static_cast<int>(directories.size()); const int offset = directoryOffset();
const int totalItems = offset + static_cast<int>(directories.size());
const bool goUp = showGoUp();
GUI.drawList( GUI.drawList(
renderer, Rect{0, contentTop, pageWidth, contentHeight}, totalItems, selectorIndex, renderer, Rect{0, contentTop, pageWidth, contentHeight}, totalItems, selectorIndex,
[this](int index) -> std::string { [this, offset, goUp](int index) -> std::string {
if (index == 0) { if (index == 0) {
std::string label = std::string(tr(STR_SAVE_HERE)) + " (" + basepath + ")"; return std::string(tr(STR_SAVE_HERE)) + " (" + basepath + ")";
return label;
} }
// Strip trailing '/' for display if (goUp && index == 1) {
const auto& dir = directories[index - 1]; return "..";
}
const auto& dir = directories[index - offset];
return dir.substr(0, dir.length() - 1); return dir.substr(0, dir.length() - 1);
}, },
nullptr, nullptr,
[this](int index) -> UIIcon { [](int index) -> UIIcon {
return (index == 0) ? UIIcon::File : UIIcon::Folder; return (index == 0) ? UIIcon::File : UIIcon::Folder;
}); });

View File

@@ -41,4 +41,7 @@ class DirectoryPickerActivity final : public Activity {
std::function<void()> onCancel; std::function<void()> onCancel;
void loadDirectories(); void loadDirectories();
void navigateToParent();
[[nodiscard]] bool showGoUp() const { return basepath != "/"; }
[[nodiscard]] int directoryOffset() const { return showGoUp() ? 2 : 1; }
}; };