mirror of
https://github.com/zadam/trilium.git
synced 2026-01-10 16:44:29 +01:00
chore(save_indicator): basic infrastructure to display state
This commit is contained in:
parent
345378d97f
commit
e8d1fa7447
@ -23,6 +23,8 @@ export interface SetNoteOpts {
|
||||
|
||||
export type GetTextEditorCallback = (editor: CKTextEditor) => void;
|
||||
|
||||
export type SaveState = "saved" | "saving" | "unsaved" | "error";
|
||||
|
||||
export interface NoteContextDataMap {
|
||||
toc: HeadingContext;
|
||||
pdfPages: {
|
||||
@ -39,6 +41,9 @@ export interface NoteContextDataMap {
|
||||
layers: Array<{ id: string; name: string; visible: boolean }>;
|
||||
toggleLayer(layerId: string, visible: boolean): void;
|
||||
};
|
||||
saveState: {
|
||||
state: SaveState;
|
||||
}
|
||||
}
|
||||
|
||||
type ContextDataKey = keyof NoteContextDataMap;
|
||||
|
||||
@ -1,22 +1,29 @@
|
||||
import type { SaveState } from "../components/note_context";
|
||||
|
||||
type Callback = () => Promise<void> | void;
|
||||
|
||||
export type StateCallback = (state: SaveState) => void;
|
||||
|
||||
export default class SpacedUpdate {
|
||||
private updater: Callback;
|
||||
private lastUpdated: number;
|
||||
private changed: boolean;
|
||||
private updateInterval: number;
|
||||
private changeForbidden?: boolean;
|
||||
private stateCallback?: StateCallback;
|
||||
|
||||
constructor(updater: Callback, updateInterval = 1000) {
|
||||
constructor(updater: Callback, updateInterval = 1000, stateCallback?: StateCallback) {
|
||||
this.updater = updater;
|
||||
this.lastUpdated = Date.now();
|
||||
this.changed = false;
|
||||
this.updateInterval = updateInterval;
|
||||
this.stateCallback = stateCallback;
|
||||
}
|
||||
|
||||
scheduleUpdate() {
|
||||
if (!this.changeForbidden) {
|
||||
this.changed = true;
|
||||
this.stateCallback?.("unsaved");
|
||||
setTimeout(() => this.triggerUpdate());
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import { t } from "../../services/i18n";
|
||||
import { goToLinkExt } from "../../services/link";
|
||||
import { Badge, BadgeWithDropdown } from "../react/Badge";
|
||||
import { FormDropdownDivider, FormListItem } from "../react/FormList";
|
||||
import { useIsNoteReadOnly, useNoteContext, useNoteLabel, useNoteLabelBoolean } from "../react/hooks";
|
||||
import { useGetContextData, useIsNoteReadOnly, useNoteContext, useNoteLabel, useNoteLabelBoolean } from "../react/hooks";
|
||||
import { useShareState } from "../ribbon/BasicPropertiesTab";
|
||||
import { useShareInfo } from "../shared_info";
|
||||
|
||||
@ -110,12 +110,13 @@ function ExecuteBadge() {
|
||||
}
|
||||
|
||||
function SaveStatusBadge() {
|
||||
const state: "saved" | "saving" | "unsaved" | "error" = "error"; // TODO: implement save state tracking
|
||||
const saveState = useGetContextData("saveState");
|
||||
if (!saveState) return;
|
||||
|
||||
let icon: string;
|
||||
let title: string;
|
||||
let tooltip: string;
|
||||
switch (state) {
|
||||
switch (saveState?.state) {
|
||||
case "saved":
|
||||
icon = "bx bx-check";
|
||||
title = t("breadcrumb_badges.save_status_saved");
|
||||
@ -140,7 +141,7 @@ function SaveStatusBadge() {
|
||||
|
||||
return (
|
||||
<Badge
|
||||
className={clsx("save-status-badge", state)}
|
||||
className={clsx("save-status-badge", saveState)}
|
||||
icon={icon}
|
||||
text={title}
|
||||
tooltip={tooltip}
|
||||
|
||||
@ -19,7 +19,7 @@ import options, { type OptionValue } from "../../services/options";
|
||||
import protected_session_holder from "../../services/protected_session_holder";
|
||||
import server from "../../services/server";
|
||||
import shortcuts, { Handler, removeIndividualBinding } from "../../services/shortcuts";
|
||||
import SpacedUpdate from "../../services/spaced_update";
|
||||
import SpacedUpdate, { type StateCallback } from "../../services/spaced_update";
|
||||
import toast, { ToastOptions } from "../../services/toast";
|
||||
import tree from "../../services/tree";
|
||||
import utils, { escapeRegExp, getErrorMessage, randomString, reloadFrontendApp } from "../../services/utils";
|
||||
@ -63,11 +63,12 @@ export function useTriliumEvents<T extends EventNames>(eventNames: T[], handler:
|
||||
useDebugValue(() => eventNames.join(", "));
|
||||
}
|
||||
|
||||
export function useSpacedUpdate(callback: () => void | Promise<void>, interval = 1000) {
|
||||
export function useSpacedUpdate(callback: () => void | Promise<void>, interval = 1000, stateCallback?: StateCallback) {
|
||||
const callbackRef = useRef(callback);
|
||||
const spacedUpdateRef = useRef<SpacedUpdate>(new SpacedUpdate(
|
||||
() => callbackRef.current(),
|
||||
interval
|
||||
interval,
|
||||
stateCallback
|
||||
));
|
||||
|
||||
// Update callback ref when it changes
|
||||
@ -121,7 +122,12 @@ export function useEditorSpacedUpdate({ note, noteType, noteContext, getData, on
|
||||
dataSaved?.(data);
|
||||
};
|
||||
}, [ note, getData, dataSaved, noteType, parentComponent ]);
|
||||
const spacedUpdate = useSpacedUpdate(callback);
|
||||
const stateCallback = useCallback<StateCallback>((state) => {
|
||||
noteContext?.setContextData("saveState", {
|
||||
state
|
||||
});
|
||||
}, [ noteContext ]);
|
||||
const spacedUpdate = useSpacedUpdate(callback, updateInterval, stateCallback);
|
||||
|
||||
// React to note/blob changes.
|
||||
useEffect(() => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user