Skip to content

Commit

Permalink
feat: dropped/completed buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
aleganza committed Jul 7, 2024
1 parent d19856f commit 5d33acb
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 40 deletions.
59 changes: 48 additions & 11 deletions src/renderer/components/Buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import 'react-activity/dist/Dots.css';
import { IconDefinition } from '@fortawesome/free-regular-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Dots from 'react-activity/dist/Dots';
import { useSearchParams } from 'react-router-dom';
import { useState } from 'react';
import { faCheck } from '@fortawesome/free-solid-svg-icons';

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
tint?: 'primary' | 'light' | 'dark' | 'warning' | 'empty';
Expand Down Expand Up @@ -45,10 +48,17 @@ export const ButtonMain: React.FC<ButtonMainProps> = ({
);
};

type HoverButton = {
icon: IconDefinition;
text: string;
action: () => void;
};

interface ButtonCircleProps extends ButtonProps {
icon: IconDefinition;
small?: boolean;
tooltipText?: string; // Nuova prop per il testo del tooltip
tooltipText?: string;
hoverButtons?: HoverButton[];
}

export const ButtonCircle: React.FC<ButtonCircleProps> = ({
Expand All @@ -57,18 +67,45 @@ export const ButtonCircle: React.FC<ButtonCircleProps> = ({
shadow = false,
small = false,
disabled = false,
tooltipText, // Destructure della prop aggiunta
tooltipText,
hoverButtons,
...rest
}) => {
const [showHoverButtons, setShowHoverButtons] = useState<boolean>(false);

const handleShowHoverButtons = () => {
setShowHoverButtons(true);
console.log('ciao');
};

const handleHideHoverButtons = () => {
setShowHoverButtons(false);
};

return (
<button
className={`bc ${tint} ${shadow ? 'shadow' : ''} ${small ? 'small' : ''} ${disabled ? 'disabled' : ''}`}
{...rest}
>
<div className="tooltip">
<FontAwesomeIcon className="i" icon={icon} />
{tooltipText && <span className="tooltip-text">{tooltipText}</span>}
</div>
</button>
<div className="circle-button-container">
{hoverButtons && (
<div className="hover-buttons">
{hoverButtons?.map((value) => (
<ButtonCircle
icon={value.icon}
tint="empty"
shadow
tooltipText={value.text}
onClick={value.action}
/>
))}
</div>
)}
<button
className={`bc ${tint} ${shadow ? 'shadow' : ''} ${small ? 'small' : ''} ${disabled ? 'disabled' : ''}`}
{...rest}
>
<div className="tooltip">
<FontAwesomeIcon className="i" icon={icon} />
{tooltipText && <span className="tooltip-text">{tooltipText}</span>}
</div>
</button>
</div>
);
};
12 changes: 8 additions & 4 deletions src/renderer/components/Slideshow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@ const Slide: React.FC<SlideProps> = ({ listAnimeData, index, isVisible }) => {
}, [isVisible]);

const fetchEpisodesInfo = async () => {
axios.get(`${EPISODES_INFO_URL}${listAnimeData.media.id}`).then((data) => {
if (data.data && data.data.episodes) setEpisodesInfo(data.data.episodes);
});
axios
.get(`${EPISODES_INFO_URL}${listAnimeData.media.id}`)
.then((data) => {
if (data.data && data.data.episodes)
setEpisodesInfo(data.data.episodes);
})
.catch(() => {});
};

const handlePressButton = async () => {
Expand Down Expand Up @@ -165,7 +169,7 @@ const Slide: React.FC<SlideProps> = ({ listAnimeData, index, isVisible }) => {
if (!hasModalBeenShowed) setHasModalBeenShowed(true);
}}
/>
<IsInListButton listAnimeData={listAnimeData} />
{/* <IsInListButton listAnimeData={listAnimeData} /> */}
</div>
</div>
</div>
Expand Down
20 changes: 12 additions & 8 deletions src/renderer/components/modals/AnimeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,18 @@ const AnimeModal: React.FC<AnimeModalProps> = ({
};

const fetchEpisodesInfo = async () => {
axios.get(`${EPISODES_INFO_URL}${listAnimeData.media.id}`).then((data) => {
if (data.data && data.data.episodes) setEpisodesInfo(data.data.episodes);
data.data.images &&
setAlternativeBanner(
getUrlByCoverType(data.data.images, 'fanart') ?? undefined,
);
setEpisodesInfoHasFetched(true);
});
axios
.get(`${EPISODES_INFO_URL}${listAnimeData.media.id}`)
.then((data) => {
if (data.data && data.data.episodes)
setEpisodesInfo(data.data.episodes);
data.data.images &&
setAlternativeBanner(
getUrlByCoverType(data.data.images, 'fanart') ?? undefined,
);
setEpisodesInfoHasFetched(true);
})
.catch(() => {});
};

const handleTrailerPlay = () => {
Expand Down
102 changes: 86 additions & 16 deletions src/renderer/components/modals/AnimeModalElements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,27 @@ import {
faClock,
} from '@fortawesome/free-regular-svg-icons';
import {
faBookmark as faBookmarkSolid,
faBan,
faCheck,
faChevronDown,
faChevronUp,
faFilm,
faHourglass,
faPlay,
faRotate,
faStopwatch,
faBookmark as faBookmarkFull,
faCheck,
faXmark,
faTrash,
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import DOMPurify from 'dompurify';
import React, { useContext, useEffect, useRef, useState } from 'react';

import {
deleteAnimeFromList,
updateAnimeFromList,
} from '../../../modules/anilist/anilistApi';
import {
getAvailableEpisodes,
getEpisodes,
Expand All @@ -32,13 +38,13 @@ import {
parseDescription,
} from '../../../modules/utils';
import { ListAnimeData } from '../../../types/anilistAPITypes';
import { MediaStatus } from '../../../types/anilistGraphQLTypes';
import { AuthContext } from '../../App';
import { ButtonCircle, ButtonLoading, ButtonMain } from '../Buttons';
import {
deleteAnimeFromList,
updateAnimeFromList,
} from '../../../modules/anilist/anilistApi';
MediaListStatus,
MediaStatus,
} from '../../../types/anilistGraphQLTypes';
import { AuthContext } from '../../App';
import { ButtonCircle, ButtonMain } from '../Buttons';
import { stat } from 'fs';

export const AnimeModalStatus: React.FC<{
status: MediaStatus | undefined;
Expand Down Expand Up @@ -236,6 +242,10 @@ export const AnimeModalWatchButtons: React.FC<{
getProgress(listAnimeData.media),
);

const [listStatus, setListStatus] = useState<MediaListStatus | undefined>(
listAnimeData.media.mediaListEntry?.status,
);

// const progress = getProgress(listAnimeData.media);
const episodes = getEpisodes(listAnimeData.media);
const availableEpisodes = getAvailableEpisodes(listAnimeData.media);
Expand All @@ -245,6 +255,10 @@ export const AnimeModalWatchButtons: React.FC<{
if (localProgress) setProgress(localProgress);
}, [localProgress]);

const handleListStatusChange = (status: MediaListStatus | undefined) => {
setListStatus(status);
};

return logged ? (
<div className="watch-buttons">
{listAnimeData.media.status !== 'NOT_YET_RELEASED' && (
Expand Down Expand Up @@ -293,7 +307,19 @@ export const AnimeModalWatchButtons: React.FC<{
</>
)}

<IsInListButton listAnimeData={listAnimeData} />
{listStatus === 'CURRENT' || listStatus === 'REPEATING' ? (
<RemoveButton
listAnimeData={listAnimeData}
listStatus={listStatus}
onListStatusChange={handleListStatusChange}
/>
) : (
<IsInListButton
listAnimeData={listAnimeData}
listStatus={listStatus}
onListStatusChange={handleListStatusChange}
/>
)}
</div>
) : (
<div className="watch-buttons">
Expand All @@ -310,15 +336,20 @@ export const AnimeModalWatchButtons: React.FC<{

export const IsInListButton: React.FC<{
listAnimeData: ListAnimeData;
}> = ({ listAnimeData }) => {
listStatus?: MediaListStatus | undefined;
onListStatusChange: (status: MediaListStatus | undefined) => void;
}> = ({ listAnimeData, listStatus, onListStatusChange }) => {
const [inList, setInList] = useState<boolean>(false);
const [listId, setListId] = useState<number | undefined>(
listAnimeData.media.mediaListEntry?.id,
);

const removeFromList = () => {
deleteAnimeFromList(listId).then((deleted) => {
if (deleted) setInList(false);
if (deleted) {
setInList(false);
onListStatusChange(undefined);
}
});
};

Expand All @@ -327,17 +358,56 @@ export const IsInListButton: React.FC<{
if (data) {
setListId(data);
setInList(true);
onListStatusChange('PLANNING');
}
});
};

useEffect(() => {
setInList(!!listAnimeData.media.mediaListEntry);
setInList(listStatus === 'PLANNING');
}, []);

return inList ? (
<ButtonCircle icon={faCheck} tint="empty" shadow tooltipText='Remove from list' onClick={removeFromList} />
) : (
<ButtonCircle icon={faBookmark} tint="empty" shadow tooltipText='Add to list' onClick={addToList} />
return (
<ButtonCircle
icon={inList ? faBookmarkSolid : faBookmark}
tint="empty"
shadow
tooltipText={inList ? 'Remove from list' : 'Add to list'}
onClick={inList ? removeFromList : addToList}
/>
);
};

export const RemoveButton: React.FC<{
listAnimeData: ListAnimeData;
listStatus?: MediaListStatus | undefined;
onListStatusChange: (status: MediaListStatus | undefined) => void;
}> = ({ listAnimeData, listStatus, onListStatusChange }) => {
const markAsCompleted = () => {
updateAnimeFromList(listAnimeData.media.id, 'COMPLETED').then((data) => {
if (data) {
onListStatusChange('COMPLETED');
}
});
};

const markAsDropped = () => {
updateAnimeFromList(listAnimeData.media.id, 'DROPPED').then((data) => {
if (data) {
onListStatusChange('DROPPED');
}
});
};

return (
<ButtonCircle
icon={faXmark}
tint="empty"
hoverButtons={[
{ icon: faCheck, text: 'Completed', action: markAsCompleted },
{ icon: faTrash, text: 'Dropped', action: markAsDropped },
]}
shadow
/>
);
};
31 changes: 30 additions & 1 deletion src/renderer/components/styles/Buttons.css
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,35 @@ button.bc.disabled {
opacity: 0.5;
}

/* button circle hover buttons */

.circle-button-container {
position: relative;
}

.circle-button-container .hover-buttons {
position: absolute;
/* can't figure out how to center automatically :( */
top: -9px;
left: -90%;
display: flex;
gap: 18px;
visibility: hidden;
opacity: 0;
padding: 10px;
background-color: var(--color-1);
border-radius: 100px;
transform: scale(0.9);
}

.circle-button-container:hover .hover-buttons button,
.circle-button-container:hover .hover-buttons {
visibility: visible;
opacity: 1;
transform: scale(1);
transition: 0.2s;
}

/* button circle hover tooltip */

.tooltip {
Expand All @@ -109,6 +138,7 @@ button.bc.disabled {

.tooltip .tooltip-text {
visibility: hidden;
position: absolute;
white-space: nowrap;
width: auto;
background-color: var(--font-1);
Expand All @@ -118,7 +148,6 @@ button.bc.disabled {
text-align: center;
border-radius: 6px;
padding: 8px 14px;
position: absolute;
z-index: 1;
bottom: 50px;
left: 50%;
Expand Down

0 comments on commit 5d33acb

Please sign in to comment.