From 163155c3191f4d80d87d2d26e901a6718f874dc5 Mon Sep 17 00:00:00 2001 From: Nikita Galaiko Date: Fri, 3 Feb 2023 15:20:55 +0100 Subject: [PATCH] load project files when it opens --- src-tauri/src/main.rs | 37 +++++++++++++++++++++++--- src/lib/crdt.ts | 2 +- src/lib/log.ts | 18 ++++++++----- src/lib/tauri.ts | 18 +++++++++++-- src/routes/projects/[id]/+page.svelte | 38 +++++++++++++++++++-------- 5 files changed, 90 insertions(+), 23 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1f81e6e91..6fcd53b52 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,13 +1,44 @@ -use std::fs::read_to_string; +use std::{fs, path::Path}; use tauri::InvokeError; use tauri_plugin_log::{ fern::colors::{Color, ColoredLevelConfig}, LogTarget, }; +// return a list of files in directory recursively +fn list_files(path: &Path) -> Vec { + let mut files = Vec::new(); + if path.is_dir() { + for entry in fs::read_dir(path).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + if path.is_dir() { + files.append(&mut list_files(&path)); + } else { + files.push(path.to_str().unwrap().to_string()); + } + } + } + files.sort(); + files +} + +// returns a list of files in directory recursively +#[tauri::command] +fn read_dir(path: &str) -> Result, InvokeError> { + let path = Path::new(path); + if path.is_dir() { + let files = list_files(path); + return Ok(files); + } else { + return Err("Path is not a directory".into()); + } +} + +// reads file contents and returns it #[tauri::command] fn read_file(file_path: &str) -> Result { - let contents = read_to_string(file_path); + let contents = fs::read_to_string(file_path); if contents.is_ok() { return Ok(contents.unwrap()); } else { @@ -33,7 +64,7 @@ fn main() { .targets([LogTarget::LogDir, LogTarget::Stdout, LogTarget::Webview]) .build(), ) - .invoke_handler(tauri::generate_handler![read_file]) + .invoke_handler(tauri::generate_handler![read_file, read_dir]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/src/lib/crdt.ts b/src/lib/crdt.ts index 836d07963..483819190 100644 --- a/src/lib/crdt.ts +++ b/src/lib/crdt.ts @@ -55,7 +55,7 @@ export class TextDocument { if (content !== undefined && history.length > 0) { throw new Error("only one of content and history can be set"); } else if (content !== undefined) { - this.update(content); + this.doc.getText().insert(0, content); } else if (history.length > 0) { this.doc .getText() diff --git a/src/lib/log.ts b/src/lib/log.ts index ec14ce0e7..fdcbad443 100644 --- a/src/lib/log.ts +++ b/src/lib/log.ts @@ -1,6 +1,12 @@ -export { - debug, - info, - error, - attachConsole as setup, -} from "tauri-plugin-log-api"; +export { attachConsole as setup } from "tauri-plugin-log-api"; + +import * as log from "tauri-plugin-log-api"; + +export const debug = (...args: any[]) => + log.debug(args.map((argument) => JSON.stringify(argument)).join(" ")); + +export const info = (...args: any[]) => + log.info(args.map((argument) => JSON.stringify(argument)).join(" ")); + +export const error = (...args: any[]) => + log.error(args.map((argument) => JSON.stringify(argument)).join(" ")); diff --git a/src/lib/tauri.ts b/src/lib/tauri.ts index 0ccac7931..fd799624f 100644 --- a/src/lib/tauri.ts +++ b/src/lib/tauri.ts @@ -1,4 +1,5 @@ import { invoke } from "@tauri-apps/api"; +import { log } from "$lib"; export class NoSuchFileOrDirectoryError extends Error { constructor(message: string) { @@ -6,11 +7,24 @@ export class NoSuchFileOrDirectoryError extends Error { } } -export const readFile = (filePath: string) => - invoke("read_file", { filePath }).catch((err) => { +export const readFile = async (filePath: string) => { + log.info("readFile", { path: filePath }); + return invoke("read_file", { filePath }).catch((err) => { if (err.message === "No such file or directory (os error 2)") { throw new NoSuchFileOrDirectoryError(err.message); } else { throw err; } }); +}; + +export const readDir = async (path: string) => { + log.info("readDir", { path }); + return invoke("read_dir", { path }).catch((err) => { + if (err.message === "No such file or directory (os error 2)") { + throw new NoSuchFileOrDirectoryError(err.message); + } else { + throw err; + } + }); +}; diff --git a/src/routes/projects/[id]/+page.svelte b/src/routes/projects/[id]/+page.svelte index 8a2c77f59..bd19f785d 100644 --- a/src/routes/projects/[id]/+page.svelte +++ b/src/routes/projects/[id]/+page.svelte @@ -2,12 +2,15 @@ import { derived, writable } from "svelte/store"; import { EventType, watch, type Event } from "$lib/watch"; import { TextDocument } from "$lib/crdt"; - import { NoSuchFileOrDirectoryError, readFile } from "$lib/tauri"; + import { NoSuchFileOrDirectoryError, readFile, readDir } from "$lib/tauri"; import type { PageData } from "./$types"; import { Timeline } from "$lib/components"; + import { onMount } from "svelte"; export let data: PageData; + const project = data.project; + const docs = writable>({}); const deleteDocs = (...filepaths: string[]) => { @@ -18,8 +21,16 @@ ); }; - const upsertDoc = (filepath: string) => - readFile(filepath) + // TODO + const shouldIgnore = (filepath: string) => { + if (filepath.includes(".git")) return true; + if (filepath.includes("node_modules")) return true; + return false; + }; + + const upsertDoc = async (filepath: string) => { + if (shouldIgnore(filepath)) return; + return readFile(filepath) .then((content) => { if (filepath in $docs) { $docs[filepath].update(content); @@ -35,26 +46,31 @@ throw err; } }); + }; - const onEvent = (event: Event) => { + const onEvent = async (event: Event) => { const isFileCreate = EventType.isCreate(event.type) && event.type.create.kind === "file"; const isFileUpdate = EventType.isModify(event.type) && event.type.modify.kind === "data"; const isFileRemove = EventType.isRemove(event.type); - if (isFileCreate) { - event.paths.forEach(upsertDoc); - } else if (isFileUpdate) { - event.paths.forEach(upsertDoc); + if (isFileCreate || isFileUpdate) { + for (const path of event.paths) { + await upsertDoc(path); + } } else if (isFileRemove) { deleteDocs(...event.paths); } }; - $: data.project?.subscribe(async (project) => { - if (project === undefined) return; - return await watch(project.path, onEvent); + onMount(async () => { + if ($project === undefined) return; + const filepaths = await readDir($project.path); + for (const filepath of filepaths) { + await upsertDoc(filepath); + } + return watch($project.path, onEvent); }); const timestamps = derived(docs, (docs) =>