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
1 change: 1 addition & 0 deletions .claude/rules/updater.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
paths:
- "client/updater.py"
- "client/update_coord.py"
- "client/update_channel_choice.py"
- "client/update_background.py"
- "client/update_package.py"
- "client/update_progress.py"
Expand Down
2 changes: 2 additions & 0 deletions client/changelog_en-US.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ WHAT'S NEW

FIXES

- Updates: "Check for updates" in the Help menu now tells you when WinZapp could not reach the update server, instead of saying nothing.

- Synchronization: replayed history messages keep their chronological position instead of appearing as new arrivals. Temporary failures when checking an alternate chat address remain queued for retry.

- Forwarding no longer opens a box when it worked. "Message forwarded." (or how many messages were forwarded) is now said by the screen reader, with no window to close and without cutting off what is being read; it works with WinZapp in the tray too.
Expand Down
2 changes: 2 additions & 0 deletions client/changelog_es-ES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ NOVEDADES

CORRECCIONES

- Actualizaciones: "Comprobar actualizaciones", en el menú Ayuda, ahora avisa cuando WinZapp no puede conectar con el servidor de actualizaciones, en lugar de no decir nada.

- Sincronización: los mensajes antiguos recibidos de nuevo mantienen su orden cronológico en lugar de aparecer como nuevos. Los fallos temporales al consultar una dirección alternativa del chat quedan pendientes para volver a intentarlo.

- Reenviar ya no abre un cuadro cuando sale bien. "Mensaje reenviado." (o cuántos mensajes se han reenviado) ahora lo dice el lector de pantalla, sin ventana que cerrar y sin interrumpir lo que se está leyendo; también funciona con WinZapp en la bandeja.
Expand Down
2 changes: 2 additions & 0 deletions client/changelog_pl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ NOWOŚCI

POPRAWKI

- Aktualizacje: „Sprawdź aktualizacje” w menu Pomoc informuje teraz, gdy WinZapp nie może połączyć się z serwerem aktualizacji, zamiast nic nie mówić.

- Synchronizacja: ponownie otrzymane starsze wiadomości zachowują kolejność chronologiczną, zamiast pojawiać się jako nowe. Tymczasowe błędy sprawdzania alternatywnego adresu czatu pozostają w kolejce do ponowienia.

- Przekazywanie dalej nie otwiera już okna, gdy się uda. „Wiadomość przekazana.” (albo liczbę przekazanych wiadomości) mówi teraz czytnik ekranu, bez okna do zamknięcia i bez przerywania tego, co jest czytane; działa też, gdy WinZapp jest w zasobniku.
Expand Down
2 changes: 2 additions & 0 deletions client/changelog_pt-BR.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ NOVIDADES

CORREÇÕES

- Atualizações: "Verificar atualizações", no menu Ajuda, agora avisa quando o WinZapp não consegue acessar o servidor de atualizações, em vez de não dizer nada.

- Sincronização: mensagens antigas recebidas novamente mantêm a ordem cronológica, em vez de aparecerem como novas. Falhas temporárias ao consultar um endereço alternativo da conversa continuam na fila para nova tentativa.

- Encaminhar não abre mais uma caixa quando dá certo. "Mensagem encaminhada." (ou quantas mensagens foram encaminhadas) agora é falado pelo leitor de tela, sem janela para fechar e sem interromper o que está sendo lido; funciona também com o WinZapp na bandeja.
Expand Down
2 changes: 2 additions & 0 deletions client/changelog_pt-PT.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ NOVIDADES

CORREÇÕES

- Atualizações: "Verificar atualizações", no menu Ajuda, passa a avisar quando o WinZapp não consegue aceder ao servidor de atualizações, em vez de não dizer nada.

- Sincronização: mensagens antigas recebidas novamente mantêm a ordem cronológica, em vez de aparecerem como novas. Falhas temporárias ao consultar um endereço alternativo da conversa continuam na fila para nova tentativa.

- Reencaminhar deixa de abrir uma caixa quando corre bem. "Mensagem reencaminhada." (ou quantas mensagens foram reencaminhadas) passa a ser dito pelo leitor de ecrã, sem janela para fechar e sem interromper o que está a ser lido; funciona também com o WinZapp na área de notificação.
Expand Down
2 changes: 2 additions & 0 deletions client/changelog_ro.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ NOUTĂȚI

CORECTĂRI

- Actualizări: „Verificați actualizările” din meniul Ajutor vă anunță acum când WinZapp nu poate contacta serverul de actualizări, în loc să nu spună nimic.

- Sincronizare: mesajele vechi primite din nou își păstrează ordinea cronologică, în loc să apară ca mesaje noi. Erorile temporare la verificarea unei adrese alternative a conversației rămân în coadă pentru o nouă încercare.

- Redirecționarea nu mai deschide o casetă când a reușit. „Mesajul a fost redirecționat.” (sau câte mesaje au fost redirecționate) este acum rostit de cititorul de ecran, fără o fereastră de închis și fără a întrerupe ce se citește; funcționează și cu WinZapp în bara de sistem.
Expand Down
2 changes: 2 additions & 0 deletions client/changelog_tr-TR.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ YENİLİKLER

DÜZELTMELER

- Güncellemeler: Yardım menüsündeki "Güncellemeleri denetle", WinZapp güncelleme sunucusuna ulaşamadığında artık sessiz kalmak yerine bunu bildirir.

- Eşitleme: Tekrar gelen geçmiş mesajlar yeni gelmiş gibi sona eklenmez; tarih sırası korunur. Sohbetin alternatif adresini sorgularken oluşan geçici hatalar yeniden denemek üzere kuyrukta tutulur.

- İletme başarılı olduğunda artık bir kutu açmıyor. "Mesaj iletildi." (ya da kaç mesajın iletildiği) artık ekran okuyucu tarafından söyleniyor; kapatılacak bir pencere yok ve okunan şey kesilmiyor. WinZapp sistem tepsisindeyken de çalışır.
Expand Down
6 changes: 3 additions & 3 deletions client/core/update_keeps_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@

def _read_package(path: str) -> dict:
try:
with open(path, encoding="utf-8-sig") as fh:
data = json.load(fh)
with open(path, encoding="utf-8") as fh:
data = json.loads(fh.read().removeprefix("\ufeff"))
return data if isinstance(data, dict) else {}
except (OSError, ValueError):
except (OSError, ValueError, LookupError):
return {}


Expand Down
6 changes: 3 additions & 3 deletions client/core/wa_version_refresh.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,9 @@ def safe_extract(tar_bytes: bytes, dest: str) -> None:

def _read_json(path: str):
try:
with open(path, encoding="utf-8-sig") as fh:
return json.load(fh)
except (OSError, ValueError):
with open(path, encoding="utf-8") as fh:
return json.loads(fh.read().removeprefix("\ufeff"))
except (OSError, ValueError, LookupError):
return None


Expand Down
19 changes: 9 additions & 10 deletions client/core/wpp_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,12 @@ def read_homologated_wpp_version(path: str) -> str:
with no Node server behind it and nothing said out loud.
"""
try:
# utf-8-sig, not utf-8: the file is committed and edited by hand on
# Windows, where an editor saving it with a BOM would otherwise leave
# the BOM character glued to the front of the version — and to the
# front of the tag every install path then tries to check out.
with open(path, encoding="utf-8-sig") as fh:
return fh.read().strip()
except (OSError, ValueError):
# Keep BOM support without depending on the separately loaded
# utf_8_sig codec in frozen installs. Strict decoding still rejects a
# corrupt version instead of turning it into a non-existent git tag.
with open(path, encoding="utf-8") as fh:
return fh.read().removeprefix("\ufeff").strip()
except (OSError, ValueError, LookupError):
return ""


Expand Down Expand Up @@ -77,10 +76,10 @@ def _read_json(path: str) -> dict:
"""
try:
import json
with open(path, encoding="utf-8-sig") as fh:
data = json.load(fh)
with open(path, encoding="utf-8") as fh:
data = json.loads(fh.read().removeprefix("\ufeff"))
return data if isinstance(data, dict) else {}
except (OSError, ValueError):
except (OSError, ValueError, LookupError):
return {}


Expand Down
103 changes: 103 additions & 0 deletions client/update_channel_choice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""One explicitly requested alpha offer, without changing the saved channel.

The normal updater still owns release eligibility, signatures and installation.
This mixin only owns the additional consent dialog and its prompt claim.
"""
import logging

import wx

from core.dialog_foreground import message_box


class AlphaChannelChoiceMixin:
def _queue_alpha_channel_choice(self, release: dict, changelog: str) -> None:
with self._channel_choice_lock:
if self._channel_choice_pending:
return
self._channel_choice_pending = True
token = self._channel_choice_token = object()
version = release["tag_name"].lstrip("vV")
claimed = self._claim_prompt(version)
if not claimed:
self._channel_choice_pending = False
self._channel_choice_token = None
if not claimed:
self._schedule_retry()
wx.CallAfter(self._show_prompt_open_elsewhere)
return
try:
wx.CallAfter(self._show_alpha_channel_choice, release, changelog, token)
except Exception:
self._finish_alpha_channel_choice(token)
raise

def _finish_alpha_channel_choice(self, token) -> None:
with self._channel_choice_lock:
if token is not self._channel_choice_token:
return
self._channel_choice_pending = False
self._channel_choice_token = None
if getattr(self, "_install_pending", False) or getattr(self, "_background_version", ""):
return
self._release_prompt()
if not self._channel_choice_cancelled:
self._schedule_retry()

def _show_alpha_channel_choice(self, release: dict, changelog: str, token) -> None:
with self._channel_choice_lock:
if token is not self._channel_choice_token:
return
if getattr(self, "_install_pending", False) or getattr(self, "_background_version", ""):
# An accepted installation now owns the claim; a stale consent
# callback must not hand that installation's claim back.
self._finish_alpha_channel_choice(token)
return
if self._channel_choice_cancelled or getattr(self._mw, "_shutting_down", False):
self._finish_alpha_channel_choice(token)
return
if not self._main_window_ready():
try:
wx.CallLater(self._UI_NOT_READY_RETRY_MS, self._show_alpha_channel_choice,
release, changelog, token)
except Exception:
logging.exception("Auto-updater: could not defer the alpha choice")
self._finish_alpha_channel_choice(token)
return
handed_over = False
try:
from updater import (__version__, find_zip_asset, _find_sha256sums_asset,
_find_signature_asset, is_alpha_release)
i18n = self._mw.i18n
title = i18n.t("update_alpha_choice_title")
message = i18n.t("update_alpha_choice_message").format(
current=__version__, new=release["tag_name"].lstrip("vV"))
answer = message_box(
self._mw, message, title,
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION,
announce=lambda: self._mw.output(f"{title}. {message}", interrupt=True),
)
if answer != wx.YES:
return
with self._channel_choice_lock:
if self._channel_choice_cancelled or token is not self._channel_choice_token:
return
# Consent covers this snapshot only. Do not turn the install-wide
# checkbox on, and do not refetch a different alpha after consent.
self._show_update_dialog(
release["tag_name"].lstrip("vV"), changelog,
find_zip_asset(release.get("assets", [])),
_find_sha256sums_asset(release.get("assets", [])),
signature_url=_find_signature_asset(release.get("assets", [])),
is_alpha=is_alpha_release(release),
)
handed_over = True
with self._channel_choice_lock:
if token is self._channel_choice_token:
self._channel_choice_pending = False
self._channel_choice_token = None
except Exception:
logging.exception("Auto-updater: the alpha channel choice failed")
finally:
if not handed_over:
self._finish_alpha_channel_choice(token)
Loading