From 769213288e256c7b40cfac927c1f512f9e2543bc Mon Sep 17 00:00:00 2001 From: Novattz Date: Sat, 28 Mar 2026 15:06:09 +0100 Subject: [PATCH] reflect votes in dialogs #22 --- .../dialogs/SmokeAPIVotesDialog.tsx | 110 ++++++++++++++++++ .../dialogs/UnlockerSelectionDialog.tsx | 35 +++++- 2 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 src/components/dialogs/SmokeAPIVotesDialog.tsx diff --git a/src/components/dialogs/SmokeAPIVotesDialog.tsx b/src/components/dialogs/SmokeAPIVotesDialog.tsx new file mode 100644 index 0000000..d6eb063 --- /dev/null +++ b/src/components/dialogs/SmokeAPIVotesDialog.tsx @@ -0,0 +1,110 @@ +import React, { useEffect, useState } from 'react' +import { invoke } from '@tauri-apps/api/core' +import { + Dialog, + DialogHeader, + DialogBody, + DialogFooter, + DialogActions, +} from '@/components/dialogs' +import { Button } from '@/components/buttons' +import { Icon, info } from '@/components/icons' +import VotesDisplay, { GameVotes } from '@/components/common/VotesDisplay' + +export interface SmokeAPIVotesDialogProps { + visible: boolean + gameId: string | null + gameTitle: string | null + onConfirm: () => void + onClose: () => void +} + +/** + * Shown before installing SmokeAPI on a Proton game. + * Fetches and displays community votes for SmokeAPI specifically, + * then lets the user confirm or cancel the installation. + */ +const SmokeAPIVotesDialog: React.FC = ({ + visible, + gameId, + gameTitle, + onConfirm, + onClose, +}) => { + const [votes, setVotes] = useState(null) + const [loading, setLoading] = useState(false) + + useEffect(() => { + if (!visible || !gameId) { + setVotes(null) + return + } + + setLoading(true) + invoke('get_game_votes', { gameId }) + .then((results) => { + setVotes(results.find((v) => v.unlocker === 'smokeapi') ?? null) + }) + .catch(() => setVotes(null)) + .finally(() => setLoading(false)) + }, [visible, gameId]) + + const hasVotes = votes && (votes.success > 0 || votes.fail > 0) + + return ( + + +

Install SmokeAPI

+
+ + +
+

+ {gameTitle} +

+ +
+

Community compatibility

+ {loading ? ( +

Fetching votes...

+ ) : ( + + )} +
+ + {!loading && !hasVotes && ( +
+ + + No one has rated this game yet. You'll be able to submit a rating after + installing. + +
+ )} + + {!loading && hasVotes && ( +
+ + + These ratings are from other CreamLinux users. Results may vary. + +
+ )} +
+
+ + + + + + + +
+ ) +} + +export default SmokeAPIVotesDialog \ No newline at end of file diff --git a/src/components/dialogs/UnlockerSelectionDialog.tsx b/src/components/dialogs/UnlockerSelectionDialog.tsx index ec89b8c..802786c 100644 --- a/src/components/dialogs/UnlockerSelectionDialog.tsx +++ b/src/components/dialogs/UnlockerSelectionDialog.tsx @@ -1,4 +1,5 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' +import { invoke } from '@tauri-apps/api/core' import { Dialog, DialogHeader, @@ -8,10 +9,12 @@ import { } from '@/components/dialogs' import { Button } from '@/components/buttons' import { Icon, info } from '@/components/icons' +import VotesDisplay, { GameVotes } from '@/components/common/VotesDisplay' export interface UnlockerSelectionDialogProps { visible: boolean - gameTitle: string + gameId: string | null + gameTitle: string | null onClose: () => void onSelectCreamLinux: () => void onSelectSmokeAPI: () => void @@ -19,15 +22,39 @@ export interface UnlockerSelectionDialogProps { /** * Unlocker Selection Dialog component - * Allows users to choose between CreamLinux and SmokeAPI for native Linux games + * Allows users to choose between CreamLinux and SmokeAPI for native Linux games. + * Fetches and displays community vote data per unlocker. */ const UnlockerSelectionDialog: React.FC = ({ visible, + gameId, gameTitle, onClose, onSelectCreamLinux, onSelectSmokeAPI, }) => { + const [creamVotes, setCreamVotes] = useState(null) + const [smokeVotes, setSmokeVotes] = useState(null) + + useEffect(() => { + if (!visible || !gameId) { + setCreamVotes(null) + setSmokeVotes(null) + return + } + + invoke('get_game_votes', { gameId }) + .then((results) => { + setCreamVotes(results.find((v) => v.unlocker === 'creamlinux') ?? null) + setSmokeVotes(results.find((v) => v.unlocker === 'smokeapi') ?? null) + }) + .catch(() => { + // Votes are non-critical — silently fall back to "No votes yet" + setCreamVotes(null) + setSmokeVotes(null) + }) + }, [visible, gameId]) + return ( @@ -52,6 +79,7 @@ const UnlockerSelectionDialog: React.FC = ({ Native Linux DLC unlocker. Works best with most native Linux games and provides better compatibility.

+ @@ -66,6 +94,7 @@ const UnlockerSelectionDialog: React.FC = ({ Cross-platform DLC unlocker. Try this if CreamLinux doesn't work for your game. Automatically fetches DLC information.

+