fixing edge cases...

This commit is contained in:
Jade (Rose) Rowland 2024-01-17 09:45:00 -05:00
parent 45df7bfea3
commit 7adfe6f2df
4 changed files with 96 additions and 49 deletions

View file

@ -22,7 +22,6 @@ import {
setViewingPattern, setViewingPattern,
createPatternID, createPatternID,
userPattern, userPattern,
examplePattern,
getNextCloneID, getNextCloneID,
} from '../settings.mjs'; } from '../settings.mjs';
import { Header } from './Header'; import { Header } from './Header';
@ -33,9 +32,12 @@ import { prebake } from './prebake.mjs';
import { getRandomTune, initCode, loadModules, shareCode, ReplContext } from './util.mjs'; import { getRandomTune, initCode, loadModules, shareCode, ReplContext } from './util.mjs';
import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon'; import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon';
import './Repl.css'; import './Repl.css';
import { useExamplePatterns } from './useExamplePatterns';
const { code: randomTune, name } = getRandomTune(); const { code: randomTune, name } = getRandomTune();
//
const { latestCode } = settingsMap.get(); const { latestCode } = settingsMap.get();
let modulesLoading, presets, drawContext, clearCanvas, isIframe; let modulesLoading, presets, drawContext, clearCanvas, isIframe;
@ -47,10 +49,12 @@ if (typeof window !== 'undefined') {
clearCanvas = () => drawContext.clearRect(0, 0, drawContext.canvas.height, drawContext.canvas.width); clearCanvas = () => drawContext.clearRect(0, 0, drawContext.canvas.height, drawContext.canvas.width);
isIframe = window.location !== window.parent.location; isIframe = window.location !== window.parent.location;
} }
let viewingPatternData = { id: '', code: null, collection: userPattern.source };
export function Repl({ embedded = false }) { export function Repl({ embedded = false }) {
const isEmbedded = embedded || isIframe; const isEmbedded = embedded || isIframe;
const { panelPosition, isZen } = useSettings(); const { panelPosition, isZen } = useSettings();
const init = useCallback(() => { const init = useCallback(() => {
const drawTime = [-2, 2]; const drawTime = [-2, 2];
const drawContext = getDrawContext(); const drawContext = getDrawContext();
@ -75,30 +79,29 @@ export function Repl({ embedded = false }) {
onUpdateState: (state) => { onUpdateState: (state) => {
setReplState({ ...state }); setReplState({ ...state });
}, },
afterEval: ({ code }) => { afterEval: (all) => {
const { code } = all;
setLatestCode(code); setLatestCode(code);
const data = { code };
let id = getViewingPattern();
window.location.hash = '#' + code2hash(code); window.location.hash = '#' + code2hash(code);
const examplePatternData = examplePattern.getPatternData(id); const data = { ...viewingPatternData, code };
const isExamplePattern = examplePatternData != null; let id = getViewingPattern();
const isExamplePattern = viewingPatternData.collection != userPattern.source;
if (isExamplePattern) { if (isExamplePattern) {
const codeHasChanged = code !== examplePatternData.code; const codeHasChanged = code !== viewingPatternData.code;
if (codeHasChanged) { if (codeHasChanged) {
// fork example // fork example
id = getNextCloneID(id); id = getNextCloneID(id);
setViewingPattern(id); setViewingPattern(id);
userPattern.update(id, data); viewingPatternData = userPattern.update(id, data).data;
} }
setActivePattern(id);
} else { } else {
id = id == null ? createPatternID() : id; id = id == null ? createPatternID() : id;
setActivePattern(id);
setViewingPattern(id); setViewingPattern(id);
userPattern.update(id, data); viewingPatternData = userPattern.update(id, data).data;
} }
setActivePattern(id);
}, },
bgFill: false, bgFill: false,
}); });
@ -172,12 +175,13 @@ export function Repl({ embedded = false }) {
await prebake(); // declare default samples await prebake(); // declare default samples
}; };
const handleUpdate = async (id, code, reset = false) => { const handleUpdate = async (id, data, reset = false) => {
viewingPatternData = data;
if (reset) { if (reset) {
await resetEditor(); await resetEditor();
} }
setViewingPattern(id); setViewingPattern(id);
editorRef.current.setCode(code); editorRef.current.setCode(data.code);
}; };
const handleEvaluate = () => { const handleEvaluate = () => {

View file

@ -14,9 +14,9 @@ import {
import { useMemo } from 'react'; import { useMemo } from 'react';
import * as tunes from '../tunes.mjs';
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { getMetadata } from '../../metadata_parser'; import { getMetadata } from '../../metadata_parser';
import { useExamplePatterns } from '../useExamplePatterns';
function classNames(...classes) { function classNames(...classes) {
return classes.filter(Boolean).join(' '); return classes.filter(Boolean).join(' ');
@ -90,27 +90,21 @@ function PatternButtons({ patterns, activePattern, onClick, viewingPattern, star
} }
export function PatternsTab({ context }) { export function PatternsTab({ context }) {
const { userPatterns } = useSettings();
const activePattern = useActivePattern(); const activePattern = useActivePattern();
const featuredPatterns = useStore($featuredPatterns);
const publicPatterns = useStore($publicPatterns);
// const otherPatterns = [
// {source: 'Stock Examples', patterns: examplePatterns }
// ]
const otherPatterns = useMemo(() => {
const pats = new Map();
pats.set('Featured', featuredPatterns);
pats.set('Last Creations', publicPatterns);
pats.set('Stock Examples', examplePattern.getAll());
return pats;
}, [featuredPatterns, publicPatterns]);
const viewingPattern = useViewingPattern(); const viewingPattern = useViewingPattern();
const updateCodeWindow = (id, code, reset = false) => { const { userPatterns } = useSettings();
context.handleUpdate(id, code, reset); const examplePatterns = useExamplePatterns();
const collections = examplePatterns.collections;
const examplesData = examplePatterns.patterns;
const updateCodeWindow = (id, data, reset = false) => {
context.handleUpdate(id, data, reset);
// if (patternSource === userPattern.source) {
// } else {
// const source = otherPatterns.get(patternSource);
// const data = source[id];
// }
}; };
const isUserPattern = userPatterns[viewingPattern] != null; const isUserPattern = userPatterns[viewingPattern] != null;
@ -151,7 +145,7 @@ export function PatternsTab({ context }) {
className="hover:opacity-50" className="hover:opacity-50"
onClick={() => { onClick={() => {
const { id, data } = userPattern.delete(viewingPattern); const { id, data } = userPattern.delete(viewingPattern);
updateCodeWindow(id, data.code); updateCodeWindow(id, { ...data, collection: userPattern.source });
}} }}
title="Delete" title="Delete"
> >
@ -162,7 +156,7 @@ export function PatternsTab({ context }) {
</div> </div>
)} )}
<PatternButtons <PatternButtons
onClick={(id) => updateCodeWindow(id, userPatterns[id]?.code, false)} onClick={(id) => updateCodeWindow(id, { ...userPatterns[id], collection: userPattern.source }, false)}
patterns={userPatterns} patterns={userPatterns}
started={context.started} started={context.started}
activePattern={activePattern} activePattern={activePattern}
@ -202,15 +196,15 @@ export function PatternsTab({ context }) {
</button> </button>
</div> </div>
</section> </section>
{Array.from(otherPatterns.keys()).map((key) => { {Array.from(collections.keys()).map((collection) => {
const patterns = otherPatterns.get(key); const patterns = collections.get(collection);
return ( return (
<section key={key}> <section key={collection}>
<h2 className="text-xl mb-2">{key}</h2> <h2 className="text-xl mb-2">{collection}</h2>
<div className="font-mono text-sm"> <div className="font-mono text-sm">
<PatternButtons <PatternButtons
onClick={(id) => updateCodeWindow(id, patterns[id]?.code, true)} onClick={(id) => updateCodeWindow(id, { ...patterns[id], collection }, true)}
started={context.started} started={context.started}
patterns={patterns} patterns={patterns}
activePattern={activePattern} activePattern={activePattern}

View file

@ -0,0 +1,34 @@
import { examplePattern, $featuredPatterns, $publicPatterns } from '../settings.mjs';
import { useStore } from '@nanostores/react';
import { useCallback, useMemo } from 'react';
export const useExamplePatterns = () => {
const featuredPatterns = useStore($featuredPatterns);
const publicPatterns = useStore($publicPatterns);
const collections = useMemo(() => {
const pats = new Map();
pats.set('Featured', featuredPatterns);
pats.set('Last Creations', publicPatterns);
pats.set(examplePattern.source, examplePattern.getAll());
return pats;
}, [featuredPatterns, publicPatterns]);
const patterns = useMemo(() => {
const allPatterns = Object.assign({}, ...collections.values());
return allPatterns;
}, [collections]);
// const examplePatterns = examplePattern.getAll();
// const collections = new Map();
// collections.set('Featured', featuredPatterns);
// collections.set('Last Creations', publicPatterns);
// collections.set(examplePattern.source, examplePatterns);
// const patterns = {
// ...examplePatterns,
// ...publicPatterns,
// ...examplePatterns,
// };
return { patterns, collections };
};

View file

@ -46,9 +46,22 @@ export function getViewingPattern() {
export function useViewingPattern() { export function useViewingPattern() {
return useStore($viewingPattern); return useStore($viewingPattern);
} }
// const $viewingCollection = persistentAtom('viewingCollection', '', { listen: false });
// export function setViewingCollection(key) {
// $viewingCollection.set(key);
// }
// export function getViewingCollection() {
// return $viewingCollection.get();
// }
// export function useViewingCollection() {
// return useStore($viewingCollection);
// }
// active pattern is separate, because it shouldn't sync state across tabs // active pattern is separate, because it shouldn't sync state across tabs
// reason: https://github.com/tidalcycles/strudel/issues/857 // reason: https://github.com/tidalcycles/strudel/issues/857
const $activePattern = persistentAtom('activePattern', '', { listen: false }); const $activePattern = persistentAtom('activePattern', '', { listen: false });
export function setActivePattern(key) { export function setActivePattern(key) {
$activePattern.set(key); $activePattern.set(key);
} }
@ -135,6 +148,7 @@ export const getNextCloneID = (id) => {
const examplePatterns = Object.fromEntries(Object.entries(tunes).map(([key, code], i) => [i, { id: i, code }])); const examplePatterns = Object.fromEntries(Object.entries(tunes).map(([key, code], i) => [i, { id: i, code }]));
export const examplePattern = { export const examplePattern = {
source: 'Stock Examples',
getAll() { getAll() {
return examplePatterns; return examplePatterns;
}, },
@ -149,6 +163,8 @@ export const examplePattern = {
// break // break
export const userPattern = { export const userPattern = {
source: 'user',
collection: 'user',
getAll() { getAll() {
const patterns = JSON.parse(settingsMap.get().userPatterns); const patterns = JSON.parse(settingsMap.get().userPatterns);
return patterns; return patterns;
@ -164,22 +180,20 @@ export const userPattern = {
create() { create() {
const newID = createPatternID(); const newID = createPatternID();
const code = defaultCode; const code = defaultCode;
const data = { code, created_at: Date.now(), id: newID, collection: this.collection };
// const meta = getMetadata return this.update(newID, data);
const data = { code, created_at: Date.now(), id: newID };
this.update(newID, data);
return { id: newID, data };
}, },
update(id, data) { update(id, data) {
const userPatterns = this.getAll(); const userPatterns = this.getAll();
data = { ...data, id, collection: this.collection };
setUserPatterns({ ...userPatterns, [id]: data }); setUserPatterns({ ...userPatterns, [id]: data });
return { id, data };
}, },
duplicate(id) { duplicate(id) {
const examplePatternData = examplePattern.getPatternData(id); const examplePatternData = examplePattern.getPatternData(id);
const data = examplePatternData != null ? examplePatternData : this.getPatternData(id); const data = examplePatternData != null ? examplePatternData : this.getPatternData(id);
const newID = getNextCloneID(id); const newID = getNextCloneID(id);
this.update(newID, data); return this.update(newID, data);
return { id: newID, data };
}, },
clearAll() { clearAll() {
if (!confirm(`This will delete all your patterns. Are you really sure?`)) { if (!confirm(`This will delete all your patterns. Are you really sure?`)) {
@ -193,7 +207,8 @@ export const userPattern = {
} }
// setViewingPattern(null); // setViewingPattern(null);
setActivePattern(null); setActivePattern(null);
return { id: null, data: { code: defaultCode } };
return { id: null, data: { code: defaultCode, id: null, collection: this.collection } };
}, },
delete(id) { delete(id) {
const userPatterns = this.getAll(); const userPatterns = this.getAll();