From 3e0cb7181183292cc4dcbf312a910f740671fc7b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 14:25:12 +0000 Subject: [PATCH 1/3] Chamadas em grupo: limite de 32 participantes Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01TxZ4WQst6v5HP4WM9yMPC9 --- client/changelog_en-US.txt | 2 + client/changelog_es-ES.txt | 2 + client/changelog_pl.txt | 2 + client/changelog_pt-BR.txt | 2 + client/changelog_pt-PT.txt | 2 + client/changelog_ro.txt | 2 + client/changelog_tr-TR.txt | 2 + client/core/call_logic.py | 14 +++ client/data/help_guide/en-US.html | 1 + client/data/help_guide/es-ES.html | 1 + client/data/help_guide/pl.html | 1 + client/data/help_guide/pt-BR.html | 1 + client/data/help_guide/pt-PT.html | 1 + client/data/help_guide/ro.html | 1 + client/data/help_guide/tr-TR.html | 1 + client/ui/conversation_panel/composer.py | 36 +++++++- .../conversation_navigation.py | 1 + client/ui/conversation_panel/mentions.py | 1 + client/ui/conversations.py | 13 +++ docs/user-guide/cobertura.json | 1 + docs/user-guide/secoes/en-US/09-ligacoes.html | 1 + docs/user-guide/secoes/es-ES/09-ligacoes.html | 1 + docs/user-guide/secoes/pl/09-ligacoes.html | 1 + docs/user-guide/secoes/pt-BR/09-ligacoes.html | 1 + docs/user-guide/secoes/pt-PT/09-ligacoes.html | 1 + docs/user-guide/secoes/ro/09-ligacoes.html | 1 + docs/user-guide/secoes/tr-TR/09-ligacoes.html | 1 + tests/test_sync_voice_call_button.py | 87 +++++++++++++++++++ translations/en-US/LC_MESSAGES/winzapp.po | 12 +++ translations/es-ES/LC_MESSAGES/winzapp.po | 12 +++ translations/pl/LC_MESSAGES/winzapp.po | 12 +++ translations/pt-BR/LC_MESSAGES/winzapp.po | 12 +++ translations/pt-PT/LC_MESSAGES/winzapp.po | 12 +++ translations/ro/LC_MESSAGES/winzapp.po | 12 +++ translations/tr-TR/LC_MESSAGES/winzapp.po | 12 +++ translations/winzapp.pot | 12 +++ 36 files changed, 275 insertions(+), 2 deletions(-) diff --git a/client/changelog_en-US.txt b/client/changelog_en-US.txt index a373f5d11..2b671c260 100644 --- a/client/changelog_en-US.txt +++ b/client/changelog_en-US.txt @@ -4,6 +4,8 @@ This release brings communities and a reorganized settings window, on top of eve WHAT'S NEW +- Group calls: a group with more than 32 participants cannot be called on WhatsApp, so the call buttons are replaced by a "Calling is not possible" button whose note says the group has more than 32 participants, and the call shortcuts say the same instead of starting a call. + - Group calls: the voice and video call buttons now appear in a group conversation and start a call to the group, and an incoming group call rings, is announced by the group's name and can be answered, with the same Answer button and global answer key as a one-to-one call. Turning the camera on during a voice call works as it does in a one-to-one call, and call events from each participant stay with the group, so the call window keeps the group's name from the first ring to the end. - Video calls: WinZapp now finds the camera with the FFmpeg build it ships, which lists DirectShow devices without the "DirectShow video devices" heading. That build returned no camera at all, so a video call went out receive-only, with "No camera found" in the log. diff --git a/client/changelog_es-ES.txt b/client/changelog_es-ES.txt index 35e43aba2..5c219428f 100644 --- a/client/changelog_es-ES.txt +++ b/client/changelog_es-ES.txt @@ -4,6 +4,8 @@ Esta versión trae las comunidades y una ventana de configuración reorganizada, NOVEDADES +- Llamadas de grupo: WhatsApp no permite llamar a grupos con más de 32 participantes, así que los botones de llamada se sustituyen por un botón "No es posible llamar" cuya nota dice que el grupo tiene más de 32 participantes, y los atajos de llamada dicen lo mismo en lugar de iniciar la llamada. + - Llamadas grupales: los botones de llamada de voz y de vídeo aparecen ahora en la conversación del grupo e inician una llamada al grupo, y una llamada grupal entrante suena, se anuncia con el nombre del grupo y se puede contestar, con el mismo botón de contestar y el mismo atajo global de contestar que una llamada individual. Activar la cámara durante una llamada de voz funciona como en una llamada individual, y los eventos de llamada de cada participante quedan con el grupo, así que la ventana de la llamada mantiene el nombre del grupo desde el primer tono hasta el final. - Videollamadas: WinZapp ahora encuentra la cámara con el FFmpeg incluido en WinZapp, que enumera los dispositivos DirectShow sin el encabezado "DirectShow video devices". Esa versión de FFmpeg no devolvía ninguna cámara, así que la videollamada salía solo recibiendo, con "No camera found" en el registro. diff --git a/client/changelog_pl.txt b/client/changelog_pl.txt index d1333c8b0..c4162e10a 100644 --- a/client/changelog_pl.txt +++ b/client/changelog_pl.txt @@ -4,6 +4,8 @@ W tej wersji pojawiają się społeczności i zreorganizowane okno ustawień, op NOWOŚCI +- Połączenia grupowe: WhatsApp nie pozwala dzwonić do grup liczących więcej niż 32 członków, więc przyciski połączeń zastępuje przycisk "Nie można zadzwonić", którego opis mówi, że grupa ma więcej niż 32 członków, a skróty połączeń mówią to samo zamiast rozpoczynać połączenie. + - Połączenia grupowe: przyciski połączenia głosowego i wideo pojawiają się teraz w rozmowie grupowej i rozpoczynają połączenie z grupą, a przychodzące połączenie grupowe dzwoni, jest zapowiadane nazwą grupy i można je odebrać tym samym przyciskiem odbierania i tym samym globalnym skrótem odbierania co połączenie indywidualne. Włączenie kamery podczas połączenia głosowego działa jak w połączeniu indywidualnym, a zdarzenia połączenia od każdego uczestnika pozostają przy grupie, więc okno połączenia zachowuje nazwę grupy od pierwszego dzwonka do końca. - Połączenia wideo: WinZapp znajduje teraz kamerę za pomocą dołączonego FFmpeg, który wyświetla urządzenia DirectShow bez nagłówka „DirectShow video devices”. Ta wersja FFmpeg nie zwracała żadnej kamery, więc połączenie wideo było tylko odbiorcze, z „No camera found” w logu. diff --git a/client/changelog_pt-BR.txt b/client/changelog_pt-BR.txt index 3d80f0533..5ee76660c 100644 --- a/client/changelog_pt-BR.txt +++ b/client/changelog_pt-BR.txt @@ -4,6 +4,8 @@ Esta versão traz as comunidades e uma janela de configurações reorganizada, a NOVIDADES +- Chamadas em grupo: o WhatsApp não permite ligar para grupos com mais de 32 participantes, então os botões de ligação são trocados por um botão "Não é possível ligar" cuja nota diz que o grupo possui mais de 32 participantes, e os atalhos de ligação dizem o mesmo em vez de iniciar a ligação. + - Chamadas em grupo: os botões de chamada de voz e de vídeo agora aparecem na conversa do grupo e iniciam uma chamada para o grupo, e uma chamada em grupo recebida toca, é anunciada pelo nome do grupo e pode ser atendida, com o mesmo botão de atender e o mesmo atalho global de atender de uma chamada individual. Ligar a câmera durante uma chamada de voz funciona como numa chamada individual, e os eventos de chamada de cada participante ficam com o grupo, então a janela da chamada mantém o nome do grupo do primeiro toque até o fim. - Chamadas de vídeo: o WinZapp agora encontra a câmera com o FFmpeg incluído no WinZapp, que lista os dispositivos DirectShow sem o cabeçalho "DirectShow video devices". Essa versão do FFmpeg não retornava câmera nenhuma, então a chamada de vídeo saía só recebendo, com "No camera found" no log. diff --git a/client/changelog_pt-PT.txt b/client/changelog_pt-PT.txt index 876d805fa..fc143d1b9 100644 --- a/client/changelog_pt-PT.txt +++ b/client/changelog_pt-PT.txt @@ -4,6 +4,8 @@ Esta versão traz as comunidades e uma janela de definições reorganizada, alé NOVIDADES +- Chamadas de grupo: o WhatsApp não permite ligar para grupos com mais de 32 membros, pelo que os botões de chamada são substituídos por um botão "Não é possível ligar" cuja nota diz que o grupo tem mais de 32 membros, e os atalhos de chamada dizem o mesmo em vez de iniciar a chamada. + - Chamadas de grupo: os botões de chamada de voz e de vídeo aparecem agora na conversa do grupo e iniciam uma chamada para o grupo, e uma chamada de grupo recebida toca, é anunciada pelo nome do grupo e pode ser atendida, com o mesmo botão de atender e o mesmo atalho global de atender de uma chamada individual. Ligar a câmara durante uma chamada de voz funciona como numa chamada individual, e os eventos de chamada de cada participante ficam com o grupo, pelo que a janela da chamada mantém o nome do grupo desde o primeiro toque até ao fim. - Chamadas de vídeo: o WinZapp encontra agora a câmara com o FFmpeg incluído no WinZapp, que lista os dispositivos DirectShow sem o cabeçalho "DirectShow video devices". Essa versão do FFmpeg não devolvia câmara nenhuma, pelo que a chamada de vídeo seguia apenas a receber, com "No camera found" no registo. diff --git a/client/changelog_ro.txt b/client/changelog_ro.txt index 7c0f2c513..7892bb6ae 100644 --- a/client/changelog_ro.txt +++ b/client/changelog_ro.txt @@ -4,6 +4,8 @@ Această versiune aduce comunitățile și o fereastră de setări reorganizată NOUTĂȚI +- Apeluri de grup: WhatsApp nu permite apeluri către grupuri cu mai mult de 32 de participanți, așa că butoanele de apel sunt înlocuite cu un buton "Nu se poate apela" a cărui notă spune că grupul are mai mult de 32 de participanți, iar comenzile rapide de apel spun același lucru în loc să pornească apelul. + - Apeluri de grup: butoanele de apel vocal și video apar acum în conversația de grup și pornesc un apel către grup, iar un apel de grup primit sună, este anunțat cu numele grupului și poate fi răspuns, cu același buton de răspuns și aceeași comandă rapidă globală de răspuns ca un apel individual. Pornirea camerei în timpul unui apel vocal funcționează ca într-un apel individual, iar evenimentele de apel de la fiecare participant rămân la grup, așa că fereastra apelului păstrează numele grupului de la primul sunet până la final. - Apeluri video: WinZapp găsește acum camera cu FFmpeg-ul inclus în WinZapp, care listează dispozitivele DirectShow fără antetul „DirectShow video devices”. Acea versiune de FFmpeg nu returna nicio cameră, așa că apelul video ieșea doar cu recepție, cu „No camera found” în log. diff --git a/client/changelog_tr-TR.txt b/client/changelog_tr-TR.txt index 5fd02db11..a19d499f6 100644 --- a/client/changelog_tr-TR.txt +++ b/client/changelog_tr-TR.txt @@ -4,6 +4,8 @@ Bu sürüm, 2.1.0.0 sürümündeki her şeye ek olarak toplulukları ve yeniden YENİLİKLER +- Grup aramaları: WhatsApp 32'den fazla katılımcısı olan gruplarda arama yapılmasına izin vermez; bu yüzden arama düğmelerinin yerine notu grubun 32'den fazla katılımcısı olduğunu söyleyen bir "Arama yapılamıyor" düğmesi gelir ve arama kısayolları aramayı başlatmak yerine aynı şeyi söyler. + - Grup aramaları: sesli ve görüntülü arama düğmeleri artık grup sohbetinde görünür ve gruba arama başlatır; gelen bir grup araması çalar, grubun adıyla duyurulur ve tek kişilik aramadaki aynı Yanıtla düğmesi ve genel yanıtlama kısayoluyla yanıtlanabilir. Sesli arama sırasında kamerayı açmak tek kişilik aramadaki gibi çalışır ve her katılımcıdan gelen arama olayları grupta kalır, böylece arama penceresi ilk çalmadan sona kadar grubun adını korur. - Görüntülü aramalar: WinZapp artık kamerayı, DirectShow aygıtlarını "DirectShow video devices" başlığı olmadan listeleyen ve WinZapp ile birlikte gelen FFmpeg ile bulur. Bu FFmpeg sürümü hiçbir kamera döndürmüyordu, bu yüzden görüntülü arama yalnızca alım modunda başlıyordu ve günlükte "No camera found" yazıyordu. diff --git a/client/core/call_logic.py b/client/core/call_logic.py index 42cf6b0c9..87d04fe51 100644 --- a/client/core/call_logic.py +++ b/client/core/call_logic.py @@ -1,6 +1,20 @@ """Pure call-state helpers shared by the wx UI and headless tests.""" +# WhatsApp only places a group call for groups of up to this many participants +# (the account itself included, as the group-info participant list counts it). +MAX_GROUP_CALL_PARTICIPANTS = 32 + + +def group_too_large_for_call(participant_count: int | None) -> bool: + """Return whether a group has too many participants for a call. + + An unknown count (the group info has not arrived yet) is not "too large": + the call buttons stay, and WhatsApp answers for itself. + """ + return bool(participant_count) and participant_count > MAX_GROUP_CALL_PARTICIPANTS + + def incoming_call_can_answer(details: dict | None) -> bool: """Return whether this incoming call can be answered. diff --git a/client/data/help_guide/en-US.html b/client/data/help_guide/en-US.html index 36e3f3b75..ec1d06abd 100644 --- a/client/data/help_guide/en-US.html +++ b/client/data/help_guide/en-US.html @@ -687,6 +687,7 @@

