Sync while typing not just on save
This commit is contained in:
parent
60ed4e5109
commit
e5a0c5830a
4 changed files with 72 additions and 93 deletions
|
|
@ -1,58 +0,0 @@
|
|||
import type { SyncClient } from "sync-client";
|
||||
import type { TAbstractFile } from "obsidian";
|
||||
import { TFile } from "obsidian";
|
||||
|
||||
export class ObsidianFileEventHandler {
|
||||
public constructor(private readonly client: SyncClient) {}
|
||||
|
||||
public async onCreate(file: TAbstractFile): Promise<void> {
|
||||
if (file instanceof TFile) {
|
||||
this.client.logger.info(`File created: ${file.path}`);
|
||||
|
||||
await this.client.syncLocallyCreatedFile(file.path);
|
||||
} else {
|
||||
this.client.logger.debug(`Folder created: ${file.path}, ignored`);
|
||||
}
|
||||
}
|
||||
|
||||
public async onDelete(file: TAbstractFile): Promise<void> {
|
||||
if (file instanceof TFile) {
|
||||
this.client.logger.info(`File deleted: ${file.path}`);
|
||||
|
||||
await this.client.syncLocallyDeletedFile(file.path);
|
||||
} else {
|
||||
this.client.logger.debug(`Folder deleted: ${file.path}, ignored`);
|
||||
}
|
||||
}
|
||||
|
||||
public async onRename(file: TAbstractFile, oldPath: string): Promise<void> {
|
||||
if (file instanceof TFile) {
|
||||
this.client.logger.info(`File renamed: ${oldPath} -> ${file.path}`);
|
||||
|
||||
await this.client.syncLocallyUpdatedFile({
|
||||
oldPath,
|
||||
relativePath: file.path
|
||||
});
|
||||
} else {
|
||||
this.client.logger.debug(
|
||||
`Folder renamed: ${oldPath} -> ${file.path}, ignored`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async onModify(file: TAbstractFile): Promise<void> {
|
||||
if (file instanceof TFile) {
|
||||
if (file.basename.startsWith("console-log.iPhone")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.client.logger.info(`File modified: ${file.path}`);
|
||||
|
||||
await this.client.syncLocallyUpdatedFile({
|
||||
relativePath: file.path
|
||||
});
|
||||
} else {
|
||||
this.client.logger.debug(`Folder modified: ${file.path}, ignored`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,23 @@
|
|||
import type { Stat, Vault } from "obsidian";
|
||||
import { normalizePath } from "obsidian";
|
||||
import type { Stat, Vault, Workspace } from "obsidian";
|
||||
import { MarkdownView, normalizePath } from "obsidian";
|
||||
import type { FileSystemOperations, RelativePath } from "sync-client";
|
||||
|
||||
export class ObsidianFileSystemOperations implements FileSystemOperations {
|
||||
public constructor(private readonly vault: Vault) {}
|
||||
public constructor(
|
||||
private readonly vault: Vault,
|
||||
private readonly workspace: Workspace
|
||||
) {}
|
||||
|
||||
public async listAllFiles(): Promise<RelativePath[]> {
|
||||
return this.vault.getFiles().map((file) => file.path);
|
||||
}
|
||||
|
||||
public async read(path: RelativePath): Promise<Uint8Array> {
|
||||
const view = this.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (view?.file?.path === path) {
|
||||
return new TextEncoder().encode(view.editor.getValue());
|
||||
}
|
||||
|
||||
return new Uint8Array(
|
||||
await this.vault.adapter.readBinary(normalizePath(path))
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
import type { WorkspaceLeaf } from "obsidian";
|
||||
import { Platform, Plugin } from "obsidian";
|
||||
import type {
|
||||
Editor,
|
||||
MarkdownFileInfo,
|
||||
MarkdownView,
|
||||
TAbstractFile,
|
||||
WorkspaceLeaf
|
||||
} from "obsidian";
|
||||
import { Platform, Plugin, TFile } from "obsidian";
|
||||
import "./styles.scss";
|
||||
import "../manifest.json";
|
||||
import { SyncSettingsTab } from "./views/settings-tab";
|
||||
import { HistoryView } from "./views/history-view";
|
||||
import { ObsidianFileEventHandler } from "./obisidan-event-handler";
|
||||
import { StatusBar } from "./views/status-bar";
|
||||
import { LogsView } from "./views/logs-view";
|
||||
import { StatusDescription } from "./views/status-description";
|
||||
|
|
@ -15,6 +20,7 @@ import { ObsidianFileSystemOperations } from "./obsidian-file-system";
|
|||
export default class VaultLinkPlugin extends Plugin {
|
||||
private settingsTab: SyncSettingsTab | undefined;
|
||||
private client!: SyncClient;
|
||||
|
||||
private static registerConsoleForLogging(client: SyncClient): void {
|
||||
client.logger.addOnMessageListener((logLine: LogLine) => {
|
||||
const formatted = `${logLine.timestamp.toISOString()} ${logLine.level} ${logLine.message}`;
|
||||
|
|
@ -38,7 +44,10 @@ export default class VaultLinkPlugin extends Plugin {
|
|||
|
||||
public async onload(): Promise<void> {
|
||||
this.client = await SyncClient.create({
|
||||
fs: new ObsidianFileSystemOperations(this.app.vault),
|
||||
fs: new ObsidianFileSystemOperations(
|
||||
this.app.vault,
|
||||
this.app.workspace
|
||||
),
|
||||
persistence: {
|
||||
load: this.loadData.bind(this),
|
||||
save: this.saveData.bind(this)
|
||||
|
|
@ -80,35 +89,9 @@ export default class VaultLinkPlugin extends Plugin {
|
|||
async (_: MouseEvent) => this.activateView(LogsView.TYPE)
|
||||
);
|
||||
|
||||
const eventHandler = new ObsidianFileEventHandler(this.client);
|
||||
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
this.client.logger.info("Initialising sync handlers");
|
||||
|
||||
[
|
||||
this.app.vault.on(
|
||||
"create",
|
||||
eventHandler.onCreate.bind(eventHandler)
|
||||
),
|
||||
this.app.vault.on(
|
||||
"modify",
|
||||
eventHandler.onModify.bind(eventHandler)
|
||||
),
|
||||
this.app.vault.on(
|
||||
"delete",
|
||||
eventHandler.onDelete.bind(eventHandler)
|
||||
),
|
||||
this.app.vault.on(
|
||||
"rename",
|
||||
eventHandler.onRename.bind(eventHandler)
|
||||
)
|
||||
].forEach((event) => {
|
||||
this.registerEvent(event);
|
||||
});
|
||||
|
||||
this.registerEditorEvents();
|
||||
void this.client.start();
|
||||
|
||||
this.client.logger.info("Sync handlers initialised");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -145,4 +128,51 @@ export default class VaultLinkPlugin extends Plugin {
|
|||
await workspace.revealLeaf(leaf);
|
||||
}
|
||||
}
|
||||
|
||||
private registerEditorEvents() {
|
||||
[
|
||||
this.app.workspace.on(
|
||||
"editor-change",
|
||||
async (
|
||||
_editor: Editor,
|
||||
info: MarkdownView | MarkdownFileInfo
|
||||
) => {
|
||||
const file = info.file;
|
||||
if (file) {
|
||||
await this.client.syncLocallyUpdatedFile({
|
||||
relativePath: file.path
|
||||
});
|
||||
}
|
||||
}
|
||||
),
|
||||
this.app.vault.on("create", async (file: TAbstractFile) => {
|
||||
if (file instanceof TFile) {
|
||||
await this.client.syncLocallyCreatedFile(file.path);
|
||||
}
|
||||
}),
|
||||
this.app.vault.on("modify", async (file: TAbstractFile) => {
|
||||
if (file instanceof TFile) {
|
||||
await this.client.syncLocallyUpdatedFile({
|
||||
relativePath: file.path
|
||||
});
|
||||
}
|
||||
}),
|
||||
this.app.vault.on("delete", async (file: TAbstractFile) => {
|
||||
await this.client.syncLocallyDeletedFile(file.path);
|
||||
}),
|
||||
this.app.vault.on(
|
||||
"rename",
|
||||
async (file: TAbstractFile, oldPath: string) => {
|
||||
if (file instanceof TFile) {
|
||||
await this.client.syncLocallyUpdatedFile({
|
||||
oldPath,
|
||||
relativePath: file.path
|
||||
});
|
||||
}
|
||||
}
|
||||
)
|
||||
].forEach((event) => {
|
||||
this.registerEvent(event);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import type { IconName, WorkspaceLeaf } from "obsidian";
|
||||
import { ItemView, setIcon } from "obsidian";
|
||||
|
||||
import { intlFormatDistance } from "date-fns";
|
||||
import type { HistoryEntry, SyncClient } from "sync-client";
|
||||
import { SyncType } from "sync-client";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue