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

View File

@ -14,9 +14,9 @@ import {
import { useMemo } from 'react';
import * as tunes from '../tunes.mjs';
import { useStore } from '@nanostores/react';
import { getMetadata } from '../../metadata_parser';
import { useExamplePatterns } from '../useExamplePatterns';
function classNames(...classes) {
return classes.filter(Boolean).join(' ');
@ -90,27 +90,21 @@ function PatternButtons({ patterns, activePattern, onClick, viewingPattern, star
}
export function PatternsTab({ context }) {
const { userPatterns } = useSettings();
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 updateCodeWindow = (id, code, reset = false) => {
context.handleUpdate(id, code, reset);
const { userPatterns } = useSettings();
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;
@ -151,7 +145,7 @@ export function PatternsTab({ context }) {
className="hover:opacity-50"
onClick={() => {
const { id, data } = userPattern.delete(viewingPattern);
updateCodeWindow(id, data.code);
updateCodeWindow(id, { ...data, collection: userPattern.source });
}}
title="Delete"
>
@ -162,7 +156,7 @@ export function PatternsTab({ context }) {
</div>
)}
<PatternButtons
onClick={(id) => updateCodeWindow(id, userPatterns[id]?.code, false)}
onClick={(id) => updateCodeWindow(id, { ...userPatterns[id], collection: userPattern.source }, false)}
patterns={userPatterns}
started={context.started}
activePattern={activePattern}
@ -202,15 +196,15 @@ export function PatternsTab({ context }) {
</button>
</div>
</section>
{Array.from(otherPatterns.keys()).map((key) => {
const patterns = otherPatterns.get(key);
{Array.from(collections.keys()).map((collection) => {
const patterns = collections.get(collection);
return (
<section key={key}>
<h2 className="text-xl mb-2">{key}</h2>
<section key={collection}>
<h2 className="text-xl mb-2">{collection}</h2>
<div className="font-mono text-sm">
<PatternButtons
onClick={(id) => updateCodeWindow(id, patterns[id]?.code, true)}
onClick={(id) => updateCodeWindow(id, { ...patterns[id], collection }, true)}
started={context.started}
patterns={patterns}
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() {
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
// reason: https://github.com/tidalcycles/strudel/issues/857
const $activePattern = persistentAtom('activePattern', '', { listen: false });
export function setActivePattern(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 }]));
export const examplePattern = {
source: 'Stock Examples',
getAll() {
return examplePatterns;
},
@ -149,6 +163,8 @@ export const examplePattern = {
// break
export const userPattern = {
source: 'user',
collection: 'user',
getAll() {
const patterns = JSON.parse(settingsMap.get().userPatterns);
return patterns;
@ -164,22 +180,20 @@ export const userPattern = {
create() {
const newID = createPatternID();
const code = defaultCode;
// const meta = getMetadata
const data = { code, created_at: Date.now(), id: newID };
this.update(newID, data);
return { id: newID, data };
const data = { code, created_at: Date.now(), id: newID, collection: this.collection };
return this.update(newID, data);
},
update(id, data) {
const userPatterns = this.getAll();
data = { ...data, id, collection: this.collection };
setUserPatterns({ ...userPatterns, [id]: data });
return { id, data };
},
duplicate(id) {
const examplePatternData = examplePattern.getPatternData(id);
const data = examplePatternData != null ? examplePatternData : this.getPatternData(id);
const newID = getNextCloneID(id);
this.update(newID, data);
return { id: newID, data };
return this.update(newID, data);
},
clearAll() {
if (!confirm(`This will delete all your patterns. Are you really sure?`)) {
@ -193,7 +207,8 @@ export const userPattern = {
}
// setViewingPattern(null);
setActivePattern(null);
return { id: null, data: { code: defaultCode } };
return { id: null, data: { code: defaultCode, id: null, collection: this.collection } };
},
delete(id) {
const userPatterns = this.getAll();