mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-26 04:58:27 +00:00
commit
47a5080352
120
website/database.types.ts
Normal file
120
website/database.types.ts
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
// generated with https://supabase.com/docs/reference/javascript/typescript-support#generating-typescript-types
|
||||||
|
export type Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[];
|
||||||
|
|
||||||
|
export interface Database {
|
||||||
|
public: {
|
||||||
|
Tables: {
|
||||||
|
code: {
|
||||||
|
Row: {
|
||||||
|
code: string | null;
|
||||||
|
created_at: string | null;
|
||||||
|
featured: boolean | null;
|
||||||
|
hash: string | null;
|
||||||
|
id: number;
|
||||||
|
public: boolean | null;
|
||||||
|
};
|
||||||
|
Insert: {
|
||||||
|
code?: string | null;
|
||||||
|
created_at?: string | null;
|
||||||
|
featured?: boolean | null;
|
||||||
|
hash?: string | null;
|
||||||
|
id?: number;
|
||||||
|
public?: boolean | null;
|
||||||
|
};
|
||||||
|
Update: {
|
||||||
|
code?: string | null;
|
||||||
|
created_at?: string | null;
|
||||||
|
featured?: boolean | null;
|
||||||
|
hash?: string | null;
|
||||||
|
id?: number;
|
||||||
|
public?: boolean | null;
|
||||||
|
};
|
||||||
|
Relationships: [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
Views: {
|
||||||
|
[_ in never]: never;
|
||||||
|
};
|
||||||
|
Functions: {
|
||||||
|
[_ in never]: never;
|
||||||
|
};
|
||||||
|
Enums: {
|
||||||
|
[_ in never]: never;
|
||||||
|
};
|
||||||
|
CompositeTypes: {
|
||||||
|
[_ in never]: never;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Tables<
|
||||||
|
PublicTableNameOrOptions extends
|
||||||
|
| keyof (Database['public']['Tables'] & Database['public']['Views'])
|
||||||
|
| { schema: keyof Database },
|
||||||
|
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
|
||||||
|
? keyof (Database[PublicTableNameOrOptions['schema']]['Tables'] &
|
||||||
|
Database[PublicTableNameOrOptions['schema']]['Views'])
|
||||||
|
: never = never,
|
||||||
|
> = PublicTableNameOrOptions extends { schema: keyof Database }
|
||||||
|
? (Database[PublicTableNameOrOptions['schema']]['Tables'] &
|
||||||
|
Database[PublicTableNameOrOptions['schema']]['Views'])[TableName] extends {
|
||||||
|
Row: infer R;
|
||||||
|
}
|
||||||
|
? R
|
||||||
|
: never
|
||||||
|
: PublicTableNameOrOptions extends keyof (Database['public']['Tables'] & Database['public']['Views'])
|
||||||
|
? (Database['public']['Tables'] & Database['public']['Views'])[PublicTableNameOrOptions] extends {
|
||||||
|
Row: infer R;
|
||||||
|
}
|
||||||
|
? R
|
||||||
|
: never
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export type TablesInsert<
|
||||||
|
PublicTableNameOrOptions extends keyof Database['public']['Tables'] | { schema: keyof Database },
|
||||||
|
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
|
||||||
|
? keyof Database[PublicTableNameOrOptions['schema']]['Tables']
|
||||||
|
: never = never,
|
||||||
|
> = PublicTableNameOrOptions extends { schema: keyof Database }
|
||||||
|
? Database[PublicTableNameOrOptions['schema']]['Tables'][TableName] extends {
|
||||||
|
Insert: infer I;
|
||||||
|
}
|
||||||
|
? I
|
||||||
|
: never
|
||||||
|
: PublicTableNameOrOptions extends keyof Database['public']['Tables']
|
||||||
|
? Database['public']['Tables'][PublicTableNameOrOptions] extends {
|
||||||
|
Insert: infer I;
|
||||||
|
}
|
||||||
|
? I
|
||||||
|
: never
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export type TablesUpdate<
|
||||||
|
PublicTableNameOrOptions extends keyof Database['public']['Tables'] | { schema: keyof Database },
|
||||||
|
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
|
||||||
|
? keyof Database[PublicTableNameOrOptions['schema']]['Tables']
|
||||||
|
: never = never,
|
||||||
|
> = PublicTableNameOrOptions extends { schema: keyof Database }
|
||||||
|
? Database[PublicTableNameOrOptions['schema']]['Tables'][TableName] extends {
|
||||||
|
Update: infer U;
|
||||||
|
}
|
||||||
|
? U
|
||||||
|
: never
|
||||||
|
: PublicTableNameOrOptions extends keyof Database['public']['Tables']
|
||||||
|
? Database['public']['Tables'][PublicTableNameOrOptions] extends {
|
||||||
|
Update: infer U;
|
||||||
|
}
|
||||||
|
? U
|
||||||
|
: never
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export type Enums<
|
||||||
|
PublicEnumNameOrOptions extends keyof Database['public']['Enums'] | { schema: keyof Database },
|
||||||
|
EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database }
|
||||||
|
? keyof Database[PublicEnumNameOrOptions['schema']]['Enums']
|
||||||
|
: never = never,
|
||||||
|
> = PublicEnumNameOrOptions extends { schema: keyof Database }
|
||||||
|
? Database[PublicEnumNameOrOptions['schema']]['Enums'][EnumName]
|
||||||
|
: PublicEnumNameOrOptions extends keyof Database['public']['Enums']
|
||||||
|
? Database['public']['Enums'][PublicEnumNameOrOptions]
|
||||||
|
: never;
|
||||||
@ -1,6 +1,8 @@
|
|||||||
import { DocumentDuplicateIcon, PencilSquareIcon, TrashIcon } from '@heroicons/react/20/solid';
|
import { DocumentDuplicateIcon, PencilSquareIcon, TrashIcon } from '@heroicons/react/20/solid';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import {
|
import {
|
||||||
|
$featuredPatterns,
|
||||||
|
$publicPatterns,
|
||||||
clearUserPatterns,
|
clearUserPatterns,
|
||||||
deleteActivePattern,
|
deleteActivePattern,
|
||||||
duplicateActivePattern,
|
duplicateActivePattern,
|
||||||
@ -14,6 +16,8 @@ import {
|
|||||||
useSettings,
|
useSettings,
|
||||||
} from '../../settings.mjs';
|
} from '../../settings.mjs';
|
||||||
import * as tunes from '../tunes.mjs';
|
import * as tunes from '../tunes.mjs';
|
||||||
|
import { useStore } from '@nanostores/react';
|
||||||
|
import { getMetadata } from '../../metadata_parser';
|
||||||
|
|
||||||
function classNames(...classes) {
|
function classNames(...classes) {
|
||||||
return classes.filter(Boolean).join(' ');
|
return classes.filter(Boolean).join(' ');
|
||||||
@ -22,6 +26,8 @@ function classNames(...classes) {
|
|||||||
export function PatternsTab({ context }) {
|
export function PatternsTab({ context }) {
|
||||||
const { userPatterns } = useSettings();
|
const { userPatterns } = useSettings();
|
||||||
const activePattern = useActivePattern();
|
const activePattern = useActivePattern();
|
||||||
|
const featuredPatterns = useStore($featuredPatterns);
|
||||||
|
const publicPatterns = useStore($publicPatterns);
|
||||||
const isExample = useMemo(() => activePattern && !!tunes[activePattern], [activePattern]);
|
const isExample = useMemo(() => activePattern && !!tunes[activePattern], [activePattern]);
|
||||||
return (
|
return (
|
||||||
<div className="px-4 w-full dark:text-white text-stone-900 space-y-4 pb-4">
|
<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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</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>
|
<section>
|
||||||
<h2 className="text-xl mb-2">Examples</h2>
|
<h2 className="text-xl mb-2">Stock Examples</h2>
|
||||||
<div className="font-mono text-sm">
|
<div className="font-mono text-sm">
|
||||||
{Object.entries(tunes).map(([key, tune]) => (
|
{Object.entries(tunes).map(([key, tune]) => (
|
||||||
<a
|
<a
|
||||||
@ -117,3 +167,12 @@ export function PatternsTab({ context }) {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) {
|
||||||
|
const meta = useMemo(() => getMetadata(pattern.code), [pattern]);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{pattern.id}. {meta.title || pattern.hash} by {meta.by.join(',') || 'Anonymous'}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { writeText } from '@tauri-apps/api/clipboard';
|
|||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
|
|
||||||
// Create a single supabase client for interacting with your database
|
// Create a single supabase client for interacting with your database
|
||||||
const supabase = createClient(
|
export const supabase = createClient(
|
||||||
'https://pidxdsxphlhzjnzmifth.supabase.co',
|
'https://pidxdsxphlhzjnzmifth.supabase.co',
|
||||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBpZHhkc3hwaGxoempuem1pZnRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NTYyMzA1NTYsImV4cCI6MTk3MTgwNjU1Nn0.bqlw7802fsWRnqU5BLYtmXk_k-D1VFmbkHMywWc15NM',
|
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBpZHhkc3hwaGxoempuem1pZnRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NTYyMzA1NTYsImV4cCI6MTk3MTgwNjU1Nn0.bqlw7802fsWRnqU5BLYtmXk_k-D1VFmbkHMywWc15NM',
|
||||||
);
|
);
|
||||||
@ -90,10 +90,13 @@ export async function shareCode(codeToShare) {
|
|||||||
logger(`Link already generated!`, 'error');
|
logger(`Link already generated!`, 'error');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const isPublic = confirm(
|
||||||
|
'Do you want your pattern to be public? If no, press cancel and you will get just a private link.',
|
||||||
|
);
|
||||||
// generate uuid in the browser
|
// generate uuid in the browser
|
||||||
const hash = nanoid(12);
|
const hash = nanoid(12);
|
||||||
const shareUrl = window.location.origin + window.location.pathname + '?' + hash;
|
const shareUrl = window.location.origin + window.location.pathname + '?' + hash;
|
||||||
const { data, error } = await supabase.from('code').insert([{ code: codeToShare, hash }]);
|
const { error } = await supabase.from('code').insert([{ code: codeToShare, hash, ['public']: isPublic }]);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
lastShared = codeToShare;
|
lastShared = codeToShare;
|
||||||
// copy shareUrl to clipboard
|
// copy shareUrl to clipboard
|
||||||
@ -147,3 +150,11 @@ export const setAudioDevice = async (id) => {
|
|||||||
}
|
}
|
||||||
initializeAudioOutput();
|
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 { persistentMap, persistentAtom } from '@nanostores/persistent';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
import { register } from '@strudel.cycles/core';
|
import { register } from '@strudel.cycles/core';
|
||||||
import * as tunes from './repl/tunes.mjs';
|
import * as tunes from './repl/tunes.mjs';
|
||||||
import { logger } from '@strudel.cycles/core';
|
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';
|
export const defaultAudioDeviceName = 'System Standard';
|
||||||
|
|
||||||
@ -172,12 +186,25 @@ export function updateUserCode(code) {
|
|||||||
setActivePattern(example);
|
setActivePattern(example);
|
||||||
return;
|
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) {
|
if (!activePattern) {
|
||||||
// create new user pattern
|
// create new user pattern
|
||||||
activePattern = newUserPattern();
|
activePattern = newUserPattern();
|
||||||
setActivePattern(activePattern);
|
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
|
// fork example
|
||||||
activePattern = getNextCloneName(activePattern);
|
activePattern = getNextCloneName(activePattern);
|
||||||
setActivePattern(activePattern);
|
setActivePattern(activePattern);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user