📞 9. Calls

Make a call

In an individual chat, use the "Voice call" (Ctrl+Shift+V) and "Video call" (Ctrl+Alt+Shift+V) buttons; the shortcuts also work with the message field focused. The screen reader announces when the call connects, when it is reconnecting and when it ends.

+

WhatsApp only allows calls to groups of up to 32 participants. In a larger group, a "Calling is not possible" button with the note "The group has more than 32 participants" replaces the call buttons, and the call shortcuts say the same.

In a group chat the same buttons call the whole group. An incoming group call rings, is announced by the group's name and is answered like any other call, and the camera can be turned on during the call. WinZapp finds the camera with the FFmpeg it ships, so a video call no longer goes out receive-only.

During the call

diff --git a/client/data/help_guide/es-ES.html b/client/data/help_guide/es-ES.html index 84a0e7332..1d94dd244 100644 --- a/client/data/help_guide/es-ES.html +++ b/client/data/help_guide/es-ES.html @@ -687,6 +687,7 @@

📞 9. Llamadas

Hacer una llamada

En un chat individual, usa los botones "Llamada de voz" (Ctrl+Shift+V) y "Videollamada" (Ctrl+Alt+Shift+V); los atajos también funcionan con el foco en el campo de mensaje. El lector de pantalla anuncia cuándo se conecta la llamada, cuándo se está reconectando y cuándo termina.

+

WhatsApp solo permite llamar a grupos de hasta 32 participantes. En un grupo mayor, un botón "No es posible llamar" con la nota "El grupo tiene más de 32 participantes" sustituye a los botones de llamada, y los atajos de llamada dicen lo mismo.

En un chat de grupo, los mismos botones llaman a todo el grupo. Una llamada de grupo entrante suena, se anuncia con el nombre del grupo y se contesta como cualquier otra llamada, y se puede activar la cámara durante la llamada. WinZapp encuentra la cámara con el FFmpeg que incluye, así que una videollamada ya no sale solo recibiendo.

Durante la llamada

diff --git a/client/data/help_guide/pl.html b/client/data/help_guide/pl.html index 93ca9bc55..36b3e400e 100644 --- a/client/data/help_guide/pl.html +++ b/client/data/help_guide/pl.html @@ -687,6 +687,7 @@

📞 9. Połączenia

Wykonanie połączenia

W czacie indywidualnym użyj przycisków "Połączenie głosowe" (Ctrl+Shift+V) i "Połączenie wideo" (Ctrl+Alt+Shift+V); skróty działają także przy fokusie w polu wiadomości. Czytnik ekranu ogłasza, kiedy połączenie zostaje nawiązane, kiedy się łączy ponownie i kiedy się kończy.

+

WhatsApp pozwala dzwonić tylko do grup liczących do 32 członków. W większej grupie przyciski połączeń zastępuje przycisk "Nie można zadzwonić" z opisem "Grupa ma więcej niż 32 członków", a skróty połączeń mówią to samo.

W czacie grupowym te same przyciski dzwonią do całej grupy. Przychodzące połączenie grupowe dzwoni, jest ogłaszane nazwą grupy i odbiera się je jak każde inne, a kamerę można włączyć w trakcie połączenia. WinZapp znajduje kamerę za pomocą dołączonego FFmpeg, więc połączenie wideo nie jest już tylko odbierające.

Podczas połączenia

diff --git a/client/data/help_guide/pt-BR.html b/client/data/help_guide/pt-BR.html index 9c0637f1d..87cd28611 100644 --- a/client/data/help_guide/pt-BR.html +++ b/client/data/help_guide/pt-BR.html @@ -687,6 +687,7 @@

📞 9. Ligações

Ligar

Numa conversa individual, use os botões "Ligação de voz" (Ctrl+Shift+V) e "Ligação de vídeo" (Ctrl+Alt+Shift+V); os atalhos funcionam também com o campo de mensagem em foco. O leitor de tela avisa quando a ligação conecta, quando está reconectando e quando termina.

+

O WhatsApp só permite ligar para grupos com até 32 participantes. Num grupo maior, no lugar dos botões de ligação aparece um botão "Não é possível ligar", com a nota "O grupo possui mais de 32 participantes", e os atalhos de ligação dizem o mesmo.

Numa conversa em grupo os mesmos botões ligam para o grupo todo. Uma ligação de grupo recebida toca, é anunciada pelo nome do grupo e é atendida como qualquer outra ligação, e dá para ligar a câmera durante a ligação. O WinZapp encontra a câmera com o FFmpeg que acompanha o programa, então uma ligação de vídeo não sai mais só recebendo.

Durante a ligação

diff --git a/client/data/help_guide/pt-PT.html b/client/data/help_guide/pt-PT.html index b07da68cf..f230378c3 100644 --- a/client/data/help_guide/pt-PT.html +++ b/client/data/help_guide/pt-PT.html @@ -687,6 +687,7 @@

📞 9. Ligações

Ligar

Numa conversa individual, use os botões "Chamada de voz" (Ctrl+Shift+V) e "Chamada de vídeo" (Ctrl+Alt+Shift+V); os atalhos funcionam também com o campo de mensagem em foco. O leitor de ecrã avisa quando a chamada liga, quando está a religar e quando termina.

+

O WhatsApp só permite ligar para grupos com até 32 membros. Num grupo maior, no lugar dos botões de chamada aparece um botão "Não é possível ligar", com a nota "O grupo tem mais de 32 membros", e os atalhos de chamada dizem o mesmo.

Numa conversa de grupo, os mesmos botões ligam para o grupo todo. Uma chamada de grupo recebida toca, é anunciada pelo nome do grupo e é atendida como qualquer outra chamada, sendo possível ligar a câmara durante a chamada. O WinZapp encontra a câmara com o FFmpeg que acompanha o programa, pelo que uma chamada de vídeo já não sai apenas a receber.

Durante a chamada

diff --git a/client/data/help_guide/ro.html b/client/data/help_guide/ro.html index 51458808d..91c159d1a 100644 --- a/client/data/help_guide/ro.html +++ b/client/data/help_guide/ro.html @@ -687,6 +687,7 @@

📞 9. Apeluri

Efectuarea unui apel

Într-o conversație individuală, folosește butoanele "Apel vocal" (Ctrl+Shift+V) și "Apel video" (Ctrl+Alt+Shift+V); comenzile rapide funcționează și cu focalizarea pe câmpul de mesaj. Cititorul de ecran anunță când se conectează apelul, când se reconectează și când se termină.

+

WhatsApp permite apeluri doar către grupuri de până la 32 de participanți. Într-un grup mai mare, butoanele de apel sunt înlocuite cu un buton "Nu se poate apela", cu nota "Grupul are mai mult de 32 de participanți", iar comenzile rapide de apel spun același lucru.

Într-o conversație de grup, aceleași butoane sună tot grupul. Un apel de grup primit sună, este anunțat cu numele grupului și se răspunde ca la orice alt apel, iar camera poate fi pornită în timpul apelului. WinZapp găsește camera cu FFmpeg-ul inclus, deci un apel video nu mai pleacă doar în recepție.

În timpul apelului

diff --git a/client/data/help_guide/tr-TR.html b/client/data/help_guide/tr-TR.html index 174453e05..000f8db69 100644 --- a/client/data/help_guide/tr-TR.html +++ b/client/data/help_guide/tr-TR.html @@ -687,6 +687,7 @@

📞 9. Aramalar

Arama yapma

Bireysel bir sohbette "Sesli arama" (Ctrl+Shift+V) ve "Görüntülü arama" (Ctrl+Alt+Shift+V) düğmelerini kullanın; kısayollar odak mesaj alanındayken de çalışır. Ekran okuyucu aramanın ne zaman bağlandığını, ne zaman yeniden bağlandığını ve ne zaman bittiğini duyurur.

+

WhatsApp yalnızca en fazla 32 katılımcılı gruplarda arama yapılmasına izin verir. Daha büyük bir grupta arama düğmelerinin yerine "Arama yapılamıyor" düğmesi ve "Grupta 32 üzerinde katılımcı var" notu gelir; arama kısayolları da aynısını söyler.

Grup sohbetinde aynı düğmeler tüm grubu arar. Gelen grup araması çalar, grubun adıyla duyurulur ve diğer aramalar gibi yanıtlanır; kamera arama sırasında açılabilir. WinZapp kamerayı birlikte gelen FFmpeg ile bulur, bu yüzden görüntülü arama artık yalnızca alma modunda başlamaz.

Arama sırasında

