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 (
+
+ )
+}
+
+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 (
+
@@ -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.
+