Handle quota exceeded and running low on disk space errors while saving a key in localStorage (#2947)

This commit is contained in:
Rishabh Saxena 2021-02-16 11:47:23 +05:30 committed by GitHub
parent a973d779fd
commit 2e72be0f8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 84 additions and 3 deletions

View File

@ -1,3 +1,5 @@
import localStorage from "utils/localStorage";
export const CANVAS_DEFAULT_WIDTH_PX = 1242;
export const CANVAS_DEFAULT_HEIGHT_PX = 1292;
export const CANVAS_DEFAULT_GRID_HEIGHT_PX = 1;
@ -13,7 +15,7 @@ export const getAppStore = (appId: string) => {
const appStoreName = getAppStoreName(appId);
let storeString = "{}";
// Check if localStorage exists
if (localStorage) {
if (localStorage.isSupported()) {
const appStore = localStorage.getItem(appStoreName);
if (appStore) storeString = appStore;
}

View File

@ -177,3 +177,8 @@ export const GOOGLE_RECAPTCHA_DOMAIN_ERROR =
export const SERVER_API_TIMEOUT_ERROR =
"Appsmith server is taking too long to respond. Please try again after some time";
export const DEFAULT_ERROR_MESSAGE = "There was an unexpected error";
export const LOCAL_STORAGE_QUOTA_EXCEEDED_MESSAGE =
"Error saving a key in localStorage. You have exceeded the allowed storage size limit";
export const LOCAL_STORAGE_NO_SPACE_LEFT_ON_DEVICE_MESSAGE =
"Error saving a key in localStorage. You have run out of disk space";

View File

@ -15,6 +15,7 @@ import { connect } from "react-redux";
import { AppState } from "reducers";
import { setThemeMode } from "actions/themeActions";
import { StyledToastContainer } from "components/ads/Toast";
import localStorage from "utils/localStorage";
// enable autofreeze only in development
import { setAutoFreeze } from "immer";

View File

@ -88,6 +88,8 @@ import {
import copy from "copy-to-clipboard";
import { EMPTY_RESPONSE } from "../components/editorComponents/ApiResponseView";
import localStorage from "utils/localStorage";
export enum NavigationTargetType {
SAME_WINDOW = "SAME_WINDOW",
NEW_WINDOW = "NEW_WINDOW",

View File

@ -1,5 +1,6 @@
import { ReduxActionTypes, ReduxAction } from "constants/ReduxActionConstants";
import { takeLatest } from "redux-saga/effects";
import localStorage from "utils/localStorage";
import { ThemeMode } from "../selectors/themeSelectors";
export function* setThemeSaga(actionPayload: ReduxAction<ThemeMode>) {

View File

@ -37,6 +37,7 @@ import PerformanceTracker, {
import { ERROR_CODES } from "constants/ApiConstants";
import { ANONYMOUS_USERNAME } from "constants/userConstants";
import { flushErrorsAndRedirect } from "actions/errorActions";
import localStorage from "utils/localStorage";
export function* createUserSaga(
action: ReduxActionWithPromise<CreateUserRequest>,

View File

@ -13,6 +13,7 @@ import produce from "immer";
import { AppIconCollection, AppIconName } from "components/ads/AppIcon";
import { ERROR_CODES } from "constants/ApiConstants";
import { ERROR_500 } from "../constants/messages";
import localStorage from "utils/localStorage";
export const createReducer = (
initialState: any,

View File

@ -1,4 +1,5 @@
import { FeatureFlagConfig, FeatureFlagsEnum } from "configs/types";
import localStorage from "utils/localStorage";
const optimizelySDK = require("@optimizely/optimizely-sdk");
class FeatureFlag {

View File

@ -1,4 +1,5 @@
import { useState } from "react";
import localStorage from "utils/localStorage";
export function useLocalStorage(key: string, initialValue: string) {
// State to store our value
@ -6,7 +7,7 @@ export function useLocalStorage(key: string, initialValue: string) {
const [storedValue, setStoredValue] = useState(() => {
try {
// Get from local storage by key
const item = window.localStorage.getItem(key);
const item = localStorage.getItem(key);
// Parse stored json or if none return initialValue
return item ? JSON.parse(item) : initialValue;
} catch (error) {
@ -26,7 +27,7 @@ export function useLocalStorage(key: string, initialValue: string) {
// Save state
setStoredValue(valueToStore);
// Save to local storage
window.localStorage.setItem(key, JSON.stringify(valueToStore));
localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
// A more advanced implementation would handle the error case
console.log(error);

View File

@ -0,0 +1,66 @@
import { Variant } from "components/ads/common";
import { Toaster } from "components/ads/Toast";
import {
LOCAL_STORAGE_QUOTA_EXCEEDED_MESSAGE,
LOCAL_STORAGE_NO_SPACE_LEFT_ON_DEVICE_MESSAGE,
} from "constants/messages";
const getLocalStorage = () => {
const storage = window.localStorage;
const handleError = (e: Error) => {
let message;
if (e.name === "QuotaExceededError") {
message = LOCAL_STORAGE_QUOTA_EXCEEDED_MESSAGE;
} else if (e.name === "NS_ERROR_FILE_NO_DEVICE_SPACE") {
message = LOCAL_STORAGE_NO_SPACE_LEFT_ON_DEVICE_MESSAGE;
}
if (message) {
Toaster.show({
text: message,
variant: Variant.danger,
});
} else {
throw e;
}
};
const getItem = (key: string): string | null => {
try {
return storage.getItem(key);
} catch (e) {
handleError(e);
}
return null;
};
const setItem = (key: string, value: string) => {
try {
storage.setItem(key, value);
} catch (e) {
handleError(e);
}
};
const removeItem = (key: string) => {
try {
storage.removeItem(key);
} catch (e) {
handleError(e);
}
};
const isSupported = () => !!window.localStorage;
return {
getItem,
setItem,
removeItem,
isSupported,
};
};
const localStorage = getLocalStorage();
export default localStorage;