From c645d964bfee57572c748cb89280d8804c514a4f Mon Sep 17 00:00:00 2001 From: benya Date: Sun, 15 Feb 2026 23:30:12 +0300 Subject: [PATCH] fix(auth,ui): add auth webview cli entrypoint and bulk action progress bar --- auth_webview.py | 18 +++++++++++++++- main.py | 55 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/auth_webview.py b/auth_webview.py index c43eeac..7bcb69b 100644 --- a/auth_webview.py +++ b/auth_webview.py @@ -74,5 +74,21 @@ def main_auth(auth_url, output_path): webview.start(private_mode=False, storage_path=storage_path) +def main(): + # Supports both: `python auth_webview.py ` + # and: `python auth_webview.py --auth ` + args = sys.argv[1:] + if len(args) == 3 and args[0] == "--auth": + auth_url, output_path = args[1], args[2] + elif len(args) == 2: + auth_url, output_path = args[0], args[1] + else: + print("Usage: auth_webview.py [--auth] ") + return 1 + + main_auth(auth_url, output_path) + return 0 + + if __name__ == "__main__": - main() + sys.exit(main()) diff --git a/main.py b/main.py index 08edaf3..01d8458 100644 --- a/main.py +++ b/main.py @@ -85,6 +85,8 @@ class VkChatManager(QMainWindow): self._auth_ui_busy = False self._auth_relogin_in_progress = False self._last_auth_relogin_ts = 0.0 + self._active_action_button = None + self._active_action_button_text = "" self.update_repository_url = detect_update_repository_url(UPDATE_REPOSITORY_URL, UPDATE_REPOSITORY) self.update_channel = UPDATE_CHANNEL_DEFAULT self.update_checker = None @@ -184,6 +186,12 @@ class VkChatManager(QMainWindow): self.add_user_btn.setMinimumHeight(50) self.add_user_btn.clicked.connect(self.add_user_to_chat) layout.addWidget(self.add_user_btn) + self.operation_progress = QProgressBar() + self.operation_progress.setRange(0, 100) + self.operation_progress.setValue(0) + self.operation_progress.setTextVisible(True) + self.operation_progress.hide() + layout.addWidget(self.operation_progress) self.status_label = QLabel("Статус: не авторизован") self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter) layout.addWidget(self.status_label) @@ -550,6 +558,36 @@ class VkChatManager(QMainWindow): else: self.set_ui_state(True) + def _start_operation_progress(self, total, label_text, action_button=None): + total = max(1, int(total)) + self.operation_progress.setRange(0, total) + self.operation_progress.setValue(0) + self.operation_progress.setFormat(f"{label_text}: %v/%m") + self.operation_progress.show() + self._active_action_button = action_button + self._active_action_button_text = action_button.text() if action_button else "" + if action_button is not None: + action_button.setText(f"{label_text} (0/{total})") + action_button.setEnabled(False) + + def _update_operation_progress(self, processed, total, label_text): + total = max(1, int(total)) + processed = max(0, min(int(processed), total)) + self.operation_progress.setRange(0, total) + self.operation_progress.setValue(processed) + self.operation_progress.setFormat(f"{label_text}: {processed}/{total}") + if self._active_action_button is not None: + self._active_action_button.setText(f"{label_text} ({processed}/{total})") + + def _finish_operation_progress(self): + self.operation_progress.hide() + self.operation_progress.setValue(0) + self.operation_progress.setFormat("%p%") + if self._active_action_button is not None: + self._active_action_button.setText(self._active_action_button_text or self._active_action_button.text()) + self._active_action_button = None + self._active_action_button_text = "" + def _ensure_log_dir(self): os.makedirs(APP_DATA_DIR, exist_ok=True) @@ -914,7 +952,7 @@ class VkChatManager(QMainWindow): selected.append({'id': chat_id, 'title': title}) return selected - def _execute_user_action(self, action_type): + def _execute_user_action(self, action_type, action_button=None): if not self.user_ids_to_process: QMessageBox.warning(self, "Ошибка", f"Нет ID пользователей для операции.") return @@ -978,6 +1016,7 @@ class VkChatManager(QMainWindow): try: action_label = "исключение" if action_type == "remove" else "приглашение" self._set_busy(True, f"Статус: выполняется {action_label} (0/{total})...") + self._start_operation_progress(total, action_label, action_button=action_button) for chat in selected_chats: for user_id, user_info in user_infos.items(): try: @@ -996,8 +1035,10 @@ class VkChatManager(QMainWindow): results.append(f"✗ Ошибка для '{user_info}' в '{chat['title']}': {self._format_vk_error(e)}") finally: processed += 1 + self._update_operation_progress(processed, total, action_label) self.status_label.setText(f"Статус: выполняется {action_label} ({processed}/{total})...") finally: + self._finish_operation_progress() self._set_busy(False) QMessageBox.information(self, "Результаты", "\n".join(results)) @@ -1006,10 +1047,10 @@ class VkChatManager(QMainWindow): self.set_ui_state(self.token is not None) def remove_user(self): - self._execute_user_action("remove") + self._execute_user_action("remove", action_button=self.remove_user_btn) def add_user_to_chat(self): - self._execute_user_action("add") + self._execute_user_action("add", action_button=self.add_user_btn) def set_user_admin(self): """Назначает пользователя администратором чата.""" @@ -1052,7 +1093,9 @@ class VkChatManager(QMainWindow): total = len(selected_chats) * len(user_infos) processed = 0 try: - self._set_busy(True, f"Статус: назначение админов (0/{total})...") + action_label = "назначение админов" + self._set_busy(True, f"Статус: {action_label} (0/{total})...") + self._start_operation_progress(total, action_label) for chat in selected_chats: # VK API требует peer_id. Для чатов это 2000000000 + local_id try: @@ -1076,8 +1119,10 @@ class VkChatManager(QMainWindow): results.append(f"✗ Ошибка для '{user_info}' в '{chat['title']}': {self._format_vk_error(e)}") finally: processed += 1 - self.status_label.setText(f"Статус: назначение админов ({processed}/{total})...") + self._update_operation_progress(processed, total, action_label) + self.status_label.setText(f"Статус: {action_label} ({processed}/{total})...") finally: + self._finish_operation_progress() self._set_busy(False) # 5. Вывод результата