diff --git a/website/src/repl/panel/PatternsTab.jsx b/website/src/repl/panel/PatternsTab.jsx index 8c66d2ea..cce1275d 100644 --- a/website/src/repl/panel/PatternsTab.jsx +++ b/website/src/repl/panel/PatternsTab.jsx @@ -10,6 +10,7 @@ import { import { useMemo } from 'react'; import { getMetadata } from '../../metadata_parser'; import { useExamplePatterns } from '../useExamplePatterns'; +import { parseJSON } from '../util.mjs'; function classNames(...classes) { return classes.filter(Boolean).join(' '); @@ -42,7 +43,7 @@ function PatternButton({ showOutline, onClick, pattern, showHiglight }) { function PatternButtons({ patterns, activePattern, onClick, started }) { const viewingPatternStore = useViewingPatternData(); - const viewingPatternData = JSON.parse(viewingPatternStore); + const viewingPatternData = parseJSON(viewingPatternStore); const viewingPatternID = viewingPatternData.id; return (
@@ -76,7 +77,7 @@ function ActionButton({ children, onClick, label, labelIsHidden }) { export function PatternsTab({ context }) { const activePattern = useActivePattern(); const viewingPatternStore = useViewingPatternData(); - const viewingPatternData = JSON.parse(viewingPatternStore); + const viewingPatternData = parseJSON(viewingPatternStore); const { userPatterns } = useSettings(); const examplePatterns = useExamplePatterns(); @@ -164,7 +165,7 @@ export function PatternsTab({ context }) {

{collection}

updateCodeWindow({ ...patterns[id], collection }, true)} + onClick={(id) => updateCodeWindow({ ...patterns[id], collection }, false)} started={context.started} patterns={patterns} activePattern={activePattern} diff --git a/website/src/repl/util.mjs b/website/src/repl/util.mjs index 6d9e3087..65fdb4cf 100644 --- a/website/src/repl/util.mjs +++ b/website/src/repl/util.mjs @@ -52,6 +52,15 @@ export async function initCode() { } } +export const parseJSON = (json) => { + json = json != null && json.length ? json : '{}'; + try { + return JSON.parse(json); + } catch { + return '{}'; + } +}; + export function getRandomTune() { const allTunes = Object.entries(stockPatterns); const randomItem = (arr) => arr[Math.floor(Math.random() * arr.length)]; diff --git a/website/src/user_pattern_utils.mjs b/website/src/user_pattern_utils.mjs index 7509e498..6d5c4e3e 100644 --- a/website/src/user_pattern_utils.mjs +++ b/website/src/user_pattern_utils.mjs @@ -4,7 +4,7 @@ import { useStore } from '@nanostores/react'; import { logger } from '@strudel/core'; import { nanoid } from 'nanoid'; import { settingsMap } from './settings.mjs'; -import { supabase } from './repl/util.mjs'; +import { parseJSON, supabase } from './repl/util.mjs'; export let $publicPatterns = atom([]); export let $featuredPatterns = atom([]); @@ -28,7 +28,7 @@ export let $viewingPatternData = persistentAtom( ); export const getViewingPatternData = () => { - return JSON.parse($viewingPatternData.get()); + return parseJSON($viewingPatternData.get()); }; export const useViewingPatternData = () => { return useStore($viewingPatternData); @@ -81,7 +81,7 @@ const defaultCode = ''; export const userPattern = { collection: collectionName.user, getAll() { - const patterns = JSON.parse(settingsMap.get().userPatterns); + const patterns = parseJSON(settingsMap.get().userPatterns); return patterns ?? {}; }, getPatternData(id) { @@ -160,7 +160,7 @@ export async function importPatterns(fileList) { const content = await file.text(); if (file.type === 'application/json') { const userPatterns = userPattern.getAll(); - setUserPatterns({ ...userPatterns, ...JSON.parse(content) }); + setUserPatterns({ ...userPatterns, ...parseJSON(content) }); } else if (file.type === 'text/plain') { const id = file.name.replace(/\.[^/.]+$/, ''); userPattern.update(id, { code: content });