Skip to content
Open
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
10 changes: 7 additions & 3 deletions src/controls/bar/ControlsBar.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from "react";
import * as Tooltip from "@radix-ui/react-tooltip";
import clsx from "clsx";
import { useVolumeControl } from "../volume/useVolumeControl.js";
import { useFullscreenControl } from "../fullscreen/useFullscreenControl.js";
import { useChannelInfo } from "../info/useChannelInfo.js";
import { useKeyboardControls } from "./useKeyboardControls.js";
Expand All @@ -22,9 +21,12 @@ export default function ControlsBar({
showControls,
clickToPlayPause,
onClickToPlayChange,
volume,
isMuted,
handleVolumeChange,
handleVolumeScroll,
handleMuteToggle,
}) {
const { volume, isMuted, handleVolumeChange, handleMuteToggle } =
useVolumeControl(core);
const { isFullscreen, handleFullscreenToggle } =
useFullscreenControl(videoContainer);
const { username, viewerCount, uptime } = useChannelInfo();
Expand All @@ -45,6 +47,7 @@ export default function ControlsBar({
>
<div
ref={barRef}
onWheel={(event) => event.stopPropagation()}
className={clsx("controls-bar", !shouldShow && "controls-bar--hidden")}
>
<div className="controls-bar__left">
Expand All @@ -57,6 +60,7 @@ export default function ControlsBar({
volume={volume}
isMuted={isMuted}
onVolumeChange={handleVolumeChange}
onVolumeScroll={handleVolumeScroll}
onMuteToggle={handleMuteToggle}
/>
</div>
Expand Down
14 changes: 14 additions & 0 deletions src/controls/container/Container.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import ControlsBar from "../bar/ControlsBar.jsx";
import { useControlsVisibility } from "./useControlsVisibility.js";
import { usePlaybackControl } from "../play/usePlaybackControl.js";
import { usePreferences } from "../usePreferences.js";
import { useVolumeControl } from "../volume/useVolumeControl.js";

export default function Container({ core, videoContainer }) {
const containerRef = useRef(null);
Expand All @@ -13,6 +14,13 @@ export default function Container({ core, videoContainer }) {
);
const { isPlaying, handlePlayPause } = usePlaybackControl(core);
const { clickToPlayPause, setClickToPlayPause } = usePreferences();
const {
volume,
isMuted,
handleVolumeChange,
handleVolumeScroll,
handleMuteToggle,
} = useVolumeControl(core);

const handleContainerClick = (e) => {
const isInControlsBar = barRef.current?.contains(e.target);
Expand All @@ -29,6 +37,7 @@ export default function Container({ core, videoContainer }) {
ref={containerRef}
className="kickstiny-container"
onClick={handleContainerClick}
onWheel={handleVolumeScroll}
>
<ControlsBar
core={core}
Expand All @@ -40,6 +49,11 @@ export default function Container({ core, videoContainer }) {
showControls={showControls}
clickToPlayPause={clickToPlayPause}
onClickToPlayChange={setClickToPlayPause}
volume={volume}
isMuted={isMuted}
handleVolumeChange={handleVolumeChange}
handleVolumeScroll={handleVolumeScroll}
handleMuteToggle={handleMuteToggle}
/>
</div>
);
Expand Down
2 changes: 2 additions & 0 deletions src/controls/volume/VolumeControls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default function VolumeControls({
volume,
isMuted,
onVolumeChange,
onVolumeScroll,
onMuteToggle,
}) {
const label = isMuted ? "Unmute" : "Mute";
Expand Down Expand Up @@ -36,6 +37,7 @@ export default function VolumeControls({
className="slider"
value={[volume]}
onValueChange={([value]) => onVolumeChange(value)}
onWheel={onVolumeScroll}
min={0}
max={100}
step={1}
Expand Down
22 changes: 21 additions & 1 deletion src/controls/volume/useVolumeControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,32 @@ export function useVolumeControl(core) {
const handleVolumeChange = useCallback(
(newVolume) => {
const clampedVolume = clampVolume(newVolume);
if (clampedVolume === volume) return;
setVolume(clampedVolume);
setSavedVolume(clampedVolume);
core.setVolume(normalizeVolume(clampedVolume));
core.setMuted(clampedVolume === 0);
setIsMuted(clampedVolume === 0);
},
[core, setSavedVolume],
[core, volume, setSavedVolume],
);

const handleVolumeScroll = useCallback(
(event) => {
event.preventDefault();

if (event.deltaY === 0) return;

// Step 1 unit if trackpad, 5 units if mouse wheel
const isLikelyTrackpad =
!Number.isInteger(event.deltaY) ||
(event.deltaMode === 0 && Math.abs(event.deltaY) < 10);
const stepSize = isLikelyTrackpad ? 1 : 5;
const direction = Math.sign(-event.deltaY);

handleVolumeChange(volume + direction * stepSize);
},
[volume, handleVolumeChange],
);

const handleMuteToggle = useCallback(() => {
Expand Down Expand Up @@ -82,6 +101,7 @@ export function useVolumeControl(core) {
volume,
isMuted,
handleVolumeChange,
handleVolumeScroll,
handleMuteToggle,
};
}
Loading