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:
@@ -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;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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; }
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user