Add sync status inside editor

This commit is contained in:
Andras Schmelczer 2025-05-11 22:25:19 +01:00
parent 8b22549f5e
commit de346b9fcf
No known key found for this signature in database
GPG key ID: FC8F2C3D3D1A718C
4 changed files with 111 additions and 1 deletions

View file

@ -15,8 +15,10 @@ import { SyncClient, rateLimit } from "sync-client";
import { ObsidianFileSystemOperations } from "./obsidian-file-system";
import { SyncSettingsTab } from "./views/settings/settings-tab";
import { registerConsoleForLogging } from "./utils/register-console-for-logging";
import { updateEditorStatusDisplay } from "./views/editor-sync-line/editor-sync-line";
export default class VaultLinkPlugin extends Plugin {
private readonly disposables: (() => void)[] = [];
private settingsTab: SyncSettingsTab | undefined;
private client!: SyncClient;
private readonly rateLimitedUpdatesPerFile = new Map<
@ -74,11 +76,21 @@ export default class VaultLinkPlugin extends Plugin {
this.app.workspace.onLayoutReady(async () => {
this.registerEditorEvents();
void this.client.start();
const interval = setInterval(() => {
updateEditorStatusDisplay(this.app.workspace, this.client);
}, 200);
this.disposables.push(() => {
clearInterval(interval);
});
});
}
public onunload(): void {
this.client.stop();
this.disposables.forEach((disposable) => {
disposable();
});
}
public openSettings(): void {

View file

@ -0,0 +1,43 @@
.vault-link-sync-status {
position: absolute;
right: var(--size-4-4);
top: var(--size-4-2);
opacity: 0.7;
cursor: pointer;
> span {
opacity: 0;
position: absolute;
min-width: 200px;
text-align: right;
padding-right: var(--size-2-2);
top: 50%;
left: 0;
transform: translateY(-50%) translateX(-100%) translateY(-2px);
transition: opacity 200ms;
}
&:hover {
> span {
opacity: 1;
}
}
> .icon {
line-height: 0;
}
&.loading > .icon {
animation: spin 2s linear infinite;
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
}
}

View file

@ -0,0 +1,55 @@
import type { Workspace } from "obsidian";
import { FileView, setIcon } from "obsidian";
import type { SyncClient } from "sync-client";
import { DocumentUpdateStatus } from "sync-client";
import "./editor-sync-line.scss";
export function updateEditorStatusDisplay(
workspace: Workspace,
client: SyncClient
): void {
workspace.iterateAllLeaves((leaf) => {
if (leaf.view instanceof FileView) {
const filePath = leaf.view.file?.path;
if (filePath == null) {
return;
}
const parent = leaf.view.contentEl.querySelector(".cm-editor");
if (parent == null) {
return;
}
const element =
parent.querySelector(".vault-link-sync-status") ??
parent.createDiv(
{
cls: "vault-link-sync-status"
},
(el) => {
el.createSpan({ text: "VaultLink sync state" });
el.createDiv({
cls: "icon"
});
}
);
const isLoading =
client.getDocumentSyncingStatus(filePath) ==
DocumentUpdateStatus.SYNCING;
if (isLoading) {
element.classList.add("loading");
} else {
element.classList.remove("loading");
}
const iconContainer = element.querySelector(".icon");
if (iconContainer != null) {
setIcon(
iconContainer as HTMLElement, // eslint-disable-line @typescript-eslint/no-unsafe-type-assertion
isLoading ? "loader" : "circle-check"
);
}
}
});
}