mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-23 07:57:51 -05:00
Merge branch 'main' of https://github.com/geode-sdk/geode
This commit is contained in:
commit
1fbfbd85ae
3 changed files with 106 additions and 2 deletions
|
@ -252,4 +252,40 @@ namespace geode::utils::file {
|
|||
* @param options Picker options
|
||||
*/
|
||||
GEODE_DLL Result<std::vector<ghc::filesystem::path>> pickFiles(FilePickOptions const& options);
|
||||
|
||||
class GEODE_DLL FileWatchEvent : public Event {
|
||||
protected:
|
||||
ghc::filesystem::path m_path;
|
||||
|
||||
public:
|
||||
FileWatchEvent(ghc::filesystem::path const& path);
|
||||
ghc::filesystem::path getPath() const;
|
||||
};
|
||||
|
||||
class GEODE_DLL FileWatchFilter : public EventFilter<FileWatchEvent> {
|
||||
protected:
|
||||
ghc::filesystem::path m_path;
|
||||
|
||||
public:
|
||||
using Callback = void(FileWatchEvent*);
|
||||
|
||||
ListenerResult handle(utils::MiniFunction<Callback> callback, FileWatchEvent* event);
|
||||
FileWatchFilter(ghc::filesystem::path const& path);
|
||||
};
|
||||
|
||||
/**
|
||||
* Watch a file for changes. Whenever the file is modified on disk, a
|
||||
* FileWatchEvent is emitted. Add an EventListener with FileWatchFilter
|
||||
* to catch these events
|
||||
* @param file The file to watch
|
||||
* @note Watching uses file system equivalence instead of path equivalence,
|
||||
* so different paths that point to the same file will be considered the
|
||||
* same
|
||||
*/
|
||||
GEODE_DLL Result<> watchFile(ghc::filesystem::path const& file);
|
||||
/**
|
||||
* Stop watching a file for changes
|
||||
* @param file The file to unwatch
|
||||
*/
|
||||
GEODE_DLL void unwatchFile(ghc::filesystem::path const& file);
|
||||
}
|
||||
|
|
|
@ -25,12 +25,28 @@ protected:
|
|||
public:
|
||||
bool watching() const;
|
||||
|
||||
ghc::filesystem::path path() {
|
||||
ghc::filesystem::path path() const {
|
||||
return m_file;
|
||||
}
|
||||
|
||||
FileWatcher(
|
||||
ghc::filesystem::path const& file, FileWatchCallback callback, ErrorCallback error = nullptr
|
||||
ghc::filesystem::path const& file,
|
||||
FileWatchCallback callback,
|
||||
ErrorCallback error = nullptr
|
||||
);
|
||||
FileWatcher(FileWatcher const&) = delete;
|
||||
inline FileWatcher(FileWatcher&& other)
|
||||
: m_file(std::move(other.m_file)),
|
||||
m_callback(std::move(other.m_callback)),
|
||||
m_error(std::move(other.m_error)),
|
||||
m_filemode(other.m_filemode),
|
||||
m_platformHandle(other.m_platformHandle),
|
||||
m_exiting(other.m_exiting)
|
||||
{
|
||||
other.m_callback = nullptr;
|
||||
other.m_error = nullptr;
|
||||
other.m_platformHandle = nullptr;
|
||||
other.m_exiting = true;
|
||||
}
|
||||
~FileWatcher();
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <mz_strm_os.h>
|
||||
#include <mz_strm_mem.h>
|
||||
#include <mz_zip.h>
|
||||
#include <internal/FileWatcher.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
using namespace geode::utils::file;
|
||||
|
@ -551,3 +552,54 @@ Result<> Zip::addAllFrom(Path const& dir) {
|
|||
Result<> Zip::addFolder(Path const& entry) {
|
||||
return m_impl->addFolder(entry);
|
||||
}
|
||||
|
||||
FileWatchEvent::FileWatchEvent(ghc::filesystem::path const& path)
|
||||
: m_path(path) {}
|
||||
|
||||
ghc::filesystem::path FileWatchEvent::getPath() const {
|
||||
return m_path;
|
||||
}
|
||||
|
||||
ListenerResult FileWatchFilter::handle(
|
||||
MiniFunction<Callback> callback,
|
||||
FileWatchEvent* event
|
||||
) {
|
||||
std::error_code ec;
|
||||
if (ghc::filesystem::equivalent(event->getPath(), m_path, ec)) {
|
||||
callback(event);
|
||||
}
|
||||
return ListenerResult::Propagate;
|
||||
}
|
||||
|
||||
FileWatchFilter::FileWatchFilter(ghc::filesystem::path const& path)
|
||||
: m_path(path) {}
|
||||
|
||||
// This is a vector because need to use ghc::filesystem::equivalent for
|
||||
// comparisons and removal is not exactly performance-critical here
|
||||
// (who's going to add and remove 500 file watchers every frame)
|
||||
static std::vector<std::unique_ptr<FileWatcher>> FILE_WATCHERS {};
|
||||
|
||||
Result<> file::watchFile(ghc::filesystem::path const& file) {
|
||||
if (!ghc::filesystem::exists(file)) {
|
||||
return Err("File does not exist");
|
||||
}
|
||||
auto watcher = std::make_unique<FileWatcher>(
|
||||
file,
|
||||
[](auto const& path) {
|
||||
Loader::get()->queueInGDThread([=] {
|
||||
FileWatchEvent(path).post();
|
||||
});
|
||||
}
|
||||
);
|
||||
if (!watcher->watching()) {
|
||||
return Err("Unknown error watching file");
|
||||
}
|
||||
FILE_WATCHERS.emplace_back(std::move(watcher));
|
||||
return Ok();
|
||||
}
|
||||
|
||||
void file::unwatchFile(ghc::filesystem::path const& file) {
|
||||
ranges::remove(FILE_WATCHERS, [=](std::unique_ptr<FileWatcher> const& watcher) {
|
||||
return ghc::filesystem::equivalent(file, watcher->path());
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue