2 Commits
Author SHA1 Message Date
oxpoe e0090fc1c3 feat: suite uji mencetak pesan hasil + GAMEMAX_DEBUG menyalin log ke stdout
docs: bagian Updates (pemeriksaan & pembaruan satu klik dari GitHub Releases)
versi 1.2.2
2026-10-13 07:53:51 +07:00
oxpoe a47b5c251c fix(app): arahkan OpenSSL ke CA sistem pada bundel beku (periksa/unduh pembaruan gagal dengan CERTIFICATE_VERIFY_FAILED)
versi 1.2.1
2026-10-13 07:48:00 +07:00
2 changed files with 34 additions and 3 deletions

No files matched your search

+15
View File
@@ -105,6 +105,7 @@ temperature source (Tctl vs Tccd).
- **Plug and play**: the service waits for the device, streams while present and keeps - **Plug and play**: the service waits for the device, streams while present and keeps
waiting through unplug/replug; a udev rule grants access to the logged-in user waiting through unplug/replug; a udev rule grants access to the logged-in user
- **Single instance**: launching the app again just raises the running window - **Single instance**: launching the app again just raises the running window
- **Self-update from GitHub Releases** (check + one-click update)
- **Donate / GitHub buttons** in the app (window and tray menu) - **Donate / GitHub buttons** in the app (window and tray menu)
- **AppImage build** script (`packaging/build_appimage.sh`, PySide6 bundled) - **AppImage build** script (`packaging/build_appimage.sh`, PySide6 bundled)
@@ -208,6 +209,20 @@ docs/ reverse-engineering.md — full analysis (Indonesian)
assets/ previews and icon assets/ previews and icon
``` ```
## Updates
The app keeps itself current from GitHub Releases:
- On start (when running from an AppImage) and from the **Periksa pembaruan** button or the
tray menu, it asks the GitHub API for the latest release and compares it with its version.
- When a newer release exists, a **Perbarui ke vX.Y.Z** button appears. One click downloads
the release asset, replaces the running AppImage atomically, refreshes the sender from the
new bundle and restarts the service. Restart the app to use the new version.
- Nothing is downloaded without that click, and no other files are touched.
If the check fails (offline, proxy), the message appears in the app log. `GAMEMAX_DEBUG=1`
also mirrors the log to stdout for headless runs.
## Support ## Support
If this project is useful to you: If this project is useful to you:
+19 -3
View File
@@ -30,7 +30,7 @@ from PySide6.QtWidgets import (
) )
from PySide6.QtNetwork import QLocalServer, QLocalSocket from PySide6.QtNetwork import QLocalServer, QLocalSocket
APP_VERSION = "1.2.0" APP_VERSION = "1.2.2"
REPO = "oxpoe/Gamemax-linux-apps" REPO = "oxpoe/Gamemax-linux-apps"
RELEASES_API = f"https://api.github.com/repos/{REPO}/releases/latest" RELEASES_API = f"https://api.github.com/repos/{REPO}/releases/latest"
UPDATE_ASSET = "GAMEMAX-LCD-x86_64.AppImage" UPDATE_ASSET = "GAMEMAX-LCD-x86_64.AppImage"
@@ -84,8 +84,21 @@ def version_tuple(tag):
return tuple(int(p) for p in parts) or (0,) return tuple(int(p) for p in parts) or (0,)
def ensure_ca_bundle():
"""Bundel PyInstaller tidak menemukan CA sistem sendiri; arahkan OpenSSL ke sana."""
if os.environ.get("SSL_CERT_FILE"):
return
for path in ("/etc/ssl/certs/ca-certificates.crt", # Arch/Debian
"/etc/pki/tls/certs/ca-bundle.crt", # Fedora/openSUSE
"/etc/ssl/cert.pem"): # Alpine/BSD
if os.path.exists(path):
os.environ["SSL_CERT_FILE"] = path
return
def latest_release(): def latest_release():
"""(tag, url aset) dari rilis terbaru GitHub — dipanggil dari thread pekerja.""" """(tag, url aset) dari rilis terbaru GitHub — dipanggil dari thread pekerja."""
ensure_ca_bundle()
req = urllib.request.Request(RELEASES_API, headers={ req = urllib.request.Request(RELEASES_API, headers={
"Accept": "application/vnd.github+json", "User-Agent": "gamemax-lcd"}) "Accept": "application/vnd.github+json", "User-Agent": "gamemax-lcd"})
with urllib.request.urlopen(req, timeout=10) as resp: with urllib.request.urlopen(req, timeout=10) as resp:
@@ -487,6 +500,7 @@ class Window(QWidget):
self.start_task(f"mengunduh {tag}", lambda: self.do_update(tag, url, target)) self.start_task(f"mengunduh {tag}", lambda: self.do_update(tag, url, target))
def do_update(self, tag, url, target): def do_update(self, tag, url, target):
ensure_ca_bundle()
tmp = target + ".new" tmp = target + ".new"
urllib.request.urlretrieve(url, tmp) urllib.request.urlretrieve(url, tmp)
os.chmod(tmp, 0o755) os.chmod(tmp, 0o755)
@@ -671,6 +685,8 @@ class Window(QWidget):
def log(self, text): def log(self, text):
self.logview.appendPlainText(text) self.logview.appendPlainText(text)
if os.environ.get("GAMEMAX_DEBUG"):
print(text, flush=True)
def warn_once(self, text): def warn_once(self, text):
if getattr(self, "_warned", None) != text: if getattr(self, "_warned", None) != text:
@@ -882,8 +898,8 @@ def _main():
("periksa pembaruan", w.do_check_update)) ("periksa pembaruan", w.do_check_update))
for name, fn in steps: for name, fn in steps:
try: try:
fn() out = fn()
print(f"[ OK ] {name}") print(f"[ OK ] {name}" + (f" — {out}" if isinstance(out, str) and out else ""))
except Exception as exc: # noqa: BLE001 except Exception as exc: # noqa: BLE001
print(f"[GAGAL] {name}: {exc}") print(f"[GAGAL] {name}: {exc}")
# jalur asinkron yang dipakai tombol: centang layar kosong + simpan # jalur asinkron yang dipakai tombol: centang layar kosong + simpan