fix: Unable to access localStorage in document embedded in iframe with third party cookies blocked (#4777)
* fix: Pasting from Microsoft Office pastes image. Closes #3058 * fix: Use Storage wrapper implementation for all editor calls to localStorage closes #4776
This commit is contained in:
95
shared/utils/Storage.ts
Normal file
95
shared/utils/Storage.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Storage is a wrapper class for localStorage that allow safe usage when
|
||||
* localStorage is not available.
|
||||
*/
|
||||
class Storage {
|
||||
interface: typeof localStorage | MemoryStorage;
|
||||
|
||||
public constructor() {
|
||||
try {
|
||||
localStorage.setItem("test", "test");
|
||||
localStorage.removeItem("test");
|
||||
this.interface = localStorage;
|
||||
} catch (_err) {
|
||||
this.interface = new MemoryStorage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in storage. For efficiency, this method will remove the
|
||||
* value if it is undefined.
|
||||
*
|
||||
* @param key The key to set under.
|
||||
* @param value The value to set
|
||||
*/
|
||||
public set<T>(key: string, value: T) {
|
||||
try {
|
||||
if (value === undefined) {
|
||||
this.remove(key);
|
||||
} else {
|
||||
this.interface.setItem(key, JSON.stringify(value));
|
||||
}
|
||||
} catch (_err) {
|
||||
// Ignore errors
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from storage.
|
||||
*
|
||||
* @param key The key to get.
|
||||
* @param fallback The fallback value if the key doesn't exist.
|
||||
* @returns The value or undefined if it doesn't exist.
|
||||
*/
|
||||
public get(key: string, fallback?: any) {
|
||||
try {
|
||||
const value = this.interface.getItem(key);
|
||||
if (typeof value === "string") {
|
||||
return JSON.parse(value);
|
||||
}
|
||||
} catch (_err) {
|
||||
// Ignore errors
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a value from storage.
|
||||
*
|
||||
* @param key The key to remove.
|
||||
*/
|
||||
public remove(key: string) {
|
||||
try {
|
||||
this.interface.removeItem(key);
|
||||
} catch (_err) {
|
||||
// Ignore errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MemoryStorage is a simple in-memory storage implementation that is used
|
||||
* when localStorage is not available.
|
||||
*/
|
||||
class MemoryStorage {
|
||||
private data = {};
|
||||
|
||||
getItem(key: string) {
|
||||
return this.data[key] || null;
|
||||
}
|
||||
|
||||
setItem(key: string, value: any) {
|
||||
return (this.data[key] = String(value));
|
||||
}
|
||||
|
||||
removeItem(key: string) {
|
||||
return delete this.data[key];
|
||||
}
|
||||
|
||||
clear() {
|
||||
return (this.data = {});
|
||||
}
|
||||
}
|
||||
|
||||
export default new Storage();
|
||||
Reference in New Issue
Block a user