mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 21:58:31 +00:00
fixing edge cases...
This commit is contained in:
parent
45df7bfea3
commit
7adfe6f2df
@ -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 = () => {
|
||||
|
||||
@ -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}
|
||||
|
||||
34
website/src/repl/useExamplePatterns.jsx
Normal file
34
website/src/repl/useExamplePatterns.jsx
Normal 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 };
|
||||
};
|
||||
@ -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();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user