Skip to content

Commit

Permalink
feat & fix: desc
Browse files Browse the repository at this point in the history
fix one piece stuff
fix video timeline
refactor video settings
  • Loading branch information
aleganza committed Oct 18, 2024
1 parent 620ef23 commit 68b6eef
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 253 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions src/modules/anilist/anilistApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,13 @@ const MEDIA_DATA: string = `
timeUntilAiring
episode
}
airingSchedule {
edges {
node {
episode
}
}
}
mediaListEntry {
id
mediaId
Expand Down
243 changes: 106 additions & 137 deletions src/renderer/components/player/BottomControls.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Store from 'electron-store';
import { useEffect, useRef, useState } from 'react';

import { formatTime } from '../../../modules/utils';
import { faPlus } from '@fortawesome/free-solid-svg-icons';
import { ButtonMain } from '../Buttons';
Expand All @@ -14,6 +13,8 @@ interface BottomControlsProps {
duration?: number;
buffered?: TimeRanges;
skipEvents?: SkipEvent[];
playVideo: () => void;
pauseVideo: () => void;
onClick?: (event: any) => void;
onDblClick?: (event: any) => void;
}
Expand All @@ -25,122 +26,120 @@ const BottomControls: React.FC<BottomControlsProps> = ({
duration,
buffered,
skipEvents,
playVideo,
pauseVideo,
onClick,
onDblClick,
}) => {
const videoTimelineRef = useRef<HTMLDivElement>(null);

const [isMouseDown, setIsMouseDown] = useState<boolean>(false);
const [isDragging, setIsDragging] = useState(false);
const [progressBarWidth, setProgressBarWidth] = useState('0%');
const [bufferedBarWidth, setBufferedBarWidth] = useState('0%');

const [videoCurrentTime, setVideoCurrentTime] = useState<string>('00:00');
const [videoDuration, setVideoDuration] = useState<string>('00:00');
const [remainingtime, setRemainingTime] = useState<string>('00:00');
const [progressBarWidth, setProgressBarWidth] = useState<string>('0%');
const [bufferedBarWidth, setBufferedBarWidth] = useState<string>('0%');
const [videoCurrentTime, setVideoCurrentTime] = useState('00:00');
const [remainingTime, setRemainingTime] = useState('00:00');
const [videoDuration, setVideoDuration] = useState('00:00');

const [offsetX, setOffsetX] = useState(0);
const [percent, setPercent] = useState(0);
const [hoverTime, setHoverTime] = useState(0);
const [hoverOffset, setHoverOffset] = useState(0);

const [introSkip, setIntroSkip] = useState<number>(
STORE.get('intro_skip_time') as number,
);
const [showDuration, setShowDuration] = useState<boolean>(
const introSkip = STORE.get('intro_skip_time') as number;
const [showDuration, setShowDuration] = useState(
STORE.get('show_duration') as boolean,
);
useEffect(() => {
setVideoCurrentTime(formatTime(videoRef.current?.currentTime ?? 0));
setVideoDuration(formatTime(videoRef.current?.duration ?? 0));
setProgressBarWidth('0%');
setBufferedBarWidth('0%');
}, []);

const [isHovering, setIsHovering] = useState(false);

useEffect(() => {
setVideoCurrentTime(formatTime(currentTime ?? 0));
setRemainingTime(formatTime((duration ?? 0) - (currentTime ?? 0)));
setVideoDuration(formatTime(duration ?? 0));
setProgressBarWidth(`${((currentTime ?? 0) / (duration ?? 0)) * 100}%`);
setRemainingTime(formatTime((duration ?? 0) - (currentTime ?? 0)));
}, [currentTime, duration]);

if (videoRef.current && buffered && buffered.length > 0) {
setBufferedBarWidth(`${(buffered.end(0) / (duration ?? 0)) * 100}%`);
useEffect(() => {
if (!duration || !currentTime) return;

const progress = (currentTime / duration) * 100;
setProgressBarWidth(`${progress}%`);

if (buffered && buffered.length > 0) {
const bufferedEnd = buffered.end(buffered.length - 1);
const bufferedProgress = (bufferedEnd / duration) * 100;
setBufferedBarWidth(`${bufferedProgress}%`);
}
}, [currentTime, duration, buffered]);

useEffect(() => {
window.addEventListener('mouseup', () => {
setIsMouseDown(false);
});
});
// failed attempt to improve performance, gonna keep it here
const updateTimeOnDragVisually = (event: MouseEvent) => {
if (!videoTimelineRef.current || !duration) return;

const handleShowDuration = () => {
const show = !showDuration;
const rect = videoTimelineRef.current.getBoundingClientRect();
const offsetX = Math.max(
0,
Math.min(event.clientX - rect.left, rect.width),
);
const percentage = offsetX / rect.width;
const newTime = percentage * duration;

STORE.set('show_duration', show);
setShowDuration(show);
setHoverOffset(offsetX);
setHoverTime(newTime);

setProgressBarWidth(`${(newTime / duration) * 100}%`);
setVideoCurrentTime(formatTime(newTime));
setRemainingTime(formatTime((duration ?? 0) - newTime));

return newTime;
};

// Funzione per calcolare il tempo in base alla posizione sull'asse X
const calculateProgressTime = (event: React.MouseEvent) => {
if (!videoTimelineRef.current || !duration) return;
let timelineWidth = videoTimelineRef.current.clientWidth;
const newOffsetX = event.movementX > event.nativeEvent.offsetX ? event.movementX : event.nativeEvent.offsetX;

let newPercent = Math.floor((newOffsetX / timelineWidth) * duration);
if (newPercent < 0) newPercent = 0;
if (newPercent > duration) newPercent = duration;
const clampedOffsetX =
newOffsetX < 20
? 20
: newOffsetX > timelineWidth - 20
? timelineWidth - 20
: newOffsetX;

setOffsetX(clampedOffsetX);
setPercent(newPercent);
const updateTimeOnDrag = (event: MouseEvent) => {
const newTime = updateTimeOnDragVisually(event);

if (!videoRef.current || !newTime) return;
videoRef.current.currentTime = newTime;
};

const getTimePercent = (time: number) => {
if(!videoRef.current) return 0;
const video = videoRef.current;
return (time / video.duration) * 100;
}
useEffect(() => {
if (!isDragging) playVideo();
}, [isDragging]);

const getSkipEventBarStyle = (event: SkipEvent) => {
const interval = event.interval;
const handleMouseDown = (event: React.MouseEvent) => {
setIsDragging(true);
pauseVideo();
updateTimeOnDrag(event.nativeEvent);

return {
left: `${getTimePercent(interval.startTime)}%`,
width: `${getTimePercent(interval.endTime - interval.startTime)}%`
}
}
window.addEventListener('mousemove', updateTimeOnDrag);
window.addEventListener('mouseup', stopDrag);
};

const dragProgressBar = (event: React.MouseEvent<HTMLDivElement>) => {
if (!videoRef.current) return;
const stopDrag = () => {
setIsDragging(false);

const timeline = event.currentTarget;
const rect = timeline.getBoundingClientRect();
const offsetX = event.clientX - rect.left;
window.removeEventListener('mousemove', updateTimeOnDrag);
window.removeEventListener('mouseup', stopDrag);
};

const percentage = offsetX / timeline.clientWidth;
const calculateHoverTime = (event: React.MouseEvent) => {
if (!videoTimelineRef.current || !duration) return;

let newTime = percentage * videoRef.current.duration;
if (newTime < 0) newTime = 0;
if (newTime > videoRef.current.duration) newTime = videoRef.current.duration;
setProgressBarWidth(`${((newTime ?? 0) / (duration ?? 0)) * 100}%`);
const rect = videoTimelineRef.current.getBoundingClientRect();
const offsetX = event.clientX - rect.left;
const percentage = offsetX / rect.width;
const newHoverTime = percentage * duration;

try {
videoRef.current.currentTime = newTime;
} catch (error) {
console.log(error);
}
setHoverOffset(offsetX);
setHoverTime(newHoverTime);
};

const handleSkipIntro = () => {
if (!videoRef.current) return;
const handleShowDuration = () => {
const show = !showDuration;
STORE.set('show_duration', show);
setShowDuration(show);
};

try {
const handleSkipIntro = () => {
if (videoRef.current) {
videoRef.current.currentTime += introSkip;
} catch (error) {
console.log(error)
}
};

Expand All @@ -150,19 +149,6 @@ const BottomControls: React.FC<BottomControlsProps> = ({
onClick={onClick}
onDoubleClick={onDblClick}
>
{/* {showSkipEvent && skipEvents && skipEvents.length > 0 && (
<div
className="skip-button"
style={{opacity: '1', zIndex: '900'}}
>
<ButtonMain
text={skipEvent}
icon={faFastForward}
tint="light"
onClick={handleSkipIntro}
/>
</div>
)} */}
<div className="skip-button">
<ButtonMain
text={introSkip}
Expand All @@ -171,60 +157,43 @@ const BottomControls: React.FC<BottomControlsProps> = ({
onClick={handleSkipIntro}
/>
</div>

<p className="current-time">{videoCurrentTime}</p>

<div
className="video-timeline"
onClick={dragProgressBar}
onMouseMove={(event) => {
const target = event.target as HTMLDivElement;
if(target.className === 'video-event-bar') {
const parentElement = target.parentElement as HTMLDivElement;
const parentDimensions = parentElement.getBoundingClientRect();
const eventDimensions = target.getBoundingClientRect();

/* lol this is a bit hacky replacing movementX but it works */
event.movementX = Math.floor(eventDimensions.x - parentDimensions.x) + event.nativeEvent.offsetX;
event.clientX = Math.floor(eventDimensions.x + event.nativeEvent.offsetX)
event.currentTarget = parentElement as HTMLDivElement;
}
calculateProgressTime(event);
if (!isMouseDown) return;
dragProgressBar(event);
}}
onMouseDown={() => setIsMouseDown(true)}
onMouseUp={() => setIsMouseDown(false)}
className={`video-timeline${isDragging ? ' is-dragging' : ''}`}
ref={videoTimelineRef}
onMouseMove={calculateHoverTime}
onMouseDown={handleMouseDown}
onMouseEnter={() => setIsHovering(true)}
onMouseLeave={() => setIsHovering(false)}
>
<div className="progress-area">
<div
className="video-buffered-bar"
style={{ width: bufferedBarWidth }}
></div>
{(skipEvents ?? []).map((event) => (
<div
className="video-event-bar"
style={getSkipEventBarStyle(event)}
></div>
))}
/>
<div
className="video-progress-bar"
style={{ width: progressBarWidth }}
></div>
{/* <div className="preview-thumbnail">
<img src={previewThumbnailSrc} alt="preview" />
<div className="time">
<span>{videoCurrentTime}</span>
</div>
</div> */}
<span style={{ left: `${offsetX}px` }}>{formatTime(percent)}</span>
style={{
width: progressBarWidth,
}}
/>

<span
className="hover-time-tooltip"
style={{
left: `${hoverOffset}px`,
opacity: isDragging || isHovering ? '1' : '0',
}}
>
{formatTime(hoverTime)}
</span>
</div>
</div>
<p
className="video-duration"
onClick={handleShowDuration}
style={{ marginLeft: showDuration ? 8 : '' }}
>
{showDuration ? videoDuration : `-${remainingtime}`}

<p className="video-duration" onClick={handleShowDuration}>
{showDuration ? videoDuration : `-${remainingTime}`}
</p>
</div>
);
Expand Down
Loading

0 comments on commit 68b6eef

Please sign in to comment.