mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-24 05:29:51 +03:00
load project files when it opens
This commit is contained in:
parent
1e26d05e69
commit
163155c319
@ -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<String> {
|
||||
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<Vec<String>, 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<String, InvokeError> {
|
||||
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");
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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(" "));
|
||||
|
@ -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<string>("read_file", { filePath }).catch((err) => {
|
||||
export const readFile = async (filePath: string) => {
|
||||
log.info("readFile", { path: filePath });
|
||||
return invoke<string>("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<string[]>("read_dir", { path }).catch((err) => {
|
||||
if (err.message === "No such file or directory (os error 2)") {
|
||||
throw new NoSuchFileOrDirectoryError(err.message);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -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<Record<string, TextDocument>>({});
|
||||
|
||||
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) =>
|
||||
|
Loading…
Reference in New Issue
Block a user