Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a speed modifier slider #103

Merged
merged 5 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/renderer/src/components/popover/Popover.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import PopoverContent from "./PopoverContent";
import PopoverOverlay from "./PopoverOverlay";
import PopoverTrigger from "./PopoverTrigger";
import { PopoverAnchor } from "./PopoverTrigger";
import "./styles.css";
import {
computePosition,
Expand Down Expand Up @@ -39,10 +40,10 @@ function useProviderValue(props: Props) {
});

const [position, setPosition] = createSignal<ComputePositionReturn | null>(null);
const [triggerRef, _setTriggerRef] = createSignal<HTMLButtonElement | null>(null);
const [triggerRef, _setTriggerRef] = createSignal<HTMLElement | null>(null);
const [contentRef, _setContentRef] = createSignal<HTMLDivElement | null>(null);

const setTriggerRef = (element: HTMLButtonElement) => {
const setTriggerRef = (element: HTMLElement) => {
_setTriggerRef(element);
listenResize();
};
Expand Down Expand Up @@ -119,6 +120,7 @@ export function usePopover(): Context {
}

const Popover = Object.assign(PopoverRoot, {
Anchor: PopoverAnchor,
Content: PopoverContent,
Trigger: PopoverTrigger,
Overlay: PopoverOverlay,
Expand Down
6 changes: 6 additions & 0 deletions src/renderer/src/components/popover/PopoverTrigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,10 @@ const PopoverTrigger: Component<Props> = (props) => {
);
};

type PopoverAnchorProps = JSX.IntrinsicElements["div"];
export const PopoverAnchor: Component<PopoverAnchorProps> = (props) => {
const state = usePopover();
return <div ref={state.setTriggerRef} {...props} />;
};

export default PopoverTrigger;
76 changes: 74 additions & 2 deletions src/renderer/src/components/song/song-detail/SongControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import {
song,
setVolume,
volume,
setSpeed,
speed,
handleMuteSong,
} from "../song.utils";
import Button from "@renderer/components/button/Button";
import Slider from "@renderer/components/slider/Slider";
import {
CirclePlusIcon,
GaugeIcon,
PauseIcon,
PlayIcon,
RepeatIcon,
Expand All @@ -23,7 +26,10 @@ import {
Volume2Icon,
VolumeXIcon,
} from "lucide-solid";
import { Component, createEffect, createSignal, Match, Show, Switch } from "solid-js";
import { Component, createEffect, createSignal, Match, Show, Switch, For } from "solid-js";
import Popover from "../../popover/Popover";
import { ParentComponent } from "solid-js";
import { Portal } from "solid-js/web";

// Add a prop to accept the averageColor
type SongControlsProps = {
Expand Down Expand Up @@ -167,14 +173,80 @@ const LeftPart = () => {
);
};

const PREDEFINED_SPEEDS: number[] = [0.25, 0.5, 1, 1.5, 2] as const;
const MIN_SPEED_AMOUNT = PREDEFINED_SPEEDS[0];
const MAX_SPEED_AMOUNT = PREDEFINED_SPEEDS.at(-1);
const RightPart = () => {
const [isPopoverOpen, setisPopoverOpen] = createSignal(false);

return (
<div class="flex flex-1 justify-end">
<div class="flex flex-1 justify-end gap-4">
<Popover
isOpen={isPopoverOpen}
onValueChange={setisPopoverOpen}
placement="top-end"
offset={{
mainAxis: 10,
}}
>
<Popover.Anchor>
<Button
onClick={() => setisPopoverOpen(true)}
size="icon"
variant="ghost"
title="Set speed"
>
<GaugeIcon size={20} />
</Button>
</Popover.Anchor>

<Portal>
<Popover.Overlay />
<Popover.Content class="flex w-fit min-w-48 flex-col rounded-xl ring-stroke ring-1 ring-inset bg-thick-material px-1.5 py-3 backdrop-blur-md shadow-xl">
<p class="font-medium text-sm text-subtext gap-1 px-2">Custom Speed</p>
<div class="flex flex-col px-2">
<Slider
class="flex h-8 flex-grow items-center"
min={MIN_SPEED_AMOUNT}
max={MAX_SPEED_AMOUNT}
value={speed}
onValueChange={setSpeed}
enableWheelSlide
>
<Slider.Track class="h-1 flex-1 rounded bg-thick-material ring-1 ring-stroke">
<Slider.Range class="block h-1 rounded bg-white" />
</Slider.Track>
<Slider.Thumb class="mt-2 block h-4 w-4 rounded-full bg-white" />
</Slider>
<div class="text-xs ">{Math.round(speed() * 100) / 100}x</div>
</div>
<div class="w-full bg-stroke h-px my-2" />

<For each={PREDEFINED_SPEEDS}>
{(amount) => <SpeedOption amount={amount}>{amount}</SpeedOption>}
</For>
</Popover.Content>
</Portal>
</Popover>
<Button size="icon" variant="ghost">
<CirclePlusIcon size={20} />
</Button>
</div>
);
};

type SpeedOptionProps = {
amount: number;
};
const SpeedOption: ParentComponent<SpeedOptionProps> = (props) => {
return (
<button
onClick={() => setSpeed(props.amount)}
class="flex items-center justify-between rounded-md px-2 py-1.5 disabled:opacity-50 disabled:pointer-events-none focus:outline-none hover:bg-surface"
>
{props.children}
</button>
);
};

export default SongControls;
9 changes: 8 additions & 1 deletion src/renderer/src/components/song/song.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ export const setVolume = (newValue: ZeroToOne) => {
_setVolume(newValue);
setValueBeforeMute(undefined);
};
export { volume };

const [speed, _setSpeed] = createSignal<ZeroToOne>(1);
export const setSpeed = (newValue: ZeroToOne) => {
_setSpeed(newValue);
player.playbackRate = newValue;
};
export { volume, speed };

let bgPath: Optional<string>;

Expand Down Expand Up @@ -295,6 +301,7 @@ window.api.listen("queue::songChanged", async (s) => {
setSong(s);
await window.api.request("discord::play", s);
await play();
player.playbackRate = speed();
});

player.addEventListener("ended", async () => {
Expand Down