flipper-plugin
Version:
Flipper Desktop plugin SDK and components
109 lines • 3.67 kB
JavaScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.useValue = exports.isAtom = exports.createState = exports.AtomValue = void 0;
const react_1 = require("react");
const immer_1 = require("immer");
const PluginBase_1 = require("../plugin/PluginBase");
const shallowSerialization_1 = require("../utils/shallowSerialization");
(0, immer_1.enableMapSet)();
class AtomValue {
constructor(initialValue) {
this.listeners = [];
this.value = initialValue;
}
get() {
return this.value;
}
set(nextValue) {
if (nextValue !== this.value) {
const prevValue = this.value;
this.value = nextValue;
this.notifyChanged(prevValue);
}
}
deserialize(value) {
this.set((0, shallowSerialization_1.deserializeShallowObject)(value));
}
serialize() {
return (0, shallowSerialization_1.makeShallowSerializable)(this.get());
}
update(recipe) {
this.set((0, immer_1.produce)(this.value, recipe));
}
notifyChanged(prevValue) {
// TODO: add scheduling
this.listeners.slice().forEach((l) => l(this.value, prevValue));
}
subscribe(listener) {
this.listeners.push(listener);
return () => this.unsubscribe(listener);
}
unsubscribe(listener) {
const idx = this.listeners.indexOf(listener);
if (idx !== -1) {
this.listeners.splice(idx, 1);
}
}
}
exports.AtomValue = AtomValue;
function createState(initialValue = undefined, options = {}) {
const atom = new AtomValue(initialValue);
if (options?.persistToLocalStorage) {
syncAtomWithLocalStorage(options, atom);
}
else {
(0, PluginBase_1.registerStorageAtom)(options.persist, atom);
}
return atom;
}
exports.createState = createState;
function syncAtomWithLocalStorage(options, atom) {
if (!options?.persist) {
throw new Error("The 'persist' option should be set when 'persistToLocalStorage' is set");
}
const pluginInstance = (0, PluginBase_1.getCurrentPluginInstance)();
if (!pluginInstance) {
throw new Error("The 'persistToLocalStorage' option cannot be used outside a plugin definition");
}
const storageKey = `flipper:${pluginInstance.definition.id}:atom:${options.persist}`;
const storedValue = window.localStorage.getItem(storageKey);
if (storedValue != null) {
atom.deserialize(JSON.parse(storedValue));
}
atom.subscribe(() => {
window.localStorage.setItem(storageKey, JSON.stringify(atom.serialize()));
});
}
function isAtom(value) {
return value instanceof AtomValue;
}
exports.isAtom = isAtom;
function useValue(atom, defaultValue) {
const [localValue, setLocalValue] = (0, react_1.useState)(
// TODO: Fix this the next time the file is edited.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
atom ? atom.get() : defaultValue);
(0, react_1.useEffect)(() => {
if (!atom) {
return;
}
// atom might have changed between mounting and effect setup
// in that case, this will cause a re-render, otherwise not
setLocalValue(atom.get());
atom.subscribe(setLocalValue);
return () => {
atom.unsubscribe(setLocalValue);
};
}, [atom]);
return localValue;
}
exports.useValue = useValue;
//# sourceMappingURL=atom.js.map
;