mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-25 20:48:27 +00:00
Merge pull request #333 from tidalcycles/embed-route
Embed mode improvements
This commit is contained in:
commit
8ef1ae5202
@ -8127,10 +8127,10 @@ exports[`renders tunes > tune: loungeSponge 1`] = `
|
|||||||
|
|
||||||
exports[`renders tunes > tune: meltingsubmarine 1`] = `
|
exports[`renders tunes > tune: meltingsubmarine 1`] = `
|
||||||
[
|
[
|
||||||
"[ (0/1 → 1/1) ⇝ 3/2 | s:bd speed:0.7519542165100574 ]",
|
"[ (0/1 → 1/1) ⇝ 3/2 | s:bd:5 speed:0.7519542165100574 ]",
|
||||||
"[ (3/4 → 1/1) ⇝ 3/2 | s:sd speed:0.7931522866332671 ]",
|
"[ (3/4 → 1/1) ⇝ 3/2 | s:sd:1 speed:0.7931522866332671 ]",
|
||||||
"[ 3/8 → 3/4 | s:hh speed:0.7285963821098448 ]",
|
"[ 3/8 → 3/4 | s:hh27 speed:0.7285963821098448 ]",
|
||||||
"[ (3/4 → 1/1) ⇝ 9/8 | s:hh speed:0.77531205091027 ]",
|
"[ (3/4 → 1/1) ⇝ 9/8 | s:hh27 speed:0.77531205091027 ]",
|
||||||
"[ (0/1 → 1/1) ⇝ 3/2 | n:33.129885541275144 decay:0.15 sustain:0 s:sawtooth gain:0.4 cutoff:3669.6267869262615 ]",
|
"[ (0/1 → 1/1) ⇝ 3/2 | n:33.129885541275144 decay:0.15 sustain:0 s:sawtooth gain:0.4 cutoff:3669.6267869262615 ]",
|
||||||
"[ (0/1 → 1/1) ⇝ 3/2 | n:33.17988554127514 decay:0.15 sustain:0 s:sawtooth gain:0.4 cutoff:3669.6267869262615 ]",
|
"[ (0/1 → 1/1) ⇝ 3/2 | n:33.17988554127514 decay:0.15 sustain:0 s:sawtooth gain:0.4 cutoff:3669.6267869262615 ]",
|
||||||
"[ (0/1 → 1/1) ⇝ 3/2 | n:55.129885541275144 s:sawtooth gain:0.16 cutoff:500 attack:1 ]",
|
"[ (0/1 → 1/1) ⇝ 3/2 | n:55.129885541275144 s:sawtooth gain:0.16 cutoff:500 attack:1 ]",
|
||||||
|
|||||||
14
website/src/pages/embed.astro
Normal file
14
website/src/pages/embed.astro
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
import HeadCommon from '../components/HeadCommon.astro';
|
||||||
|
import { Repl } from '../repl/Repl.jsx';
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<HeadCommon />
|
||||||
|
<title>Strudel REPL</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<Repl client:only="react" embedded />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import AcademicCapIcon from '@heroicons/react/20/solid/AcademicCapIcon';
|
import AcademicCapIcon from '@heroicons/react/20/solid/AcademicCapIcon';
|
||||||
import CommandLineIcon from '@heroicons/react/20/solid/CommandLineIcon';
|
import ArrowPathIcon from '@heroicons/react/20/solid/ArrowPathIcon';
|
||||||
import LinkIcon from '@heroicons/react/20/solid/LinkIcon';
|
import LinkIcon from '@heroicons/react/20/solid/LinkIcon';
|
||||||
import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon';
|
import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon';
|
||||||
import SparklesIcon from '@heroicons/react/20/solid/SparklesIcon';
|
import SparklesIcon from '@heroicons/react/20/solid/SparklesIcon';
|
||||||
@ -9,10 +9,9 @@ import React, { useContext } from 'react';
|
|||||||
// import { ReplContext } from './Repl';
|
// import { ReplContext } from './Repl';
|
||||||
import './Repl.css';
|
import './Repl.css';
|
||||||
|
|
||||||
const isEmbedded = window.location !== window.parent.location;
|
|
||||||
|
|
||||||
export function Header({ context }) {
|
export function Header({ context }) {
|
||||||
const {
|
const {
|
||||||
|
embedded,
|
||||||
started,
|
started,
|
||||||
pending,
|
pending,
|
||||||
isDirty,
|
isDirty,
|
||||||
@ -25,32 +24,37 @@ export function Header({ context }) {
|
|||||||
isZen,
|
isZen,
|
||||||
setIsZen,
|
setIsZen,
|
||||||
} = context;
|
} = context;
|
||||||
|
const isEmbedded = embedded || window.location !== window.parent.location;
|
||||||
// useContext(ReplContext)
|
// useContext(ReplContext)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
id="header"
|
id="header"
|
||||||
className={cx(
|
className={cx(
|
||||||
'py-1 flex-none w-full md:flex text-black justify-between z-[100] text-lg select-none sticky top-0',
|
'py-1 flex-none w-full text-black justify-between z-[100] text-lg select-none sticky top-0',
|
||||||
!isZen && 'bg-header',
|
!isZen && !isEmbedded && 'bg-header',
|
||||||
|
isEmbedded ? 'flex' : 'md:flex',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="px-4 flex space-x-2 pt-2 md:pt-0 select-none">
|
<div className="px-4 flex space-x-2 md:pt-0 select-none">
|
||||||
{/* <img
|
{/* <img
|
||||||
src={logo}
|
src={logo}
|
||||||
className={cx('Tidal-logo', isEmbedded ? 'w-8 h-8' : 'w-10 h-10', started && 'animate-pulse')} // 'bg-[#ffffff80] rounded-full'
|
className={cx('Tidal-logo', isEmbedded ? 'w-8 h-8' : 'w-10 h-10', started && 'animate-pulse')} // 'bg-[#ffffff80] rounded-full'
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/> */}
|
/> */}
|
||||||
<h1
|
<h1
|
||||||
|
onClick={() => {
|
||||||
|
if (isEmbedded) window.open(window.location.href.replace('embed', ''));
|
||||||
|
}}
|
||||||
className={cx(
|
className={cx(
|
||||||
isEmbedded ? 'text-l' : 'text-xl',
|
isEmbedded ? 'text-l cursor-pointer' : 'text-xl',
|
||||||
// 'bg-clip-text bg-gradient-to-r from-primary to-secondary text-transparent font-bold',
|
// 'bg-clip-text bg-gradient-to-r from-primary to-secondary text-transparent font-bold',
|
||||||
'text-white font-bold flex space-x-2 items-center',
|
'text-white font-bold flex space-x-2 items-center',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={cx('mt-[1px]', started && 'animate-spin', 'cursor-pointer')}
|
className={cx('mt-[1px]', started && 'animate-spin', 'cursor-pointer')}
|
||||||
onClick={() => setIsZen((z) => !z)}
|
onClick={() => !isEmbedded && setIsZen((z) => !z)}
|
||||||
>
|
>
|
||||||
🌀
|
🌀
|
||||||
</div>
|
</div>
|
||||||
@ -65,12 +69,13 @@ export function Header({ context }) {
|
|||||||
<div className="flex max-w-full overflow-auto text-white ">
|
<div className="flex max-w-full overflow-auto text-white ">
|
||||||
<button
|
<button
|
||||||
onClick={handleTogglePlay}
|
onClick={handleTogglePlay}
|
||||||
|
title={started ? 'stop' : 'play'}
|
||||||
className={cx(!isEmbedded ? 'p-2' : 'px-2', 'hover:text-tertiary', !started && 'animate-pulse')}
|
className={cx(!isEmbedded ? 'p-2' : 'px-2', 'hover:text-tertiary', !started && 'animate-pulse')}
|
||||||
>
|
>
|
||||||
{!pending ? (
|
{!pending ? (
|
||||||
<span className={cx('flex items-center space-x-1', isEmbedded ? 'w-16' : 'w-16')}>
|
<span className={cx('flex items-center space-x-1', isEmbedded ? '' : 'w-16')}>
|
||||||
{started ? <StopCircleIcon className="w-5 h-5" /> : <PlayCircleIcon className="w-5 h-5" />}
|
{started ? <StopCircleIcon className="w-6 h-6" /> : <PlayCircleIcon className="w-6 h-6" />}
|
||||||
<span>{started ? 'stop' : 'play'}</span>
|
{!isEmbedded && <span>{started ? 'stop' : 'play'}</span>}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<>loading...</>
|
<>loading...</>
|
||||||
@ -78,46 +83,54 @@ export function Header({ context }) {
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleUpdate}
|
onClick={handleUpdate}
|
||||||
|
title="update"
|
||||||
className={cx(
|
className={cx(
|
||||||
'flex items-center space-x-1',
|
'flex items-center space-x-1',
|
||||||
!isEmbedded ? 'p-2' : 'px-2',
|
!isEmbedded ? 'p-2' : 'px-2',
|
||||||
!isDirty || !activeCode ? 'opacity-50' : 'hover:text-tertiary',
|
!isDirty || !activeCode ? 'opacity-50' : 'hover:text-tertiary',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<CommandLineIcon className="w-5 h-5" />
|
{/* <CommandLineIcon className="w-6 h-6" /> */}
|
||||||
<span>update</span>
|
<ArrowPathIcon className="w-6 h-6" />
|
||||||
|
{!isEmbedded && <span>update</span>}
|
||||||
</button>
|
</button>
|
||||||
{!isEmbedded && (
|
{!isEmbedded && (
|
||||||
<button className="hover:text-tertiary p-2 flex items-center space-x-1" onClick={handleShuffle}>
|
<button
|
||||||
<SparklesIcon className="w-5 h-5" />
|
title="shuffle"
|
||||||
|
className="hover:text-tertiary p-2 flex items-center space-x-1"
|
||||||
|
onClick={handleShuffle}
|
||||||
|
>
|
||||||
|
<SparklesIcon className="w-6 h-6" />
|
||||||
<span> shuffle</span>
|
<span> shuffle</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{!isEmbedded && (
|
{!isEmbedded && (
|
||||||
<button
|
<button
|
||||||
|
title="share"
|
||||||
className={cx(
|
className={cx(
|
||||||
'cursor-pointer hover:text-tertiary flex items-center space-x-1',
|
'cursor-pointer hover:text-tertiary flex items-center space-x-1',
|
||||||
!isEmbedded ? 'p-2' : 'px-2',
|
!isEmbedded ? 'p-2' : 'px-2',
|
||||||
)}
|
)}
|
||||||
onClick={handleShare}
|
onClick={handleShare}
|
||||||
>
|
>
|
||||||
<LinkIcon className="w-5 h-5" />
|
<LinkIcon className="w-6 h-6" />
|
||||||
<span>share{lastShared && lastShared === (activeCode || code) ? 'd!' : ''}</span>
|
<span>share{lastShared && lastShared === (activeCode || code) ? 'd!' : ''}</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{!isEmbedded && (
|
{!isEmbedded && (
|
||||||
<a
|
<a
|
||||||
|
title="learn"
|
||||||
href="./learn/getting-started"
|
href="./learn/getting-started"
|
||||||
className={cx('hover:text-tertiary flex items-center space-x-1', !isEmbedded ? 'p-2' : 'px-2')}
|
className={cx('hover:text-tertiary flex items-center space-x-1', !isEmbedded ? 'p-2' : 'px-2')}
|
||||||
>
|
>
|
||||||
<AcademicCapIcon className="w-5 h-5" />
|
<AcademicCapIcon className="w-6 h-6" />
|
||||||
<span>learn</span>
|
<span>learn</span>
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
{isEmbedded && (
|
{/* {isEmbedded && (
|
||||||
<button className={cx('hover:text-tertiary px-2')}>
|
<button className={cx('hover:text-tertiary px-2')}>
|
||||||
<a href={window.location.href} target="_blank" rel="noopener noreferrer" title="Open in REPL">
|
<a href={window.location.href} target="_blank" rel="noopener noreferrer" title="Open in REPL">
|
||||||
🚀 open
|
🚀
|
||||||
</a>
|
</a>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
@ -130,10 +143,10 @@ export function Header({ context }) {
|
|||||||
}}
|
}}
|
||||||
title="Reset"
|
title="Reset"
|
||||||
>
|
>
|
||||||
💔 reset
|
💔
|
||||||
</a>
|
</a>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import { Footer } from './Footer';
|
|||||||
import { Header } from './Header';
|
import { Header } from './Header';
|
||||||
import { prebake } from './prebake.mjs';
|
import { prebake } from './prebake.mjs';
|
||||||
import * as tunes from './tunes.mjs';
|
import * as tunes from './tunes.mjs';
|
||||||
|
import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon';
|
||||||
|
|
||||||
initAudioOnFirstClick();
|
initAudioOnFirstClick();
|
||||||
|
|
||||||
@ -101,7 +102,8 @@ const { code: randomTune, name } = getRandomTune();
|
|||||||
|
|
||||||
export const ReplContext = createContext(null);
|
export const ReplContext = createContext(null);
|
||||||
|
|
||||||
export function Repl() {
|
export function Repl({ embedded = false }) {
|
||||||
|
const isEmbedded = embedded || window.location !== window.parent.location;
|
||||||
const [view, setView] = useState(); // codemirror view
|
const [view, setView] = useState(); // codemirror view
|
||||||
const [lastShared, setLastShared] = useState();
|
const [lastShared, setLastShared] = useState();
|
||||||
const [activeFooter, setActiveFooter] = useState('');
|
const [activeFooter, setActiveFooter] = useState('');
|
||||||
@ -232,6 +234,7 @@ export function Repl() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const context = {
|
const context = {
|
||||||
|
embedded,
|
||||||
started,
|
started,
|
||||||
pending,
|
pending,
|
||||||
isDirty,
|
isDirty,
|
||||||
@ -269,7 +272,16 @@ export function Repl() {
|
|||||||
{error && (
|
{error && (
|
||||||
<div className="text-red-500 p-4 bg-lineblack animate-pulse">{error.message || 'Unknown Error :-/'}</div>
|
<div className="text-red-500 p-4 bg-lineblack animate-pulse">{error.message || 'Unknown Error :-/'}</div>
|
||||||
)}
|
)}
|
||||||
<Footer context={context} />
|
{isEmbedded && !started && (
|
||||||
|
<button
|
||||||
|
onClick={() => handleTogglePlay()}
|
||||||
|
className="text-white text-2xl fixed left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] z-[1000] m-auto p-4 bg-black rounded-md flex items-center space-x-2"
|
||||||
|
>
|
||||||
|
<PlayCircleIcon className="w-6 h-6" />
|
||||||
|
<span>play</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{!isEmbedded && <Footer context={context} />}
|
||||||
</div>
|
</div>
|
||||||
</ReplContext.Provider>
|
</ReplContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -518,13 +518,9 @@ export const festivalOfFingers3 = `// licensed with CC BY-NC-SA 4.0 https://crea
|
|||||||
|
|
||||||
export const meltingsubmarine = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
export const meltingsubmarine = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
// by Felix Roos
|
// by Felix Roos
|
||||||
samples({
|
await samples('github:tidalcycles/Dirt-Samples/master/')
|
||||||
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'],
|
|
||||||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
|
||||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
|
||||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
|
||||||
stack(
|
stack(
|
||||||
s("bd,[~ <sd!3 sd(3,4,2)>],hh(3,4)") // drums
|
s("bd:5,[~ <sd:1!3 sd:1(3,4,2)>],hh27(3,4)") // drums
|
||||||
.speed(perlin.range(.7,.9)) // random sample speed variation
|
.speed(perlin.range(.7,.9)) // random sample speed variation
|
||||||
//.hush()
|
//.hush()
|
||||||
,"<a1 b1*2 a1(3,8) e2>" // bassline
|
,"<a1 b1*2 a1(3,8) e2>" // bassline
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user