Merge branch 'master' into mtolmacs/feat/fixed-point-simple-arrow-binding

This commit is contained in:
Mark Tolmacs
2025-10-01 10:46:38 +02:00
11 changed files with 133 additions and 35 deletions

View File

@@ -119,6 +119,7 @@ import {
LibraryIndexedDBAdapter,
LibraryLocalStorageMigrationAdapter,
LocalData,
localStorageQuotaExceededAtom,
} from "./data/LocalData";
import { isBrowserStorageStateNewer } from "./data/tabSync";
import { ShareDialog, shareDialogStateAtom } from "./share/ShareDialog";
@@ -727,6 +728,8 @@ const ExcalidrawWrapper = () => {
const isOffline = useAtomValue(isOfflineAtom);
const localStorageQuotaExceeded = useAtomValue(localStorageQuotaExceededAtom);
const onCollabDialogOpen = useCallback(
() => setShareDialogState({ isOpen: true, type: "collaborationOnly" }),
[setShareDialogState],
@@ -901,10 +904,15 @@ const ExcalidrawWrapper = () => {
<TTDDialogTrigger />
{isCollaborating && isOffline && (
<div className="collab-offline-warning">
<div className="alertalert--warning">
{t("alerts.collabOfflineWarning")}
</div>
)}
{localStorageQuotaExceeded && (
<div className="alert alert--danger">
{t("alerts.localStorageQuotaExceeded")}
</div>
)}
{latestShareableLink && (
<ShareableLinkDialog
link={latestShareableLink}

View File

@@ -26,6 +26,8 @@ import {
get,
} from "idb-keyval";
import { appJotaiStore, atom } from "excalidraw-app/app-jotai";
import type { LibraryPersistedData } from "@excalidraw/excalidraw/data/library";
import type { ImportedDataState } from "@excalidraw/excalidraw/data/types";
import type { ExcalidrawElement, FileId } from "@excalidraw/element/types";
@@ -44,6 +46,8 @@ import { updateBrowserStateVersion } from "./tabSync";
const filesStore = createStore("files-db", "files-store");
export const localStorageQuotaExceededAtom = atom(false);
class LocalFileManager extends FileManager {
clearObsoleteFiles = async (opts: { currentFileIds: FileId[] }) => {
await entries(filesStore).then((entries) => {
@@ -68,6 +72,9 @@ const saveDataStateToLocalStorage = (
elements: readonly ExcalidrawElement[],
appState: AppState,
) => {
const localStorageQuotaExceeded = appJotaiStore.get(
localStorageQuotaExceededAtom,
);
try {
const _appState = clearAppStateForLocalStorage(appState);
@@ -87,12 +94,22 @@ const saveDataStateToLocalStorage = (
JSON.stringify(_appState),
);
updateBrowserStateVersion(STORAGE_KEYS.VERSION_DATA_STATE);
if (localStorageQuotaExceeded) {
appJotaiStore.set(localStorageQuotaExceededAtom, false);
}
} catch (error: any) {
// Unable to access window.localStorage
console.error(error);
if (isQuotaExceededError(error) && !localStorageQuotaExceeded) {
appJotaiStore.set(localStorageQuotaExceededAtom, true);
}
}
};
const isQuotaExceededError = (error: any) => {
return error instanceof DOMException && error.name === "QuotaExceededError";
};
type SavingLockTypes = "collaboration";
export class LocalData {

View File

@@ -58,7 +58,7 @@
}
}
.collab-offline-warning {
.alert {
pointer-events: none;
position: absolute;
top: 6.5rem;
@@ -69,10 +69,18 @@
text-align: center;
line-height: 1.5;
border-radius: var(--border-radius-md);
background-color: var(--color-warning);
color: var(--color-text-warning);
z-index: 6;
white-space: pre;
&--warning {
background-color: var(--color-warning);
color: var(--color-text-warning);
}
&--danger {
background-color: var(--color-danger-dark);
color: var(--color-danger-text);
}
}
}