diff --git a/gameyfin/src/main/frontend/components/general/input/ComboButton.tsx b/gameyfin/src/main/frontend/components/general/input/ComboButton.tsx new file mode 100644 index 0000000..55e66be --- /dev/null +++ b/gameyfin/src/main/frontend/components/general/input/ComboButton.tsx @@ -0,0 +1,87 @@ +import {useEffect, useState} from "react"; +import { + Button, + ButtonGroup, + Dropdown, + DropdownItem, + DropdownMenu, + DropdownTrigger, + SharedSelection +} from "@heroui/react"; +import {CaretDown} from "@phosphor-icons/react"; +import {UserPreferenceService} from "Frontend/util/user-preference-service"; + +export interface ComboButtonOption { + label: string; + description: string; + action: () => void; + isDisabled?: boolean; +} + +export interface ComboButtonProps { + options: Record; + preferredOptionKey?: string; +} + +export default function ComboButton({options, preferredOptionKey}: ComboButtonProps) { + const [selectedOption, setSelectedOption] = useState(new Set([Object.keys(options)[0]])); + const [disabledOptions] = useState(getDisabledKeys(options)); + const selectedOptionValue = Array.from(selectedOption)[0]; + + useEffect(() => { + if (!preferredOptionKey) return; + + UserPreferenceService.get(preferredOptionKey).then((key) => { + if (key && options[key]) { + setSelectedOption(new Set([key])); + } else { + setSelectedOption(new Set([Object.keys(options)[0]])); + } + }) + }, []); + + async function onSelectionChange(keys: SharedSelection) { + if (!keys.currentKey) return; + + if (preferredOptionKey) { + await UserPreferenceService.set(preferredOptionKey, keys.currentKey); + } + + setSelectedOption(new Set([keys.currentKey])); + } + + function getDisabledKeys(options: Record): string[] { + return Object.keys(options).filter(key => options[key].isDisabled); + } + + return ( + + + + + + + + {Object.entries(options).map(([key, option]) => ( + + {option.label} + + ))} + + + + ); +} \ No newline at end of file diff --git a/gameyfin/src/main/frontend/views/GameView.tsx b/gameyfin/src/main/frontend/views/GameView.tsx index 736a660..585ff78 100644 --- a/gameyfin/src/main/frontend/views/GameView.tsx +++ b/gameyfin/src/main/frontend/views/GameView.tsx @@ -3,11 +3,31 @@ import GameDto from "Frontend/generated/de/grimsi/gameyfin/games/dto/GameDto"; import {GameEndpoint} from "Frontend/generated/endpoints"; import {useParams} from "react-router"; import {GameCover} from "Frontend/components/general/covers/GameCover"; +import ComboButton, {ComboButtonOption} from "Frontend/components/general/input/ComboButton"; export default function GameView() { const {gameId} = useParams(); const [game, setGame] = useState(); + const [selectedDownloadOption, setSelectedDownloadOption] = useState(null); + + const downloadOptions: Record = { + browser: { + label: "Direct Download", + description: "Download the game in this browser", + action: () => { + alert("Direct download not yet implemented") + } + }, + torrent: { + label: "Torrent Download", + description: "Download the game as a torrent", + action: () => { + alert("Torrent download not yet implemented") + }, + isDisabled: true + } + } useEffect(() => { if (gameId) { @@ -24,14 +44,17 @@ export default function GameView() { }
-
-
- -
-
-

{game.title}

-

{game.release !== undefined ? new Date(game.release).getFullYear() : "unknown"}

+
+
+
+ +
+
+

{game.title}

+

{game.release !== undefined ? new Date(game.release).getFullYear() : "unknown"}

+
+

Summary