Warn to save content
Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
parent
8ca4cf3260
commit
fe318126bd
@ -126,6 +126,8 @@ import DebugCanvas, {
|
|||||||
loadSavedDebugState,
|
loadSavedDebugState,
|
||||||
} from "./components/DebugCanvas";
|
} from "./components/DebugCanvas";
|
||||||
import { AIComponents } from "./components/AI";
|
import { AIComponents } from "./components/AI";
|
||||||
|
import type { SaveWarningRef } from "./components/SaveWarning";
|
||||||
|
import { SaveWarning } from "./components/SaveWarning";
|
||||||
|
|
||||||
polyfill();
|
polyfill();
|
||||||
|
|
||||||
@ -331,6 +333,8 @@ const ExcalidrawWrapper = () => {
|
|||||||
|
|
||||||
const [langCode, setLangCode] = useAppLangCode();
|
const [langCode, setLangCode] = useAppLangCode();
|
||||||
|
|
||||||
|
const activityRef = useRef<SaveWarningRef | null>(null);
|
||||||
|
|
||||||
// initial state
|
// initial state
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -615,6 +619,8 @@ const ExcalidrawWrapper = () => {
|
|||||||
collabAPI.syncElements(elements);
|
collabAPI.syncElements(elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
activityRef.current?.activity();
|
||||||
|
|
||||||
// this check is redundant, but since this is a hot path, it's best
|
// this check is redundant, but since this is a hot path, it's best
|
||||||
// not to evaludate the nested expression every time
|
// not to evaludate the nested expression every time
|
||||||
if (!LocalData.isSavePaused()) {
|
if (!LocalData.isSavePaused()) {
|
||||||
@ -856,6 +862,7 @@ const ExcalidrawWrapper = () => {
|
|||||||
setTheme={(theme) => setAppTheme(theme)}
|
setTheme={(theme) => setAppTheme(theme)}
|
||||||
refresh={() => forceRefresh((prev) => !prev)}
|
refresh={() => forceRefresh((prev) => !prev)}
|
||||||
/>
|
/>
|
||||||
|
<SaveWarning ref={activityRef} />
|
||||||
<AppWelcomeScreen
|
<AppWelcomeScreen
|
||||||
onCollabDialogOpen={onCollabDialogOpen}
|
onCollabDialogOpen={onCollabDialogOpen}
|
||||||
isCollabEnabled={!isCollabDisabled}
|
isCollabEnabled={!isCollabDisabled}
|
||||||
|
40
excalidraw-app/components/SaveWarning.tsx
Normal file
40
excalidraw-app/components/SaveWarning.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { forwardRef, useImperativeHandle, useRef } from "react";
|
||||||
|
import { t } from "../../packages/excalidraw/i18n";
|
||||||
|
import { getShortcutKey } from "../../packages/excalidraw/utils";
|
||||||
|
|
||||||
|
export type SaveWarningRef = {
|
||||||
|
activity: () => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SaveWarning = forwardRef<SaveWarningRef, {}>((props, ref) => {
|
||||||
|
const dialogRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
/**
|
||||||
|
* Call this API method via the ref to hide warning message
|
||||||
|
* and start an idle timer again.
|
||||||
|
*/
|
||||||
|
activity: async () => {
|
||||||
|
if (timerRef.current != null) {
|
||||||
|
clearTimeout(timerRef.current);
|
||||||
|
dialogRef.current?.classList.remove("animate");
|
||||||
|
}
|
||||||
|
|
||||||
|
timerRef.current = setTimeout(() => {
|
||||||
|
timerRef.current = null;
|
||||||
|
dialogRef.current?.classList.add("animate");
|
||||||
|
}, 5000);
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={dialogRef} className="alert-save">
|
||||||
|
<div className="dialog">
|
||||||
|
{t("alerts.saveYourContent", {
|
||||||
|
shortcut: getShortcutKey("CtrlOrCmd + S"),
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
@ -1,3 +1,13 @@
|
|||||||
|
@mixin animate($animation,$duration,$method,$times){
|
||||||
|
animation: $animation $duration $method $times;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin keyframes($name){
|
||||||
|
@keyframes #{$name}{
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.excalidraw {
|
.excalidraw {
|
||||||
--color-primary-contrast-offset: #625ee0; // to offset Chubb illusion
|
--color-primary-contrast-offset: #625ee0; // to offset Chubb illusion
|
||||||
|
|
||||||
@ -18,6 +28,43 @@
|
|||||||
margin-inline-start: auto;
|
margin-inline-start: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alert-save {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 10vh;
|
||||||
|
margin-inline: auto;
|
||||||
|
width: fit-content;
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 0s;
|
||||||
|
|
||||||
|
&.animate {
|
||||||
|
opacity: 1;
|
||||||
|
transition: all 0.2s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog {
|
||||||
|
margin-inline: 10px;
|
||||||
|
padding: 1rem;
|
||||||
|
padding-inline: 1.25rem;
|
||||||
|
|
||||||
|
resize: none;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
background-color: var(--color-warning);
|
||||||
|
border-radius: var(--border-radius-md);
|
||||||
|
border: 1px solid var(--dialog-border-color);
|
||||||
|
|
||||||
|
font-size: 0.875rem;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--color-text-warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.encrypted-icon {
|
.encrypted-icon {
|
||||||
border-radius: var(--space-factor);
|
border-radius: var(--space-factor);
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
|
@ -230,7 +230,8 @@
|
|||||||
"resetLibrary": "This will clear your library. Are you sure?",
|
"resetLibrary": "This will clear your library. Are you sure?",
|
||||||
"removeItemsFromsLibrary": "Delete {{count}} item(s) from library?",
|
"removeItemsFromsLibrary": "Delete {{count}} item(s) from library?",
|
||||||
"invalidEncryptionKey": "Encryption key must be of 22 characters. Live collaboration is disabled.",
|
"invalidEncryptionKey": "Encryption key must be of 22 characters. Live collaboration is disabled.",
|
||||||
"collabOfflineWarning": "No internet connection available.\nYour changes will not be saved!"
|
"collabOfflineWarning": "No internet connection available.\nYour changes will not be saved!",
|
||||||
|
"saveYourContent": "Don't forget to save your content ({{shortcut}})!"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"unsupportedFileType": "Unsupported file type.",
|
"unsupportedFileType": "Unsupported file type.",
|
||||||
@ -609,4 +610,4 @@
|
|||||||
"itemNotAvailable": "Command is not available...",
|
"itemNotAvailable": "Command is not available...",
|
||||||
"shortcutHint": "For Command palette, use {{shortcut}}"
|
"shortcutHint": "For Command palette, use {{shortcut}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user