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"): if os.environ.get("WAYLAND_DISPLAY"):
os.environ.setdefault("QT_QPA_PLATFORM", "wayland") os.environ.setdefault("QT_QPA_PLATFORM", "wayland")
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel 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 from PyQt6.QtGui import QPixmap, QFont, QIcon
VERSION = "v0.1.0" VERSION = "v0.1.0"
@@ -32,12 +32,15 @@ STEAM_ID = "76561198000382373"
IMG_W = 460 IMG_W = 460
IMG_H = 215 IMG_H = 215
MARGIN = 20 MARGIN = 20
TOP_ROW_H = 46 # refresh button (28) + gap (4) + cooldown label (14)
TITLE_H = 30 TITLE_H = 30
STATUS_H = 20 STATUS_H = 20
DICE_H = 100 DICE_H = 100
SPACING = 12 SPACING = 12
REFRESH_COOLDOWN = 60 # seconds
WIN_W = IMG_W + MARGIN * 2 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 = "⚀⚁⚂⚃⚄⚅" DICE_FACES = "⚀⚁⚂⚃⚄⚅"
@@ -58,6 +61,18 @@ DICE_STYLE = """
QPushButton:disabled { color: #4a5a6a; } 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): class FetchLibraryThread(QThread):
done = pyqtSignal(list) done = pyqtSignal(list)
@@ -101,6 +116,7 @@ class SteamDice(QMainWindow):
super().__init__() super().__init__()
self.games = [] self.games = []
self.image_thread = None self.image_thread = None
self.cooldown_remaining = 0
self.setWindowTitle("Steam Dice") self.setWindowTitle("Steam Dice")
self.setFixedSize(WIN_W, WIN_H) self.setFixedSize(WIN_W, WIN_H)
@@ -114,6 +130,43 @@ class SteamDice(QMainWindow):
layout.setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN) layout.setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN)
layout.setSpacing(SPACING) 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 # Game title
self.title_label = QLabel() self.title_label = QLabel()
self.title_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
@@ -186,9 +239,30 @@ class SteamDice(QMainWindow):
self.games = games self.games = games
self.status_label.setText(f"{len(games)} games — roll the dice!") self.status_label.setText(f"{len(games)} games — roll the dice!")
self.dice_btn.setEnabled(True) self.dice_btn.setEnabled(True)
self.refresh_btn.setEnabled(True)
def _on_library_error(self, msg): def _on_library_error(self, msg):
self.status_label.setText(f"Error loading library: {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): def roll(self):
if not self.games: if not self.games: