Skip to content

Commit

Permalink
Update 1.3.0
Browse files Browse the repository at this point in the history
Removed the Sidebar, navigation is now done by the navigation bar at the bottom.

Added Watchlist system, you can add movies into your watchlist by hovering over the item and pressing the + button.

Added Continue Watching system, you will now see movies on the homepage (Shows and Episode support coming asap.)

Added Discord Server link at the top of the homepage.
  • Loading branch information
synthofficial committed Aug 22, 2024
1 parent 8952790 commit 2ec8daf
Show file tree
Hide file tree
Showing 21 changed files with 1,021 additions and 214 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"@fluentui/react-components": "^9.54.7",
"bottleneck": "^2.19.5",
"chroma-js": "^2.6.0",
"discord-rpc": "^4.0.1",
"electron-debug": "^3.2.0",
"electron-log": "^4.4.8",
"electron-updater": "^6.2.1",
Expand Down Expand Up @@ -200,7 +201,9 @@
"extraFiles": [
{
"from": ".",
"filter": ["electron-builder.yml"]
"filter": [
"electron-builder.yml"
]
}
],
"mac": {
Expand Down
4 changes: 2 additions & 2 deletions release/app/package-lock.json

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

84 changes: 84 additions & 0 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Avatar, Flex, IconButton, Tooltip } from "@chakra-ui/react";
import { IoHomeOutline, IoHomeSharp } from "react-icons/io5";
import { FaCog, FaListAlt } from "react-icons/fa";
import { useState } from "react";
import ProfileModal from "../renderer/pages/modals/ProfileModal";
import SettingsModal from "../renderer/pages/modals/SettingsModal";

interface Props {
selectedTab : string;
onTabChange : (tab: string) => void;
}

const Navbar : React.FC<Props> = ({ selectedTab, onTabChange }) => {

const [isProfileOpen, setIsProfileOpen] = useState(false);
const [isSettingsOpen, setIsSettingsOpen] = useState(false);


return(
<>
<Flex
as="header"
position="absolute"
bottom={10}
left={"48%"}
mb={4}
height="50px"
zIndex={10}
w={"200px"}
bg="dark.200"
borderRadius={"20px"}
className="items-center"
flexDirection="row"
p={2}
>
<Tooltip hasArrow label="Home">
<IconButton
aria-label="Home"
icon={<IoHomeSharp />}
size="md"
variant="ghost"
color="white"
cursor="pointer"
_hover={{ bg: 'dark.300' }}
onClick={() => onTabChange('home')}
/>
</Tooltip>

<Tooltip hasArrow label="Watchlist">
<IconButton
aria-label="List"
icon={<FaListAlt />}
size="md"
variant="ghost"
color="white"
cursor="pointer"
_hover={{ bg: 'dark.300' }}
onClick={() => onTabChange('watchlist')}
/>
</Tooltip>
<Tooltip hasArrow label="Settings">
<IconButton
aria-label="Settings"
icon={<FaCog className="text-white" />}
_hover={{ bg: 'dark.200'}}
onClick={() => setIsSettingsOpen(true)}
variant="ghost"
mr={2}
/>
</Tooltip>
<Avatar
size="sm"
src={localStorage.getItem('avatarUrl') || undefined}
cursor="pointer"
onClick={() => setIsProfileOpen(true)}
/>
</Flex>
<SettingsModal isOpen={isSettingsOpen} onClose={() => setIsSettingsOpen(false)} onOpen={() => setIsSettingsOpen(true)} />
<ProfileModal isOpen={isProfileOpen} onClose={() => setIsProfileOpen(false)} onOpen={() => setIsProfileOpen(true)} />
</>
);
}

export default Navbar
69 changes: 0 additions & 69 deletions src/components/Sidebar.tsx

This file was deleted.

3 changes: 1 addition & 2 deletions src/components/TitleBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { FaMinus, FaRegSquare, FaTimes } from 'react-icons/fa';
import { ipcRenderer } from 'electron';

const TitleBar: React.FC = () => {
const bgColor = useColorModeValue('gray.800', 'gray.900');
const iconColor = useColorModeValue('white', 'gray.200');

const handleMinimize = () => {
Expand All @@ -25,7 +24,7 @@ const TitleBar: React.FC = () => {
align="center"
justify="space-between"
px={2}
bg={"gray.900"}
bg={"dark.200"}
className="draggable overflow-hidden"
>
<Flex marginLeft={'auto'} gap={4}>
Expand Down
62 changes: 28 additions & 34 deletions src/components/VideoPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getEpisodeSource } from "../modules/api/Movies";
import discordRPCManager from "../constants/DiscordRPC";
import { useVideoPlayer } from "../renderer/contexts/VideoPlayerContext";
import { getAnimeSource } from "../modules/api/Anime";
import { getWatchingList, isInWatchingList, isInWatchlist, updateWatchingListMovieTime, updateWatchlistMovieTime } from "../modules/functions";

const convertSecondsToTime = (seconds: number) => {
const hours = Math.floor(seconds / 3600);
Expand Down Expand Up @@ -43,6 +44,8 @@ const VideoPlayer: React.FC = () => {
const [volume, setVolume] = useState<number>(50);
const [hideTimeout, setHideTimeout] = useState<NodeJS.Timeout | null>(null);

const watchingList = getWatchingList();

const handleControlsVisibility = useCallback(() => {
setShowControls(true);

Expand Down Expand Up @@ -76,18 +79,31 @@ const VideoPlayer: React.FC = () => {

const playHlsVideo = useCallback((url: string) => {
if (Hls.isSupported() && videoRef.current) {
const hls = new Hls();
const hls = new Hls({
// Start at a lower quality and switch to higher quality as the buffer builds
startLevel: -1, // Start with the lowest level
autoStartLoad: true,
maxBufferLength: 30,
maxBufferSize: 60 * 1000 * 1000, // 60 MB
maxBufferHole: 0.5, // Reduce buffer hole to minimize stalls
lowLatencyMode: true, // Enable low-latency streaming
liveSyncDurationCount: 3, // Sync to the live edge with less delay
});
console.log(url);
hls.loadSource(url);
hls.attachMedia(videoRef.current);

hls.on(Hls.Events.MANIFEST_PARSED, () => {
if(videoRef.current){
hls.currentLevel = hls.levels.length - 1;
hls.currentLevel = hls.levels.length - 1; // Automatically switch to the highest quality
setHlsData(hls);
videoRef.current.play().catch(e => console.error("Playback failed:", e));
}
});

if(watchingList.find((m) => m.id == movieData?.id)){
videoRef.current.currentTime = getWatchingList().find((m) => m.id == movieData?.id)?.timestamp || 0;
}

hls.on(Hls.Events.ERROR, (event, data) => {
console.error("HLS error:", event, data);
Expand All @@ -112,7 +128,15 @@ const VideoPlayer: React.FC = () => {
const video = videoRef.current;
if (!video) return;

const onTimeUpdate = () => setCurrentTime(convertSecondsToTime(video.currentTime));
const onTimeUpdate = () => {
setCurrentTime(convertSecondsToTime(video.currentTime));
if(isInWatchingList(movieData?.id as string)){
updateWatchingListMovieTime(movieData?.id as string, video.currentTime);
}
if(isInWatchlist(movieData?.id as string)){
updateWatchlistMovieTime(movieData?.id as string, video.currentTime);
}
}
const onLoadedMetadata = () => setDuration(convertSecondsToTime(video.duration));
const onPlay = () => setPlaying(true);
const onPause = () => setPlaying(false);
Expand Down Expand Up @@ -183,43 +207,13 @@ const VideoPlayer: React.FC = () => {
setCurrentEpisode(nextEpisodeData);
setCurrentUrl(source);
playHlsVideo(source);
toast({
title: "Next Episode Loaded",
description: "Enjoy watching!",
status: "success",
duration: 3000,
isClosable: true,
});
} else {
throw new Error("Failed to fetch episode URL");
}
} catch (error) {
console.error("Error changing episode:", error);
toast({
title: "Error",
description: "Failed to load the next episode. Please try again.",
status: "error",
duration: 5000,
isClosable: true,
});
console.error("Error fetching next episode:", error);
}
} else {
toast({
title: "End of Series",
description: "You've reached the last episode.",
status: "warning",
duration: 5000,
isClosable: true,
});
}
};

useEffect(() => {
const handleFullscreenChange = () => setFullscreen(!!document.fullscreenElement);
document.addEventListener("fullscreenchange", handleFullscreenChange);
return () => document.removeEventListener("fullscreenchange", handleFullscreenChange);
}, []);

if (!showPlayer) return null;

return (
Expand Down
Loading

0 comments on commit 2ec8daf

Please sign in to comment.