diff --git a/Auto_Use/macOS_use/remote_connection/telegram/service.py b/Auto_Use/macOS_use/remote_connection/telegram/service.py index e8d7230..7a40b02 100644 --- a/Auto_Use/macOS_use/remote_connection/telegram/service.py +++ b/Auto_Use/macOS_use/remote_connection/telegram/service.py @@ -628,10 +628,12 @@ def _read_and_forward(): def _run_agent(task, provider, model, chat_id, bot, loop): """Run the agent and ping the chat when done. Streams scratchpad milestones back to the chat live while the agent works. Pops a compact pill so the - Mac user can see a Telegram task is running, and minimises the main app - window so the agent has the screen to itself. Restores phase to 'ready'.""" - # Compact "Telegram task in progress" indicator + minimise AutoUse window. - # Both are best-effort — never let UI fluff block the actual task. + Mac user can see a Telegram task is running, and overlays the main app + window with a "Currently occupied by Telegram" state. Restores phase to + 'ready'.""" + # Compact "Telegram task in progress" indicator + "occupied" overlay on + # the main window. Both are best-effort — never let UI fluff block the + # actual task. from Auto_Use.macOS_use.remote_connection.banner import StatusBanner, CoderBannerManager task_banner = StatusBanner(compact=True) try: @@ -642,18 +644,20 @@ def _run_agent(task, provider, model, chat_id, bot, loop): # todo checklist + minion spinner rows) while the main agent is halted in # cli_await, then collapses back. Drives the same task_banner. Best-effort. coder_mgr = CoderBannerManager(task_banner) - # Minimise the AutoUse pywebview window so the agent has the screen to - # itself. We talk to pywebview directly via its global `windows` list - # rather than importing from app.py — `python app.py` makes app.py the - # __main__ module, so `from app import …` would re-import a *second* - # copy of app.py whose webview_window is still None, and the call would - # silently no-op. + # Fade the AutoUse UI away and show the Telegram "occupied" overlay (orb + + # message) on the main window instead of minimising it. We talk to pywebview + # directly via its global `windows` list rather than importing from app.py — + # `python app.py` makes app.py the __main__ module, so `from app import …` + # would re-import a *second* copy of app.py whose webview_window is still + # None, and the call would silently no-op. evaluate_js from this worker + # thread is the same path app.py's send_*_to_frontend helpers already use. try: import webview as _webview if _webview.windows: - _webview.windows[0].minimize() + _webview.windows[0].evaluate_js( + "window.telegramOccupiedShow && window.telegramOccupiedShow()") except Exception: - logger.warning("could not minimise AutoUse window", exc_info=True) + logger.warning("could not show Telegram occupied overlay", exc_info=True) # Reset the milestone scratchpad to empty before starting the monitor. # AgentService.__init__ wipes the entire scratchpad/ directory in @@ -760,6 +764,16 @@ def _banner_update(text: str) -> None: coder_mgr.close_all() except Exception: pass + # Restore the main UI — hide the "occupied" overlay. If a queued task + # follows, its _run_agent start re-shows it almost immediately (at worst + # a brief flicker between back-to-back tasks). + try: + import webview as _webview + if _webview.windows: + _webview.windows[0].evaluate_js( + "window.telegramOccupiedHide && window.telegramOccupiedHide()") + except Exception: + pass with _state_lock: state = _chat_state.get(chat_id) if state is not None and state.get("phase") == "running": diff --git a/Auto_Use/windows_use/remote_connection/telegram/service.py b/Auto_Use/windows_use/remote_connection/telegram/service.py index 0e7837b..83ba7b3 100644 --- a/Auto_Use/windows_use/remote_connection/telegram/service.py +++ b/Auto_Use/windows_use/remote_connection/telegram/service.py @@ -629,11 +629,12 @@ def _read_and_forward(): def _run_agent(task, provider, model, chat_id, bot, loop): """Run the agent and ping the chat when done. Streams scratchpad milestones back to the chat live while the agent works. Pops a compact pill so the - Windows user can see a Telegram task is running, and minimises the main - app window so the agent has the screen to itself. Restores phase to + Windows user can see a Telegram task is running, and overlays the main app + window with a "Currently occupied by Telegram" state. Restores phase to 'ready'.""" - # Compact "Telegram task in progress" indicator + minimise AutoUse window. - # Both are best-effort — never let UI fluff block the actual task. + # Compact "Telegram task in progress" indicator + "occupied" overlay on + # the main window. Both are best-effort — never let UI fluff block the + # actual task. from Auto_Use.windows_use.remote_connection.banner import StatusBanner, CoderBannerManager task_banner = StatusBanner(compact=True) try: @@ -644,18 +645,20 @@ def _run_agent(task, provider, model, chat_id, bot, loop): # todo checklist + minion spinner rows) while the main agent is halted in # cli_await, then collapses back. Drives the same task_banner. Best-effort. coder_mgr = CoderBannerManager(task_banner) - # Minimise the AutoUse pywebview window so the agent has the screen to - # itself. We talk to pywebview directly via its global `windows` list - # rather than importing from app.py — `python app.py` makes app.py the - # __main__ module, so `from app import …` would re-import a *second* - # copy of app.py whose webview_window is still None, and the call would - # silently no-op. + # Fade the AutoUse UI away and show the Telegram "occupied" overlay (orb + + # message) on the main window instead of minimising it. We talk to pywebview + # directly via its global `windows` list rather than importing from app.py — + # `python app.py` makes app.py the __main__ module, so `from app import …` + # would re-import a *second* copy of app.py whose webview_window is still + # None, and the call would silently no-op. evaluate_js from this worker + # thread is the same path app.py's send_*_to_frontend helpers already use. try: import webview as _webview if _webview.windows: - _webview.windows[0].minimize() + _webview.windows[0].evaluate_js( + "window.telegramOccupiedShow && window.telegramOccupiedShow()") except Exception: - logger.warning("could not minimise AutoUse window", exc_info=True) + logger.warning("could not show Telegram occupied overlay", exc_info=True) # Reset the milestone scratchpad to empty before starting the monitor. # AgentService.__init__ wipes the entire scratchpad/ directory in @@ -764,6 +767,16 @@ def _banner_update(text: str) -> None: coder_mgr.close_all() except Exception: pass + # Restore the main UI — hide the "occupied" overlay. If a queued task + # follows, its _run_agent start re-shows it almost immediately (at worst + # a brief flicker between back-to-back tasks). + try: + import webview as _webview + if _webview.windows: + _webview.windows[0].evaluate_js( + "window.telegramOccupiedHide && window.telegramOccupiedHide()") + except Exception: + pass with _state_lock: state = _chat_state.get(chat_id) if state is not None and state.get("phase") == "running": diff --git a/frontend/css/style.css b/frontend/css/style.css index 797d814..bc1c21f 100644 --- a/frontend/css/style.css +++ b/frontend/css/style.css @@ -774,6 +774,89 @@ body { transform: scale(1) translateY(0); } +/* ── Telegram "occupied" overlay (shown while a Telegram task runs) ───────── */ +.telegram-task-overlay { + position: fixed; + inset: 0; + /* Transparent — the app's background video (#bgVideo) stays visible; only + the UI components fade out (see body.tg-occupied) while the orb fades in. */ + background: transparent; + z-index: 101; + + display: flex; + align-items: center; + justify-content: center; + + opacity: 0; + visibility: hidden; + pointer-events: none; + transition: opacity 0.4s ease, visibility 0.4s ease; +} + +.telegram-task-overlay.active { + opacity: 1; + visibility: visible; + pointer-events: auto; +} + +/* While a Telegram task occupies the machine: fade the app's UI components away + but keep the background video. The orb + message live in the transparent + overlay above. (id-based selector wins over the components' own .active / + .agent-visible show states.) */ +body.tg-occupied #chatWrapper, +body.tg-occupied #llmWrapper, +body.tg-occupied #settingsBtn, +body.tg-occupied #imageStreamContainer, +body.tg-occupied #mainGlobeContainer, +body.tg-occupied #shellTerminalContainer { + opacity: 0; + pointer-events: none; + transition: opacity 0.4s ease; +} + +.telegram-task-content { + display: flex; + flex-direction: column; + align-items: center; + gap: 18px; + + transform: scale(0.92); + transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); +} + +.telegram-task-overlay.active .telegram-task-content { + transform: scale(1); +} + +.telegram-task-orb { + width: 140px; + height: 140px; + display: flex; + align-items: center; + justify-content: center; + overflow: visible; +} + +/* The orb renders at native 42px when iframed (its 6x preview-scale only kicks + in when the file is opened directly). It centres itself in the iframe, so we + scale the iframe up to enlarge the orb while keeping a fixed 140px layout box + (transform doesn't affect layout) — that keeps the gap to the message clean. */ +.telegram-task-orb iframe { + width: 58px; + height: 58px; + border: 0; + background: transparent; + pointer-events: none; + transform: scale(2.4); + transform-origin: center; +} + +.telegram-task-message { + font-size: 16px; + color: #8a8a92; + letter-spacing: 0.2px; +} + .settings-panel-content { position: relative; z-index: 3; diff --git a/frontend/index.html b/frontend/index.html index 8d4c08f..9a0dab4 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -437,6 +437,16 @@ + +
+
+
+ +
+
Currently occupied by Telegram
+
+
+ diff --git a/frontend/script.js b/frontend/script.js index f394fda..77a4f1b 100644 --- a/frontend/script.js +++ b/frontend/script.js @@ -1405,6 +1405,20 @@ document.addEventListener('DOMContentLoaded', () => { imageStreamContainer.classList.remove('web-active'); }; + // ============================================ + // TELEGRAM "OCCUPIED" OVERLAY + // Shown while a Telegram task runs (instead of minimizing the window). + // ============================================ + const telegramTaskOverlay = document.getElementById('telegramTaskOverlay'); + window.telegramOccupiedShow = () => { + document.body.classList.add('tg-occupied'); // fade UI components away + if (telegramTaskOverlay) telegramTaskOverlay.classList.add('active'); + }; + window.telegramOccupiedHide = () => { + document.body.classList.remove('tg-occupied'); + if (telegramTaskOverlay) telegramTaskOverlay.classList.remove('active'); + }; + // ============================================ // SHELL TERMINAL ANIMATION // ============================================