mirror of
https://github.com/geode-sdk/geode.git
synced 2025-04-01 07:40:18 -04:00
Move pick file APIs to Tasks (#899)
This commit is contained in:
parent
fbc64166b1
commit
4f400b530f
5 changed files with 128 additions and 167 deletions
loader
include/Geode/utils
src
|
@ -254,33 +254,15 @@ namespace geode::utils::file {
|
|||
|
||||
/**
|
||||
* Prompt the user to pick a file using the system's file system picker
|
||||
* @deprecated Will not work on Android, use the callback version instead
|
||||
* @param mode Type of file selection prompt to show
|
||||
* @param options Picker options
|
||||
*/
|
||||
[[deprecated("Use pick() instead, this will be removed in a later version.")]]
|
||||
GEODE_DLL Result<std::filesystem::path> pickFile(PickMode mode, FilePickOptions const& options);
|
||||
|
||||
GEODE_DLL void pickFile(
|
||||
PickMode mode, FilePickOptions const& options,
|
||||
utils::MiniFunction<void(std::filesystem::path)> callback,
|
||||
utils::MiniFunction<void()> failed = {}
|
||||
);
|
||||
GEODE_DLL Task<Result<std::filesystem::path>> pick(PickMode mode, FilePickOptions const& options);
|
||||
|
||||
/**
|
||||
* Prompt the user to pick a bunch of files for opening using the system's file system picker
|
||||
* @deprecated Will not work on Android, use the callback version instead
|
||||
* @param options Picker options
|
||||
*/
|
||||
[[deprecated("Use pickMany() instead, this will be removed in a later version.")]]
|
||||
GEODE_DLL Result<std::vector<std::filesystem::path>> pickFiles(FilePickOptions const& options);
|
||||
|
||||
GEODE_DLL void pickFiles(
|
||||
FilePickOptions const& options,
|
||||
utils::MiniFunction<void(std::vector<std::filesystem::path>)> callback,
|
||||
utils::MiniFunction<void()> failed = {}
|
||||
);
|
||||
GEODE_DLL Task<Result<std::vector<std::filesystem::path>>> pickMany(FilePickOptions const& options);
|
||||
|
||||
class GEODE_DLL FileWatchEvent : public Event {
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
#include <Geode/DefaultInclude.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
#include <Geode/loader/Dirs.hpp>
|
||||
#include <Geode/utils/file.hpp>
|
||||
#include <Geode/utils/web.hpp>
|
||||
#include <filesystem>
|
||||
#include <Geode/utils/file.hpp>
|
||||
#include <Geode/utils/general.hpp>
|
||||
#include <Geode/utils/MiniFunction.hpp>
|
||||
#include <Geode/utils/permission.hpp>
|
||||
#include <Geode/utils/Task.hpp>
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <Geode/binding/AppDelegate.hpp>
|
||||
#include <Geode/loader/Log.hpp>
|
||||
#include <Geode/binding/MenuLayer.hpp>
|
||||
#include <Geode/utils/Result.hpp>
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <optional>
|
||||
#include <mutex>
|
||||
|
||||
#include <jni.h>
|
||||
#include <Geode/cocos/platform/android/jni/JniHelper.h>
|
||||
|
@ -135,10 +138,10 @@ bool utils::file::openFolder(std::filesystem::path const& path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
static utils::MiniFunction<void(std::filesystem::path)> s_fileCallback;
|
||||
static utils::MiniFunction<void(std::vector<std::filesystem::path>)> s_filesCallback;
|
||||
static utils::MiniFunction<void()> s_failedCallback;
|
||||
std::mutex s_callbackMutex;
|
||||
static utils::MiniFunction<void(Result<std::filesystem::path>)> s_fileCallback {};
|
||||
static utils::MiniFunction<void(Result<std::vector<std::filesystem::path>>)> s_filesCallback {};
|
||||
static utils::MiniFunction<bool()> s_taskCancelled {};
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL Java_com_geode_launcher_utils_GeodeUtils_selectFileCallback(
|
||||
|
@ -149,11 +152,16 @@ JNIEXPORT void JNICALL Java_com_geode_launcher_utils_GeodeUtils_selectFileCallba
|
|||
auto isCopy = jboolean();
|
||||
auto dataStr = env->GetStringUTFChars(data, &isCopy);
|
||||
|
||||
log::debug("Selected file: {}", dataStr);
|
||||
|
||||
Loader::get()->queueInMainThread([dataStr]() {
|
||||
s_fileCallback(dataStr);
|
||||
});
|
||||
const std::lock_guard lock(s_callbackMutex);
|
||||
if (s_taskCancelled && s_taskCancelled()) {
|
||||
s_taskCancelled = {};
|
||||
return;
|
||||
}
|
||||
if (s_fileCallback) {
|
||||
s_fileCallback(Ok(std::filesystem::path(dataStr)));
|
||||
s_fileCallback = {};
|
||||
s_taskCancelled = {};
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
|
@ -169,13 +177,17 @@ JNIEXPORT void JNICALL Java_com_geode_launcher_utils_GeodeUtils_selectFilesCallb
|
|||
auto data = (jstring)env->GetObjectArrayElement(datas, i);
|
||||
auto dataStr = env->GetStringUTFChars(data, &isCopy);
|
||||
result.push_back(dataStr);
|
||||
|
||||
log::debug("Selected file {}: {}", i, dataStr);
|
||||
}
|
||||
|
||||
Loader::get()->queueInMainThread([result]() {
|
||||
s_filesCallback(result);
|
||||
});
|
||||
const std::lock_guard lock(s_callbackMutex);
|
||||
if (s_taskCancelled && s_taskCancelled()) {
|
||||
s_taskCancelled = {};
|
||||
return;
|
||||
}
|
||||
if (s_filesCallback) {
|
||||
s_filesCallback(Ok(std::move(result)));
|
||||
s_filesCallback = {};
|
||||
s_taskCancelled = {};
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
|
@ -183,24 +195,27 @@ JNIEXPORT void JNICALL Java_com_geode_launcher_utils_GeodeUtils_failedCallback(
|
|||
JNIEnv *env,
|
||||
jobject
|
||||
) {
|
||||
if (s_failedCallback) {
|
||||
Loader::get()->queueInMainThread([]() {
|
||||
s_failedCallback();
|
||||
});
|
||||
const std::lock_guard lock(s_callbackMutex);
|
||||
if (s_fileCallback) {
|
||||
s_fileCallback(Err("Permission error"));
|
||||
s_fileCallback = {};
|
||||
}
|
||||
if (s_filesCallback) {
|
||||
s_filesCallback(Err("Permission error"));
|
||||
s_filesCallback = {};
|
||||
}
|
||||
if (s_taskCancelled) {
|
||||
s_taskCancelled = {};
|
||||
}
|
||||
}
|
||||
|
||||
Result<std::filesystem::path> file::pickFile(file::PickMode mode, file::FilePickOptions const& options) {
|
||||
return Err("Use the callback version");
|
||||
}
|
||||
Task<Result<std::filesystem::path>> file::pick(file::PickMode mode, file::FilePickOptions const& options) {
|
||||
using RetTask = Task<Result<std::filesystem::path>>;
|
||||
|
||||
void file::pickFile(
|
||||
PickMode mode, FilePickOptions const& options,
|
||||
MiniFunction<void(std::filesystem::path)> callback,
|
||||
MiniFunction<void()> failed
|
||||
) {
|
||||
s_fileCallback = callback;
|
||||
s_failedCallback = failed;
|
||||
const std::lock_guard lock(s_callbackMutex);
|
||||
if (s_fileCallback || s_filesCallback || s_taskCancelled) {
|
||||
return RetTask::immediate(Err("File picker was already called this frame"));
|
||||
}
|
||||
|
||||
std::string method;
|
||||
switch (mode) {
|
||||
|
@ -223,28 +238,24 @@ void file::pickFile(
|
|||
|
||||
t.env->DeleteLocalRef(stringArg1);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
if (result) {
|
||||
return;
|
||||
if (!result) {
|
||||
return RetTask::immediate(Err("Failed to open file picker"));
|
||||
}
|
||||
}
|
||||
if (s_failedCallback) {
|
||||
Loader::get()->queueInMainThread([]() {
|
||||
s_failedCallback();
|
||||
});
|
||||
return RetTask::runWithCallback([] (auto result, auto progress, auto cancelled) {
|
||||
const std::lock_guard lock(s_callbackMutex);
|
||||
s_fileCallback = result;
|
||||
s_taskCancelled = cancelled;
|
||||
});
|
||||
}
|
||||
|
||||
Task<Result<std::vector<std::filesystem::path>>> file::pickMany(FilePickOptions const& options) {
|
||||
using RetTask = Task<Result<std::vector<std::filesystem::path>>>;
|
||||
|
||||
const std::lock_guard lock(s_callbackMutex);
|
||||
if (s_fileCallback || s_filesCallback || s_taskCancelled) {
|
||||
return RetTask::immediate(Err("File picker was already called this frame"));
|
||||
}
|
||||
}
|
||||
|
||||
Result<std::vector<std::filesystem::path>> file::pickFiles(file::FilePickOptions const& options) {
|
||||
return Err("Use the callback version");
|
||||
}
|
||||
|
||||
void file::pickFiles(
|
||||
FilePickOptions const& options,
|
||||
MiniFunction<void(std::vector<std::filesystem::path>)> callback,
|
||||
MiniFunction<void()> failed
|
||||
) {
|
||||
s_filesCallback = callback;
|
||||
s_failedCallback = failed;
|
||||
|
||||
JniMethodInfo t;
|
||||
if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "selectFiles", "(Ljava/lang/String;)Z")) {
|
||||
|
@ -254,15 +265,16 @@ void file::pickFiles(
|
|||
|
||||
t.env->DeleteLocalRef(stringArg1);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
if (result) {
|
||||
return;
|
||||
if (!result) {
|
||||
return RetTask::immediate(Err("Failed to open file dialog"));
|
||||
}
|
||||
}
|
||||
if (s_failedCallback) {
|
||||
Loader::get()->queueInMainThread([]() {
|
||||
s_failedCallback();
|
||||
});
|
||||
}
|
||||
|
||||
return RetTask::runWithCallback([options](auto result, auto progress, auto cancelled){
|
||||
const std::lock_guard lock(s_callbackMutex);
|
||||
s_filesCallback = result;
|
||||
s_taskCancelled = cancelled;
|
||||
});
|
||||
}
|
||||
|
||||
void geode::utils::game::launchLoaderUninstaller(bool deleteSaveData) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "Geode/utils/file.hpp"
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
@ -8,6 +9,7 @@ using namespace geode::prelude;
|
|||
#include <Geode/binding/GameManager.hpp>
|
||||
#include <objc/runtime.h>
|
||||
#include <Geode/utils/web.hpp>
|
||||
#include <Geode/utils/Task.hpp>
|
||||
|
||||
#define CommentType CommentTypeDummy
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
@ -159,48 +161,35 @@ namespace {
|
|||
|
||||
@end
|
||||
|
||||
Result<std::filesystem::path> file::pickFile(
|
||||
file::PickMode mode, file::FilePickOptions const& options
|
||||
) {
|
||||
return Err("Use the callback version");
|
||||
}
|
||||
|
||||
GEODE_DLL void file::pickFile(
|
||||
PickMode mode, FilePickOptions const& options,
|
||||
MiniFunction<void(std::filesystem::path)> callback,
|
||||
MiniFunction<void()> failed
|
||||
) {
|
||||
[FileDialog dispatchFilePickerWithMode:mode options:options multiple:false onCompletion: ^(FileResult result) {
|
||||
Loader::get()->queueInMainThread([=]() {
|
||||
if (result.isOk()) {
|
||||
callback(std::move(result.unwrap()[0]));
|
||||
GEODE_DLL Task<Result<std::filesystem::path>> file::pick(file::PickMode mode, file::FilePickOptions const& options) {
|
||||
using RetTask = Task<Result<std::filesystem::path>>;
|
||||
return RetTask::runWithCallback([mode, options](auto resultCallback, auto progress, auto cancelled) {
|
||||
[FileDialog dispatchFilePickerWithMode:mode options:options multiple:false onCompletion: ^(FileResult result) {
|
||||
if (cancelled()) {
|
||||
resultCallback(RetTask::Cancel());
|
||||
} else {
|
||||
failed();
|
||||
if (result.isOk()) {
|
||||
std::filesystem::path path = result.unwrap()[0];
|
||||
resultCallback(Ok(path));
|
||||
} else {
|
||||
resultCallback(Err(result.err().value()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}];
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
Result<std::vector<std::filesystem::path>> file::pickFiles(
|
||||
file::FilePickOptions const& options
|
||||
) {
|
||||
return Err("Use the callback version");
|
||||
}
|
||||
|
||||
GEODE_DLL void file::pickFiles(
|
||||
FilePickOptions const& options,
|
||||
MiniFunction<void(std::vector<std::filesystem::path>)> callback,
|
||||
MiniFunction<void()> failed
|
||||
) {
|
||||
[FileDialog dispatchFilePickerWithMode: file::PickMode::OpenFile options:options multiple:true onCompletion: ^(FileResult result) {
|
||||
Loader::get()->queueInMainThread([=]() {
|
||||
if (result.isOk()) {
|
||||
callback(std::move(result.unwrap()));
|
||||
GEODE_DLL Task<Result<std::vector<std::filesystem::path>>> file::pickMany(file::FilePickOptions const& options) {
|
||||
using RetTask = Task<Result<std::vector<std::filesystem::path>>>;
|
||||
return RetTask::runWithCallback([options](auto resultCallback, auto progress, auto cancelled) {
|
||||
[FileDialog dispatchFilePickerWithMode: file::PickMode::OpenFile options:options multiple:true onCompletion: ^(FileResult result) {
|
||||
if (cancelled()) {
|
||||
resultCallback(RetTask::Cancel());
|
||||
} else {
|
||||
failed();
|
||||
resultCallback(result);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
CCPoint cocos::getMousePos() {
|
||||
|
|
|
@ -7,11 +7,9 @@ using namespace geode::prelude;
|
|||
#include "nfdwin.hpp"
|
||||
#include <Windows.h>
|
||||
#include <processthreadsapi.h>
|
||||
#include <iostream>
|
||||
#include <ShlObj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shobjidl.h>
|
||||
#include <sstream>
|
||||
#include <Geode/utils/web.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
#include <Geode/loader/Log.hpp>
|
||||
|
@ -103,9 +101,8 @@ bool utils::file::openFolder(std::filesystem::path const& path) {
|
|||
return success;
|
||||
}
|
||||
|
||||
Result<std::filesystem::path> utils::file::pickFile(
|
||||
file::PickMode mode, file::FilePickOptions const& options
|
||||
) {
|
||||
Task<Result<std::filesystem::path>> file::pick(PickMode mode, FilePickOptions const& options) {
|
||||
using RetTask = Task<Result<std::filesystem::path>>;
|
||||
#define TURN_INTO_NFDMODE(mode) \
|
||||
case file::PickMode::mode: nfdMode = NFDMode::mode; break;
|
||||
|
||||
|
@ -114,57 +111,33 @@ Result<std::filesystem::path> utils::file::pickFile(
|
|||
TURN_INTO_NFDMODE(OpenFile);
|
||||
TURN_INTO_NFDMODE(SaveFile);
|
||||
TURN_INTO_NFDMODE(OpenFolder);
|
||||
default: return Err<std::string>("Unknown open mode");
|
||||
default:
|
||||
return RetTask::immediate(Err<std::string>("Invalid pick mode"));
|
||||
}
|
||||
std::filesystem::path path;
|
||||
GEODE_UNWRAP(nfdPick(nfdMode, options, &path));
|
||||
return Ok(path);
|
||||
}
|
||||
|
||||
void file::pickFile(
|
||||
PickMode mode, FilePickOptions const& options,
|
||||
MiniFunction<void(std::filesystem::path)> callback,
|
||||
MiniFunction<void()> failed
|
||||
) {
|
||||
auto result = file::pickFile(mode, options);
|
||||
|
||||
if (result.isOk()) {
|
||||
callback(std::move(result.unwrap()));
|
||||
Result<std::filesystem::path> result;
|
||||
auto pickresult = nfdPick(nfdMode, options, &path);
|
||||
if (pickresult.isErr()) {
|
||||
result = Err(pickresult.err().value());
|
||||
} else {
|
||||
if (failed) {
|
||||
failed();
|
||||
}
|
||||
result = Ok(path);
|
||||
}
|
||||
}
|
||||
Task<Result<std::filesystem::path>> file::pick(PickMode mode, FilePickOptions const& options) {
|
||||
return Task<Result<std::filesystem::path>>::immediate(std::move(file::pickFile(mode, options)));
|
||||
return RetTask::immediate(std::move(result));
|
||||
}
|
||||
|
||||
Result<std::vector<std::filesystem::path>> utils::file::pickFiles(
|
||||
file::FilePickOptions const& options
|
||||
) {
|
||||
std::vector<std::filesystem::path> paths;
|
||||
GEODE_UNWRAP(nfdPick(NFDMode::OpenFiles, options, &paths));
|
||||
return Ok(paths);
|
||||
}
|
||||
|
||||
void file::pickFiles(
|
||||
FilePickOptions const& options,
|
||||
MiniFunction<void(std::vector<std::filesystem::path>)> callback,
|
||||
MiniFunction<void()> failed
|
||||
) {
|
||||
auto result = file::pickFiles(options);
|
||||
|
||||
if (result.isOk()) {
|
||||
callback(std::move(result.unwrap()));
|
||||
} else {
|
||||
if (failed) {
|
||||
failed();
|
||||
}
|
||||
}
|
||||
}
|
||||
Task<Result<std::vector<std::filesystem::path>>> file::pickMany(FilePickOptions const& options) {
|
||||
return Task<Result<std::vector<std::filesystem::path>>>::immediate(std::move(file::pickFiles(options)));
|
||||
using RetTask = Task<Result<std::vector<std::filesystem::path>>>;
|
||||
|
||||
std::vector<std::filesystem::path> paths;
|
||||
auto pickResult = nfdPick(NFDMode::OpenFiles, options, &paths);
|
||||
Result<std::vector<std::filesystem::path>> result;
|
||||
if (pickResult.isErr()) {
|
||||
result = Err(pickResult.err().value());
|
||||
} else {
|
||||
result = Ok(paths);
|
||||
}
|
||||
return RetTask::immediate(std::move(result));
|
||||
// return Task<Result<std::vector<std::filesystem::path>>>::immediate(std::move(file::pickFiles(options)));
|
||||
}
|
||||
|
||||
void utils::web::openLinkInBrowser(std::string const& url) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <Geode/loader/Dirs.hpp>
|
||||
#include <charconv>
|
||||
#include <clocale>
|
||||
#include <filesystem>
|
||||
|
||||
// Helpers
|
||||
|
||||
|
@ -364,16 +365,20 @@ void FileSettingNode::valueChanged(bool updateText) {
|
|||
}
|
||||
|
||||
void FileSettingNode::onPickFile(CCObject*) {
|
||||
file::pickFile(
|
||||
file::PickMode::OpenFile,
|
||||
file::pick(
|
||||
file::PickMode::OpenFile,
|
||||
{
|
||||
dirs::getGameDir(),
|
||||
setting()->castDefinition().controls.filters
|
||||
}).listen(
|
||||
[this](Result<std::filesystem::path>* path) {
|
||||
if (path->isOk()) {
|
||||
m_uncommittedValue = path->unwrap();
|
||||
this->valueChanged(true);
|
||||
}
|
||||
},
|
||||
[&](auto path) {
|
||||
m_uncommittedValue = path;
|
||||
this->valueChanged(true);
|
||||
}
|
||||
[] (auto progress) {},
|
||||
[] () {}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue