Skip to content

Commit a474d9a

Browse files
committed
Refactor changes from Site UI
1 parent e8a2443 commit a474d9a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1458
-1167
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ coverage
1111

1212
# Transpiled files
1313
build/
14+
dist/
1415
main/
1516
out/
1617
.next/

package-lock.json

+6-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
"vitest": "^1.6.0"
9191
},
9292
"dependencies": {
93-
"@studiorack/core": "^2.0.15",
93+
"@studiorack/core": "^2.0.16",
9494
"electron-is-dev": "^2.0.0",
9595
"electron-next": "^3.1.5",
9696
"fix-path": "^3.0.0",
@@ -99,7 +99,8 @@
9999
"react": "^18.3.1",
100100
"react-dom": "^18.3.1",
101101
"remark": "^15.0.1",
102-
"remark-html": "^16.0.1"
102+
"remark-html": "^16.0.1",
103+
"slugify": "^1.6.6"
103104
},
104105
"overrides": {
105106
"path-to-regexp": "^8.1.0"

renderer/components/audio.tsx

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { useState } from 'react';
2+
import { getBasePath } from '../lib/path';
3+
import styles from '../styles/components/audio.module.css';
4+
import { PluginFile } from '@studiorack/core';
5+
6+
type AudioProps = {
7+
file: PluginFile;
8+
};
9+
10+
const Audio = ({ file }: AudioProps) => {
11+
const [isPlaying, setIsPlaying] = useState(false);
12+
13+
const play = () => {
14+
const el = document.getElementById('audio') as HTMLAudioElement;
15+
if (el.paused) {
16+
el.removeEventListener('ended', ended);
17+
el.addEventListener('ended', ended);
18+
el.currentTime = 0;
19+
el.play();
20+
setIsPlaying(true);
21+
}
22+
};
23+
24+
const pause = () => {
25+
const el = document.getElementById('audio') as HTMLAudioElement;
26+
if (!el.paused) {
27+
el.pause();
28+
setIsPlaying(false);
29+
}
30+
};
31+
32+
const ended = () => {
33+
setIsPlaying(false);
34+
};
35+
36+
return (
37+
<div>
38+
{isPlaying ? (
39+
<img className={styles.audio} src={`${getBasePath()}/images/icon-pause.svg`} alt="Pause" onClick={pause} />
40+
) : (
41+
<img className={styles.audio} src={`${getBasePath()}/images/icon-play.svg`} alt="Play" onClick={play} />
42+
)}
43+
<audio src={file.url} id="audio">
44+
Your browser does not support the audio element.
45+
</audio>
46+
</div>
47+
);
48+
};
49+
50+
export default Audio;

renderer/components/card.tsx

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import styles from '../styles/components/card.module.css';
2+
import Link from 'next/link';
3+
import { getBasePath } from '../lib/path';
4+
import { imageError } from '../lib/image';
5+
import { pluginFileUrl } from '@studiorack/core';
6+
7+
type CardProps = {
8+
section: string;
9+
plugin: any;
10+
pluginIndex: number;
11+
};
12+
13+
const Card = ({ section, plugin, pluginIndex }: CardProps) => (
14+
<Link href={`/${section}/[userId]/[pluginId]`} as={`/${section}/${plugin.id}`} className={styles.cardLink}>
15+
<div className={styles.card}>
16+
<div className={styles.cardDetails}>
17+
<div className={styles.cardHead}>
18+
<h4 className={styles.cardTitle}>
19+
{plugin.name} <span className={styles.cardVersion}>v{plugin.version}</span>
20+
</h4>
21+
<span className={styles.cardButton}>
22+
<img
23+
className={styles.cardButtonIcon}
24+
src={`${getBasePath()}/images/icon-download.svg`}
25+
alt="Download"
26+
loading="lazy"
27+
/>
28+
</span>
29+
</div>
30+
<ul className={styles.cardTags}>
31+
<img className={styles.cardIcon} src={`${getBasePath()}/images/icon-tag.svg`} alt="Tags" loading="lazy" />
32+
{plugin.tags.map((tag: string, tagIndex: number) => (
33+
<li className={styles.cardTag} key={`${tag}-${tagIndex}-${pluginIndex}`}>
34+
{tag}
35+
{tagIndex !== plugin.tags.length - 1 ? ',' : ''}
36+
</li>
37+
))}
38+
</ul>
39+
</div>
40+
{plugin.files.image ? (
41+
<img
42+
className={styles.cardImage}
43+
src={pluginFileUrl(plugin, 'image')}
44+
alt={plugin.name}
45+
onError={imageError}
46+
loading="lazy"
47+
/>
48+
) : (
49+
''
50+
)}
51+
</div>
52+
</Link>
53+
);
54+
55+
export default Card;

renderer/components/code.tsx

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import styles from '../styles/components/code.module.css';
2+
import { PluginVersion } from '@studiorack/core';
3+
4+
type CodeProps = {
5+
plugin: PluginVersion;
6+
};
7+
8+
const Code = ({ plugin }: CodeProps) => (
9+
<div className={`${styles.code}`}>
10+
<p>
11+
Install via{' '}
12+
<a href="https://www.npmjs.com/package/@studiorack/cli" target="_blank">
13+
StudioRack CLI
14+
</a>
15+
</p>
16+
{plugin.tags.includes('sfz') ? (
17+
<span>
18+
<pre className={styles.codeLine}>studiorack plugin install sfztools/sfizz</pre>
19+
<pre className={styles.codeLine}>studiorack plugin install {plugin.id}</pre>
20+
</span>
21+
) : plugin.tags.includes('sf2') ? (
22+
<span>
23+
<pre className={styles.codeLine}>studiorack plugin install studiorack/juicysf</pre>
24+
<pre className={styles.codeLine}>studiorack plugin install {plugin.id}</pre>
25+
</span>
26+
) : (
27+
<pre className={styles.codeLine}>studiorack plugin install {plugin.id}</pre>
28+
)}
29+
</div>
30+
);
31+
32+
export default Code;

renderer/components/dependency.tsx

+21-31
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,33 @@
1-
import styles from '../styles/plugin.module.css';
21
import { getBasePath } from '../lib/path';
32
import { PluginVersion } from '@studiorack/core';
43

54
type DependencyProps = {
65
plugin: PluginVersion;
7-
message?: boolean;
86
};
97

10-
const Dependency = ({ plugin, message = false }: DependencyProps) => {
8+
const Dependency = ({ plugin }: DependencyProps) => {
119
if (plugin.tags.includes('sfz')) {
12-
if (message) {
13-
return (
14-
<span>
15-
{' '}
16-
(This instrument needs to be loaded into a{' '}
17-
<a href={`${getBasePath()}/instruments/studiorack/sfizz`} target="_blank">
18-
SFZ player
19-
</a>
20-
)
21-
</span>
22-
);
23-
} else {
24-
return <pre className={styles.codeBox}>studiorack plugin install studiorack/sfizz</pre>;
25-
}
10+
return (
11+
<span>
12+
{' '}
13+
(This instrument needs to be loaded into a{' '}
14+
<a href={`${getBasePath()}/instruments/sfztools/sfizz`} target="_blank">
15+
SFZ player
16+
</a>
17+
)
18+
</span>
19+
);
2620
} else if (plugin.tags.includes('sf2')) {
27-
if (message) {
28-
return (
29-
<span>
30-
{' '}
31-
(This instrument needs to be loaded into a{' '}
32-
<a href={`${getBasePath()}/instruments/studiorack/juicysf`} target="_blank">
33-
SoundFont 2 player
34-
</a>
35-
)
36-
</span>
37-
);
38-
} else {
39-
return <pre className={styles.codeBox}>studiorack plugin install studiorack/juicysf</pre>;
40-
}
21+
return (
22+
<span>
23+
{' '}
24+
(This instrument needs to be loaded into a{' '}
25+
<a href={`${getBasePath()}/instruments/studiorack/juicysf`} target="_blank">
26+
SoundFont 2 player
27+
</a>
28+
)
29+
</span>
30+
);
4131
} else {
4232
return <span />;
4333
}

renderer/components/details.tsx

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import styles from '../styles/components/details.module.css';
2+
import { getBasePath } from '../lib/path';
3+
import Crumb from './crumb';
4+
import { pluginGetOrgId, pluginGetPluginId, timeSince } from '../lib/utils';
5+
import { pluginFileUrl, PluginVersion, PluginVersionLocal } from '@studiorack/core';
6+
import Audio from './audio';
7+
import Player from './player';
8+
import Dependency from './dependency';
9+
import Downloads from './download';
10+
import Code from './code';
11+
import { pluginLicense } from '../lib/plugin';
12+
13+
type DetailsProps = {
14+
plugin: PluginVersion | PluginVersionLocal;
15+
type: string;
16+
};
17+
18+
const Details = ({ plugin, type }: DetailsProps) => (
19+
<article>
20+
<div className={styles.header}>
21+
<div className={styles.headerInner2}>
22+
<Crumb items={[type, pluginGetOrgId(plugin), pluginGetPluginId(plugin)]}></Crumb>
23+
</div>
24+
<div className={styles.headerInner}>
25+
<div className={styles.media}>
26+
<div className={styles.imageContainer}>
27+
{plugin.files.audio ? <Audio file={plugin.files.audio} /> : ''}
28+
{plugin.tags.includes('sfz') ? <Player plugin={plugin} /> : ''}
29+
{plugin.files.image ? (
30+
<img className={styles.image} src={pluginFileUrl(plugin, 'image')} alt={plugin.name || ''} />
31+
) : (
32+
''
33+
)}
34+
</div>
35+
</div>
36+
<div className={styles.details}>
37+
<h3 className={styles.title}>
38+
{plugin.name || ''} <span className={styles.version}>v{plugin.version}</span>
39+
</h3>
40+
<p className={styles.author}>
41+
By{' '}
42+
<a href={plugin.homepage} target="_blank">
43+
{plugin.author}
44+
</a>
45+
</p>
46+
<p>
47+
{plugin.description}
48+
<Dependency plugin={plugin} />
49+
</p>
50+
<div className={styles.metadataList}>
51+
{/* <div className={styles.metadata}><img className={styles.icon} src={`${getBasePath()}/images/icon-filesize.svg`} alt="Filesize" loading="lazy" /> {formatBytes(plugin.files.linux.size)}</div> */}
52+
<div className={styles.metadata}>
53+
<img
54+
className={styles.icon}
55+
src={`${getBasePath()}/images/icon-date.svg`}
56+
alt="Date updated"
57+
loading="lazy"
58+
/>{' '}
59+
{timeSince(plugin.date)} ago
60+
</div>
61+
<div className={styles.metadata}>
62+
<img
63+
className={styles.icon}
64+
src={`${getBasePath()}/images/icon-license.svg`}
65+
alt="License"
66+
loading="lazy"
67+
/>{' '}
68+
{plugin.license ? (
69+
<a href={pluginLicense(plugin.license).url} target="_blank">
70+
{pluginLicense(plugin.license).name}
71+
</a>
72+
) : (
73+
'none'
74+
)}
75+
</div>
76+
<div className={styles.metadata}>
77+
<img className={styles.icon} src={`${getBasePath()}/images/icon-tag.svg`} alt="Tags" loading="lazy" />
78+
<ul className={styles.tags}>
79+
{plugin.tags.map((tag: string, tagIndex: number) => (
80+
<li className={styles.tag} key={`${tag}-${tagIndex}`}>
81+
{tag}
82+
{tagIndex !== plugin.tags.length - 1 ? ',' : ''}
83+
</li>
84+
))}
85+
</ul>
86+
</div>
87+
<div className={styles.metadataFooter}>
88+
<a href={plugin.homepage} target="_blank">
89+
<button className="button button-clear">View source</button>
90+
</a>
91+
</div>
92+
</div>
93+
</div>
94+
</div>
95+
</div>
96+
<div id="sfzPlayer"></div>
97+
<div className={styles.options}>
98+
<div className={styles.row}>
99+
<Downloads plugin={plugin} />
100+
<Code plugin={plugin} />
101+
</div>
102+
</div>
103+
</article>
104+
);
105+
106+
export default Details;

0 commit comments

Comments
 (0)