mirror of
https://github.com/eliasstepanik/strudel.git
synced 2026-01-11 21:58:37 +00:00
integrate public patterns into patterns tab
This commit is contained in:
parent
1ede99f71e
commit
204c964050
@ -1,53 +1,43 @@
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import type { Database, Tables } from '../../database.types';
|
||||
import type { Tables } from '../../database.types';
|
||||
import { getMetadata } from '../metadata_parser';
|
||||
import { loadFeaturedPatterns, loadPublicPatterns } from '../repl/util.mjs';
|
||||
|
||||
function PatternLink({ pattern }: { pattern: Tables<'code'> }) {
|
||||
export function PatternLabel({ pattern }: { pattern: Tables<'code'> }) {
|
||||
const meta = useMemo(() => getMetadata(pattern.code), [pattern]);
|
||||
// console.log('meta', meta);
|
||||
return (
|
||||
<a href={`/?${pattern.hash}`} target="_blank">
|
||||
<>
|
||||
{pattern.id}. {meta.title || pattern.hash} by {meta.by.join(',') || 'Anonymous'}
|
||||
</a>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function SharedPatterns() {
|
||||
export const usePublicPatterns = () => {
|
||||
const [publicPatterns, setPublicPatterns] = useState<Tables<'code'>[] | null>([]);
|
||||
const [featuredPatterns, setFeaturedPatterns] = useState<Tables<'code'>[] | null>([]);
|
||||
const init = useCallback(async () => {
|
||||
const supabase = createClient<Database>(
|
||||
'https://pidxdsxphlhzjnzmifth.supabase.co',
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBpZHhkc3hwaGxoempuem1pZnRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NTYyMzA1NTYsImV4cCI6MTk3MTgwNjU1Nn0.bqlw7802fsWRnqU5BLYtmXk_k-D1VFmbkHMywWc15NM',
|
||||
);
|
||||
const { data: _publicPatterns } = await supabase
|
||||
.from('code')
|
||||
.select()
|
||||
.eq('public', true)
|
||||
.limit(20)
|
||||
.order('id', { ascending: false });
|
||||
const { data: _featuredPatterns } = await supabase
|
||||
.from('code')
|
||||
.select()
|
||||
.eq('featured', true)
|
||||
.limit(20)
|
||||
.order('id', { ascending: false });
|
||||
const { data: _publicPatterns } = await loadPublicPatterns();
|
||||
const { data: _featuredPatterns } = await loadFeaturedPatterns();
|
||||
setPublicPatterns(_publicPatterns);
|
||||
setFeaturedPatterns(_featuredPatterns);
|
||||
/* console.log('public', publicPatterns);
|
||||
console.log('featured', featuredPatterns); */
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
init();
|
||||
}, [useCallback]);
|
||||
return { publicPatterns, featuredPatterns };
|
||||
};
|
||||
|
||||
export function SharedPatterns() {
|
||||
const { publicPatterns, featuredPatterns } = usePublicPatterns();
|
||||
return (
|
||||
<div>
|
||||
<h2 className="">Featured</h2>
|
||||
<section>
|
||||
{featuredPatterns?.map((pattern, i) => (
|
||||
<div key={i}>
|
||||
<PatternLink pattern={pattern} />
|
||||
<a href={`/?${pattern.hash}`} target="_blank">
|
||||
<PatternLabel pattern={pattern} />
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</section>
|
||||
@ -55,7 +45,9 @@ export function SharedPatterns() {
|
||||
<section>
|
||||
{publicPatterns?.map((pattern, i) => (
|
||||
<div key={i}>
|
||||
<PatternLink pattern={pattern} />
|
||||
<a href={`/?${pattern.hash}`} target="_blank">
|
||||
<PatternLabel pattern={pattern} />
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</section>
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { DocumentDuplicateIcon, PencilSquareIcon, TrashIcon } from '@heroicons/react/20/solid';
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
$featuredPatterns,
|
||||
$publicPatterns,
|
||||
clearUserPatterns,
|
||||
deleteActivePattern,
|
||||
duplicateActivePattern,
|
||||
@ -14,6 +16,8 @@ import {
|
||||
useSettings,
|
||||
} from '../../settings.mjs';
|
||||
import * as tunes from '../tunes.mjs';
|
||||
import { PatternLabel } from '../../components/SharedPatterns';
|
||||
import { useStore } from '@nanostores/react';
|
||||
|
||||
function classNames(...classes) {
|
||||
return classes.filter(Boolean).join(' ');
|
||||
@ -22,6 +26,8 @@ function classNames(...classes) {
|
||||
export function PatternsTab({ context }) {
|
||||
const { userPatterns } = useSettings();
|
||||
const activePattern = useActivePattern();
|
||||
const featuredPatterns = useStore($featuredPatterns);
|
||||
const publicPatterns = useStore($publicPatterns);
|
||||
const isExample = useMemo(() => activePattern && !!tunes[activePattern], [activePattern]);
|
||||
return (
|
||||
<div className="px-4 w-full dark:text-white text-stone-900 space-y-4 pb-4">
|
||||
@ -94,8 +100,52 @@ export function PatternsTab({ context }) {
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
{featuredPatterns && (
|
||||
<section>
|
||||
<h2 className="text-xl mb-2">Featured Patterns</h2>
|
||||
<div className="font-mono text-sm">
|
||||
{featuredPatterns.map((pattern) => (
|
||||
<a
|
||||
key={pattern.id}
|
||||
className={classNames(
|
||||
'mr-4 hover:opacity-50 cursor-pointer block',
|
||||
pattern.hash === activePattern ? 'outline outline-1' : '',
|
||||
)}
|
||||
onClick={() => {
|
||||
setActivePattern(pattern.hash);
|
||||
context.handleUpdate(pattern.code, true);
|
||||
}}
|
||||
>
|
||||
<PatternLabel pattern={pattern} />
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
{publicPatterns && (
|
||||
<section>
|
||||
<h2 className="text-xl mb-2">Last Creations</h2>
|
||||
<div className="font-mono text-sm">
|
||||
{publicPatterns.map((pattern) => (
|
||||
<a
|
||||
key={'public-' + pattern.id}
|
||||
className={classNames(
|
||||
'mr-4 hover:opacity-50 cursor-pointer block', // inline-block
|
||||
pattern.hash === activePattern ? 'outline outline-1' : '',
|
||||
)}
|
||||
onClick={() => {
|
||||
setActivePattern(pattern.hash);
|
||||
context.handleUpdate(pattern.code, true);
|
||||
}}
|
||||
>
|
||||
<PatternLabel pattern={pattern} />
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
<section>
|
||||
<h2 className="text-xl mb-2">Examples</h2>
|
||||
<h2 className="text-xl mb-2">Stock Examples</h2>
|
||||
<div className="font-mono text-sm">
|
||||
{Object.entries(tunes).map(([key, tune]) => (
|
||||
<a
|
||||
|
||||
@ -11,7 +11,7 @@ import { writeText } from '@tauri-apps/api/clipboard';
|
||||
import { createContext } from 'react';
|
||||
|
||||
// Create a single supabase client for interacting with your database
|
||||
const supabase = createClient(
|
||||
export const supabase = createClient(
|
||||
'https://pidxdsxphlhzjnzmifth.supabase.co',
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBpZHhkc3hwaGxoempuem1pZnRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NTYyMzA1NTYsImV4cCI6MTk3MTgwNjU1Nn0.bqlw7802fsWRnqU5BLYtmXk_k-D1VFmbkHMywWc15NM',
|
||||
);
|
||||
@ -150,3 +150,11 @@ export const setAudioDevice = async (id) => {
|
||||
}
|
||||
initializeAudioOutput();
|
||||
};
|
||||
|
||||
export function loadPublicPatterns() {
|
||||
return supabase.from('code').select().eq('public', true).limit(20).order('id', { ascending: false });
|
||||
}
|
||||
|
||||
export function loadFeaturedPatterns() {
|
||||
return supabase.from('code').select().eq('featured', true).limit(20).order('id', { ascending: false });
|
||||
}
|
||||
|
||||
@ -1,8 +1,22 @@
|
||||
import { atom } from 'nanostores';
|
||||
import { persistentMap, persistentAtom } from '@nanostores/persistent';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { register } from '@strudel.cycles/core';
|
||||
import * as tunes from './repl/tunes.mjs';
|
||||
import { logger } from '@strudel.cycles/core';
|
||||
import { loadPublicPatterns, loadFeaturedPatterns } from './repl/util.mjs';
|
||||
|
||||
export let $publicPatterns = atom([]);
|
||||
export let $featuredPatterns = atom([]);
|
||||
|
||||
async function loadDBPatterns() {
|
||||
const { data: publicPatterns } = await loadPublicPatterns();
|
||||
$publicPatterns.set(publicPatterns);
|
||||
const { data: featuredPatterns } = await loadFeaturedPatterns();
|
||||
$featuredPatterns.set(featuredPatterns);
|
||||
}
|
||||
|
||||
loadDBPatterns();
|
||||
|
||||
export const defaultAudioDeviceName = 'System Standard';
|
||||
|
||||
@ -172,12 +186,25 @@ export function updateUserCode(code) {
|
||||
setActivePattern(example);
|
||||
return;
|
||||
}
|
||||
|
||||
const publicPattern = $publicPatterns.get().find((pat) => pat.code === code);
|
||||
if (publicPattern) {
|
||||
setActivePattern(publicPattern.hash);
|
||||
return;
|
||||
}
|
||||
const featuredPattern = $featuredPatterns.get().find((pat) => pat.code === code);
|
||||
if (featuredPattern) {
|
||||
setActivePattern(featuredPattern.hash);
|
||||
return;
|
||||
}
|
||||
if (!activePattern) {
|
||||
// create new user pattern
|
||||
activePattern = newUserPattern();
|
||||
setActivePattern(activePattern);
|
||||
} else if (!!tunes[activePattern] && code !== tunes[activePattern]) {
|
||||
} else if (
|
||||
(!!tunes[activePattern] && code !== tunes[activePattern]) || // fork example tune?
|
||||
$publicPatterns.get().find((p) => p.hash === activePattern) || // fork public pattern?
|
||||
$featuredPatterns.get().find((p) => p.hash === activePattern) // fork featured pattern?
|
||||
) {
|
||||
// fork example
|
||||
activePattern = getNextCloneName(activePattern);
|
||||
setActivePattern(activePattern);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user