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 });