diff --git a/client/ui/conversation_panel/composer.py b/client/ui/conversation_panel/composer.py index 0e082682f..c4f62aa42 100644 --- a/client/ui/conversation_panel/composer.py +++ b/client/ui/conversation_panel/composer.py @@ -10,6 +10,7 @@ import threading import wx from ui.shortcut_bindings import command_key_event +from core.call_logic import MAX_GROUP_CALL_PARTICIPANTS, group_too_large_for_call from ui.dialogs.emoji_picker import choose_and_insert_emoji from core.attachment_types import DEFAULT_PASTED_AUDIO_AS, pasted_attachment_media_type from core.link_preview import ( @@ -409,15 +410,44 @@ def _sync_voice_call_button(self, jid: str): # same native group call WinZapp asks the Node patch for. Newsletters, # broadcast lists and the self-chat have no call to place. unavailable = jid.endswith(("@newsletter", "@broadcast")) or is_self_chat - self._voice_call_btn.Show(bool(jid) and not unavailable) - self._video_call_btn.Show(bool(jid) and not unavailable) + too_large = ( + jid.endswith("@g.us") and getattr(self, "_group_call_blocked_jid", "") == jid + ) + callable_chat = bool(jid) and not unavailable + self._voice_call_btn.Show(callable_chat and not too_large) + self._video_call_btn.Show(callable_chat and not too_large) + self._group_call_unavailable_btn.Show(callable_chat and too_large) self.conversation_panel.Layout() self.Layout() + def _set_group_call_limit(self, jid: str, participant_count: int): + """Main-thread callback: swap the call buttons for the "cannot call" + link button when the open group is over the WhatsApp call limit.""" + if not self.conversation or self.conversation.get("remoteJid") != jid: + return + self._group_call_blocked_jid = ( + jid if group_too_large_for_call(participant_count) else "" + ) + self._sync_voice_call_button(jid) + + def _group_call_refused(self, jid: str) -> bool: + """Say why a call cannot start in a group over the limit (the shortcuts + reach the call handlers even though the buttons are hidden).""" + if not jid.endswith("@g.us") or getattr(self, "_group_call_blocked_jid", "") != jid: + return False + i18n = self.main_window.i18n + self.main_window.output( + i18n.t("group_call_unavailable_note").format(limit=MAX_GROUP_CALL_PARTICIPANTS), + interrupt=True, + ) + return True + def _on_voice_call(self, _event=None): if not self.conversation: return jid = str(self.conversation.get("remoteJid") or "") + if self._group_call_refused(jid): + return name = self.conversation_name or self.conversation.get("name") or "" self.main_window.start_voice_call(jid, name) @@ -425,6 +455,8 @@ def _on_video_call(self, _event=None): if not self.conversation: return jid = str(self.conversation.get("remoteJid") or "") + if self._group_call_refused(jid): + return name = self.conversation_name or self.conversation.get("name") or "" self.main_window.start_video_call(jid, name) diff --git a/client/ui/conversation_panel/conversation_navigation.py b/client/ui/conversation_panel/conversation_navigation.py index a256f966c..016880afb 100644 --- a/client/ui/conversation_panel/conversation_navigation.py +++ b/client/ui/conversation_panel/conversation_navigation.py @@ -333,6 +333,7 @@ def navigate_to_conversation(self, conversation, *, origin=None, self._pending_mentions.clear() self._pending_mention_display_names.clear() self._group_participants_cache = [] + self._group_call_blocked_jid = "" self._hide_mention_suggestions() if hasattr(self, "_pending_mentions_panel"): self._rebuild_mention_pills() diff --git a/client/ui/conversation_panel/mentions.py b/client/ui/conversation_panel/mentions.py index 46af60ba1..38ab0c4dd 100644 --- a/client/ui/conversation_panel/mentions.py +++ b/client/ui/conversation_panel/mentions.py @@ -496,6 +496,7 @@ def _fetch_group_participants(self, jid: str): participants = data.get("participants", []) logging.info(f"[mention] get_group_info({jid}) attempt {attempt+1}/{max_retries} → {len(participants)} participants") if participants: + wx.CallAfter(self._set_group_call_limit, jid, len(participants)) my_jid = getattr(self.main_window, "my_jid", "") or "" # Build initial cache first so UI is populated instantly cache = [] diff --git a/client/ui/conversations.py b/client/ui/conversations.py index 94c038585..63eca38eb 100644 --- a/client/ui/conversations.py +++ b/client/ui/conversations.py @@ -91,6 +91,7 @@ from core.video_player import VideoPlayer from core.focus_cloak import cloak_panel_focus_fallback from core.chain_repaint_guard import ChainRepaintGuard +from core.call_logic import MAX_GROUP_CALL_PARTICIPANTS from core.spell_checker import ( WindowsSpellChecker, spell_check_active, windows_spellcheck_enabled, ) @@ -625,6 +626,18 @@ def init_UI(self): self._conv_data_btn.Bind(wx.EVT_BUTTON, self._show_conversation_data) conv_sizer.Add(self._conv_data_btn, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5) + # Shown in place of the two call buttons when the group is too large to + # call; a link button so the reason is read with it, like the data one. + self._group_call_unavailable_btn = wx.adv.CommandLinkButton( + self.conversation_panel, + mainLabel=i18n.t("group_call_unavailable_label"), + note=i18n.t("group_call_unavailable_note").format( + limit=MAX_GROUP_CALL_PARTICIPANTS + ), + ) + conv_sizer.Add(self._group_call_unavailable_btn, 0, wx.LEFT | wx.TOP, 5) + self._group_call_unavailable_btn.Hide() + self._video_call_btn = wx.Button( self.conversation_panel, label=i18n.t("video_call_button") ) diff --git a/docs/user-guide/cobertura.json b/docs/user-guide/cobertura.json index 067d74459..82194ac41 100644 --- a/docs/user-guide/cobertura.json +++ b/docs/user-guide/cobertura.json @@ -4,6 +4,7 @@ "commit": "4b8a5c6a", "data": "14/10/2026", "itens": { + "e5655e6399c7": "Chamadas em grupo: o WhatsApp não permite ligar para grupos com mais de 32 parti", "05947e90a05a": "Chamadas em grupo: os botões de chamada de voz e de vídeo agora aparecem na conv", "8dc1cc789b43": "Chamadas de vídeo: o WinZapp agora encontra a câmera com o FFmpeg incluído no Wi", "ebe407996699": "Os botões das mensagens de empresas agora podem ser usados: um botão de resposta", diff --git a/docs/user-guide/secoes/en-US/09-ligacoes.html b/docs/user-guide/secoes/en-US/09-ligacoes.html index 591a1c39f..a6e3fee71 100644 --- a/docs/user-guide/secoes/en-US/09-ligacoes.html +++ b/docs/user-guide/secoes/en-US/09-ligacoes.html @@ -3,6 +3,7 @@

Make a call

In an individual chat, use the "Voice call" (Ctrl+Shift+V) and "Video call" (Ctrl+Alt+Shift+V) buttons; the shortcuts also work with the message field focused. The screen reader announces when the call connects, when it is reconnecting and when it ends.

+

WhatsApp only allows calls to groups of up to 32 participants. In a larger group, a "Calling is not possible" button with the note "The group has more than 32 participants" replaces the call buttons, and the call shortcuts say the same.

In a group chat the same buttons call the whole group. An incoming group call rings, is announced by the group's name and is answered like any other call, and the camera can be turned on during the call. WinZapp finds the camera with the FFmpeg it ships, so a video call no longer goes out receive-only.

During the call

diff --git a/docs/user-guide/secoes/es-ES/09-ligacoes.html b/docs/user-guide/secoes/es-ES/09-ligacoes.html index 6cadafad4..7e721ff29 100644 --- a/docs/user-guide/secoes/es-ES/09-ligacoes.html +++ b/docs/user-guide/secoes/es-ES/09-ligacoes.html @@ -3,6 +3,7 @@

Hacer una llamada

En un chat individual, usa los botones "Llamada de voz" (Ctrl+Shift+V) y "Videollamada" (Ctrl+Alt+Shift+V); los atajos también funcionan con el foco en el campo de mensaje. El lector de pantalla anuncia cuándo se conecta la llamada, cuándo se está reconectando y cuándo termina.

+

WhatsApp solo permite llamar a grupos de hasta 32 participantes. En un grupo mayor, un botón "No es posible llamar" con la nota "El grupo tiene más de 32 participantes" sustituye a los botones de llamada, y los atajos de llamada dicen lo mismo.

En un chat de grupo, los mismos botones llaman a todo el grupo. Una llamada de grupo entrante suena, se anuncia con el nombre del grupo y se contesta como cualquier otra llamada, y se puede activar la cámara durante la llamada. WinZapp encuentra la cámara con el FFmpeg que incluye, así que una videollamada ya no sale solo recibiendo.

Durante la llamada

diff --git a/docs/user-guide/secoes/pl/09-ligacoes.html b/docs/user-guide/secoes/pl/09-ligacoes.html index 2b4a81a5e..56beadca8 100644 --- a/docs/user-guide/secoes/pl/09-ligacoes.html +++ b/docs/user-guide/secoes/pl/09-ligacoes.html @@ -3,6 +3,7 @@

Wykonanie połączenia

W czacie indywidualnym użyj przycisków "Połączenie głosowe" (Ctrl+Shift+V) i "Połączenie wideo" (Ctrl+Alt+Shift+V); skróty działają także przy fokusie w polu wiadomości. Czytnik ekranu ogłasza, kiedy połączenie zostaje nawiązane, kiedy się łączy ponownie i kiedy się kończy.

+

WhatsApp pozwala dzwonić tylko do grup liczących do 32 członków. W większej grupie przyciski połączeń zastępuje przycisk "Nie można zadzwonić" z opisem "Grupa ma więcej niż 32 członków", a skróty połączeń mówią to samo.

W czacie grupowym te same przyciski dzwonią do całej grupy. Przychodzące połączenie grupowe dzwoni, jest ogłaszane nazwą grupy i odbiera się je jak każde inne, a kamerę można włączyć w trakcie połączenia. WinZapp znajduje kamerę za pomocą dołączonego FFmpeg, więc połączenie wideo nie jest już tylko odbierające.

Podczas połączenia

diff --git a/docs/user-guide/secoes/pt-BR/09-ligacoes.html b/docs/user-guide/secoes/pt-BR/09-ligacoes.html index 0675518ef..de080dd16 100644 --- a/docs/user-guide/secoes/pt-BR/09-ligacoes.html +++ b/docs/user-guide/secoes/pt-BR/09-ligacoes.html @@ -3,6 +3,7 @@

Ligar

Numa conversa individual, use os botões "Ligação de voz" (Ctrl+Shift+V) e "Ligação de vídeo" (Ctrl+Alt+Shift+V); os atalhos funcionam também com o campo de mensagem em foco. O leitor de tela avisa quando a ligação conecta, quando está reconectando e quando termina.

+

O WhatsApp só permite ligar para grupos com até 32 participantes. Num grupo maior, no lugar dos botões de ligação aparece um botão "Não é possível ligar", com a nota "O grupo possui mais de 32 participantes", e os atalhos de ligação dizem o mesmo.

Numa conversa em grupo os mesmos botões ligam para o grupo todo. Uma ligação de grupo recebida toca, é anunciada pelo nome do grupo e é atendida como qualquer outra ligação, e dá para ligar a câmera durante a ligação. O WinZapp encontra a câmera com o FFmpeg que acompanha o programa, então uma ligação de vídeo não sai mais só recebendo.

Durante a ligação

diff --git a/docs/user-guide/secoes/pt-PT/09-ligacoes.html b/docs/user-guide/secoes/pt-PT/09-ligacoes.html index 5a9cc7b7e..5d4aefc76 100644 --- a/docs/user-guide/secoes/pt-PT/09-ligacoes.html +++ b/docs/user-guide/secoes/pt-PT/09-ligacoes.html @@ -3,6 +3,7 @@

Ligar

Numa conversa individual, use os botões "Chamada de voz" (Ctrl+Shift+V) e "Chamada de vídeo" (Ctrl+Alt+Shift+V); os atalhos funcionam também com o campo de mensagem em foco. O leitor de ecrã avisa quando a chamada liga, quando está a religar e quando termina.

+

O WhatsApp só permite ligar para grupos com até 32 membros. Num grupo maior, no lugar dos botões de chamada aparece um botão "Não é possível ligar", com a nota "O grupo tem mais de 32 membros", e os atalhos de chamada dizem o mesmo.

Numa conversa de grupo, os mesmos botões ligam para o grupo todo. Uma chamada de grupo recebida toca, é anunciada pelo nome do grupo e é atendida como qualquer outra chamada, sendo possível ligar a câmara durante a chamada. O WinZapp encontra a câmara com o FFmpeg que acompanha o programa, pelo que uma chamada de vídeo já não sai apenas a receber.

Durante a chamada

diff --git a/docs/user-guide/secoes/ro/09-ligacoes.html b/docs/user-guide/secoes/ro/09-ligacoes.html index 4b8ad6c3a..83ba977d7 100644 --- a/docs/user-guide/secoes/ro/09-ligacoes.html +++ b/docs/user-guide/secoes/ro/09-ligacoes.html @@ -3,6 +3,7 @@

Efectuarea unui apel

Într-o conversație individuală, folosește butoanele "Apel vocal" (Ctrl+Shift+V) și "Apel video" (Ctrl+Alt+Shift+V); comenzile rapide funcționează și cu focalizarea pe câmpul de mesaj. Cititorul de ecran anunță când se conectează apelul, când se reconectează și când se termină.

+

WhatsApp permite apeluri doar către grupuri de până la 32 de participanți. Într-un grup mai mare, butoanele de apel sunt înlocuite cu un buton "Nu se poate apela", cu nota "Grupul are mai mult de 32 de participanți", iar comenzile rapide de apel spun același lucru.

Într-o conversație de grup, aceleași butoane sună tot grupul. Un apel de grup primit sună, este anunțat cu numele grupului și se răspunde ca la orice alt apel, iar camera poate fi pornită în timpul apelului. WinZapp găsește camera cu FFmpeg-ul inclus, deci un apel video nu mai pleacă doar în recepție.

În timpul apelului

diff --git a/docs/user-guide/secoes/tr-TR/09-ligacoes.html b/docs/user-guide/secoes/tr-TR/09-ligacoes.html index c8b339d3f..73def0693 100644 --- a/docs/user-guide/secoes/tr-TR/09-ligacoes.html +++ b/docs/user-guide/secoes/tr-TR/09-ligacoes.html @@ -3,6 +3,7 @@

Arama yapma

Bireysel bir sohbette "Sesli arama" (Ctrl+Shift+V) ve "Görüntülü arama" (Ctrl+Alt+Shift+V) düğmelerini kullanın; kısayollar odak mesaj alanındayken de çalışır. Ekran okuyucu aramanın ne zaman bağlandığını, ne zaman yeniden bağlandığını ve ne zaman bittiğini duyurur.

+

WhatsApp yalnızca en fazla 32 katılımcılı gruplarda arama yapılmasına izin verir. Daha büyük bir grupta arama düğmelerinin yerine "Arama yapılamıyor" düğmesi ve "Grupta 32 üzerinde katılımcı var" notu gelir; arama kısayolları da aynısını söyler.

Grup sohbetinde aynı düğmeler tüm grubu arar. Gelen grup araması çalar, grubun adıyla duyurulur ve diğer aramalar gibi yanıtlanır; kamera arama sırasında açılabilir. WinZapp kamerayı birlikte gelen FFmpeg ile bulur, bu yüzden görüntülü arama artık yalnızca alma modunda başlamaz.

Arama sırasında

diff --git a/tests/test_sync_voice_call_button.py b/tests/test_sync_voice_call_button.py index 8dd453e5a..cf38e2b26 100644 --- a/tests/test_sync_voice_call_button.py +++ b/tests/test_sync_voice_call_button.py @@ -76,3 +76,90 @@ def test_newsletter_and_broadcast_hide_both_call_buttons(): panel._sync_voice_call_button(jid) assert panel._voice_call_btn.IsShown() is False assert panel._video_call_btn.IsShown() is False + + +# ── Groups over the call limit ─────────────────────────────────────────────── + +from core.call_logic import MAX_GROUP_CALL_PARTICIPANTS, group_too_large_for_call + + +def test_the_limit_is_thirty_two_participants(): + assert MAX_GROUP_CALL_PARTICIPANTS == 32 + assert not group_too_large_for_call(32) + assert group_too_large_for_call(33) + assert not group_too_large_for_call(None) + assert not group_too_large_for_call(0) + + +class _LimitStub(_Stub): + _set_group_call_limit = ConversationsPanel._set_group_call_limit + _group_call_refused = ConversationsPanel._group_call_refused + _on_voice_call = ConversationsPanel._on_voice_call + _on_video_call = ConversationsPanel._on_video_call + + def __init__(self, jid): + super().__init__() + self._group_call_unavailable_btn = _FakeWidget() + self.conversation = {"remoteJid": jid} + self.conversation_name = "G" + self._group_call_blocked_jid = "" + spoken = self.spoken = [] + started = self.started = [] + + class _I18n: + def t(self, key): + return "note {limit}" if key == "group_call_unavailable_note" else key + + class _MW(_FakeMainWindow): + i18n = _I18n() + + def output(self, text, interrupt=False): + spoken.append(text) + + def start_voice_call(self, jid, name): + started.append(jid) + + start_video_call = start_voice_call + + self.main_window = _MW() + + +def test_a_group_over_the_limit_swaps_the_call_buttons_for_the_note_button(): + jid = "120363000000000000@g.us" + panel = _LimitStub(jid) + panel._set_group_call_limit(jid, 33) + assert panel._voice_call_btn.IsShown() is False + assert panel._video_call_btn.IsShown() is False + assert panel._group_call_unavailable_btn.IsShown() is True + + +def test_a_group_within_the_limit_keeps_the_call_buttons(): + jid = "120363000000000000@g.us" + panel = _LimitStub(jid) + panel._set_group_call_limit(jid, 32) + assert panel._voice_call_btn.IsShown() is True + assert panel._group_call_unavailable_btn.IsShown() is False + + +def test_the_limit_of_a_group_no_longer_open_is_ignored(): + panel = _LimitStub("120363000000000000@g.us") + panel._set_group_call_limit("999@g.us", 40) + assert panel._group_call_blocked_jid == "" + + +def test_the_call_shortcuts_say_why_instead_of_calling_an_oversized_group(): + jid = "120363000000000000@g.us" + panel = _LimitStub(jid) + panel._set_group_call_limit(jid, 40) + panel._on_voice_call() + panel._on_video_call() + assert panel.started == [] + assert panel.spoken == ["note 32"] * 2 + + +def test_the_call_shortcuts_still_call_a_group_within_the_limit(): + jid = "120363000000000000@g.us" + panel = _LimitStub(jid) + panel._set_group_call_limit(jid, 10) + panel._on_voice_call() + assert panel.started == [jid] diff --git a/translations/en-US/LC_MESSAGES/winzapp.po b/translations/en-US/LC_MESSAGES/winzapp.po index f9c4492f4..a40be5281 100644 --- a/translations/en-US/LC_MESSAGES/winzapp.po +++ b/translations/en-US/LC_MESSAGES/winzapp.po @@ -5606,6 +5606,18 @@ msgctxt "group_admins_only" msgid "Only admins can send messages in this grou&p" msgstr "Only admins can send messages in this grou&p" +#: translations/en-US/LC_MESSAGES/winzapp.po client/ui/conversations.py +msgctxt "group_call_unavailable_label" +msgid "Calling is not possible" +msgstr "Calling is not possible" + +#: translations/en-US/LC_MESSAGES/winzapp.po +#: client/ui/conversation_panel/composer.py client/ui/conversations.py +#, python-brace-format +msgctxt "group_call_unavailable_note" +msgid "The group has more than {limit} participants" +msgstr "The group has more than {limit} participants" + #: translations/en-US/LC_MESSAGES/winzapp.po client/ui/dialogs/new_group.py msgctxt "group_contacts_label" msgid "&Participants" diff --git a/translations/es-ES/LC_MESSAGES/winzapp.po b/translations/es-ES/LC_MESSAGES/winzapp.po index 18156bc35..c3f7fb42f 100644 --- a/translations/es-ES/LC_MESSAGES/winzapp.po +++ b/translations/es-ES/LC_MESSAGES/winzapp.po @@ -5659,6 +5659,18 @@ msgctxt "group_admins_only" msgid "Only admins can send messages in this grou&p" msgstr "Solo los administradores pueden &enviar mensajes en este grupo" +#: translations/en-US/LC_MESSAGES/winzapp.po client/ui/conversations.py +msgctxt "group_call_unavailable_label" +msgid "Calling is not possible" +msgstr "No es posible llamar" + +#: translations/en-US/LC_MESSAGES/winzapp.po +#: client/ui/conversation_panel/composer.py client/ui/conversations.py +#, python-brace-format +msgctxt "group_call_unavailable_note" +msgid "The group has more than {limit} participants" +msgstr "El grupo tiene más de {limit} participantes" + #: translations/en-US/LC_MESSAGES/winzapp.po client/ui/dialogs/new_group.py msgctxt "group_contacts_label" msgid "&Participants" diff --git a/translations/pl/LC_MESSAGES/winzapp.po b/translations/pl/LC_MESSAGES/winzapp.po index b03f58a4a..1739eca5d 100644 --- a/translations/pl/LC_MESSAGES/winzapp.po +++ b/translations/pl/LC_MESSAGES/winzapp.po @@ -5671,6 +5671,18 @@ msgctxt "group_admins_only" msgid "Only admins can send messages in this grou&p" msgstr "Tylko a&dministratorzy mogą wysyłać wiadomości w tej grupie" +#: translations/en-US/LC_MESSAGES/winzapp.po client/ui/conversations.py +msgctxt "group_call_unavailable_label" +msgid "Calling is not possible" +msgstr "Nie można zadzwonić" + +#: translations/en-US/LC_MESSAGES/winzapp.po +#: client/ui/conversation_panel/composer.py client/ui/conversations.py +#, python-brace-format +msgctxt "group_call_unavailable_note" +msgid "The group has more than {limit} participants" +msgstr "Grupa ma więcej niż {limit} członków" + #: translations/en-US/LC_MESSAGES/winzapp.po client/ui/dialogs/new_group.py msgctxt "group_contacts_label" msgid "&Participants" diff --git a/translations/pt-BR/LC_MESSAGES/winzapp.po b/translations/pt-BR/LC_MESSAGES/winzapp.po index fc201f142..cfebfedf7 100644 --- a/translations/pt-BR/LC_MESSAGES/winzapp.po +++ b/translations/pt-BR/LC_MESSAGES/winzapp.po @@ -5651,6 +5651,18 @@ msgctxt "group_admins_only" msgid "Only admins can send messages in this grou&p" msgstr "Somente a&dmins podem enviar mensagens neste grupo" +#: translations/en-US/LC_MESSAGES/winzapp.po client/ui/conversations.py +msgctxt "group_call_unavailable_label" +msgid "Calling is not possible" +msgstr "Não é possível ligar" + +#: translations/en-US/LC_MESSAGES/winzapp.po +#: client/ui/conversation_panel/composer.py client/ui/conversations.py +#, python-brace-format +msgctxt "group_call_unavailable_note" +msgid "The group has more than {limit} participants" +msgstr "O grupo possui mais de {limit} participantes" + #: translations/en-US/LC_MESSAGES/winzapp.po client/ui/dialogs/new_group.py msgctxt "group_contacts_label" msgid "&Participants" diff --git a/translations/pt-PT/LC_MESSAGES/winzapp.po b/translations/pt-PT/LC_MESSAGES/winzapp.po index a0c578782..cfa70a27c 100644 --- a/translations/pt-PT/LC_MESSAGES/winzapp.po +++ b/translations/pt-PT/LC_MESSAGES/winzapp.po @@ -5677,6 +5677,18 @@ msgctxt "group_admins_only" msgid "Only admins can send messages in this grou&p" msgstr "Somente admins podem &enviar mensagens neste grupo" +#: translations/en-US/LC_MESSAGES/winzapp.po client/ui/conversations.py +msgctxt "group_call_unavailable_label" +msgid "Calling is not possible" +msgstr "Não é possível ligar" + +#: translations/en-US/LC_MESSAGES/winzapp.po +#: client/ui/conversation_panel/composer.py client/ui/conversations.py +#, python-brace-format +msgctxt "group_call_unavailable_note" +msgid "The group has more than {limit} participants" +msgstr "O grupo tem mais de {limit} membros" + #: translations/en-US/LC_MESSAGES/winzapp.po client/ui/dialogs/new_group.py msgctxt "group_contacts_label" msgid "&Participants" diff --git a/translations/ro/LC_MESSAGES/winzapp.po b/translations/ro/LC_MESSAGES/winzapp.po index 7343224ee..36a8f8231 100644 --- a/translations/ro/LC_MESSAGES/winzapp.po +++ b/translations/ro/LC_MESSAGES/winzapp.po @@ -5653,6 +5653,18 @@ msgctxt "group_admins_only" msgid "Only admins can send messages in this grou&p" msgstr "Numai adm&inistratorii pot trimite mesaje în acest grup" +#: translations/en-US/LC_MESSAGES/winzapp.po client/ui/conversations.py +msgctxt "group_call_unavailable_label" +msgid "Calling is not possible" +msgstr "Nu se poate apela" + +#: translations/en-US/LC_MESSAGES/winzapp.po +#: client/ui/conversation_panel/composer.py client/ui/conversations.py +#, python-brace-format +msgctxt "group_call_unavailable_note" +msgid "The group has more than {limit} participants" +msgstr "Grupul are mai mult de {limit} participanți" + #: translations/en-US/LC_MESSAGES/winzapp.po client/ui/dialogs/new_group.py msgctxt "group_contacts_label" msgid "&Participants" diff --git a/translations/tr-TR/LC_MESSAGES/winzapp.po b/translations/tr-TR/LC_MESSAGES/winzapp.po index bb271ace3..04b71f59f 100644 --- a/translations/tr-TR/LC_MESSAGES/winzapp.po +++ b/translations/tr-TR/LC_MESSAGES/winzapp.po @@ -5619,6 +5619,18 @@ msgctxt "group_admins_only" msgid "Only admins can send messages in this grou&p" msgstr "Bu grupta yalnızca yöneticiler mesaj ya&zabilir" +#: translations/en-US/LC_MESSAGES/winzapp.po client/ui/conversations.py +msgctxt "group_call_unavailable_label" +msgid "Calling is not possible" +msgstr "Arama yapılamıyor" + +#: translations/en-US/LC_MESSAGES/winzapp.po +#: client/ui/conversation_panel/composer.py client/ui/conversations.py +#, python-brace-format +msgctxt "group_call_unavailable_note" +msgid "The group has more than {limit} participants" +msgstr "Grupta {limit} üzerinde katılımcı var" + #: translations/en-US/LC_MESSAGES/winzapp.po client/ui/dialogs/new_group.py msgctxt "group_contacts_label" msgid "&Participants" diff --git a/translations/winzapp.pot b/translations/winzapp.pot index d5f33c5b1..b39bac4e9 100644 --- a/translations/winzapp.pot +++ b/translations/winzapp.pot @@ -5296,6 +5296,18 @@ msgctxt "group_admins_only" msgid "Only admins can send messages in this grou&p" msgstr "" +#: translations/en-US/LC_MESSAGES/winzapp.po client/ui/conversations.py +msgctxt "group_call_unavailable_label" +msgid "Calling is not possible" +msgstr "" + +#: translations/en-US/LC_MESSAGES/winzapp.po +#: client/ui/conversation_panel/composer.py client/ui/conversations.py +#, python-brace-format +msgctxt "group_call_unavailable_note" +msgid "The group has more than {limit} participants" +msgstr "" + #: translations/en-US/LC_MESSAGES/winzapp.po client/ui/dialogs/new_group.py msgctxt "group_contacts_label" msgid "&Participants" From f4c8b5d771951962c03e94275ece9dac8e5b70d6 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 14:26:40 +0000 Subject: [PATCH 2/3] =?UTF-8?q?Rotula=20de=20novo=20o=20bot=C3=A3o=20de=20?= =?UTF-8?q?grupo=20grande=20ao=20trocar=20de=20idioma?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01TxZ4WQst6v5HP4WM9yMPC9 --- client/ui/conversations.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/ui/conversations.py b/client/ui/conversations.py index 63eca38eb..2a6b4c9a8 100644 --- a/client/ui/conversations.py +++ b/client/ui/conversations.py @@ -1261,6 +1261,10 @@ def refresh_labels(self): self._search_open_btn.SetLabel(i18n.t("search_in_conv")) self._update_pinned_messages_button() self._voice_call_btn.SetLabel(i18n.t("voice_call_button")) + self._group_call_unavailable_btn.SetMainLabel(i18n.t("group_call_unavailable_label")) + self._group_call_unavailable_btn.SetNote( + i18n.t("group_call_unavailable_note").format(limit=MAX_GROUP_CALL_PARTICIPANTS) + ) self._search_close_btn.SetLabel(i18n.t("search_close")) self._search_field_label.SetLabel(i18n.t("search_in_conv")) self._search_prev_btn.SetLabel(i18n.t("search_prev_result")) From b28326b86b3efc810b7ee616fcfb3dbbb84b39b3 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 21 Oct 2026 14:38:01 +0000 Subject: [PATCH 3/3] =?UTF-8?q?Ajusta=20testes=20do=20bot=C3=A3o=20de=20li?= =?UTF-8?q?gar=20ao=20limite=20de=20grupo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01TxZ4WQst6v5HP4WM9yMPC9 --- tests/test_call_video.py | 2 +- tests/test_sync_voice_call_button.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_call_video.py b/tests/test_call_video.py index aa0aafd86..870894597 100644 --- a/tests/test_call_video.py +++ b/tests/test_call_video.py @@ -266,7 +266,7 @@ def test_video_button_is_offered_for_groups_but_not_unreachable_chats(): source = conversations_source() assert 'unavailable = jid.endswith(("@newsletter", "@broadcast")) or is_self_chat' in source assert 'unavailable = jid.endswith(("@g.us", "@newsletter", "@broadcast"))' not in source - assert 'self._video_call_btn.Show(bool(jid) and not unavailable)' in source + assert 'self._video_call_btn.Show(callable_chat and not too_large)' in source assert 'self.main_window.start_video_call(jid, name)' in source diff --git a/tests/test_sync_voice_call_button.py b/tests/test_sync_voice_call_button.py index cf38e2b26..191488f57 100644 --- a/tests/test_sync_voice_call_button.py +++ b/tests/test_sync_voice_call_button.py @@ -40,6 +40,7 @@ def __init__(self): self.main_window = _FakeMainWindow() self._voice_call_btn = _FakeWidget() self._video_call_btn = _FakeWidget() + self._group_call_unavailable_btn = _FakeWidget() self.conversation_panel = _FakeWidget() def Layout(self): @@ -99,7 +100,6 @@ class _LimitStub(_Stub): def __init__(self, jid): super().__init__() - self._group_call_unavailable_btn = _FakeWidget() self.conversation = {"remoteJid": jid} self.conversation_name = "G" self._group_call_blocked_jid = ""