Skip to content

Commit 080a434

Browse files
committed
Empty the typing contract's exemption list
`je_auto_control` type-checks clean on win32, linux and darwin with nothing exempted. The list that started this branch at 155 modules now holds a header and no entries, and the gate fails if it grows again. The last module was webrtc_panel.py, blocked by its size rather than its types. Seven of its errors came from `_build_advanced_group(panel: TranslatableMixin, …)`, a free function that writes five widget attributes back onto the panel it is handed — none of which TranslatableMixin has. Saying that needs a Protocol, and the file was sitting exactly on the 2,555-line cap it may only shrink from. So the builder moved out, which is the split Progress.md already said that file owed: `advanced_group.py` holds the shared STUN/TURN group, the `AdvancedGroupHost` protocol naming what it reads and what it sets, and the hardware-codec row as its own function. The panel is 2,545 lines — under its cap for the first time — and both panels were rebuilt offscreen to confirm the STUN default, the TURN fields and the host-only codec picker still arrive where they did. Ten more errors there were the pattern the whole sweep kept meeting: a handle that is None until the session starts. `_produce_offer`, `_trust_session_viewer`, `_answer_and_push`, `_produce_answer` and the folder sync all reached through `_multi_host` / `_viewer` without asking. They go through `_require_multi_host()` / `_require_viewer()` now, raising a translated "start hosting first" / "connect to a host first" rather than an AttributeError on None — two new keys in all four language catalogues. Progress.md's mypy entry collapses to what is still worth knowing: the five recurring shapes, that a catch tuple has to be an annotated module constant, that `# type: ignore` only counts as a line's first comment, and that the cv2 stub omits names the library has.
1 parent f68e02b commit 080a434

10 files changed

Lines changed: 216 additions & 188 deletions

File tree

‎Progress.md‎

Lines changed: 33 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@
1818

1919
`CLAUDE.md` §Size and complexity limits 規定:超標檔案只能列在這裡,列不進來的就是缺陷。
2020
清單上的檔案**可以改、可以變短,但不得再變長**——要再長就得先拆。
21-
行數為 2026-08-19 實測(`len(text.splitlines())`)。
21+
行數為 2026-08-19 實測(`len(text.splitlines())`);`webrtc_panel.py` 於
22+
2026-08-22 拆出 `advanced_group.py` 後降到 2,545,上限跟著往下走。
2223

2324
| 檔案 | 行數 | 為何還沒拆 |
2425
| --- | ---: | --- |
2526
| `utils/mcp_server/tools/_handlers.py` | 4,789 | 676 個 MCP 工具的處理函式本體。與 `_factories.py`(表)不同,這裡是邏輯,應該依主題拆成 `_handlers/` 套件(input/screen/window/file/agent…)。拆點清楚,純粹是量大。 |
26-
| `gui/remote_desktop/webrtc_panel.py` | 2,555 | 單一 Qt 面板,但已含連線、監視器選擇、頻寬自適應、麥克風、錄影五組互動狀態。應拆成 panel + 各控制器。 |
27+
| `gui/remote_desktop/webrtc_panel.py` | 2,545 | 單一 Qt 面板,但已含連線、監視器選擇、頻寬自適應、麥克風、錄影五組互動狀態。應拆成 panel + 各控制器。 |
2728
| `utils/accessibility/backends/windows_backend.py` | 915 | 已拆出 `windows_query.py`(170)與 `windows_state.py`(98)。剩下的是同一套 UIA COM 生命週期管理,再拆會把 `CoInitialize`/介面釋放的配對邏輯切散。 |
2829

2930
**本質豁免(依 `CLAUDE.md` 的「flat data tables」條款,不算既有豁免)**:
@@ -39,7 +40,7 @@
3940
2026-08-18 重新實測時,表上原有的七列**全部**變長,而 `CLAUDE.md` 明寫
4041
「列上的檔案不得再變長,要再長就得先拆」,所以這裡曾標成 `[DECIDE]`。
4142
**維護者已於 2026-08-19 拍板:接受實測數字當新基準**——不為了回到舊數字而去拆
42-
`_handlers.py`(4,789)與 `webrtc_panel.py`(2,555)。上表的行數即是各自的新上限,
43+
`_handlers.py`(4,789)與 `webrtc_panel.py`。上表的行數即是各自的新上限,
4344
規則不變:只准變短,再變長就得先拆。
4445

4546
同一批裡有六個檔案在 2026-08-19 已經拆回線內、從表上移除,做法寫在
@@ -219,13 +220,14 @@ capability enum 值與 variadic `ei_seat_bind_capabilities`、event-type enum
219220

220221
---
221222

222-
## 兩個門檻:機制已經有了,剩下的是把數字往前推
223+
## 兩個門檻:mypy 那半已經到終點,覆蓋率那半還在爬
223224

224-
`TODO` — 兩者都已經從「講好要爬」變成「有棘輪在擋」,但都還沒到目的地
225+
`TODO` — 只剩覆蓋率;型別契約 2026-08-22 收工
225226

226227
原本這一條記的是兩個只存在於 `pyproject.toml` 註解裡、沒有任何機制的承諾。
227-
2026-08-21 把**機制**補上了(做法見 [WHATS_NEW.md](WHATS_NEW.md)),所以這裡改記
228-
還差多少、以及下一步怎麼走。
228+
2026-08-21 把**機制**補上了(做法見 [WHATS_NEW.md](WHATS_NEW.md))。
229+
型別契約已於 2026-08-22 走完(豁免清單清空,見下),所以這條剩下的實質內容
230+
只有覆蓋率;mypy 那一節留著是因為它記的那幾個坑之後還會踩到。
229231

230232
### 覆蓋率:地板 50,目標 70
231233

@@ -240,129 +242,33 @@ capability enum 值與 variadic `ei_seat_bind_capabilities`、event-type enum
240242
(`--cov-report=term-missing` 已經開著,CI 每一格都存了 `coverage.xml` artifact),
241243
而不是齊頭式地補測試。
242244

243-
### mypy:整包把關,56 個模組還沒過
245+
### mypy:整包把關,**豁免清單已經清空**
246+
247+
`TODO` → **完成(2026-08-22)**
244248

245249
範圍不再是兩條路徑,而是**整包減去一張只准變少的清單**
246250
(`test/verify/typing_contract_exempt.txt`)。差別在於預設值:路徑清單只有人想到才會長,
247-
新模組預設在圈外;現在新模組**預設就在契約裡**,1,017 個檔案有 961 個已經過關。
248-
249-
`wrapper` 那一群(6 個模組)在 2026-08-21 清掉了,做法見 [WHATS_NEW.md](WHATS_NEW.md):
250-
平台縫的八個匯出名稱先宣告型別、再讓分支去綁定,其中三個用
251-
`wrapper/backend_contract.py` 的 Protocol,四個 `_platform_*` 組裝模組各自標注自己綁了什麼。
252-
順帶帶綠了四個原本卡在縫的偶然型別上、自己其實沒問題的模組
253-
(`utils/cv2_utils/screen_grabber`、`utils/executor/mouse_aliases`、
254-
`utils/pytest_plugin/keywords`、`utils/vision/vlm_api`)。
255-
256-
`linux_wayland` 那一群(4 個模組)在 2026-08-22 清掉了:`libei` 的 33 處
257-
`Optional[BoundSymbols]` 改走一個會拋 `LibeiUnavailable` 的存取器(`_api`),
258-
`_detect` 的兩支環境查詢收 `Mapping[str, str]` 而不是 `dict`(預設值就是 `os.environ`),
259-
`capture._write_to_temp_png` 承認它的 writer 會回傳東西而它不看,
260-
`screen.get_pixel` 把 Pillow 那個「每種 mode 的答案聯集」收斂成它自己承諾的三元組。
261-
做法見 [WHATS_NEW.md](WHATS_NEW.md)。
262-
263-
`linux_with_x11`(3)與 `osx`(1)同日清掉:X11 listener 的 `record_queue`
264-
從「型別是 None」變成 `Optional[Queue]`(`stop_record()` 因此不再回一個
265-
簽章不承認的 `None`),`uinput/_device` 的 POSIX 專屬 `O_NONBLOCK` 收進一個
266-
mypy 剪得掉的 `sys.platform` 分支,`osx_keyboard` 的字串 keycode 一律當特殊鍵名。
267-
268-
`windows/` 這一群的**真實錯誤全部清掉了**:`window_message` 匯入一個
269-
`windows_window_manage` 根本沒有匯出的名字(`FindWindowW`),所以那個模組在
270-
Windows 上一直是 import 就炸;`win32_ctype_input` 則有一批標錯的註記
271-
(`_fields_: tuple` 把 ClassVar 重新宣告成 instance variable、`ctypes.POINTER`
272-
與 `user32.SendInput` 被當成型別用)以及一行改寫標準函式庫的
273-
`wintypes.ULONG_PTR = wintypes.WPARAM`——全樹沒有任何地方讀它。
274-
**以 `--platform win32` 檢查時,`je_auto_control/windows/` 底下已經零錯誤。**
275-
剩下的豁免是下面那條 `DECIDE`。
276-
277-
`utils/remote_desktop` 那一群(13 個模組、169 個錯誤,曾是最大的一群)在
278-
2026-08-22 清掉了,錯誤只有兩種形狀:九個模組是 `self._x = None` 沒有標注
279-
(mypy 就把那個屬性的**型別**判成 `None`),其中好幾個把想要的型別寫在行尾註解裡
280-
——事實一直都在,只是寫在沒有檢查器讀得到的地方;另外四個是 mixin 讀取
281-
自己不擁有的屬性,而每個 mixin 的 docstring 早就列出它跟宿主借了什麼,
282-
現在那份清單變成類別本體裡的 `if TYPE_CHECKING:` 宣告(執行期會被剝掉,
283-
所以不可能蓋掉宿主真正綁的東西)。順帶修掉三個行為問題:
284-
`WebRTCLoopBridge._run` 從共用狀態讀 loop、`_get_cursor_position` 在函式內
285-
`import sys as _sys` 導致 mypy 剪不掉平台分支、`totp` 接的是
286-
`base64.binascii.Error`(那個名字只是 `base64` 自己 import 的副作用)。
287-
做法見 [WHATS_NEW.md](WHATS_NEW.md)。
288-
289-
同日再清掉十五個:`utils/accessibility` 那一群(5)、`utils/observability`(3)、
290-
`utils/triggers`(3)、`utils/chatops/router`、`utils/rest_api/rest_server`、
291-
`utils/mcp_server/http_transport`、`utils/element_repository`。四十三個
292-
accessibility 錯誤裡有三十四個是同一個沒標的回傳型別(`_unsupported` 一定會拋,
293-
標成 `NoReturn` 就全清);另一個反覆出現的是**攔截用的 tuple 沒有被標成 tuple**
294-
(`Tuple[type, ...]` 不算「a tuple of exception classes」,
295-
`except (…, *SQLITE_ERRORS)` 的星號解包 mypy 也跟不進 `except`)。
296-
順帶修掉四個行為問題:`Gauge`/`Histogram` 用
297-
`_labels_key = Counter._labels_key` 借方法、`parse_content_length` 宣告的
298-
`Mapping[str, str]` 三個呼叫端一個都沒給過(給的是 `email.message.Message`)、
299-
`ElementRepository` 把使用者可編輯的 locator 直接 `**kwargs` 丟進無障礙 API、
300-
`_AtspiConnection._call` 在 `with` 之外沒有 bus 可以呼叫。
301-
做法見 [WHATS_NEW.md](WHATS_NEW.md)。
302-
303-
下面那條 `DECIDE` 也在同日拍板收掉,又清掉 16 個模組(做法見
304-
[WHATS_NEW.md](WHATS_NEW.md))。
305-
306-
ctypes 表面一收掉,卡在它後面的兩群也跟著清了:`utils/usb/passthrough`(3)
307-
與 `utils/clipboard`(3)。兩邊都藏著真的缺陷——`winusb_backend._load_dlls`
308-
一次公布一個 handle,第二個載入失敗時第一個已經設好,於是 `is not None` 的守衛
309-
把之後每一次重試都短路掉;`clipboard_api()` 宣告回傳 `Tuple[object, object]`,
310-
而 `object` 沒有任何屬性,所以透過它的十二個 Win32 呼叫全是型別錯誤。
311-
做法見 [WHATS_NEW.md](WHATS_NEW.md)。
312-
313-
`gui` 那一群(13 個模組)同日清掉,只剩 `webrtc_panel.py`(見下)。
314-
大宗又是 mixin 借用宿主的成員(六個分頁 mixin 借 `_tr`/`_translate`/`timer`),
315-
做法與 webrtc 那三個 mixin 相同。順帶修掉三個真的會壞的地方:
316-
`assertions_tab` 的 pixel 斷言把 `*_parse_ints(...)[:2]` 星號展開,使用者只打一個
317-
座標時 RGB 清單會被綁到 `y`,錯誤訊息變成「關鍵字參數重複」而不是「你少打了一個
318-
座標」;`_auto_click_tab._get_mouse_pos` 直接解包 `get_mouse_position()`,而
319-
Windows 後端在鎖定桌面上真的會回 `None`;`multi_language_wrapper` 的監聽器清單
320-
標成 `List[callable]`(`callable` 是內建函式,不是型別)。
321-
做法見 [WHATS_NEW.md](WHATS_NEW.md)。
322-
323-
`utils/mcp_server` 那一群(4 個模組)同日清掉,順帶抓到一個**從來沒成功過的指令**:
324-
`AC_normalize_url`/`ac_normalize_url` 都把 `drop_fragment=` 傳給
325-
`url_canon.normalize_url`,而那支函式的參數叫 `strip_fragment`——每一次呼叫都是
326-
`TypeError`。對外的名字不動(動作 schema 與工具註冊表都用它),改的是兩個呼叫點。
327-
做法見 [WHATS_NEW.md](WHATS_NEW.md)。
328-
329-
長尾那一批(13 個模組、每個 2~6 個錯誤)同日清掉,反覆出現的只有三種形狀:
330-
`callable` 被當成型別用(`callable` 是內建函式)、`x: SomeType = None` 的隱含
331-
Optional、以及「掉了長度的 tuple」(`tuple(r)`/`cv2.boundingRect()` 都是
332-
`tuple[int, ...]`,而收它的欄位承諾四個 int)。另外抓到兩個只靠呼叫圖成立的不變量
333-
(`_StabilityTracker` 的 `now - self._since`、`act_when_ready` 把可能是 `None` 的
334-
`report.point` 傳給要求座標的 callback)。做法見 [WHATS_NEW.md](WHATS_NEW.md)。
335-
336-
**順帶一個 mypy 設定上的事實**:`pyproject.toml` 把 `cv2` 列在
337-
「ship no stubs 的基礎相依」底下,但 opencv-python **有**附 `.pyi`,所以閘門會去讀它,
338-
而它的內容會隨 OpenCV 版本變動(實測 4.13.0:`cv2.MSER_create` 執行期存在、stub 裡沒有)。
339-
`>=4.8,<6` 這個範圍內版本一換,閘門的判定就可能跟著動——與 numpy 那條註解同一類的坑。
340-
341-
剩下 56 個模組要清,**不再有大群集**:最大的檔案是
342-
`gui/remote_desktop/webrtc_panel.py`(27,見下)與
343-
`utils/executor/action_executor.py`(8),其餘每個檔都只剩 1~2 個錯誤。
344-
345-
#### `webrtc_panel.py` 的型別豁免現在卡在它欠的那次拆檔
346-
347-
`TODO` — 27 個錯誤,但清掉它需要先讓這個檔可以變長
348-
349-
二十七個錯誤裡有七個來自 `_build_advanced_group(panel: TranslatableMixin, ...)`:
350-
這個自由函式**會把五個 widget 屬性寫回 panel 上**(`_stun_edit`、`_turn_edit`、
351-
`_turn_user_edit`、`_turn_cred_edit`、`_hw_codec_combo`),而 `TranslatableMixin`
352-
一個都沒有。正確的型別是一個 Protocol,把它需要與寫入的成員寫出來——但
353-
`webrtc_panel.py` **正好卡在 2,555 行的上限**(見本檔開頭那張表:只准變短),
354-
而加 Protocol 一定變長。
355-
356-
真正的解法就是那張表早就寫著的:把這個檔拆成 panel + 各控制器。
357-
`_build_advanced_group` 本身就是第一個該搬出去的——它是共用的 widget group builder,
358-
不屬於 panel 模組,搬走同時解決長度與型別兩件事。**在那之前這個模組留在豁免清單上,
359-
理由記在這裡,不是被忘記。**
360-
**下一步**是一次清一個群集,清完把行從清單刪掉——
361-
`python test/verify/typing_contract_verify.py --fix` 會替你改,CI 會在你忘了刪的時候紅掉。
362-
已經清掉的那些留下四個可以直接套用的樣板:mixin 用 `if TYPE_CHECKING:` 宣告
363-
借來的成員、`Optional` 屬性用 `TYPE_CHECKING` 匯入真正的型別去標注、
364-
一定會拋的 helper 標 `NoReturn`、攔截用的 tuple 標
365-
`Tuple[Type[BaseException], ...]` 並收成一個模組常數(不要在 `except` 裡星號解包)。
251+
新模組預設在圈外;現在新模組**預設就在契約裡**。
252+
253+
**2026-08-22 那張清單降到零**:`je_auto_control/` 的 1,018 個檔案在
254+
win32/linux/darwin 三個目標上全部乾淨。清掉 136 個模組的過程與每一群的做法寫在
255+
[WHATS_NEW.md](WHATS_NEW.md);這裡只留下之後還用得到的四件事:
256+
257+
* **反覆出現的五種形狀**:mixin 讀取宿主的成員(用類別本體裡的
258+
`if TYPE_CHECKING:` 宣告,執行期會被剝掉)、`self._x = None` 沒有標注
259+
(mypy 會把屬性的型別判成 `None`)、`callable` 被當成型別用、
260+
`x: SomeType = None` 的隱含 Optional、以及掉了長度的 tuple。
261+
* **攔截用的 tuple 必須標成 `Tuple[Type[BaseException], ...]`**,而且要收成一個
262+
模組常數——`except (A, B, *TUPLE)` 的星號解包 mypy 跟不進 `except`。
263+
* **`# type: ignore` 只有當它是那一行的第一個註解時才生效**(已實測),所以有
264+
`# nosec` 的行要把它放前面。
265+
* **`cv2` 的 stub 會隨版本變**:`pyproject.toml` 把它列在「ship no stubs 的基礎相依」
266+
底下,但 opencv-python 有附 `.pyi`,閘門會去讀。實測 4.13.0:`MSER_create`、
267+
`ORB_create`、`VideoWriter_fourcc` 執行期都在、stub 裡都沒有。`>=4.8,<6` 範圍內
268+
版本一換,判定就可能跟著動——與 numpy 那條註解同一類的坑。
269+
270+
清單現在只有標頭、沒有任何條目。**它變長就是退步**,`typing_contract_verify.py`
271+
會在有人讓它變長時紅掉。
366272

367273
#### 平台縫還缺的一半:`keyboard` 與 `mouse` 還沒有合約
368274

‎WHATS_NEW.md‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,38 @@ comparison as a `DECIDE`, because the cleanest of them changes what the gate
208208
means rather than what the code says. **136 modules left, 881 of 1,017 files
209209
inside the contract.**
210210

211+
### The Typing Contract's Exemption List Is Empty
212+
213+
`je_auto_control` type-checks clean on all three targets — win32, linux and
214+
darwin — with nothing exempted. The list that started this branch at 155 modules
215+
now holds a header and no entries, and `typing_contract_verify.py` fails if it
216+
ever grows again.
217+
218+
The last module was `gui/remote_desktop/webrtc_panel.py`, and it was blocked by
219+
its own size rather than by its types. Seven of its errors came from
220+
`_build_advanced_group(panel: TranslatableMixin, …)`, a free function that
221+
*writes* five widget attributes back onto the panel it is handed — none of which
222+
`TranslatableMixin` has. Writing that contract down needs a Protocol, and the
223+
file was sitting exactly on the 2,555-line cap it may only shrink from.
224+
225+
So the builder moved out, which is what `Progress.md` had said that file owed
226+
anyway: `gui/remote_desktop/advanced_group.py` now holds the shared
227+
STUN/TURN group, the `AdvancedGroupHost` protocol naming what it reads and what
228+
it sets, and the hardware-codec row as its own function. The panel is 2,545
229+
lines — under its cap for the first time — and both panels were rebuilt
230+
offscreen afterwards to confirm the STUN default, the TURN fields and the
231+
host-only codec picker all still arrive where they did.
232+
233+
Ten more errors in that file were the pattern the whole sweep kept meeting: a
234+
handle that is `None` until the session starts. `_produce_offer`,
235+
`_trust_session_viewer`, `_answer_and_push`, `_produce_answer` and the folder
236+
sync all reached through `self._multi_host` / `self._viewer` without asking. They
237+
go through `_require_multi_host()` / `_require_viewer()` now, which raise a
238+
translated "start hosting first" / "connect to a host first" instead of an
239+
`AttributeError` on `None` — two new keys in all four language catalogues.
240+
241+
**0 modules left. 1,018 of 1,018 files inside the contract.**
242+
211243
### Thirteen Small Modules, and a Stub That Disagrees With the Library
212244

213245
Past the big clusters the list is a long tail: thirteen modules of two to six

‎architecture_explore.md‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ iOS(WebDriverAgent)。核心能力是滑鼠/鍵盤控制、影像辨識、
1919

2020
| 指標 | 數值 |
2121
| --- | ---: |
22-
| Python 模組總數(含周邊子專案) | 1,031 |
23-
| 程式碼總行數 | 140,989 |
22+
| Python 模組總數(含周邊子專案) | 1,032 |
23+
| 程式碼總行數 | 141,079 |
2424
| `je_auto_control/utils/` 子套件數 | 310 |
2525
| `AC_*` 動作指令數(`known_commands()` 實測) | 773 |
2626
| 套件門面 `__all__` 公開名稱數 | 1,238 |
@@ -930,12 +930,13 @@ GUI 是**選用 extra**(`pip install je_auto_control[gui]`,PySide6 + qt-mate
930930
| diagnostics | `diagnostics_tab.py` | 91 | 執行子系統檢查並顯示結果。 |
931931
| report | `_report_tab.py` | 81 | 產生 HTML/JSON/XML 報表。 |
932932

933-
#### 遠端桌面 GUI(`gui/remote_desktop/`,17 檔/6,254 行)
933+
#### 遠端桌面 GUI(`gui/remote_desktop/`,18 檔/6,336 行)
934934

935935
| 模組 | 行數 | 職責 |
936936
| --- | ---: | --- |
937-
| `webrtc_panel.py` | 2,555 | WebRTC 子分頁主體。 |
937+
| `webrtc_panel.py` | 2,545 | WebRTC 子分頁主體。 |
938938
| `webrtc_dialogs.py` | 493 | WebRTC GUI 用的自訂對話框與清單元件(待審檢視者、信任清單、通訊錄、遠端檔案表、稽核記錄、LAN 瀏覽)。 |
939+
| `advanced_group.py` | 92 | 兩個 WebRTC 面板共用的 Advanced STUN/TURN(含選用硬體編碼器)群組,含它寫回面板的 Protocol。 |
939940
| `connection_screen.py` | 672 | Quick Connect —— AnyDesk 風格單畫面入口。 |
940941
| `viewer_panel.py` | 542 | 「控制另一台機器」子分頁。 |
941942
| `webrtc_known_hosts.py` | 340 | TOFU 釘選庫瀏覽器:`KnownHostsDialog` 與帶外釘選用的小表單。由 `webrtc_dialogs` 再匯出。 |
@@ -1024,7 +1025,7 @@ socket 預設綁 `127.0.0.1`;資源一律用 `with`。
10241025

10251026
| 層/子系統 | 檔案數 | 行數 |
10261027
| --- | ---: | ---: |
1027-
| `gui/` | 89 | 26,609 |
1028+
| `gui/` | 90 | 26,699 |
10281029
| `utils/mcp_server/` | 21 | 17,354 |
10291030
| `utils/remote_desktop/` | 56 | 11,990 |
10301031
| `utils/executor/` | 6 | 9,081 |
@@ -1045,5 +1046,5 @@ socket 預設綁 `127.0.0.1`;資源一律用 `with`。
10451046
| `autocontrol-lsp/` | 8 | 744 |
10461047
| `utils/hotkey/` | 7 | 727 |
10471048
| 其餘模組(約 286 個 `utils/` 子套件 + `android/`/`ios/`/周邊小工具) | 673 | 47,667 |
1048-
| **總計** | **1,025** | **140,924** |
1049+
| **總計** | **1,026** | **141,014** |
10491050

‎je_auto_control/gui/language_wrapper/english.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,8 @@
574574
"rd_webrtc_sync_start": "Start sync",
575575
"rd_webrtc_sync_stop": "Stop sync",
576576
"rd_webrtc_sync_dir_required": "Pick a local folder first",
577+
"rd_webrtc_not_started": "Start hosting first",
578+
"rd_webrtc_not_connected": "Connect to a host first",
577579
"rd_webrtc_browse": _BROWSE,
578580

579581
# Auto Click Tab

‎je_auto_control/gui/language_wrapper/japanese.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,8 @@
463463
"rd_webrtc_sync_start": "同期開始",
464464
"rd_webrtc_sync_stop": "同期停止",
465465
"rd_webrtc_sync_dir_required": "ローカルフォルダを選択してください",
466+
"rd_webrtc_not_started": "先にホストを開始してください",
467+
"rd_webrtc_not_connected": "先にホストへ接続してください",
466468
"rd_webrtc_browse": _BROWSE,
467469

468470
# Auto Click Tab

‎je_auto_control/gui/language_wrapper/simplified_chinese.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@
452452
"rd_webrtc_sync_start": "开始同步",
453453
"rd_webrtc_sync_stop": "停止同步",
454454
"rd_webrtc_sync_dir_required": "请先选一个本机目录",
455+
"rd_webrtc_not_started": "请先开始主机端",
456+
"rd_webrtc_not_connected": "请先连线到主机",
455457
"rd_webrtc_browse": _BROWSE,
456458

457459
# Auto Click Tab

‎je_auto_control/gui/language_wrapper/traditional_chinese.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,8 @@
453453
"rd_webrtc_sync_start": "開始同步",
454454
"rd_webrtc_sync_stop": "停止同步",
455455
"rd_webrtc_sync_dir_required": "請先選一個本機資料夾",
456+
"rd_webrtc_not_started": "請先開始主機端",
457+
"rd_webrtc_not_connected": "請先連線到主機",
456458
"rd_webrtc_browse": _BROWSE,
457459

458460
# Auto Click Tab

0 commit comments

Comments
 (0)