(null);
+ const [ syncServerHost ] = useTriliumOption("syncServerHost");
+ useStaticTooltip(spanRef, {
+ html: true
+ // TODO: Placement
+ });
+
+ return (syncServerHost &&
+
+ )
+}
+
+function useSyncStatus() {
+ const [ syncState, setSyncState ] = useState("unknown");
+
+ useEffect(() => {
+ let lastSyncedPush: number;
+
+ function onMessage(message: WebSocketMessage) {
+ // First, read last synced push.
+ if ("lastSyncedPush" in message) {
+ lastSyncedPush = message.lastSyncedPush;
+ } else if ("data" in message && message.data && "lastSyncedPush" in message.data && lastSyncedPush) {
+ lastSyncedPush = message.data.lastSyncedPush;
+ }
+
+ // Determine if all changes were pushed.
+ const allChangesPushed = lastSyncedPush === ws.getMaxKnownEntityChangeSyncId();
+
+ let syncState: SyncState = "unknown";
+ if (message.type === "sync-pull-in-progress") {
+ syncState = "in-progress";
+ } else if (message.type === "sync-push-in-progress") {
+ syncState = "in-progress";
+ } else if (message.type === "sync-finished") {
+ syncState = allChangesPushed ? "connected-no-changes" : "connected-with-changes";
+ } else if (message.type === "sync-failed") {
+ syncState = allChangesPushed ? "disconnected-no-changes" : "disconnected-with-changes";
+ } else if (message.type === "frontend-update") {
+ lastSyncedPush = message.data.lastSyncedPush;
+ }
+ setSyncState(syncState);
+ }
+
+ subscribeToMessages(onMessage);
+ return () => unsubscribeToMessage(onMessage);
+ }, []);
+
+ return syncState;
+}
diff --git a/apps/client/src/widgets/sync_status.ts b/apps/client/src/widgets/sync_status.ts
deleted file mode 100644
index 3ce671034..000000000
--- a/apps/client/src/widgets/sync_status.ts
+++ /dev/null
@@ -1,146 +0,0 @@
-import { t } from "../services/i18n.js";
-import BasicWidget from "./basic_widget.js";
-import ws from "../services/ws.js";
-import options from "../services/options.js";
-import syncService from "../services/sync.js";
-import { escapeQuotes, handleRightToLeftPlacement } from "../services/utils.js";
-import { Tooltip } from "bootstrap";
-import { WebSocketMessage } from "@triliumnext/commons";
-
-const TPL = /*html*/`
-
-`;
-
-export default class SyncStatusWidget extends BasicWidget {
-
- syncState: "unknown" | "in-progress" | "connected" | "disconnected";
- allChangesPushed: boolean;
- lastSyncedPush!: number;
- settings: {
- // TriliumNextTODO: narrow types and use TitlePlacement Type
- titlePlacement: string;
- };
-
- constructor() {
- super();
-
- this.syncState = "unknown";
- this.allChangesPushed = false;
- this.settings = {
- titlePlacement: "right"
- };
- }
-
- doRender() {
- this.$widget = $(TPL);
- this.$widget.hide();
-
- this.$widget.find(".sync-status-icon:not(.sync-status-in-progress)").on("click", () => syncService.syncNow());
-
- ws.subscribeToMessages((message) => this.processMessage(message));
- }
-
- showIcon(className: string) {
- if (!options.get("syncServerHost")) {
- this.toggleInt(false);
- return;
- }
-
- Tooltip.getOrCreateInstance(this.$widget.find(`.sync-status-${className}`)[0], {
- html: true,
- placement: handleRightToLeftPlacement(this.settings.titlePlacement),
- fallbackPlacements: [ handleRightToLeftPlacement(this.settings.titlePlacement) ]
- });
-
- this.$widget.show();
- this.$widget.find(".sync-status-icon").hide();
- this.$widget.find(`.sync-status-${className}`).show();
- }
-
- processMessage(message: WebSocketMessage) {
- if (message.type === "sync-pull-in-progress") {
- this.syncState = "in-progress";
- this.lastSyncedPush = message.lastSyncedPush;
- } else if (message.type === "sync-push-in-progress") {
- this.syncState = "in-progress";
- this.lastSyncedPush = message.lastSyncedPush;
- } else if (message.type === "sync-finished") {
- this.syncState = "connected";
- this.lastSyncedPush = message.lastSyncedPush;
- } else if (message.type === "sync-failed") {
- this.syncState = "disconnected";
- this.lastSyncedPush = message.lastSyncedPush;
- } else if (message.type === "frontend-update") {
- this.lastSyncedPush = message.data.lastSyncedPush;
- }
-
- this.allChangesPushed = this.lastSyncedPush === ws.getMaxKnownEntityChangeSyncId();
-
- if (["unknown", "in-progress"].includes(this.syncState)) {
- this.showIcon(this.syncState);
- } else {
- this.showIcon(`${this.syncState}-${this.allChangesPushed ? "no-changes" : "with-changes"}`);
- }
- }
-}