Skip to content

Instantly share code, notes, and snippets.

@bdougherty
Last active March 29, 2021 16:45
Show Gist options
  • Save bdougherty/281593f0df6dad595fd56af9721e743d to your computer and use it in GitHub Desktop.
Save bdougherty/281593f0df6dad595fd56af9721e743d to your computer and use it in GitHub Desktop.
import { writable, get } from 'svelte/store';
function makeBroadcastChannelSharedStore(name) {
let channel;
let receivedInitialValue = false;
function sendMessage(action, value = null) {
if (channel) {
channel.postMessage({ action, value });
}
}
const { subscribe, set, update } = writable(null, () => {
channel = new BroadcastChannel(name);
channel.onmessage = ({ data }) => {
const { action, value } = data;
if (action === 'set') {
set(value);
return;
}
if (action === 'join') {
sendMessage('setInitialValue', get({ subscribe }));
return;
}
if (action === 'setInitialValue' && !receivedInitialValue) {
receivedInitialValue = true;
set(value);
return;
}
}
sendMessage('join');
return () => {
channel.close();
};
});
return {
subscribe,
set(value) {
sendMessage('set', value);
set(value);
},
update(callback) {
const value = update(callback);
sendMessage('set', value);
}
};
}
function makeLocalStorageSharedStore(name) {
function setStorage(value) {
window.localStorage.setItem(name, JSON.stringify(value));
}
function getStorage() {
return JSON.parse(window.localStorage.getItem(name));
}
const { subscribe, set, update } = writable(null, () => {
function handleStorageEvent({ key, newValue }) {
if (key !== name) {
return;
}
set(JSON.parse(newValue));
}
set(getStorage());
window.addEventListener('storage', handleStorageEvent);
return () => window.removeEventListener('storage', handleStorageEvent);
});
return {
subscribe,
set(value) {
setStorage(value);
set(value);
},
update(callback) {
const value = update(callback);
setStorage(value);
}
};
}
export default (name) => {
const id = `svelte-shared-store:${name}`;
const broadcastChannelSupported = typeof BroadcastChannel !== 'undefined';
if (broadcastChannelSupported) {
return makeBroadcastChannelSharedStore(id);
}
return makeLocalStorageSharedStore(id);
};
export const broadcastChannelSharedStore = (name) => makeBroadcastChannelStore(`svelte-shared-store:${name}`);
export const localStorageSharedStore = (name) => makeLocalStorageSharedStore(`svelte-shared-store:${name}`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment