import { useTranslation } from 'react-i18next'
import { useLayoutEffect, useState } from 'react'
import FileSaver from 'file-saver'
import {
openUrl,
modelNameToDesc,
isApiModeSelected,
getApiModesFromConfig,
apiModeToModelName,
} from '../../utils/index.mjs'
import {
isUsingOpenAiApiModel,
isUsingAzureOpenAiApiModel,
isUsingChatGLMApiModel,
isUsingClaudeApiModel,
isUsingCustomModel,
isUsingOllamaApiModel,
isUsingGithubThirdPartyApiModel,
isUsingMultiModeModel,
ModelMode,
ThemeMode,
TriggerMode,
isUsingMoonshotApiModel,
Models,
} from '../../config/index.mjs'
import Browser from 'webextension-polyfill'
import { languageList } from '../../config/language.mjs'
import PropTypes from 'prop-types'
import { config as menuConfig } from '../../content-script/menu-tools'
import { PencilIcon } from '@primer/octicons-react'
GeneralPart.propTypes = {
config: PropTypes.object.isRequired,
updateConfig: PropTypes.func.isRequired,
setTabIndex: PropTypes.func.isRequired,
}
function formatDate(date) {
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
return `${year}-${month}-${day}`
}
async function checkBilling(apiKey, apiUrl) {
const now = new Date()
let startDate = new Date(now - 90 * 24 * 60 * 60 * 1000)
const endDate = new Date(now.getTime() + 24 * 60 * 60 * 1000)
const subDate = new Date(now)
subDate.setDate(1)
const urlSubscription = `${apiUrl}/v1/dashboard/billing/subscription`
let urlUsage = `${apiUrl}/v1/dashboard/billing/usage?start_date=${formatDate(
startDate,
)}&end_date=${formatDate(endDate)}`
const headers = {
Authorization: 'Bearer ' + apiKey,
'Content-Type': 'application/json',
}
try {
let response = await fetch(urlSubscription, { headers })
if (!response.ok) {
console.log('Your account has been suspended. Please log in to OpenAI to check.')
return [null, null, null]
}
const subscriptionData = await response.json()
const totalAmount = subscriptionData.hard_limit_usd
if (totalAmount > 20) {
startDate = subDate
}
urlUsage = `${apiUrl}/v1/dashboard/billing/usage?start_date=${formatDate(
startDate,
)}&end_date=${formatDate(endDate)}`
response = await fetch(urlUsage, { headers })
const usageData = await response.json()
const totalUsage = usageData.total_usage / 100
const remaining = totalAmount - totalUsage
return [totalAmount, totalUsage, remaining]
} catch (error) {
console.error(error)
return [null, null, null]
}
}
function isUsingSpecialCustomModel(configOrSession) {
return isUsingCustomModel(configOrSession) && !configOrSession.apiMode
}
export function GeneralPart({ config, updateConfig, setTabIndex }) {
const { t, i18n } = useTranslation()
const [balance, setBalance] = useState(null)
const [apiModes, setApiModes] = useState([])
useLayoutEffect(() => {
setApiModes(getApiModesFromConfig(config, true))
}, [
config.activeApiModes,
config.customApiModes,
config.azureDeploymentName,
config.ollamaModelName,
])
const getBalance = async () => {
const response = await fetch(`${config.customOpenAiApiUrl}/dashboard/billing/credit_grants`, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${config.apiKey}`,
},
})
if (response.ok) setBalance((await response.json()).total_available.toFixed(2))
else {
const billing = await checkBilling(config.apiKey, config.customOpenAiApiUrl)
if (billing && billing.length > 2 && billing[2]) setBalance(`${billing[2].toFixed(2)}`)
else openUrl('https://platform.openai.com/account/usage')
}
}
return (
<>
{
const checked = e.target.checked
updateConfig({ insertAtTop: checked })
}}
/>
{t('Insert ChatGPT at the top of search results')}
{
const checked = e.target.checked
updateConfig({ alwaysFloatingSidebar: checked })
}}
/>
{t('Always display floating window, disable sidebar for all site adapters')}
{
const checked = e.target.checked
updateConfig({ allowEscToCloseAll: checked })
}}
/>
{t('Allow ESC to close all floating windows')}
{
const checked = e.target.checked
updateConfig({ lockWhenAnswer: checked })
}}
/>
{t('Lock scrollbar while answering')}
{
const checked = e.target.checked
updateConfig({ autoRegenAfterSwitchModel: checked })
}}
/>
{t('Regenerate the answer after switching model')}
{
const checked = e.target.checked
updateConfig({ selectionToolsNextToInputBox: checked })
}}
/>
{t('Display selection tools next to input box to avoid blocking')}
{
const checked = e.target.checked
updateConfig({ alwaysPinWindow: checked })
}}
/>
{t('Always pin the floating window')}
{
const checked = e.target.checked
updateConfig({ focusAfterAnswer: checked })
}}
/>
{t('Focus to input box after answering')}
>
)
}