Skip to content

Commit

Permalink
fix: add sidebar scroll logic
Browse files Browse the repository at this point in the history
  • Loading branch information
ivg-design committed Nov 8, 2023
1 parent a1cffaf commit bdae018
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 49 deletions.
30 changes: 28 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const TreeNode = React.forwardRef(({
}, ref) => {
const [children, setChildren] = useState([]);
const isExpanded = expandedPaths.includes(item.path);

const itemRef = ref || React.createRef(); // Use the forwarded ref or create a new one


// Update your expand function
const expand = useCallback(async (item) => {
Expand Down Expand Up @@ -70,7 +71,31 @@ const TreeNode = React.forwardRef(({
performExpand();
}, [item, isExpanded, invoke]);


useEffect(() => {
// Only scroll into view if the current item is selected and not already in view
if (isSelected(item.path) && !isItemInView(itemRef.current)) {
itemRef.current.scrollIntoView({
behavior: 'smooth',
block: 'nearest'
});
}
}, [isSelected, item.path, itemRef]);

// Helper function to check if the element is in view
function isItemInView(element) {
if (!element) {
return false;
}
const rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}


const handleToggle = (e) => {
e.stopPropagation();
if (item.is_dir) {
Expand Down Expand Up @@ -99,6 +124,7 @@ const TreeNode = React.forwardRef(({
return (
<div>
<div
ref={itemRef} // Attach the ref to this div
className={`treeNode ${isSelected(item.path) ? 'selected' : ''}`}
onClick={handleClick}
onDoubleClick={handleToggle}
Expand Down
32 changes: 30 additions & 2 deletions src/PlayerUI.css
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,40 @@
}


.progress-bar-container {
position: relative;
width: 200px;
height: 25px;
/* Height of the progress bar */
/* margin-top: 10px; */
/* Space above the progress bar */
cursor: pointer;
}

.progress-slider {
.progress-bar-svg {
width: 100%;
cursor: pointer;
height: 8px;
top: 50%;
bottom: 50%;
}

.progress-bar-handle {
position: absolute;
top: 50%;
bottom: 50%;
transform: translate(-50%, -50%);
/* Center the handle on the progress bar */
width: 25px;
/* Handle width */
height: 25px;
/* Handle height */
cursor: grab;
}

/* Styles for when the handle is being dragged */
.progress-bar-handle:active {
cursor: grabbing;
}
.playBtn {
margin-top: 20px;
margin-left: 30px;
Expand Down
110 changes: 65 additions & 45 deletions src/PlayerUI.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,68 @@
// Import the necessary hooks and components from React and other libraries.
import React, { useState, useRef, useEffect } from 'react'; // React hooks and React base import
import LottiePlayer from './LottiePlayer'; // Importing a custom component for rendering Lottie animations
import './PlayerUI.css'; // Importing CSS for styling the player UI
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; // Component for Font Awesome icons
import { faPlay, faPause } from '@fortawesome/free-solid-svg-icons'; // Specific icons from Font Awesome
import React, { useState, useRef, useEffect, useCallback } from 'react';
import LottiePlayer from './LottiePlayer';
import './PlayerUI.css';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPlay, faPause } from '@fortawesome/free-solid-svg-icons';
import { ReactComponent as ProgressBar } from './svgUIelements/progressBar.svg';
import { ReactComponent as ProgressBarHandle } from './svgUIelements/progressBarHandle.svg';

// Defining the PlayerUI component with props for animation data and version
const PlayerUI = ({ animationData, version }) => {
// State hooks for play state and progress
const [isPlaying, setIsPlaying] = useState(true); // State for if the animation is playing
const [progress, setProgress] = useState(0); // State for the progress of the animation
const animationRef = useRef(null); // Ref hook to reference the animation DOM element
const [isPlaying, setIsPlaying] = useState(true);
const [progress, setProgress] = useState(0);
const animationRef = useRef(null);
const progressBarRef = useRef(null);

// Effect hook to handle play/pause changes
useEffect(() => {
if (animationRef.current) {
if (isPlaying) {
animationRef.current.play(); // Play animation if isPlaying is true
} else {
animationRef.current.pause(); // Pause animation if isPlaying is false
}
isPlaying ? animationRef.current.play() : animationRef.current.pause();
}
}, [isPlaying]); // This effect depends on the isPlaying state
}, [isPlaying]);


// Effect hook to handle progress changes
useEffect(() => {
if (animationRef.current) {
const frame = Math.floor(animationRef.current.totalFrames * progress);
animationRef.current.goToAndStop(frame, true); // Go to a specific frame based on progress
animationRef.current.goToAndStop(frame, true);
}
}, [progress]); // This effect depends on the progress state
}, [progress]);

// Function to toggle the play state
const togglePlay = () => {
setIsPlaying(!isPlaying); // Sets isPlaying to the opposite of its current state
};
const togglePlay = () => setIsPlaying(!isPlaying);

// Function to update the progress state
const updateProgress = (value) => {
setProgress(parseFloat(value)); // Parses the string value to a float and updates the progress state
};
const setProgressFromEvent = useCallback((e) => {
if (progressBarRef.current) {
const bounds = progressBarRef.current.getBoundingClientRect();
const newProgress = (e.clientX - bounds.left) / bounds.width;
setProgress(Math.min(Math.max(0, newProgress), 1));
} else {
console.log('progressBarRef.current is null during setProgressFromEvent');
}
}, []);

// Function to determine the button class based on the play state
const getButtonClass = () => {
return isPlaying ? "playBtn" : "pauseBtn"; // Returns the appropriate class name based on isPlaying
const handleMouseMove = useCallback((e) => {
if (progressBarRef.current) {
setProgressFromEvent(e);
} else {
console.log('progressBarRef.current is null during handleMouseMove');
}
}, [setProgressFromEvent]);

const handleMouseUp = useCallback(() => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
}, [handleMouseMove]);

const handleMouseDown = useCallback((event) => {
event.preventDefault();
setProgressFromEvent(event);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
}, [setProgressFromEvent, handleMouseMove, handleMouseUp]);

// Function to update progress when animation updates
const handleAnimationUpdate = (animationProgress) => {
setProgress(animationProgress);
};

// The component returns a UI structure rendered as JSX
return (
<div className="playbackContainer">
<LottiePlayer
Expand All @@ -55,26 +71,30 @@ const PlayerUI = ({ animationData, version }) => {
isPlaying={isPlaying}
progress={progress}
animationRef={animationRef}
onEnterFrame={({ currentTime, totalTime }) => handleAnimationUpdate(currentTime / totalTime)}
/>
<div className="player-controls">
<button
className={getButtonClass()}
className={isPlaying ? 'playBtn' : 'pauseBtn'}
onClick={togglePlay}
>
<FontAwesomeIcon icon={isPlaying ? faPause : faPlay} />
{isPlaying ? ' Pause' : ' Play'}
<FontAwesomeIcon icon={isPlaying ? faPause : faPlay} />
{isPlaying ? ' Pause' : ' Play'}
</button>
<input
type="range"
min="0"
max="1"
step="any"
value={progress}
onChange={(e) => updateProgress(e.target.value)}
/>
<div
className="progress-bar-container"
ref={progressBarRef}
onMouseDown={handleMouseDown}
>
<ProgressBar className="progress-bar-svg" />
<ProgressBarHandle
className="progress-bar-handle"
style={{ left: `${progress * 100}%` }}
/>
</div>
</div>
</div>
);
};

export default PlayerUI; // Exports the component for use in other parts of the application
export default PlayerUI;
15 changes: 15 additions & 0 deletions src/svgUIelements/progressBar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions src/svgUIelements/progressBarHandle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit bdae018

Please sign in to comment.