diff --git a/linux.py b/linux.py index 85e02f9..39cf6c3 100644 --- a/linux.py +++ b/linux.py @@ -88,6 +88,16 @@ def _on_open_in_telegram(icon=None, item=None) -> None: _show_error(f"Не удалось скопировать ссылку:\n{exc}") +def _on_copy_link(icon=None, item=None) -> None: + url = tg_proxy_url(_config) + log.info("Copying link: %s", url) + try: + pyperclip.copy(url) + except Exception as exc: + log.error("Clipboard copy failed: %s", exc) + _show_error(f"Не удалось скопировать ссылку:\n{exc}") + + def _on_restart(icon=None, item=None) -> None: threading.Thread( target=lambda: restart_proxy(_config, _show_error), daemon=True @@ -220,6 +230,7 @@ def _build_menu(): link_host = tg_ws_proxy.get_link_host(host) return pystray.Menu( pystray.MenuItem(f"Открыть в Telegram ({link_host}:{port})", _on_open_in_telegram, default=True), + pystray.MenuItem("Скопировать ссылку", _on_copy_link), pystray.Menu.SEPARATOR, pystray.MenuItem("Перезапустить прокси", _on_restart), pystray.MenuItem("Настройки...", _on_edit_config), diff --git a/macos.py b/macos.py index a2379f1..ae79576 100644 --- a/macos.py +++ b/macos.py @@ -231,6 +231,19 @@ def _on_open_in_telegram(_=None) -> None: _show_error(f"Не удалось скопировать ссылку:\n{exc}") +def _on_copy_link(_=None) -> None: + url = tg_proxy_url(_config) + log.info("Copying link: %s", url) + try: + if pyperclip: + pyperclip.copy(url) + else: + subprocess.run(["pbcopy"], input=url.encode(), check=True) + except Exception as exc: + log.error("Clipboard copy failed: %s", exc) + _show_error(f"Не удалось скопировать ссылку:\n{exc}") + + def _on_restart(_=None) -> None: def _do(): global _config @@ -487,6 +500,7 @@ class TgWsProxyApp(_TgWsProxyAppBase): self._open_tg_item = rumps.MenuItem( f"Открыть в Telegram ({link_host}:{port})", callback=_on_open_in_telegram ) + self._copy_link_item = rumps.MenuItem("Скопировать ссылку", callback=_on_copy_link) self._restart_item = rumps.MenuItem("Перезапустить прокси", callback=_on_restart) self._settings_item = rumps.MenuItem("Настройки...", callback=_on_edit_config) self._logs_item = rumps.MenuItem("Открыть логи", callback=_on_open_logs) @@ -505,6 +519,7 @@ class TgWsProxyApp(_TgWsProxyAppBase): quit_button="Выход", menu=[ self._open_tg_item, + self._copy_link_item, None, self._restart_item, self._settings_item, diff --git a/ui/ctk_theme.py b/ui/ctk_theme.py index ad76fad..fccfada 100644 --- a/ui/ctk_theme.py +++ b/ui/ctk_theme.py @@ -25,7 +25,7 @@ def install_tkinter_variable_del_guard() -> None: CONFIG_DIALOG_SIZE: Tuple[int, int] = (460, 560) CONFIG_DIALOG_FRAME_PAD: Tuple[int, int] = (20, 14) -FIRST_RUN_SIZE: Tuple[int, int] = (520, 440) +FIRST_RUN_SIZE: Tuple[int, int] = (520, 480) FIRST_RUN_FRAME_PAD: Tuple[int, int] = (28, 24) diff --git a/ui/ctk_tray_ui.py b/ui/ctk_tray_ui.py index fd42efa..f7e6d8b 100644 --- a/ui/ctk_tray_ui.py +++ b/ui/ctk_tray_ui.py @@ -464,19 +464,35 @@ def populate_first_run_window( ("Как подключить Telegram Desktop:", True), (" Автоматически:", True), (" ПКМ по иконке в трее → «Открыть в Telegram»", False), - (f" Или ссылка: {tg_url}", False), + (f" Или скопировать ссылку, отправить её себе в TG и нажать по ней: {tg_url}", False), ("\n Вручную:", True), (" Настройки → Продвинутые → Тип подключения → Прокси", False), (f" MTProto → {host} : {port}", False), (f" Secret: dd{secret}", False), ] + textbox = ctk.CTkTextbox( + frame, + font=(theme.ui_font_family, 13), + fg_color=theme.bg, + border_width=0, + text_color=theme.text_primary, + activate_scrollbars=False, + wrap="word", + height=275, + ) + textbox._textbox.tag_configure("bold", font=(theme.ui_font_family, 13, "bold")) + textbox._textbox.configure(spacing1=1, spacing3=1) for text, bold in sections: - weight = "bold" if bold else "normal" - ctk.CTkLabel(frame, text=text, - font=(theme.ui_font_family, 13, weight), - text_color=theme.text_primary, - anchor="w", justify="left").pack(anchor="w", pady=1) + if text.startswith("\n"): + textbox.insert("end", "\n") + text = text[1:] + if bold: + textbox.insert("end", text + "\n", "bold") + else: + textbox.insert("end", text + "\n") + textbox.configure(state="disabled") + textbox.pack(anchor="w", fill="x") ctk.CTkFrame(frame, fg_color="transparent", height=16).pack() diff --git a/utils/tray_common.py b/utils/tray_common.py index 4e1fc98..05e3a14 100644 --- a/utils/tray_common.py +++ b/utils/tray_common.py @@ -34,7 +34,7 @@ def _app_dir() -> Path: APP_DIR = _app_dir() CONFIG_FILE = APP_DIR / "config.json" LOG_FILE = APP_DIR / "proxy.log" -FIRST_RUN_MARKER = APP_DIR / ".first_run_done" +FIRST_RUN_MARKER = APP_DIR / ".first_run_done_mtproto" IPV6_WARN_MARKER = APP_DIR / ".ipv6_warned" DEFAULT_CONFIG: Dict[str, Any] = default_tray_config() diff --git a/windows.py b/windows.py index 22e490b..878027a 100644 --- a/windows.py +++ b/windows.py @@ -147,6 +147,21 @@ def _on_open_in_telegram(icon=None, item=None) -> None: _show_error(f"Не удалось скопировать ссылку:\n{exc}") +def _on_copy_link(icon=None, item=None) -> None: + url = tg_proxy_url(_config) + log.info("Copying link: %s", url) + if pyperclip is None: + _show_error( + "Установите пакет pyperclip для копирования в буфер обмена." + ) + return + try: + pyperclip.copy(url) + except Exception as exc: + log.error("Clipboard copy failed: %s", exc) + _show_error(f"Не удалось скопировать ссылку:\n{exc}") + + def _on_restart(icon=None, item=None) -> None: threading.Thread( target=lambda: restart_proxy(_config, _show_error), daemon=True @@ -285,6 +300,7 @@ def _build_menu(): link_host = tg_ws_proxy.get_link_host(host) return pystray.Menu( pystray.MenuItem(f"Открыть в Telegram ({link_host}:{port})", _on_open_in_telegram, default=True), + pystray.MenuItem("Скопировать ссылку", _on_copy_link), pystray.Menu.SEPARATOR, pystray.MenuItem("Перезапустить прокси", _on_restart), pystray.MenuItem("Настройки...", _on_edit_config),