Add sync status inside editor
This commit is contained in:
parent
8b22549f5e
commit
de346b9fcf
4 changed files with 111 additions and 1 deletions
|
|
@ -15,8 +15,10 @@ import { SyncClient, rateLimit } from "sync-client";
|
||||||
import { ObsidianFileSystemOperations } from "./obsidian-file-system";
|
import { ObsidianFileSystemOperations } from "./obsidian-file-system";
|
||||||
import { SyncSettingsTab } from "./views/settings/settings-tab";
|
import { SyncSettingsTab } from "./views/settings/settings-tab";
|
||||||
import { registerConsoleForLogging } from "./utils/register-console-for-logging";
|
import { registerConsoleForLogging } from "./utils/register-console-for-logging";
|
||||||
|
import { updateEditorStatusDisplay } from "./views/editor-sync-line/editor-sync-line";
|
||||||
|
|
||||||
export default class VaultLinkPlugin extends Plugin {
|
export default class VaultLinkPlugin extends Plugin {
|
||||||
|
private readonly disposables: (() => void)[] = [];
|
||||||
private settingsTab: SyncSettingsTab | undefined;
|
private settingsTab: SyncSettingsTab | undefined;
|
||||||
private client!: SyncClient;
|
private client!: SyncClient;
|
||||||
private readonly rateLimitedUpdatesPerFile = new Map<
|
private readonly rateLimitedUpdatesPerFile = new Map<
|
||||||
|
|
@ -74,11 +76,21 @@ export default class VaultLinkPlugin extends Plugin {
|
||||||
this.app.workspace.onLayoutReady(async () => {
|
this.app.workspace.onLayoutReady(async () => {
|
||||||
this.registerEditorEvents();
|
this.registerEditorEvents();
|
||||||
void this.client.start();
|
void this.client.start();
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
updateEditorStatusDisplay(this.app.workspace, this.client);
|
||||||
|
}, 200);
|
||||||
|
this.disposables.push(() => {
|
||||||
|
clearInterval(interval);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public onunload(): void {
|
public onunload(): void {
|
||||||
this.client.stop();
|
this.client.stop();
|
||||||
|
this.disposables.forEach((disposable) => {
|
||||||
|
disposable();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public openSettings(): void {
|
public openSettings(): void {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@ import { ConnectionStatus } from "./services/connection-status";
|
||||||
import { UnrestrictedSyncer } from "./sync-operations/unrestricted-syncer";
|
import { UnrestrictedSyncer } from "./sync-operations/unrestricted-syncer";
|
||||||
import { rateLimit } from "./utils/rate-limit";
|
import { rateLimit } from "./utils/rate-limit";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { NetworkConnectionStatus } from "./types/network-connection-status";
|
import type { NetworkConnectionStatus } from "./types/network-connection-status";
|
||||||
import { DocumentUpdateStatus } from "./types/document-update-status";
|
import { DocumentUpdateStatus } from "./types/document-update-status";
|
||||||
|
|
||||||
export class SyncClient {
|
export class SyncClient {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue