feat: replace emoji icons with Lucide SVG components

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 02:24:03 -04:00
parent 646f2e511b
commit be27b1b3c6
5 changed files with 62 additions and 39 deletions

33
package-lock.json generated
View File

@@ -1,14 +1,15 @@
{
"name": "gui-video-clipper",
"version": "0.1.3",
"version": "0.2.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "gui-video-clipper",
"version": "0.1.3",
"version": "0.2.0",
"license": "MIT",
"dependencies": {
"@lucide/svelte": "^1.47.0",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-dialog": "^2",
"@tauri-apps/plugin-process": "^2",
@@ -196,7 +197,6 @@
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -207,7 +207,6 @@
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
@@ -218,7 +217,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -228,20 +226,27 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
"integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@lucide/svelte": {
"version": "1.47.0",
"resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-1.47.0.tgz",
"integrity": "sha512-tpuE7JIK9FzYDWsJx6PxHj9ROyCpnDxZfvHu5q5yHGKS2CFNjzSyf1o9/Ypu2A27GLvkPGqZcIMrF6idM+eQZQ==",
"license": "ISC",
"peerDependencies": {
"svelte": "^5"
}
},
"node_modules/@oxc-project/types": {
"version": "0.150.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.150.0.tgz",
@@ -518,7 +523,6 @@
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.13.tgz",
"integrity": "sha512-wgKggnhZVL9Bfx1OaKKTrYY9BFRk6C8UAkQNUcIv1+llzYrIqy+RZm5HPKzn0NpEBvTVhTqB4kQyllZywsRBRQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"acorn": "^8.9.0"
@@ -926,7 +930,6 @@
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
"integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
@@ -991,7 +994,6 @@
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
"integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
"dev": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -1037,7 +1039,6 @@
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
"integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
@@ -1057,7 +1058,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
@@ -1093,7 +1093,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -1186,7 +1185,6 @@
"version": "5.9.4",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.9.4.tgz",
"integrity": "sha512-sPAT4pztbu6586/hrhOnMKS17IJrvg12mXiSPSS3W5qDeN2RGgvZ0diZCm31dBbnevfVmujNO3IM2wrS4Y2Rhg==",
"dev": true,
"license": "MIT"
},
"node_modules/dom-accessibility-api": {
@@ -1220,14 +1218,12 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
"dev": true,
"license": "MIT"
},
"node_modules/esrap": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.3.7.tgz",
"integrity": "sha512-n2nf7fZR3c9yXf0BPEuHuXqT+KW0SJVj4cN5FMEkpCZ3scLjOQWpiccyCxVzCC2q1wubTghuEGzngJY/7Ah0Ow==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
@@ -1359,7 +1355,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.6"
@@ -1677,7 +1672,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
"dev": true,
"license": "MIT"
},
"node_modules/lru-cache": {
@@ -1701,7 +1695,6 @@
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
@@ -1981,7 +1974,6 @@
"version": "5.57.1",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.57.1.tgz",
"integrity": "sha512-Uqj49lWKB+iSSnneuwiYYJ7MZgkB+eXr0LXBhv4uDuAkXqnWmq65Sxflfvp0Lc6MdKjMUxGaeOKWJqz5SNiVIA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.5",
@@ -2452,7 +2444,6 @@
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.5.tgz",
"integrity": "sha512-msJxIvYDYcoNL+PJsu+7qmpDWsYmAxTY+2TNYXXF0hzBzBk0BMecOqDOG/EckUoKCuKwObfbugIl8QpqHDXeFA==",
"dev": true,
"license": "MIT"
}
}

View File

@@ -14,6 +14,7 @@
},
"license": "MIT",
"dependencies": {
"@lucide/svelte": "^1.47.0",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-dialog": "^2",
"@tauri-apps/plugin-process": "^2",

View File

@@ -24,6 +24,12 @@
import { session } from '$lib/stores/videoSession.svelte';
import { listen } from '@tauri-apps/api/event';
import { fly, fade } from 'svelte/transition';
import {
PanelLeft,
PanelBottom,
Info,
Settings,
} from '@lucide/svelte';
let showSetupWizard = $state(true);
let showPreferences = $state(false);
@@ -354,11 +360,11 @@
? 'Move clip list to sidebar'
: 'Move clip list to bottom'}
>
{preferences.clipListPosition === 'bottom' ? '⬒' : '⬓'}
{#if preferences.clipListPosition === 'bottom'}<PanelLeft size={16} />{:else}<PanelBottom size={16} />{/if}
</button>
{/if}
<button class="about-btn" onclick={() => (showAboutDialog = true)} title="About">ℹ</button>
<button class="prefs-btn" onclick={() => (showPreferences = true)} title="Preferences">⚙</button>
<button class="about-btn" onclick={() => (showAboutDialog = true)} title="About"><Info size={16} /></button>
<button class="prefs-btn" onclick={() => (showPreferences = true)} title="Preferences"><Settings size={16} /></button>
</header>
<main class="content" class:player-mode={isPlayerMode} class:layout-left={!isPlayerMode && isLeft} style:--sidebar-width="{preferences.clipListWidth}px">

View File

@@ -17,6 +17,20 @@
getPlaybackRate,
} from '$lib/transport/playback';
import { formatTime } from '$lib/utils/time';
import {
VolumeX,
Volume1,
Volume2,
Rewind,
FastForward,
Pause,
Play,
Scissors,
Captions,
PictureInPicture2,
Maximize,
Minimize,
} from '@lucide/svelte';
let {
visible,
@@ -158,7 +172,7 @@
title={isMuted ? 'Unmute' : 'Mute'}
type="button"
>
{#if isMuted || volume === 0}🔇{:else if volume < 0.5}🔉{:else}🔊{/if}
{#if isMuted || volume === 0}<VolumeX size={16} />{:else if volume < 0.5}<Volume1 size={16} />{:else}<Volume2 size={16} />{/if}
</button>
<input
type="range"
@@ -178,19 +192,19 @@
onclick={() => seekBy(-10)}
title="Skip back 10s"
type="button"
>⏪</button>
><Rewind size={16} /></button>
<button
class="ctrl-btn play-btn"
onclick={togglePlayPause}
title={session.isPlaying ? 'Pause' : 'Play'}
type="button"
>{session.isPlaying ? '❚❚' : '▶'}</button>
>{#if session.isPlaying}<Pause size={18} />{:else}<Play size={18} />{/if}</button>
<button
class="ctrl-btn"
onclick={() => seekBy(10)}
title="Skip forward 10s"
type="button"
>⏩</button>
><FastForward size={16} /></button>
</div>
<!-- Right group: settings -->
@@ -219,7 +233,7 @@
oncontextmenu={handleCCContextMenu}
title={captionsEnabled ? 'Hide captions' : 'Show captions'}
type="button"
>CC</button>
><Captions size={16} /></button>
{/if}
<button
@@ -228,7 +242,7 @@
onclick={handlePiP}
title="Picture-in-Picture"
type="button"
>⧉</button>
><PictureInPicture2 size={16} /></button>
<button
class="ctrl-btn"
@@ -236,7 +250,7 @@
onclick={handleFullscreen}
title={fullscreenActive ? 'Exit fullscreen' : 'Fullscreen'}
type="button"
>{fullscreenActive ? '⤓' : '⛶'}</button>
>{#if fullscreenActive}<Minimize size={16} />{:else}<Maximize size={16} />{/if}</button>
</div>
</div>

View File

@@ -14,6 +14,17 @@
getMuted,
type TransportKeyAction,
} from '$lib/transport/playback';
import {
ChevronFirst,
ChevronLast,
SkipBack,
SkipForward,
Pause,
Play,
VolumeX,
Volume1,
Volume2,
} from '@lucide/svelte';
let hasKeyframes = $derived(session.keyframePositions.length > 0);
@@ -50,15 +61,15 @@
title="Previous keyframe (Shift+,)"
type="button"
>
◄K
<ChevronFirst size={16} />
</button>
<button onclick={() => seekBy(-5)} title="Seek back 5s (←)" type="button">-5s</button>
<button onclick={() => seekBy(-1)} title="Seek back 1s (Shift+←)" type="button">-1s</button>
<button onclick={() => stepFrame(-1)} title="Previous frame (,)" type="button">◄|</button>
<button onclick={() => stepFrame(-1)} title="Previous frame (,)" type="button"><SkipBack size={16} /></button>
<button onclick={togglePlayPause} title="Play/Pause (Space / K)" type="button">
{session.isPlaying ? '❚❚' : '▶'}
{#if session.isPlaying}<Pause size={16} />{:else}<Play size={16} />{/if}
</button>
<button onclick={() => stepFrame(1)} title="Next frame (.)" type="button">|►</button>
<button onclick={() => stepFrame(1)} title="Next frame (.)" type="button"><SkipForward size={16} /></button>
<button onclick={() => seekBy(1)} title="Seek forward 1s (Shift+→)" type="button">+1s</button>
<button onclick={() => seekBy(5)} title="Seek forward 5s (→)" type="button">+5s</button>
<button
@@ -67,7 +78,7 @@
title="Next keyframe (Shift+.)"
type="button"
>
K►
<ChevronLast size={16} />
</button>
</div>
@@ -85,11 +96,11 @@
type="button"
>
{#if isMuted || volume === 0}
🔇
<VolumeX size={14} />
{:else if volume < 0.5}
🔉
<Volume1 size={14} />
{:else}
🔊
<Volume2 size={14} />
{/if}
</button>
<input