From c6370235be3ebc71886596bfdc86c7029a27f107 Mon Sep 17 00:00:00 2001 From: nesquena-hermes Date: Mon, 29 Jun 2026 01:15:09 +0000 Subject: [PATCH] feat(composer): fit footer controls by overflow (#4657, rebased onto master) Rebased Paladin173's #4657 onto current master. The per-control visibility toggles half already shipped via his own #4598, so this rebase carries only the net-new JS fit-by-overflow engine (_fitComposerFooter: ResizeObserver + MutationObserver measure .composer-left overflow, step full -> cf-icons -> cf-burger). Co-authored-by: Paladin173 --- api/config.py | 9 +- static/boot.js | 6 +- static/i18n.js | 42 ++-- static/index.html | 10 +- static/panels.js | 11 +- static/style.css | 115 ++++------ static/ui.js | 189 +++++++++++++--- ...test_issue1431_toolsets_chip_responsive.py | 15 +- .../test_issue4650_reasoning_chip_no_storm.py | 4 + tests/test_mobile_layout.py | 201 +++++++++++------- tests/test_quota_chip_settings_toggle.py | 62 +++++- tests/test_reasoning_chip_js_behaviour.py | 12 +- 12 files changed, 454 insertions(+), 222 deletions(-) diff --git a/api/config.py b/api/config.py index 737ee0f6..1bdd2a89 100644 --- a/api/config.py +++ b/api/config.py @@ -7734,7 +7734,8 @@ _SETTINGS_DEFAULTS = { "onboarding_completed": False, "send_key": "enter", # 'enter' or 'ctrl+enter' "show_token_usage": False, # show input/output token badge below assistant messages - "show_quota_chip": False, # show ambient provider quota chip in composer footer (default off; wide desktop only when enabled, see style.css @media) + "show_quota_chip": True, # show ambient provider quota chip in composer footer by default + "show_quota_chip_opt_out": False, # post-default-flip marker for explicit user opt-out "show_conversation_outline": False, # show opt-in desktop jump-to-question outline panel "hide_empty_state_suggestions": False, # hide the default new-chat suggestion buttons "virtualize_transcript": False, # #4343: virtualize long (>80 msg) transcripts. EXPERIMENTAL, opt-IN (default OFF). Was opt-out/default-on in #4325 but caused scroll-up flicker on long sessions with tall tool-call rows (variable-height anchor oscillation) — flipped off for everyone in #4343; re-enabling requires an explicit opt-in (see virtualize_transcript_optin migration in load_settings). @@ -7934,6 +7935,11 @@ def load_settings() -> dict: # Honor a stored True only when that marker is present. if not bool(stored.get("virtualize_transcript_optin")): settings["virtualize_transcript"] = False + # show_quota_chip used to be persisted as False by default. After + # flipping it visible-by-default, treat an old stored False as + # stale unless a post-flip opt-out marker is present. + if not bool(stored.get("show_quota_chip_opt_out")): + settings["show_quota_chip"] = True except Exception: logger.debug("Failed to load settings from %s", SETTINGS_FILE) @@ -7978,6 +7984,7 @@ _SETTINGS_BOOL_KEYS = { "onboarding_completed", "show_token_usage", "show_quota_chip", + "show_quota_chip_opt_out", "show_conversation_outline", "hide_empty_state_suggestions", "virtualize_transcript", diff --git a/static/boot.js b/static/boot.js index 850d4e8b..6481e2f1 100644 --- a/static/boot.js +++ b/static/boot.js @@ -2295,7 +2295,7 @@ const _COMPOSER_SITUATIONAL_CONTROL_TOGGLE_DEFS=[ {key:'hide_composer_yolo',label:'YOLO',labelKey:'composer_control_yolo',selectors:['#yoloPill']}, {key:'hide_composer_bg_badge',label:'Background badge',labelKey:'composer_control_bg_badge',selectors:['#bgBadge']}, {key:'hide_composer_mobile_config',label:'Mobile config',labelKey:'composer_control_mobile_config',selectors:['#composerMobileConfigBtn']}, - {key:'hide_composer_quota_chip',label:'Quota chip',labelKey:'composer_control_quota_chip',selectors:['#providerQuotaChip']}, + {key:'hide_composer_quota_chip',label:'Quota chip',labelKey:'composer_control_quota_chip',selectors:['#providerQuotaChip','#composerMobileQuotaAction']}, {key:'hide_composer_toolsets',label:'Toolsets',labelKey:'composer_control_toolsets',selectors:['#composerToolsetsWrap']}, {key:'hide_composer_status',label:'Status',labelKey:'composer_control_status',selectors:['#composerStatus']}, ]; @@ -2370,7 +2370,7 @@ window._applyTitlebarProfileVisibility=_applyTitlebarProfileVisibility; // and workspace actions (New file/folder) work before the first session (#804). if(s.default_workspace) S._profileDefaultWorkspace=s.default_workspace; window._showTokenUsage=!!s.show_token_usage; - window._showQuotaChip=s.show_quota_chip===true; + window._showQuotaChip=s.show_quota_chip!==false; window._showConversationOutline=s.show_conversation_outline===true; document.documentElement.dataset.conversationOutline=window._showConversationOutline?'enabled':'disabled'; if(typeof applyConversationOutlinePreference==='function') applyConversationOutlinePreference(); @@ -2504,7 +2504,7 @@ window._applyTitlebarProfileVisibility=_applyTitlebarProfileVisibility; }catch(e){ window._sendKey='enter'; window._showTokenUsage=false; - window._showQuotaChip=false; + window._showQuotaChip=true; window._showConversationOutline=false; document.documentElement.dataset.conversationOutline='disabled'; if(typeof applyConversationOutlinePreference==='function') applyConversationOutlinePreference(); diff --git a/static/i18n.js b/static/i18n.js index 1690624a..f95a8c41 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -811,7 +811,7 @@ const LOCALES = { settings_autosave_retry: 'Retry', settings_label_language: 'Language', settings_label_quota_chip: 'Show provider quota chip in composer', - settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Default off. Only visible on wide displays (≥1400px) when enabled, to keep the composer uncluttered on laptop and standard desktop widths.', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: 'Show conversation outline', settings_desc_conversation_outline: 'Show a desktop-only jump list for user questions in the current conversation. Off by default.', settings_label_hide_suggestions: 'Hide new-chat suggestions', @@ -1600,6 +1600,7 @@ const LOCALES = { composer_disabled_empty: 'Type a message to send', composer_mobile_workspace: 'Workspace', composer_mobile_model: 'Model', + composer_mobile_quota: 'Quota', composer_mobile_reasoning: 'Reasoning', composer_mobile_context: 'Context', media_audio_label: 'Audio', @@ -2449,7 +2450,7 @@ const LOCALES = { settings_autosave_retry: 'Riprova', settings_label_language: 'Lingua', settings_label_quota_chip: 'Mostra il chip della quota del provider nel compositore', - settings_desc_quota_chip: "Mostra un indicatore di quota residua (es. saldo crediti OpenRouter) nel piè di pagina del compositore. Predefinito disattivato. Visibile solo su schermi larghi (≥1400px) quando attivato, per mantenere il compositore non affollato su laptop e desktop standard.", + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: 'Mostra struttura conversazione', settings_desc_conversation_outline: 'Mostra un elenco di salto solo desktop per le domande utente nella conversazione corrente. Disattivato per impostazione predefinita.', settings_label_hide_suggestions: 'Hide new-chat suggestions', @@ -3226,6 +3227,7 @@ const LOCALES = { composer_disabled_empty: 'Scrivi un messaggio da inviare', composer_mobile_workspace: 'Workspace', composer_mobile_model: 'Modello', + composer_mobile_quota: 'Quota', composer_mobile_reasoning: 'Ragionamento', composer_mobile_context: 'Contesto', media_audio_label: 'Audio', @@ -4078,7 +4080,7 @@ const LOCALES = { settings_autosave_retry: '再試行', settings_label_language: '言語', settings_label_quota_chip: 'コンポーザーにプロバイダーのクォータチップを表示', - settings_desc_quota_chip: 'コンポーザーのフッターに残りクォータインジケーター(例: OpenRouter のクレジット残高)を表示します。デフォルトはオフ。有効にした場合、ラップトップや標準デスクトップの幅でコンポーザーが混雑しないよう、ワイドディスプレイ(≥1400px)でのみ表示されます。', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: '会話アウトラインを表示', settings_desc_conversation_outline: '現在の会話内のユーザー質問へ移動するデスクトップ専用リストを表示します。デフォルトはオフです。', settings_label_hide_suggestions: '新規チャットの候補を非表示', @@ -4860,6 +4862,7 @@ const LOCALES = { composer_disabled_empty: '送信するメッセージを入力してください', composer_mobile_workspace: 'ワークスペース', composer_mobile_model: 'モデル', + composer_mobile_quota: 'クォータ', composer_mobile_reasoning: '思考', composer_mobile_context: 'コンテキスト', media_audio_label: '音声', @@ -5421,7 +5424,7 @@ const LOCALES = { settings_label_theme: 'Тема', settings_label_language: 'Язык', settings_label_quota_chip: 'Показывать чип квоты провайдера в композиторе', - settings_desc_quota_chip: 'Отображает фоновый индикатор остатка квоты (например, баланс кредитов OpenRouter) в подвале композитора. По умолчанию отключено. Виден только на широких экранах (≥1400px) при включении, чтобы не загромождать композитор на ноутбуках и стандартных мониторах.', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: 'Показывать структуру беседы', settings_desc_conversation_outline: 'Показывает на рабочем столе список переходов к вопросам пользователя в текущей беседе. По умолчанию отключено.', settings_label_hide_suggestions: 'Hide new-chat suggestions', @@ -6357,6 +6360,7 @@ const LOCALES = { composer_disabled_empty: 'Введите сообщение для отправки', composer_mobile_workspace: 'Рабочее пространство', composer_mobile_model: 'Модель', + composer_mobile_quota: 'Квота', composer_mobile_reasoning: 'Рассуждение', composer_mobile_context: 'Контекст', media_audio_label: 'Аудио', @@ -6977,7 +6981,7 @@ const LOCALES = { settings_autosave_retry: 'Reintentar', settings_label_language: 'Idioma', settings_label_quota_chip: 'Mostrar el chip de cuota del proveedor en el compositor', - settings_desc_quota_chip: 'Muestra un indicador ambiental de cuota restante (por ejemplo, saldo de crédito de OpenRouter) en el pie del compositor. Predeterminado: desactivado. Solo visible en pantallas anchas (≥1400px) cuando se activa, para mantener el compositor despejado en portátiles y monitores estándar.', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: 'Mostrar esquema de conversación', settings_desc_conversation_outline: 'Muestra una lista de salto solo en escritorio para las preguntas del usuario en la conversación actual. Desactivado de forma predeterminada.', settings_label_hide_suggestions: 'Hide new-chat suggestions', @@ -7911,6 +7915,7 @@ const LOCALES = { composer_disabled_empty: 'Escribe un mensaje para enviar', composer_mobile_workspace: 'Espacio de trabajo', composer_mobile_model: 'Modelo', + composer_mobile_quota: 'Cuota', composer_mobile_reasoning: 'Razonamiento', composer_mobile_context: 'Contexto', media_audio_label: 'Audio', @@ -8521,7 +8526,7 @@ const LOCALES = { settings_autosave_retry: 'Wiederholen', settings_label_language: 'Sprache', settings_label_quota_chip: 'Anbieter-Kontingent-Chip im Editor anzeigen', - settings_desc_quota_chip: 'Zeigt einen Hintergrund-Indikator des verbleibenden Kontingents (z. B. OpenRouter-Guthaben) in der Editor-Fußzeile an. Standardmäßig deaktiviert. Bei Aktivierung nur auf breiten Bildschirmen (≥1400px) sichtbar, damit der Editor auf Laptops und Standard-Desktops übersichtlich bleibt.', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: 'Konversationsgliederung anzeigen', settings_desc_conversation_outline: 'Zeigt eine Desktop-Sprungliste für Benutzerfragen in der aktuellen Konversation. Standardmäßig deaktiviert.', settings_label_hide_suggestions: 'Hide new-chat suggestions', @@ -9149,6 +9154,7 @@ const LOCALES = { composer_disabled_empty: 'Nachricht eingeben zum Senden', composer_mobile_workspace: 'Arbeitsbereich', composer_mobile_model: 'Modell', + composer_mobile_quota: 'Kontingent', composer_mobile_reasoning: 'Reasoning', composer_mobile_context: 'Kontext', model_custom_label: 'Benutzerdefinierte Modell-ID', @@ -10130,7 +10136,7 @@ const LOCALES = { settings_autosave_retry: '重试', settings_label_language: '语言', settings_label_quota_chip: '在编辑器中显示供应商配额标签', - settings_desc_quota_chip: '在编辑器底部显示剩余配额指示器(如 OpenRouter 信用余额)。默认关闭。启用时仅在宽屏(≥1400px)显示,以保持笔记本和标准桌面屏幕上编辑器的整洁。', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: '显示会话大纲', settings_desc_conversation_outline: '显示仅限桌面的跳转列表,用于跳转到当前会话中的用户问题。默认关闭。', settings_label_hide_suggestions: 'Hide new-chat suggestions', @@ -11041,6 +11047,7 @@ const LOCALES = { composer_disabled_empty: '请输入消息后发送', composer_mobile_workspace: '工作区', composer_mobile_model: '模型', + composer_mobile_quota: '配额', composer_mobile_reasoning: '推理', composer_mobile_context: '上下文', @@ -11974,7 +11981,7 @@ const LOCALES = { settings_autosave_retry: '重試', settings_label_language: '語言', settings_label_quota_chip: '在編輯器中顯示供應商配額標籤', - settings_desc_quota_chip: '在編輯器底部顯示剩餘配額指示器(如 OpenRouter 點數餘額)。預設關閉。啟用時僅在寬螢幕(≥1400px)顯示,以保持筆記型電腦和標準桌面螢幕上編輯器的整潔。', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: '顯示對話大綱', settings_desc_conversation_outline: '顯示僅限桌面的跳轉清單,用於跳轉到目前對話中的使用者問題。預設關閉。', settings_label_hide_suggestions: '隱藏新聊天建議', @@ -12759,6 +12766,7 @@ const LOCALES = { composer_disabled_empty: '請輸入訊息後傳送', composer_mobile_workspace: '工作區', composer_mobile_model: '模型', + composer_mobile_quota: '配額', composer_mobile_reasoning: '推理', composer_mobile_context: '脈絡', media_audio_label: '音訊', @@ -12922,6 +12930,7 @@ const LOCALES = { model_not_found_label: 'Modelo não encontrado', composer_mobile_workspace: 'Workspace', composer_mobile_model: 'Modelo', + composer_mobile_quota: 'Cota', composer_mobile_reasoning: 'Raciocínio', composer_mobile_context: 'Contexto', model_custom_label: 'ID de modelo customizado', @@ -13497,7 +13506,7 @@ const LOCALES = { settings_autosave_retry: 'Tentar novamente', settings_label_language: 'Idioma', settings_label_quota_chip: 'Mostrar o chip de cota do provedor no compositor', - settings_desc_quota_chip: 'Exibe um indicador ambiente de cota restante (por exemplo, saldo de crédito do OpenRouter) no rodapé do compositor. Desativado por padrão. Visível apenas em telas largas (≥1400px) quando ativado, para manter o compositor livre em laptops e monitores padrão.', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: 'Mostrar estrutura da conversa', settings_desc_conversation_outline: 'Mostra uma lista de atalhos somente no desktop para as perguntas do usuário na conversa atual. Desativado por padrão.', settings_label_hide_suggestions: 'Hide new-chat suggestions', @@ -15026,7 +15035,7 @@ const LOCALES = { settings_autosave_retry: '다시 시도', settings_label_language: '언어', settings_label_quota_chip: '작성기에 공급자 할당량 칩 표시', - settings_desc_quota_chip: '작성기 푸터에 남은 할당량 표시기(예: OpenRouter 크레딧 잔액)를 표시합니다. 기본값은 끔. 활성화 시 노트북과 표준 데스크톱에서 작성기가 복잡해지지 않도록 와이드 디스플레이(≥1400px)에서만 표시됩니다.', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: '대화 개요 표시', settings_desc_conversation_outline: '현재 대화의 사용자 질문으로 이동하는 데스크톱 전용 목록을 표시합니다. 기본값은 꺼짐입니다.', settings_label_hide_suggestions: 'Hide new-chat suggestions', @@ -15742,6 +15751,7 @@ const LOCALES = { composer_disabled_empty: '메시지를 입력하세요', composer_mobile_workspace: '워크스페이스', composer_mobile_model: '모델', + composer_mobile_quota: '할당량', composer_mobile_reasoning: '추론', composer_mobile_context: '컨텍스트', @@ -16667,7 +16677,7 @@ const LOCALES = { settings_autosave_retry: 'Réessayer', settings_label_language: 'Langue', settings_label_quota_chip: 'Afficher le jeton de quota du fournisseur dans le compositeur', - settings_desc_quota_chip: 'Affiche un indicateur de quota restant (ex. solde de crédit OpenRouter) dans le pied de page du compositeur. Désactivé par défaut. Visible uniquement sur les grands écrans (≥1400px) lorsqu\'il est activé, pour garder le compositeur épuré sur les ordinateurs portables et les écrans de bureau standards.', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: 'Afficher le plan de la conversation', settings_desc_conversation_outline: 'Afficher une liste de saut réservée au bureau pour les questions utilisateur dans la conversation actuelle. Désactivé par défaut.', settings_label_hide_suggestions: 'Masquer les suggestions de nouvelle conversation', @@ -17435,6 +17445,7 @@ const LOCALES = { composer_disabled_empty: 'Saisissez un message à envoyer', composer_mobile_workspace: 'Espace de travail', composer_mobile_model: 'Modèle', + composer_mobile_quota: 'Quota', composer_mobile_reasoning: 'Raisonnement', composer_mobile_context: 'Contexte', media_audio_label: 'Audio', @@ -18264,7 +18275,7 @@ const LOCALES = { settings_autosave_retry: 'Yeniden dene', settings_label_language: 'Dil', settings_label_quota_chip: 'Bestecide sağlayıcı kota çipini göster', - settings_desc_quota_chip: 'Besteci altbilgisinde bir ortam kalan kota göstergesini (örn. OpenRouter kredi bakiyesi) görüntüler. Varsayılan kapalı. Besteciyi dizüstü bilgisayar ve standart masaüstü genişliklerinde düzenli tutmak için yalnızca etkinleştirildiğinde geniş ekranlarda (≥1400 piksel) görünür.', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: 'Konuşma ana hattını göster', settings_desc_conversation_outline: 'Geçerli konuşmadaki kullanıcı soruları için yalnızca masaüstünde görünen bir atlama listesi gösterir. Varsayılan kapalıdır.', settings_label_hide_suggestions: 'Yeni sohbet önerilerini gizle', @@ -18978,6 +18989,7 @@ const LOCALES = { composer_disabled_empty: 'Göndermek için bir mesaj yazın', composer_mobile_workspace: 'Çalışma alanı', composer_mobile_model: 'Modeli', + composer_mobile_quota: 'Kota', composer_mobile_reasoning: 'muhakeme', composer_mobile_context: 'Bağlam', @@ -19907,7 +19919,7 @@ const LOCALES = { settings_autosave_retry: 'Ponów próbę', settings_label_language: 'Język', settings_label_quota_chip: 'Pokaż wskaźnik limitu dostawcy w polu wprowadzania', - settings_desc_quota_chip: 'Wyświetla subtelny wskaźnik pozostałego limitu (np. saldo kredytów OpenRouter) w stopce pola wprowadzania. Domyślnie wyłączone. Widoczne tylko na szerokich ekranach (≥1400px), aby utrzymać pole wprowadzania czytelnym na laptopach i standardowych monitorach.', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: 'Pokaż zarys konwersacji', settings_desc_conversation_outline: 'Pokazuje desktopową listę skrótów do pytań użytkownika w bieżącej konwersacji. Domyślnie wyłączone.', settings_label_hide_suggestions: 'Ukryj sugestie nowej konwersacji', @@ -20686,6 +20698,7 @@ const LOCALES = { composer_disabled_empty: 'Wpisz wiadomość, aby wysłać', composer_mobile_workspace: 'Obszar roboczy', composer_mobile_model: 'Model', + composer_mobile_quota: 'Limit', composer_mobile_reasoning: 'Myślenie', composer_mobile_context: 'Kontekst', media_audio_label: 'Dźwięk', @@ -21380,7 +21393,7 @@ const LOCALES = { settings_autosave_retry: 'Thử lại', settings_label_language: 'Ngôn ngữ', settings_label_quota_chip: 'Hiện hạn mức nhà cung cấp trong khung soạn thảo', - settings_desc_quota_chip: 'Hiển thị chỉ báo quota còn lại (ví dụ: số dư credit OpenRouter) ở footer của composer. Mặc định tắt. Chỉ hiển thị trên màn hình rộng (≥1400px) khi bật để giữ composer gọn gàng trên laptop và desktop thông thường.', + settings_desc_quota_chip: 'Displays an ambient remaining-quota indicator (e.g. OpenRouter credit balance) in the composer footer. Shown by default when provider quota data is available.', settings_label_conversation_outline: 'Hiện mục lục cuộc trò chuyện', settings_desc_conversation_outline: 'Hiển thị danh sách nhảy nhanh cho các câu hỏi của người dùng trong cuộc trò chuyện hiện tại trên desktop. Mặc định tắt.', settings_label_hide_suggestions: 'Ẩn gợi ý chat mới', @@ -22170,6 +22183,7 @@ const LOCALES = { composer_compression_will_queue: 'Nhập tin nhắn — hệ thống sẽ xếp hàng và gửi sau khi nén xong', composer_mobile_workspace: 'Workspace', composer_mobile_model: 'Model', + composer_mobile_quota: 'Hạn mức', composer_mobile_reasoning: 'Lập luận', composer_mobile_context: 'Ngữ cảnh', context_block_name_default: 'Ngữ cảnh', diff --git a/static/index.html b/static/index.html index 39c3139b..86a79fa2 100644 --- a/static/index.html +++ b/static/index.html @@ -624,7 +624,7 @@ -
@@ -703,7 +703,7 @@
-
+
+