mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 13:48:34 +00:00
220 lines
6.2 KiB
JavaScript
220 lines
6.2 KiB
JavaScript
import { atom } from 'nanostores';
|
|
import { useStore } from '@nanostores/react';
|
|
import { logger } from '@strudel/core';
|
|
import { nanoid } from 'nanoid';
|
|
import { settingsMap } from './settings.mjs';
|
|
import { confirmDialog, parseJSON, supabase } from './repl/util.mjs';
|
|
|
|
export let $publicPatterns = atom([]);
|
|
export let $featuredPatterns = atom([]);
|
|
|
|
const patternQueryLimit = 20;
|
|
export const patternFilterName = {
|
|
public: 'latest',
|
|
featured: 'featured',
|
|
user: 'user',
|
|
// stock: 'stock examples',
|
|
};
|
|
|
|
const sessionAtom = (name, initial = undefined) => {
|
|
const storage = typeof sessionStorage !== 'undefined' ? sessionStorage : {};
|
|
const store = atom(typeof storage[name] !== 'undefined' ? storage[name] : initial);
|
|
store.listen((newValue) => {
|
|
if (typeof newValue === 'undefined') {
|
|
delete storage[name];
|
|
} else {
|
|
storage[name] = newValue;
|
|
}
|
|
});
|
|
return store;
|
|
};
|
|
|
|
export let $viewingPatternData = sessionAtom('viewingPatternData', {
|
|
id: '',
|
|
code: '',
|
|
collection: patternFilterName.user,
|
|
created_at: Date.now(),
|
|
});
|
|
|
|
export const getViewingPatternData = () => {
|
|
return parseJSON($viewingPatternData.get());
|
|
};
|
|
export const useViewingPatternData = () => {
|
|
return useStore($viewingPatternData);
|
|
};
|
|
|
|
export const setViewingPatternData = (data) => {
|
|
$viewingPatternData.set(JSON.stringify(data));
|
|
};
|
|
|
|
function parsePageNum(page) {
|
|
return isNaN(page) ? 0 : page;
|
|
}
|
|
export function loadPublicPatterns(page) {
|
|
page = parsePageNum(page);
|
|
const offset = page * patternQueryLimit;
|
|
return supabase
|
|
.from('code_v1')
|
|
.select()
|
|
.eq('public', true)
|
|
.range(offset, offset + patternQueryLimit)
|
|
.order('id', { ascending: false });
|
|
}
|
|
|
|
export function loadFeaturedPatterns(page = 0) {
|
|
page = parsePageNum(page);
|
|
const offset = page * patternQueryLimit;
|
|
return supabase
|
|
.from('code_v1')
|
|
.select()
|
|
.eq('featured', true)
|
|
.range(offset, offset + patternQueryLimit)
|
|
.order('id', { ascending: false });
|
|
}
|
|
|
|
export async function loadAndSetPublicPatterns(page) {
|
|
const p = await loadPublicPatterns(page);
|
|
const data = p?.data;
|
|
const pats = {};
|
|
data?.forEach((data, key) => (pats[data.id ?? key] = data));
|
|
$publicPatterns.set(pats);
|
|
}
|
|
export async function loadAndSetFeaturedPatterns(page) {
|
|
const p = await loadFeaturedPatterns(page);
|
|
const data = p?.data;
|
|
const pats = {};
|
|
data?.forEach((data, key) => (pats[data.id ?? key] = data));
|
|
$featuredPatterns.set(pats);
|
|
}
|
|
|
|
export async function loadDBPatterns() {
|
|
try {
|
|
await loadAndSetPublicPatterns();
|
|
await loadAndSetFeaturedPatterns();
|
|
} catch (err) {
|
|
console.error('error loading patterns', err);
|
|
}
|
|
}
|
|
|
|
// reason: https://github.com/tidalcycles/strudel/issues/857
|
|
const $activePattern = sessionAtom('activePattern', '');
|
|
|
|
export function setActivePattern(key) {
|
|
$activePattern.set(key);
|
|
}
|
|
export function getActivePattern() {
|
|
return $activePattern.get();
|
|
}
|
|
export function useActivePattern() {
|
|
return useStore($activePattern);
|
|
}
|
|
|
|
export const setLatestCode = (code) => settingsMap.setKey('latestCode', code);
|
|
|
|
export const defaultCode = '';
|
|
export const userPattern = {
|
|
collection: patternFilterName.user,
|
|
getAll() {
|
|
const patterns = parseJSON(settingsMap.get().userPatterns);
|
|
return patterns ?? {};
|
|
},
|
|
getPatternData(id) {
|
|
const userPatterns = this.getAll();
|
|
return userPatterns[id];
|
|
},
|
|
exists(id) {
|
|
return this.getPatternData(id) != null;
|
|
},
|
|
isValidID(id) {
|
|
return id != null && id.length > 0;
|
|
},
|
|
|
|
create() {
|
|
const newID = createPatternID();
|
|
const code = defaultCode;
|
|
const data = { code, created_at: Date.now(), id: newID, collection: this.collection };
|
|
return { id: newID, data };
|
|
},
|
|
createAndAddToDB() {
|
|
const newPattern = this.create();
|
|
return this.update(newPattern.id, newPattern.data);
|
|
},
|
|
|
|
update(id, data) {
|
|
const userPatterns = this.getAll();
|
|
data = { ...data, id, collection: this.collection };
|
|
setUserPatterns({ ...userPatterns, [id]: data });
|
|
return { id, data };
|
|
},
|
|
duplicate(data) {
|
|
const newPattern = this.create();
|
|
return this.update(newPattern.id, { ...newPattern.data, code: data.code });
|
|
},
|
|
clearAll() {
|
|
confirmDialog(`This will delete all your patterns. Are you really sure?`).then((r) => {
|
|
if (r == false) {
|
|
return;
|
|
}
|
|
const viewingPatternData = getViewingPatternData();
|
|
setUserPatterns({});
|
|
|
|
if (viewingPatternData.collection !== this.collection) {
|
|
return { id: viewingPatternData.id, data: viewingPatternData };
|
|
}
|
|
setActivePattern(null);
|
|
return this.create();
|
|
});
|
|
},
|
|
delete(id) {
|
|
const userPatterns = this.getAll();
|
|
delete userPatterns[id];
|
|
if (getActivePattern() === id) {
|
|
setActivePattern(null);
|
|
}
|
|
setUserPatterns(userPatterns);
|
|
const viewingPatternData = getViewingPatternData();
|
|
const viewingID = viewingPatternData?.id;
|
|
if (viewingID === id) {
|
|
return { id: null, data: { code: defaultCode } };
|
|
}
|
|
return { id: viewingID, data: userPatterns[viewingID] };
|
|
},
|
|
};
|
|
|
|
function setUserPatterns(obj) {
|
|
return settingsMap.setKey('userPatterns', JSON.stringify(obj));
|
|
}
|
|
|
|
export const createPatternID = () => {
|
|
return nanoid(12);
|
|
};
|
|
|
|
export async function importPatterns(fileList) {
|
|
const files = Array.from(fileList);
|
|
await Promise.all(
|
|
files.map(async (file, i) => {
|
|
const content = await file.text();
|
|
if (file.type === 'application/json') {
|
|
const userPatterns = userPattern.getAll();
|
|
setUserPatterns({ ...userPatterns, ...parseJSON(content) });
|
|
} else if (file.type === 'text/plain') {
|
|
const id = file.name.replace(/\.[^/.]+$/, '');
|
|
userPattern.update(id, { code: content });
|
|
}
|
|
}),
|
|
);
|
|
logger(`import done!`);
|
|
}
|
|
|
|
export async function exportPatterns() {
|
|
const userPatterns = userPattern.getAll();
|
|
const blob = new Blob([JSON.stringify(userPatterns)], { type: 'application/json' });
|
|
const downloadLink = document.createElement('a');
|
|
downloadLink.href = window.URL.createObjectURL(blob);
|
|
const date = new Date().toISOString().split('T')[0];
|
|
downloadLink.download = `strudel_patterns_${date}.json`;
|
|
document.body.appendChild(downloadLink);
|
|
downloadLink.click();
|
|
document.body.removeChild(downloadLink);
|
|
}
|