1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:37:35 +00:00

Assistant: Add a new FileProvider to assist in searching the filesystem

When searching in Assistant, we now dispatch some background jobs to
query the whole filesystem. Activating a result will use the Desktop
launcher's default way of opening that file or directory.
This commit is contained in:
Spencer Dixon 2021-07-02 10:36:09 -04:00 committed by Andreas Kling
parent 00f93b2545
commit e6f0b2d817
3 changed files with 100 additions and 1 deletions

View file

@ -6,7 +6,11 @@
#include "Providers.h"
#include "FuzzyMatch.h"
#include <AK/URL.h>
#include <LibCore/DirIterator.h>
#include <LibCore/File.h>
#include <LibCore/StandardPaths.h>
#include <LibDesktop/Launcher.h>
#include <LibGUI/Clipboard.h>
#include <LibGUI/FileIconProvider.h>
#include <LibJS/Interpreter.h>
@ -32,6 +36,11 @@ void CalculatorResult::activate() const
GUI::Clipboard::the().set_plain_text(title());
}
void FileResult::activate() const
{
Desktop::Launcher::open(URL::create_with_file_protocol(title()));
}
void AppProvider::query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete)
{
if (query.starts_with("="))
@ -82,4 +91,64 @@ void CalculatorProvider::query(String const& query, Function<void(Vector<Nonnull
on_complete(results);
}
void FileProvider::query(const String& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete)
{
build_filesystem_cache();
if (m_fuzzy_match_work)
m_fuzzy_match_work->cancel();
m_fuzzy_match_work = Threading::BackgroundAction<Vector<NonnullRefPtr<Result>>>::create([this, query](auto& task) {
Vector<NonnullRefPtr<Result>> results;
for (auto& path : m_full_path_cache) {
if (task.is_cancelled())
return results;
auto match_result = fuzzy_match(query, path);
if (!match_result.matched)
continue;
if (match_result.score < 0)
continue;
results.append(adopt_ref(*new FileResult(path, match_result.score)));
}
return results; }, [on_complete = move(on_complete)](auto results) { on_complete(results); });
}
void FileProvider::build_filesystem_cache()
{
if (m_full_path_cache.size() > 0 || m_building_cache)
return;
m_building_cache = true;
m_work_queue.enqueue("/");
Threading::BackgroundAction<int>::create([this](auto&) {
while (!m_work_queue.is_empty()) {
auto start = m_work_queue.dequeue();
Core::DirIterator di(start, Core::DirIterator::SkipDots);
while (di.has_next()) {
auto path = di.next_full_path();
struct stat st = {};
if (lstat(path.characters(), &st) < 0) {
perror("stat");
continue;
}
if (S_ISLNK(st.st_mode))
continue;
m_full_path_cache.append(path);
if (S_ISDIR(st.st_mode)) {
m_work_queue.enqueue(path);
}
}
}
return 0; }, [this](auto) { m_building_cache = false; });
}
}