Merge pull request #1203 from tidalcycles/console-colors

colorize console + tweak header
This commit is contained in:
Felix Roos 2024-10-23 23:08:14 +02:00 committed by GitHub
commit 2e72c7f4ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 57 additions and 65 deletions

View File

@ -28,11 +28,10 @@ const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL
<div class="flex overflow-visible items-center grow" style="overflow:visible">
<div class="flex items-center text-2xl space-x-2">
<h1 class="font-bold flex space-x-2 items-baseline text-xl">
<span>🌀</span>
<span class="block rotate-90 text-blue-500">꩜</span>
<div class="flex space-x-2 items-baseline">
<span class="">strudel</span>
<span class="text-sm">DOCS</span>
<a href={`${baseNoTrailing}/`} class="text-sm opacity-25">REPL</a>
<span class="text-sm font-medium">DOCS</span>
</div>
</h1>
</div>

View File

@ -1,8 +1,4 @@
import AcademicCapIcon from '@heroicons/react/20/solid/AcademicCapIcon';
import ArrowPathIcon from '@heroicons/react/20/solid/ArrowPathIcon';
import LinkIcon from '@heroicons/react/20/solid/LinkIcon';
import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon';
import SparklesIcon from '@heroicons/react/20/solid/SparklesIcon';
import StopCircleIcon from '@heroicons/react/20/solid/StopCircleIcon';
import cx from '@src/cx.mjs';
import { useSettings, setIsZen } from '../../settings.mjs';
@ -21,7 +17,7 @@ export function Header({ context, embedded = false }) {
<header
id="header"
className={cx(
'flex-none text-black z-[100] text-lg select-none h-14',
'flex-none text-black z-[100] text-lg select-none h-20 md:h-14',
!isZen && !isEmbedded && 'bg-lineHighlight',
isZen ? 'h-12 w-8 fixed top-0 left-0' : 'sticky top-0 w-full py-1 justify-between',
isEmbedded ? 'flex' : 'md:flex',
@ -41,7 +37,7 @@ export function Header({ context, embedded = false }) {
className={cx(
'mt-[1px]',
started && !isCSSAnimationDisabled && 'animate-spin',
'cursor-pointer',
'cursor-pointer text-blue-500',
isZen && 'fixed top-2 right-4',
)}
onClick={() => {
@ -50,14 +46,14 @@ export function Header({ context, embedded = false }) {
}
}}
>
🌀
<span className="block rotate-90"></span>
</div>
{!isZen && (
<div className={cx(started && !isCSSAnimationDisabled && 'animate-pulse', 'space-x-2')}>
<div className="space-x-2">
<span className="">strudel</span>
<span className="text-sm">REPL</span>
{!isEmbedded && (
<a href={`${baseNoTrailing}/learn`} className="text-sm opacity-25">
<span className="text-sm font-medium">REPL</span>
{!isEmbedded && isButtonRowHidden && (
<a href={`${baseNoTrailing}/learn`} className="text-sm opacity-25 font-medium">
DOCS
</a>
)}
@ -66,7 +62,7 @@ export function Header({ context, embedded = false }) {
</h1>
</div>
{!isZen && !isButtonRowHidden && (
<div className="flex max-w-full overflow-auto text-foreground">
<div className="flex max-w-full overflow-auto text-foreground px-1 md:px-2">
<button
onClick={handleTogglePlay}
title={started ? 'stop' : 'play'}
@ -77,7 +73,7 @@ export function Header({ context, embedded = false }) {
)}
>
{!pending ? (
<span className={cx('flex items-center space-x-1', isEmbedded ? '' : 'w-16')}>
<span className={cx('flex items-center space-x-2')}>
{started ? <StopCircleIcon className="w-6 h-6" /> : <PlayCircleIcon className="w-6 h-6" />}
{!isEmbedded && <span>{started ? 'stop' : 'play'}</span>}
</span>
@ -94,8 +90,6 @@ export function Header({ context, embedded = false }) {
!isDirty || !activeCode ? 'opacity-50' : 'hover:opacity-50',
)}
>
{/* <CommandLineIcon className="w-6 h-6" /> */}
<ArrowPathIcon className="w-6 h-6" />
{!isEmbedded && <span>update</span>}
</button>
{!isEmbedded && (
@ -104,7 +98,6 @@ export function Header({ context, embedded = false }) {
className="hover:opacity-50 p-2 flex items-center space-x-1"
onClick={handleShuffle}
>
<SparklesIcon className="w-6 h-6" />
<span> shuffle</span>
</button>
)}
@ -117,7 +110,6 @@ export function Header({ context, embedded = false }) {
)}
onClick={handleShare}
>
<LinkIcon className="w-6 h-6" />
<span>share</span>
</button>
)}
@ -127,7 +119,6 @@ export function Header({ context, embedded = false }) {
href={`${baseNoTrailing}/workshop/getting-started/`}
className={cx('hover:opacity-50 flex items-center space-x-1', !isEmbedded ? 'p-2' : 'px-2')}
>
<AcademicCapIcon className="w-6 h-6" />
<span>learn</span>
</a>
)}

View File

@ -1,18 +1,48 @@
import { logger } from '@strudel/core';
import useEvent from '@src/useEvent.mjs';
import cx from '@src/cx.mjs';
import { nanoid } from 'nanoid';
import { useCallback, useState } from 'react';
import { useSettings } from '../../../settings.mjs';
export function ConsoleTab({ log }) {
export function ConsoleTab() {
const [log, setLog] = useState([]);
const { fontFamily, fontSize } = useSettings();
useLogger(
useCallback((e) => {
const { message, type, data } = e.detail;
setLog((l) => {
const lastLog = l.length ? l[l.length - 1] : undefined;
const id = nanoid(12);
// if (type === 'loaded-sample' && lastLog.type === 'load-sample' && lastLog.url === data.url) {
if (type === 'loaded-sample') {
// const loadIndex = l.length - 1;
const loadIndex = l.findIndex(({ data: { url }, type }) => type === 'load-sample' && url === data.url);
l[loadIndex] = { message, type, id, data };
} else if (lastLog && lastLog.message === message) {
l = l.slice(0, -1).concat([{ message, type, count: (lastLog.count ?? 1) + 1, id, data }]);
} else {
l = l.concat([{ message, type, id, data }]);
}
return l.slice(-20);
});
}, []),
);
return (
<div id="console-tab" className="break-all px-4 dark:text-white text-stone-900 text-sm py-2">
<pre aria-hidden="true">{`███████╗████████╗██████╗ ██╗ ██╗██████╗ ███████╗██╗
`}</pre>
<div
id="console-tab"
className="break-all px-4 dark:text-white text-stone-900 text-sm py-2 space-y-1"
style={{ fontFamily, fontSize }}
>
{log.map((l, i) => {
const message = linkify(l.message);
const color = l.data?.hap?.value?.color;
return (
<div key={l.id} className={cx(l.type === 'error' && 'text-red-500', l.type === 'highlight' && 'underline')}>
<div
key={l.id}
className={cx(l.type === 'error' && 'text-red-500', l.type === 'highlight' && 'underline')}
style={color ? { color } : {}}
>
<span dangerouslySetInnerHTML={{ __html: message }} />
{l.count ? ` (${l.count})` : ''}
</div>
@ -42,3 +72,7 @@ function linkify(inputText) {
return replacedText;
}
function useLogger(onTrigger) {
useEvent(logger.key, onTrigger);
}

View File

@ -1,8 +1,4 @@
import { logger } from '@strudel/core';
import useEvent from '@src/useEvent.mjs';
import cx from '@src/cx.mjs';
import { nanoid } from 'nanoid';
import { useCallback, useState } from 'react';
import { setPanelPinned, setActiveFooter as setTab, setIsPanelOpened, useSettings } from '../../../settings.mjs';
import { ConsoleTab } from './ConsoleTab';
import { FilesTab } from './FilesTab';
@ -119,33 +115,11 @@ function PanelNav({ children, className, settings, ...props }) {
}
function PanelContent({ context, tab }) {
const [log, setLog] = useState([]);
useLogger(
useCallback((e) => {
const { message, type, data } = e.detail;
setLog((l) => {
const lastLog = l.length ? l[l.length - 1] : undefined;
const id = nanoid(12);
// if (type === 'loaded-sample' && lastLog.type === 'load-sample' && lastLog.url === data.url) {
if (type === 'loaded-sample') {
// const loadIndex = l.length - 1;
const loadIndex = l.findIndex(({ data: { url }, type }) => type === 'load-sample' && url === data.url);
l[loadIndex] = { message, type, id, data };
} else if (lastLog && lastLog.message === message) {
l = l.slice(0, -1).concat([{ message, type, count: (lastLog.count ?? 1) + 1, id, data }]);
} else {
l = l.concat([{ message, type, id, data }]);
}
return l.slice(-20);
});
}, []),
);
switch (tab) {
case tabNames.patterns:
return <PatternsTab context={context} />;
case tabNames.console:
return <ConsoleTab log={log} />;
return <ConsoleTab />;
case tabNames.sounds:
return <SoundsTab />;
case tabNames.reference:
@ -236,7 +210,3 @@ function CloseButton({ onClick }) {
</button>
);
}
function useLogger(onTrigger) {
useEvent(logger.key, onTrigger);
}

View File

@ -6,9 +6,7 @@ const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL
export function WelcomeTab({ context }) {
return (
<div className="prose dark:prose-invert min-w-full pt-2 font-sans pb-8 px-4 ">
<h3>
<span className={cx('animate-spin inline-block select-none')}>🌀</span> welcome
</h3>
<h3> welcome</h3>
<p>
You have found <span className="underline">strudel</span>, a new live coding platform to write dynamic music
pieces in the browser! It is free and open-source and made for beginners and experts alike. To get started:
@ -30,7 +28,7 @@ export function WelcomeTab({ context }) {
</a>{' '}
to ask any questions, give feedback or just say hello.
</p>
<h3>about</h3>
<h3> about</h3>
<p>
strudel is a JavaScript version of{' '}
<a href="https://tidalcycles.org/" target="_blank">