Add refresh button with 60s cooldown timer

Adds a view-refresh icon button in the top-right corner to re-fetch the
Steam library. A countdown label appears below it during the cooldown and
hides when the timer expires, preventing API spam.
This commit is contained in:
2026-04-02 06:35:36 -04:00
parent 02f561b3ac
commit 8eaee99196

View File

@@ -9,7 +9,7 @@ import requests
if os.environ.get("WAYLAND_DISPLAY"):
os.environ.setdefault("QT_QPA_PLATFORM", "wayland")
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtCore import Qt, QThread, QTimer, pyqtSignal
from PyQt6.QtGui import QPixmap, QFont, QIcon
VERSION = "v0.1.0"
@@ -32,12 +32,15 @@ STEAM_ID = "76561198000382373"
IMG_W = 460
IMG_H = 215
MARGIN = 20
TOP_ROW_H = 46 # refresh button (28) + gap (4) + cooldown label (14)
TITLE_H = 30
STATUS_H = 20
DICE_H = 100
SPACING = 12
REFRESH_COOLDOWN = 60 # seconds
WIN_W = IMG_W + MARGIN * 2
WIN_H = MARGIN + TITLE_H + SPACING + IMG_H + SPACING + STATUS_H + SPACING + DICE_H + MARGIN
WIN_H = (MARGIN + TOP_ROW_H + SPACING + TITLE_H + SPACING
+ IMG_H + SPACING + STATUS_H + SPACING + DICE_H + MARGIN)
DICE_FACES = "⚀⚁⚂⚃⚄⚅"
@@ -58,6 +61,18 @@ DICE_STYLE = """
QPushButton:disabled { color: #4a5a6a; }
"""
REFRESH_STYLE = """
QPushButton {
background: transparent;
border: none;
padding: 2px;
border-radius: 4px;
}
QPushButton:hover { background: rgba(255, 255, 255, 0.08); }
QPushButton:pressed { background: rgba(255, 255, 255, 0.04); }
QPushButton:disabled { opacity: 0.3; }
"""
class FetchLibraryThread(QThread):
done = pyqtSignal(list)
@@ -101,6 +116,7 @@ class SteamDice(QMainWindow):
super().__init__()
self.games = []
self.image_thread = None
self.cooldown_remaining = 0
self.setWindowTitle("Steam Dice")
self.setFixedSize(WIN_W, WIN_H)
@@ -114,6 +130,43 @@ class SteamDice(QMainWindow):
layout.setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN)
layout.setSpacing(SPACING)
# Top row: refresh button + cooldown label pinned to right
top_row = QHBoxLayout()
top_row.setContentsMargins(0, 0, 0, 0)
top_row.addStretch()
refresh_col = QVBoxLayout()
refresh_col.setSpacing(4)
refresh_col.setContentsMargins(0, 0, 0, 0)
self.refresh_btn = QPushButton()
self.refresh_btn.setIcon(QIcon.fromTheme("view-refresh"))
self.refresh_btn.setIconSize(self.refresh_btn.sizeHint())
self.refresh_btn.setFixedSize(28, 28)
self.refresh_btn.setStyleSheet(REFRESH_STYLE)
self.refresh_btn.setCursor(Qt.CursorShape.PointingHandCursor)
self.refresh_btn.setToolTip("Refresh game library")
self.refresh_btn.setEnabled(False)
self.refresh_btn.clicked.connect(self._refresh)
refresh_col.addWidget(self.refresh_btn, alignment=Qt.AlignmentFlag.AlignRight)
self.cooldown_label = QLabel()
self.cooldown_label.setFixedHeight(14)
cooldown_font = QFont()
cooldown_font.setPointSize(8)
self.cooldown_label.setFont(cooldown_font)
self.cooldown_label.setStyleSheet("color: #4a5a6a;")
self.cooldown_label.setAlignment(Qt.AlignmentFlag.AlignRight)
self.cooldown_label.setVisible(False)
refresh_col.addWidget(self.cooldown_label)
top_row.addLayout(refresh_col)
layout.addLayout(top_row)
self._cooldown_timer = QTimer()
self._cooldown_timer.setInterval(1000)
self._cooldown_timer.timeout.connect(self._on_cooldown_tick)
# Game title
self.title_label = QLabel()
self.title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
@@ -186,9 +239,30 @@ class SteamDice(QMainWindow):
self.games = games
self.status_label.setText(f"{len(games)} games — roll the dice!")
self.dice_btn.setEnabled(True)
self.refresh_btn.setEnabled(True)
def _on_library_error(self, msg):
self.status_label.setText(f"Error loading library: {msg}")
self.refresh_btn.setEnabled(True)
def _refresh(self):
self.refresh_btn.setEnabled(False)
self.dice_btn.setEnabled(False)
self.status_label.setText("Refreshing library…")
self.cooldown_remaining = REFRESH_COOLDOWN
self.cooldown_label.setText(f"{self.cooldown_remaining}s")
self.cooldown_label.setVisible(True)
self._cooldown_timer.start()
self._fetch_library()
def _on_cooldown_tick(self):
self.cooldown_remaining -= 1
if self.cooldown_remaining <= 0:
self._cooldown_timer.stop()
self.cooldown_label.setVisible(False)
self.refresh_btn.setEnabled(True)
else:
self.cooldown_label.setText(f"{self.cooldown_remaining}s")
def roll(self):
if not self.games: