Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
attributes:
label: Version de PZ SaveSync
description: Affichée en bas à gauche de la fenêtre
placeholder: "ex. v0.3.0"
placeholder: "ex. v0.3.1"
validations:
required: true

Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/), versioning
sémantique ([SemVer](https://semver.org/lang/fr/)).

## [0.3.1] — 2026-05-21

### Fixed
- **Freeze UI à chaque clic sur certains PC** : le polling de Project Zomboid
(toutes les 15 s) appelait `tasklist` de manière synchrone sur le thread UI.
Sur les PC où `tasklist` est lent (antivirus actif, beaucoup de process), ça
bloquait l'interface plusieurs secondes à chaque tick. Le poll s'exécute
maintenant dans un thread daemon, et le résultat est marshalé sur le main
thread via `self.after(0, ...)`.

## [0.3.0] — 2026-05-21

### Added — Distribution & dev experience
Expand Down
28 changes: 28 additions & 0 deletions docs/release_notes_v0.3.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## 🩹 PZ SaveSync v0.3.1 — Hotfix anti-freeze

Patch ciblé sur un bug remonté en early testing : sur certains PC, l'interface freezait plusieurs secondes à chaque interaction.

### 📥 Installation rapide

Télécharge **`PZSaveSync.exe`** ci-dessous, double-clique pour remplacer ton ancienne version. Ta config et tes profils sont conservés.

> ℹ️ Windows SmartScreen affichera un avertissement « éditeur inconnu » au premier lancement (exe non signé). Clique sur **« Informations complémentaires » → « Exécuter quand même »**.

### 🐛 Corrigé

- **Freeze UI à chaque clic** sur certains setups. Le polling du process Project Zomboid (toutes les 15 s pour détecter quand tu fermes le jeu) appelait `tasklist` de manière synchrone sur le thread UI. Sur les PC où `tasklist` est lent à répondre (antivirus actif inspectant le call, beaucoup de process ouverts), ça bloquait l'interface plusieurs secondes à chaque tick — et la sensation était « ça freeze à chaque clic ».

Le poll s'exécute maintenant dans un **thread daemon séparé**, et le résultat est marshalé sur le main thread via `self.after(0, ...)`. Plus aucun blocage UI dû au polling.

### 🔧 Migration depuis v0.3.0

- **Aucune action requise.** Drop-in replacement du `.exe`. Config, profils et historique des versions préservés.

### 🧪 Tests

- Tous les tests existants (45 unitaires + 2 intégration) passent.
- Build PyInstaller : `.exe` final ~21 MB.

### 📜 Licence

Source Available — Tous droits réservés. Voir [LICENSE](https://github.com/Mistercarmi/PZSaveSync/blob/main/LICENSE).
29 changes: 19 additions & 10 deletions src/pzsavesync/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
import platform
import subprocess
import threading
from pathlib import Path
from tkinter import filedialog, messagebox

Expand Down Expand Up @@ -84,7 +85,7 @@ def _open_path(path: Path | str) -> None:
ACTION_DANGER = "#b24545" # rouge, attention
ACTION_RELEASE = "#7a5a3a" # brun chaud (libérer un verrou — sobre, pas dangereux)

APP_VERSION = "0.3.0"
APP_VERSION = "0.3.1"


_AppBase = (ctk.CTk, TkinterDnD.DnDWrapper) if _DND_AVAILABLE else (ctk.CTk,)
Expand Down Expand Up @@ -1996,31 +1997,39 @@ def _schedule_pz_poll(self):
self.after(15000, self._poll_pz)

def _poll_pz(self):
try:
running, _ = pz_detector.is_pz_running()
except Exception:
running = False
# On exécute is_pz_running() dans un thread daemon : sur certains PC
# (antivirus actif, beaucoup de process) tasklist peut prendre plusieurs
# secondes et bloquerait sinon le main thread → freeze UI à chaque poll.
def worker():
try:
running, _ = pz_detector.is_pz_running()
except Exception:
running = False
try:
self.after(0, self._handle_pz_poll_result, running)
except Exception:
pass

threading.Thread(target=worker, daemon=True).start()
# Re-scheduler indépendamment du résultat
self.after(15000, self._poll_pz)

def _handle_pz_poll_result(self, running: bool):
if running:
self._pz_was_running = True
# MAJ footer pour indiquer qu'on voit PZ
if hasattr(self, "footer_pz_status"):
self.footer_pz_status.configure(
text="🎮 PZ détecté", text_color=COLOR_OK,
)
else:
if self._pz_was_running and self.cfg.save_name:
# Transition running → stopped : propose un push
self._pz_was_running = False
if hasattr(self, "footer_pz_status"):
self.footer_pz_status.configure(text="", text_color=COLOR_TEXT_DIM)
self.after(0, self._prompt_push_after_pz_close)
elif hasattr(self, "footer_pz_status"):
self.footer_pz_status.configure(text="", text_color=COLOR_TEXT_DIM)

# Re-scheduler
self.after(15000, self._poll_pz)

def _prompt_push_after_pz_close(self):
if not self.cfg.save_name:
return
Expand Down
Loading