Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/_locales/de/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@
"Always pin the floating window": "Immer das schwebende Fenster anheften",
"Export": "Exportieren",
"Always Create New Conversation Window": "Immer ein neues Chatfenster erstellen",
"Automatically generate conversation titles": "Unterhaltungstitel automatisch erstellen",
"Conversation title model": "Modell für Unterhaltungstitel",
"Select a model": "Modell auswählen",
"Choose a fast, low-cost OpenAI-compatible chat model.": "Wählen Sie ein schnelles, kostengünstiges OpenAI-kompatibles Chatmodell.",
"The first completed exchange is sent once per conversation.": "Der erste abgeschlossene Austausch wird einmal pro Unterhaltung gesendet.",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "Bitte halten Sie diesen Tab geöffnet. Sie können jetzt den Webmodus von ChatGPTBox verwenden",
"Go Back": "Zurück",
"Pin Tab": "Tab anheften",
Expand Down
5 changes: 5 additions & 0 deletions src/_locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@
"Always pin the floating window": "Always pin the floating window",
"Export": "Export",
"Always Create New Conversation Window": "Always Create New Conversation Window",
"Automatically generate conversation titles": "Automatically generate conversation titles",
"Conversation title model": "Conversation title model",
"Select a model": "Select a model",
"Choose a fast, low-cost OpenAI-compatible chat model.": "Choose a fast, low-cost OpenAI-compatible chat model.",
"The first completed exchange is sent once per conversation.": "The first completed exchange is sent once per conversation.",
Comment thread
qodo-code-review[bot] marked this conversation as resolved.
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "Please keep this tab open. You can now use the web mode of ChatGPTBox",
"Go Back": "Go Back",
"Pin Tab": "Pin Tab",
Expand Down
5 changes: 5 additions & 0 deletions src/_locales/es/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@
"Always pin the floating window": "Siempre fijar la ventana flotante",
"Export": "Exportar",
"Always Create New Conversation Window": "Siempre crear una nueva ventana de conversación",
"Automatically generate conversation titles": "Generar automáticamente títulos de conversación",
"Conversation title model": "Modelo para títulos de conversación",
"Select a model": "Seleccionar un modelo",
"Choose a fast, low-cost OpenAI-compatible chat model.": "Elige un modelo de chat rápido, económico y compatible con OpenAI.",
"The first completed exchange is sent once per conversation.": "El primer intercambio completado se envía una vez por conversación.",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "Por favor, mantenga esta pestaña abierta. Ahora puede utilizar el modo web de ChatGPTBox.",
"Go Back": "Volver",
"Pin Tab": "Fijar pestaña",
Expand Down
7 changes: 6 additions & 1 deletion src/_locales/fr/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,10 @@
"The response stream from the API endpoint was interrupted.": "Le flux de réponse du point de terminaison de l’API a été interrompu.",
"Check the API endpoint URL and service availability, then try again.": "Vérifiez l’URL du point de terminaison de l’API et la disponibilité du service, puis réessayez.",
"API endpoint: %s": "Point de terminaison de l’API : %s",
"Browser message: %s": "Message du navigateur : %s"
"Browser message: %s": "Message du navigateur : %s",
"Automatically generate conversation titles": "Générer automatiquement les titres des conversations",
"Conversation title model": "Modèle de titre de conversation",
"Select a model": "Sélectionner un modèle",
"Choose a fast, low-cost OpenAI-compatible chat model.": "Choisissez un modèle de chat rapide, économique et compatible avec OpenAI.",
"The first completed exchange is sent once per conversation.": "Le premier échange terminé est envoyé une seule fois par conversation."
}
5 changes: 5 additions & 0 deletions src/_locales/id/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@
"Always pin the floating window": "Selalu selipkan jendela mengambang",
"Export": "Ekspor",
"Always Create New Conversation Window": "Selalu Buat Jendela Percakapan Baru",
"Automatically generate conversation titles": "Buat judul percakapan secara otomatis",
"Conversation title model": "Model judul percakapan",
"Select a model": "Pilih model",
"Choose a fast, low-cost OpenAI-compatible chat model.": "Pilih model chat kompatibel OpenAI yang cepat dan hemat biaya.",
"The first completed exchange is sent once per conversation.": "Pertukaran pertama yang telah selesai dikirim satu kali untuk setiap percakapan.",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "Silakan tetap buka tab ini. Anda sekarang dapat menggunakan mode web ChatGPTBox",
"Go Back": "Kembali",
"Pin Tab": "Sematkan Tab",
Expand Down
5 changes: 5 additions & 0 deletions src/_locales/it/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@
"Always pin the floating window": "Fissare sempre la finestra flottante",
"Export": "Esporta",
"Always Create New Conversation Window": "Crea sempre una nuova finestra di conversazione",
"Automatically generate conversation titles": "Genera automaticamente i titoli delle conversazioni",
"Conversation title model": "Modello per i titoli delle conversazioni",
"Select a model": "Seleziona un modello",
"Choose a fast, low-cost OpenAI-compatible chat model.": "Scegli un modello di chat rapido, economico e compatibile con OpenAI.",
"The first completed exchange is sent once per conversation.": "Il primo scambio completato viene inviato una volta per conversazione.",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "Per favore, mantieni questa scheda aperta. Ora puoi utilizzare la modalità web di ChatGPTBox",
"Go Back": "Torna indietro",
"Pin Tab": "Fissa scheda",
Expand Down
5 changes: 5 additions & 0 deletions src/_locales/ja/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@
"Always pin the floating window": "常にフローティングウィンドウをピン留め",
"Export": "エクスポート",
"Always Create New Conversation Window": "常に新しい会話ウィンドウを作成",
"Automatically generate conversation titles": "会話タイトルを自動生成",
"Conversation title model": "会話タイトル用モデル",
"Select a model": "モデルを選択",
"Choose a fast, low-cost OpenAI-compatible chat model.": "高速で低コストな OpenAI 互換チャットモデルを選択してください。",
"The first completed exchange is sent once per conversation.": "各会話で、最初に完了したやり取りが一度だけ送信されます。",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "このタブを開いたままにしてください。これでChatGPTBoxのWebモードを使用できます",
"Go Back": "戻る",
"Pin Tab": "タブをピン留め",
Expand Down
5 changes: 5 additions & 0 deletions src/_locales/ko/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@
"Always pin the floating window": "항상 떠다니는 창 고정",
"Export": "내보내기",
"Always Create New Conversation Window": "항상 새 대화 창 만들기",
"Automatically generate conversation titles": "대화 제목 자동 생성",
"Conversation title model": "대화 제목 모델",
"Select a model": "모델 선택",
"Choose a fast, low-cost OpenAI-compatible chat model.": "빠르고 저렴한 OpenAI 호환 채팅 모델을 선택하세요.",
"The first completed exchange is sent once per conversation.": "각 대화에서 처음 완료된 대화 내용이 한 번만 전송됩니다.",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "이 탭을 열어두세요. 이제 ChatGPTBox의 웹 모드를 사용할 수 있습니다.",
"Go Back": "뒤로 가기",
"Pin Tab": "탭 고정",
Expand Down
5 changes: 5 additions & 0 deletions src/_locales/pt/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@
"Always pin the floating window": "Sempre Fixar a Janela Flutuante",
"Export": "Exportar",
"Always Create New Conversation Window": "Sempre Criar Nova Janela de Conversação",
"Automatically generate conversation titles": "Gerar títulos de conversa automaticamente",
"Conversation title model": "Modelo para títulos de conversa",
"Select a model": "Selecionar um modelo",
"Choose a fast, low-cost OpenAI-compatible chat model.": "Escolha um modelo de chat rápido, econômico e compatível com OpenAI.",
"The first completed exchange is sent once per conversation.": "A primeira interação concluída é enviada uma vez por conversa.",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "Por favor, mantenha esta aba aberta. Agora pode usar o modo web do ChatGPTBox.",
"Go Back": "Voltar",
"Pin Tab": "Fixar Tab",
Expand Down
5 changes: 5 additions & 0 deletions src/_locales/ru/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
"Always pin the floating window": "Всегда прикреплять плавающее окно",
"Export": "Экспорт",
"Always Create New Conversation Window": "Всегда создавать новое окно разговора",
"Automatically generate conversation titles": "Автоматически создавать заголовки бесед",
"Conversation title model": "Модель для заголовков бесед",
"Select a model": "Выберите модель",
"Choose a fast, low-cost OpenAI-compatible chat model.": "Выберите быструю и недорогую чат-модель, совместимую с OpenAI.",
"The first completed exchange is sent once per conversation.": "Первый завершённый обмен отправляется один раз для каждой беседы.",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "Пожалуйста, оставьте эту вкладку открытой. Теперь вы можете использовать веб-режим ChatGPTBox",
"Go Back": "Назад",
"Pin Tab": "Закрепить вкладку",
Expand Down
5 changes: 5 additions & 0 deletions src/_locales/tr/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@
"Always pin the floating window": "Her zaman kayan pencereyi sabitle",
"Export": "Dışa Aktar",
"Always Create New Conversation Window": "Her zaman yeni bir konuşma penceresi oluştur",
"Automatically generate conversation titles": "Konuşma başlıklarını otomatik oluştur",
"Conversation title model": "Konuşma başlığı modeli",
"Select a model": "Bir model seçin",
"Choose a fast, low-cost OpenAI-compatible chat model.": "Hızlı, düşük maliyetli ve OpenAI uyumlu bir sohbet modeli seçin.",
"The first completed exchange is sent once per conversation.": "Tamamlanan ilk mesajlaşma her konuşma için yalnızca bir kez gönderilir.",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "Lütfen bu sekme açık kalsın. Artık ChatGPTBox'ın web modunu kullanabilirsiniz",
"Go Back": "Geri Dön",
"Pin Tab": "Sekmeyi Sabitle",
Expand Down
5 changes: 5 additions & 0 deletions src/_locales/zh-hans/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@
"Always pin the floating window": "总是固定浮动窗口",
"Export": "导出",
"Always Create New Conversation Window": "总是创建新的对话窗口",
"Automatically generate conversation titles": "自动生成对话标题",
"Conversation title model": "对话标题模型",
"Select a model": "选择模型",
"Choose a fast, low-cost OpenAI-compatible chat model.": "请选择快速、低成本且兼容 OpenAI 的对话模型。",
"The first completed exchange is sent once per conversation.": "每个对话只会发送一次首轮完整问答。",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "请保持这个页面打开, 现在你可以使用ChatGPTBox的网页版模式",
"Go Back": "返回",
"Pin Tab": "固定页面",
Expand Down
5 changes: 5 additions & 0 deletions src/_locales/zh-hant/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@
"Always pin the floating window": "總是固定浮動視窗",
"Export": "匯出",
"Always Create New Conversation Window": "總是建立新的對話視窗",
"Automatically generate conversation titles": "自動產生對話標題",
"Conversation title model": "對話標題模型",
"Select a model": "選擇模型",
"Choose a fast, low-cost OpenAI-compatible chat model.": "請選擇快速、低成本且相容 OpenAI 的對話模型。",
"The first completed exchange is sent once per conversation.": "每個對話只會傳送一次首輪完整問答。",
"Please keep this tab open. You can now use the web mode of ChatGPTBox": "請保持這個頁面開啟,現在你可以使用 ChatGPTBox 的網頁版模式",
"Go Back": "返回",
"Pin Tab": "固定頁面",
Expand Down
113 changes: 113 additions & 0 deletions src/hooks/use-conversation-title-config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { useEffect, useRef, useState } from 'react'
import Browser from 'webextension-polyfill'
import { canonicalizeApiMode } from '../config/model-key-migrations.mjs'

const STORAGE_KEYS = ['autoGenerateConversationTitle', 'conversationTitleApiMode']

export const defaultConversationTitleConfig = {
autoGenerateConversationTitle: false,
conversationTitleApiMode: null,
}

function normalizeTitleApiMode(value) {
const canonical = canonicalizeApiMode(value)
if (!canonical || typeof canonical !== 'object') return null
return { ...canonical, apiKey: '' }
}

function normalizeConversationTitleConfig(value) {
return {
autoGenerateConversationTitle: value?.autoGenerateConversationTitle === true,
conversationTitleApiMode: normalizeTitleApiMode(value?.conversationTitleApiMode),
}
}

export function isConversationTitleConfigLoadCurrent(loadRevision, currentRevision) {
return loadRevision === currentRevision
}

export async function getConversationTitleConfig() {
const stored = await Browser.storage.local.get(STORAGE_KEYS)
return normalizeConversationTitleConfig(stored)
}

export async function setConversationTitleConfig(changes) {
const requestedChanges = changes && typeof changes === 'object' ? changes : {}
const normalized = {}
if (Object.hasOwn(requestedChanges, 'autoGenerateConversationTitle')) {
normalized.autoGenerateConversationTitle =
requestedChanges.autoGenerateConversationTitle === true
}
if (Object.hasOwn(requestedChanges, 'conversationTitleApiMode')) {
normalized.conversationTitleApiMode = normalizeTitleApiMode(
requestedChanges.conversationTitleApiMode,
)
}
if (Object.keys(normalized).length > 0) await Browser.storage.local.set(normalized)
return normalized
}

export function useConversationTitleConfig() {
const [config, setConfig] = useState(defaultConversationTitleConfig)
const storageRevisionRef = useRef(0)

useEffect(() => {
let active = true

const listener = (changes, areaName) => {
if (areaName && areaName !== 'local') return
const update = {}
if (Object.hasOwn(changes, 'autoGenerateConversationTitle')) {
update.autoGenerateConversationTitle =
changes.autoGenerateConversationTitle.newValue === true
}
if (Object.hasOwn(changes, 'conversationTitleApiMode')) {
update.conversationTitleApiMode = normalizeTitleApiMode(
changes.conversationTitleApiMode.newValue,
)
}
if (Object.keys(update).length > 0) {
storageRevisionRef.current += 1
setConfig((current) => ({ ...current, ...update }))
}
}

const loadCurrentConfig = async () => {
while (active) {
const loadRevision = storageRevisionRef.current
const loadedConfig = await getConversationTitleConfig()
if (!active) return
if (isConversationTitleConfigLoadCurrent(loadRevision, storageRevisionRef.current)) {
setConfig(loadedConfig)
return
}
}
}

Browser.storage.onChanged.addListener(listener)
loadCurrentConfig().catch((error) => {
console.warn('[conversation-title] Failed to load title settings:', error)
})

return () => {
active = false
Browser.storage.onChanged.removeListener(listener)
}
}, [])

const updateConfig = async (changes) => {
storageRevisionRef.current += 1
try {
const normalized = await setConversationTitleConfig(changes)
if (Object.keys(normalized).length > 0) {
setConfig((current) => ({ ...current, ...normalized }))
}
return true
} catch (error) {
console.warn('[conversation-title] Failed to save title settings:', error)
return false
}
}

return [config, updateConfig]
}
Loading