import { reactive, ref, watch } from 'vue'; import { ElMessageBox } from 'element-plus'; import { defineStore } from 'pinia'; import { toast } from 'vue-sonner'; import { useI18n } from 'vue-i18n'; import { AppDebug } from '../../service/appConfig'; import { database } from '../../service/database'; import { languageCodes } from '../../localization'; import { useGameStore } from '../game'; import { useModalStore } from '../modal'; import { useVRCXUpdaterStore } from '../vrcxUpdater'; import { useVrcxStore } from '../vrcx'; import { watchState } from '../../service/watchState'; import configRepository from '../../service/config'; import webApiService from '../../service/webapi'; export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => { const gameStore = useGameStore(); const vrcxStore = useVrcxStore(); const VRCXUpdaterStore = useVRCXUpdaterStore(); const modalStore = useModalStore(); const { t } = useI18n(); const state = reactive({ folderSelectorDialogVisible: false }); const enablePrimaryPassword = ref(false); const bioLanguage = ref('en'); const relaunchVRChatAfterCrash = ref(false); const vrcQuitFix = ref(true); const autoSweepVRChatCache = ref(false); const selfInviteOverride = ref(false); const saveInstancePrints = ref(false); const cropInstancePrints = ref(false); const saveInstanceStickers = ref(false); const avatarRemoteDatabase = ref(true); const enableAppLauncher = ref(true); const enableAppLauncherAutoClose = ref(true); const enableAppLauncherRunProcessOnce = ref(true); const screenshotHelper = ref(true); const screenshotHelperModifyFilename = ref(false); const screenshotHelperCopyToClipboard = ref(false); const youTubeApi = ref(false); const youTubeApiKey = ref(''); const translationApi = ref(false); const translationApiKey = ref(''); const translationApiType = ref('google'); // 'google' | 'openai' const translationApiEndpoint = ref( 'https://api.openai.com/v1/chat/completions' ); const translationApiModel = ref('gpt-4o-mini'); const translationApiPrompt = ref(''); const progressPie = ref(false); const progressPieFilter = ref(true); const showConfirmationOnSwitchAvatar = ref(false); const gameLogDisabled = ref(false); const sqliteTableSizes = ref({}); const ugcFolderPath = ref(''); const autoDeleteOldPrints = ref(false); const notificationOpacity = ref(100); const currentUserInventory = reactive(new Map()); const isVRChatConfigDialogVisible = ref(false); const saveInstanceEmoji = ref(false); const vrcRegistryAutoBackup = ref(true); const vrcRegistryAskRestore = ref(true); const sentryErrorReporting = ref(false); watch( () => watchState.isLoggedIn, () => { currentUserInventory.clear(); isVRChatConfigDialogVisible.value = false; }, { flush: 'sync' } ); async function initAdvancedSettings() { const [ enablePrimaryPasswordConfig, bioLanguageConfig, relaunchVRChatAfterCrashConfig, vrcQuitFixConfig, autoSweepVRChatCacheConfig, selfInviteOverrideConfig, saveInstancePrintsConfig, cropInstancePrintsConfig, saveInstanceStickersConfig, avatarRemoteDatabaseConfig, enableAppLauncherConfig, enableAppLauncherAutoCloseConfig, enableAppLauncherRunProcessOnceConfig, screenshotHelperConfig, screenshotHelperModifyFilenameConfig, screenshotHelperCopyToClipboardConfig, youTubeApiConfig, youTubeApiKeyConfig, translationApiConfig, translationApiKeyConfig, translationApiTypeConfig, translationApiEndpointConfig, translationApiModelConfig, translationApiPromptConfig, progressPieConfig, progressPieFilterConfig, showConfirmationOnSwitchAvatarConfig, gameLogDisabledConfig, ugcFolderPathConfig, autoDeleteOldPrintsConfig, notificationOpacityConfig, saveInstanceEmojiConfig, vrcRegistryAutoBackupConfig, vrcRegistryAskRestoreConfig, sentryErrorReportingConfig ] = await Promise.all([ configRepository.getBool('enablePrimaryPassword', false), configRepository.getString('VRCX_bioLanguage'), configRepository.getBool('VRCX_relaunchVRChatAfterCrash', false), configRepository.getBool('VRCX_vrcQuitFix', true), configRepository.getBool('VRCX_autoSweepVRChatCache', false), configRepository.getBool('VRCX_selfInviteOverride', false), configRepository.getBool('VRCX_saveInstancePrints', false), configRepository.getBool('VRCX_cropInstancePrints', false), configRepository.getBool('VRCX_saveInstanceStickers', false), configRepository.getBool('VRCX_avatarRemoteDatabase', true), configRepository.getBool('VRCX_enableAppLauncher', true), configRepository.getBool('VRCX_enableAppLauncherAutoClose', true), configRepository.getBool( 'VRCX_enableAppLauncherRunProcessOnce', true ), configRepository.getBool('VRCX_screenshotHelper', true), configRepository.getBool( 'VRCX_screenshotHelperModifyFilename', false ), configRepository.getBool( 'VRCX_screenshotHelperCopyToClipboard', false ), configRepository.getBool('VRCX_youtubeAPI', false), configRepository.getString('VRCX_youtubeAPIKey', ''), configRepository.getBool('VRCX_translationAPI', false), configRepository.getString('VRCX_translationAPIKey', ''), configRepository.getString('VRCX_translationAPIType', 'google'), configRepository.getString('VRCX_translationAPIEndpoint', ''), configRepository.getString('VRCX_translationAPIModel', ''), configRepository.getString('VRCX_translationAPIPrompt', ''), configRepository.getBool('VRCX_progressPie', false), configRepository.getBool('VRCX_progressPieFilter', true), configRepository.getBool( 'VRCX_showConfirmationOnSwitchAvatar', false ), configRepository.getBool('VRCX_gameLogDisabled', false), configRepository.getString('VRCX_userGeneratedContentPath', ''), configRepository.getBool('VRCX_autoDeleteOldPrints', false), configRepository.getFloat('VRCX_notificationOpacity', 100), configRepository.getBool('VRCX_saveInstanceEmoji', false), configRepository.getBool('VRCX_vrcRegistryAutoBackup', true), configRepository.getBool('VRCX_vrcRegistryAskRestore', true), configRepository.getString('VRCX_SentryEnabled', '') ]); if (!bioLanguageConfig || !languageCodes.includes(bioLanguageConfig)) { bioLanguage.value = 'en'; } else { bioLanguage.value = bioLanguageConfig; } enablePrimaryPassword.value = enablePrimaryPasswordConfig; relaunchVRChatAfterCrash.value = relaunchVRChatAfterCrashConfig; vrcQuitFix.value = vrcQuitFixConfig; autoSweepVRChatCache.value = autoSweepVRChatCacheConfig; selfInviteOverride.value = selfInviteOverrideConfig; saveInstancePrints.value = saveInstancePrintsConfig; cropInstancePrints.value = cropInstancePrintsConfig; saveInstanceStickers.value = saveInstanceStickersConfig; avatarRemoteDatabase.value = avatarRemoteDatabaseConfig; enableAppLauncher.value = enableAppLauncherConfig; enableAppLauncherAutoClose.value = enableAppLauncherAutoCloseConfig; enableAppLauncherRunProcessOnce.value = enableAppLauncherRunProcessOnceConfig; screenshotHelper.value = screenshotHelperConfig; screenshotHelperModifyFilename.value = screenshotHelperModifyFilenameConfig; screenshotHelperCopyToClipboard.value = screenshotHelperCopyToClipboardConfig; youTubeApi.value = youTubeApiConfig; youTubeApiKey.value = youTubeApiKeyConfig; translationApi.value = translationApiConfig; translationApiKey.value = translationApiKeyConfig; translationApiType.value = translationApiTypeConfig; translationApiEndpoint.value = translationApiEndpointConfig; translationApiModel.value = translationApiModelConfig; translationApiPrompt.value = translationApiPromptConfig; progressPie.value = progressPieConfig; progressPieFilter.value = progressPieFilterConfig; showConfirmationOnSwitchAvatar.value = showConfirmationOnSwitchAvatarConfig; gameLogDisabled.value = gameLogDisabledConfig; ugcFolderPath.value = ugcFolderPathConfig; autoDeleteOldPrints.value = autoDeleteOldPrintsConfig; notificationOpacity.value = notificationOpacityConfig; saveInstanceEmoji.value = saveInstanceEmojiConfig; vrcRegistryAutoBackup.value = vrcRegistryAutoBackupConfig; vrcRegistryAskRestore.value = vrcRegistryAskRestoreConfig; sentryErrorReporting.value = sentryErrorReportingConfig === 'true'; handleSetAppLauncherSettings(); setTimeout(() => { if ( VRCXUpdaterStore.branch === 'Nightly' && sentryErrorReportingConfig === '' ) { checkSentryConsent(); } }, 2000); } initAdvancedSettings(); /** * @param {boolean} value */ function setEnablePrimaryPasswordConfigRepository(value) { configRepository.setBool('enablePrimaryPassword', value); } function setRelaunchVRChatAfterCrash() { relaunchVRChatAfterCrash.value = !relaunchVRChatAfterCrash.value; configRepository.setBool( 'VRCX_relaunchVRChatAfterCrash', relaunchVRChatAfterCrash.value ); } function setVrcQuitFix() { vrcQuitFix.value = !vrcQuitFix.value; configRepository.setBool('VRCX_vrcQuitFix', vrcQuitFix.value); } function setAutoSweepVRChatCache() { autoSweepVRChatCache.value = !autoSweepVRChatCache.value; configRepository.setBool( 'VRCX_autoSweepVRChatCache', autoSweepVRChatCache.value ); } function setSelfInviteOverride() { selfInviteOverride.value = !selfInviteOverride.value; configRepository.setBool( 'VRCX_selfInviteOverride', selfInviteOverride.value ); } function setSaveInstancePrints() { saveInstancePrints.value = !saveInstancePrints.value; configRepository.setBool( 'VRCX_saveInstancePrints', saveInstancePrints.value ); } function setCropInstancePrints() { cropInstancePrints.value = !cropInstancePrints.value; configRepository.setBool( 'VRCX_cropInstancePrints', cropInstancePrints.value ); cropPrintsChanged(); } function setSaveInstanceStickers() { saveInstanceStickers.value = !saveInstanceStickers.value; configRepository.setBool( 'VRCX_saveInstanceStickers', saveInstanceStickers.value ); } /** * @param {boolean} value */ function setAvatarRemoteDatabase(value) { avatarRemoteDatabase.value = value; configRepository.setBool( 'VRCX_avatarRemoteDatabase', avatarRemoteDatabase.value ); } async function setEnableAppLauncher() { enableAppLauncher.value = !enableAppLauncher.value; await configRepository.setBool( 'VRCX_enableAppLauncher', enableAppLauncher.value ); handleSetAppLauncherSettings(); } async function setEnableAppLauncherAutoClose() { enableAppLauncherAutoClose.value = !enableAppLauncherAutoClose.value; await configRepository.setBool( 'VRCX_enableAppLauncherAutoClose', enableAppLauncherAutoClose.value ); handleSetAppLauncherSettings(); } async function setEnableAppLauncherRunProcessOnce() { enableAppLauncherRunProcessOnce.value = !enableAppLauncherRunProcessOnce.value; await configRepository.setBool( 'VRCX_enableAppLauncherRunProcessOnce', enableAppLauncherRunProcessOnce.value ); handleSetAppLauncherSettings(); } async function setScreenshotHelper() { screenshotHelper.value = !screenshotHelper.value; await configRepository.setBool( 'VRCX_screenshotHelper', screenshotHelper.value ); } async function setScreenshotHelperModifyFilename() { screenshotHelperModifyFilename.value = !screenshotHelperModifyFilename.value; await configRepository.setBool( 'VRCX_screenshotHelperModifyFilename', screenshotHelperModifyFilename.value ); } async function setScreenshotHelperCopyToClipboard() { screenshotHelperCopyToClipboard.value = !screenshotHelperCopyToClipboard.value; await configRepository.setBool( 'VRCX_screenshotHelperCopyToClipboard', screenshotHelperCopyToClipboard.value ); } async function setYouTubeApi() { youTubeApi.value = !youTubeApi.value; await configRepository.setBool('VRCX_youtubeAPI', youTubeApi.value); } async function setTranslationApi() { translationApi.value = !translationApi.value; await configRepository.setBool( 'VRCX_translationAPI', translationApi.value ); } /** * @param {string} value */ async function setYouTubeApiKey(value) { youTubeApiKey.value = value; await configRepository.setString( 'VRCX_youtubeAPIKey', youTubeApiKey.value ); } async function setTranslationApiKey(value) { translationApiKey.value = value; await configRepository.setString( 'VRCX_translationAPIKey', translationApiKey.value ); } async function setTranslationApiType(value) { translationApiType.value = value || 'google'; await configRepository.setString( 'VRCX_translationAPIType', translationApiType.value ); } async function setTranslationApiEndpoint(value) { translationApiEndpoint.value = value; await configRepository.setString( 'VRCX_translationAPIEndpoint', translationApiEndpoint.value ); } async function setTranslationApiModel(value) { translationApiModel.value = value; await configRepository.setString( 'VRCX_translationAPIModel', translationApiModel.value ); } async function setTranslationApiPrompt(value) { translationApiPrompt.value = value; await configRepository.setString( 'VRCX_translationAPIPrompt', translationApiPrompt.value ); } function setBioLanguage(language) { bioLanguage.value = language; configRepository.setString('VRCX_bioLanguage', language); } async function setProgressPie() { progressPie.value = !progressPie.value; await configRepository.setBool('VRCX_progressPie', progressPie.value); } async function setProgressPieFilter() { progressPieFilter.value = !progressPieFilter.value; await configRepository.setBool( 'VRCX_progressPieFilter', progressPieFilter.value ); } async function setShowConfirmationOnSwitchAvatar() { showConfirmationOnSwitchAvatar.value = !showConfirmationOnSwitchAvatar.value; await configRepository.setBool( 'VRCX_showConfirmationOnSwitchAvatar', showConfirmationOnSwitchAvatar.value ); } async function setGameLogDisabled() { gameLogDisabled.value = !gameLogDisabled.value; await configRepository.setBool( 'VRCX_gameLogDisabled', gameLogDisabled.value ); } async function setSaveInstanceEmoji() { saveInstanceEmoji.value = !saveInstanceEmoji.value; await configRepository.setBool( 'VRCX_saveInstanceEmoji', saveInstanceEmoji.value ); } async function setUGCFolderPath(path) { if (typeof path !== 'string') { path = ''; } ugcFolderPath.value = path; await configRepository.setString('VRCX_userGeneratedContentPath', path); } async function setAutoDeleteOldPrints() { autoDeleteOldPrints.value = !autoDeleteOldPrints.value; await configRepository.setBool( 'VRCX_autoDeleteOldPrints', autoDeleteOldPrints.value ); } async function setNotificationOpacity(value) { notificationOpacity.value = value; await configRepository.setInt('VRCX_notificationOpacity', value); } async function setVrcRegistryAutoBackup() { vrcRegistryAutoBackup.value = !vrcRegistryAutoBackup.value; await configRepository.setBool( 'VRCX_vrcRegistryAutoBackup', vrcRegistryAutoBackup.value ); } async function setVrcRegistryAskRestore() { vrcRegistryAskRestore.value = !vrcRegistryAskRestore.value; await configRepository.setBool( 'VRCX_vrcRegistryAskRestore', vrcRegistryAskRestore.value ); } async function checkSentryConsent() { modalStore .confirm({ description: 'Help improve VRCX by allowing anonymous error reporting?

' + '• Only collects crash and error information.
' + '• No personal data or VRChat information is collected.
' + '• Only enabled in nightly builds.
' + '• Can be disabled at anytime in Advanced Settings.', title: 'Anonymous Error Reporting' }) .then(async ({ ok }) => { if (!ok) return; modalStore .confirm({ description: 'Error reporting setting has been enabled. Would you like to restart VRCX now for the change to take effect?', title: 'Restart Required', confirmText: 'Restart Now', cancelText: 'Later' }) .then(async ({ ok }) => { if (!ok) return; sentryErrorReporting.value = true; configRepository.setBool('VRCX_SentryEnabled', true); VRCXUpdaterStore.restartVRCX(false); }); }); } async function setSentryErrorReporting() { if (VRCXUpdaterStore.branch !== 'Nightly') return; modalStore .confirm({ description: 'Error reporting setting has been disabled. Would you like to restart VRCX now for the change to take effect?', title: 'Restart Required', confirmText: 'Restart Now', cancelText: 'Later' }) .then(async ({ ok }) => { if (!ok) return; sentryErrorReporting.value = !sentryErrorReporting.value; await configRepository.setBool( 'VRCX_SentryEnabled', sentryErrorReporting.value ); VRCXUpdaterStore.restartVRCX(false); }); } async function getSqliteTableSizes() { const [ gps, status, bio, avatar, onlineOffline, friendLogHistory, notification, location, joinLeave, portalSpawn, videoPlay, event, external ] = await Promise.all([ database.getGpsTableSize(), database.getStatusTableSize(), database.getBioTableSize(), database.getAvatarTableSize(), database.getOnlineOfflineTableSize(), database.getFriendLogHistoryTableSize(), database.getNotificationTableSize(), database.getLocationTableSize(), database.getJoinLeaveTableSize(), database.getPortalSpawnTableSize(), database.getVideoPlayTableSize(), database.getEventTableSize(), database.getExternalTableSize() ]); sqliteTableSizes.value = { gps, status, bio, avatar, onlineOffline, friendLogHistory, notification, location, joinLeave, portalSpawn, videoPlay, event, external }; } function handleSetAppLauncherSettings() { AppApi.SetAppLauncherSettings( enableAppLauncher.value, enableAppLauncherAutoClose.value, enableAppLauncherRunProcessOnce.value ); } /** * @param {string} videoId */ async function lookupYouTubeVideo(videoId) { if (!youTubeApiKey.value) { console.warn('no Youtube API key configured'); return null; } let data = null; let apiKey = ''; if (youTubeApiKey.value) { apiKey = youTubeApiKey.value; } try { const response = await webApiService.execute({ url: `https://www.googleapis.com/youtube/v3/videos?id=${encodeURIComponent( videoId )}&part=snippet,contentDetails&key=${apiKey}`, method: 'GET', headers: { Referer: 'https://vrcx.app' } }); const json = JSON.parse(response.data); if (AppDebug.debugWebRequests) { console.log(json, response); } if (response.status === 200) { data = json; } else { throw new Error(`Error: ${response.data}`); } } catch { console.error(`YouTube video lookup failed for ${videoId}`); } return data; } async function translateText(text, targetLang, overrides) { if (!translationApi.value) { toast.warning('Translation API disabled'); return null; } const provider = overrides?.type || translationApiType.value || 'google'; if (provider === 'google') { const keyToUse = overrides?.key ?? translationApiKey.value; if (!keyToUse) { toast.warning('No Translation API key configured'); return null; } try { const response = await webApiService.execute({ url: `https://translation.googleapis.com/language/translate/v2?key=${keyToUse}`, method: 'POST', headers: { 'Content-Type': 'application/json', Referer: 'https://vrcx.app' }, body: JSON.stringify({ q: text, target: targetLang, format: 'text' }) }); if (response.status !== 200) { throw new Error( `Translation API error: ${response.status} - ${response.data}` ); } const data = JSON.parse(response.data); if (AppDebug.debugWebRequests) { console.log(data, response); } return data.data.translations[0].translatedText; } catch (err) { toast.error(`Translation failed: ${err.message}`); return null; } } const endpoint = overrides?.endpoint || translationApiEndpoint.value || 'https://api.openai.com/v1/chat/completions'; const model = overrides?.model || translationApiModel.value || 'gpt-5.1'; const prompt = overrides?.prompt || translationApiPrompt.value || `You are a translation assistant. Translate the user message into ${targetLang}. Only return the translated text.`; if (!endpoint || !model) { toast.warning('Translation endpoint/model missing'); return null; } const headers = { 'Content-Type': 'application/json', Referer: 'https://vrcx.app' }; const keyToUse = overrides?.key ?? translationApiKey.value; if (keyToUse) { headers.Authorization = `Bearer ${keyToUse}`; } try { const response = await webApiService.execute({ url: endpoint, method: 'POST', headers, body: JSON.stringify({ model, messages: [ { role: 'system', content: prompt }, { role: 'user', content: text } ] }) }); if (response.status !== 200) { throw new Error( `Translation API error: ${response.status} - ${response.data}` ); } const data = JSON.parse(response.data); if (AppDebug.debugWebRequests) { console.log(data, response); } const translated = data?.choices?.[0]?.message?.content; return typeof translated === 'string' ? translated.trim() : null; } catch (err) { toast.error(`Translation failed: ${err.message}`); return null; } } function cropPrintsChanged() { if (!cropInstancePrints.value) return; modalStore .confirm({ description: t( 'view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old' ), title: '', confirmText: t( 'view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old_confirm' ), cancelText: t( 'view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old_cancel' ) }) .then(async ({ ok }) => { if (!ok) return; const msgBox = toast.warning( 'Batch print cropping in progress...', { duration: Infinity, position: 'bottom-right' } ); try { await AppApi.CropAllPrints(ugcFolderPath.value); toast.success('Batch print cropping complete'); } catch (err) { console.error(err); toast.error(`Batch print cropping failed: ${err}`); } finally { toast.dismiss(msgBox); } }) .catch(() => {}); } function askDeleteAllScreenshotMetadata() { modalStore .confirm({ description: t( 'view.settings.advanced.advanced.delete_all_screenshot_metadata.ask' ), title: '', confirmText: t( 'view.settings.advanced.advanced.delete_all_screenshot_metadata.confirm_yes' ), cancelText: t( 'view.settings.advanced.advanced.delete_all_screenshot_metadata.confirm_no' ) }) .then(({ ok }) => { if (!ok) return; deleteAllScreenshotMetadata(); }) .catch(() => {}); } function deleteAllScreenshotMetadata() { modalStore .confirm({ description: t( 'view.settings.advanced.advanced.delete_all_screenshot_metadata.confirm' ), title: '', confirmText: t( 'view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old_confirm' ), cancelText: t( 'view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old_cancel' ) }) .then(async ({ ok }) => { if (!ok) return; const msgBox = toast.warning( 'Batch metadata removal in progress...', { duration: Infinity, position: 'bottom-right' } ); try { await AppApi.DeleteAllScreenshotMetadata(); toast.success('Batch metadata removal complete'); } catch (err) { console.error(err); toast.error(`Batch metadata removal failed: ${err}`); } finally { toast.dismiss(msgBox); } }) .catch(() => {}); } function resetUGCFolder() { setUGCFolderPath(''); } async function openUGCFolder() { if (LINUX && ugcFolderPath.value == null) { resetUGCFolder(); } await AppApi.OpenUGCPhotosFolder(ugcFolderPath.value); } async function folderSelectorDialog(oldPath) { if (state.folderSelectorDialogVisible) return; if (!oldPath) { oldPath = ''; } state.folderSelectorDialogVisible = true; let newFolder = ''; if (WINDOWS) { newFolder = await AppApi.OpenFolderSelectorDialog(oldPath); } else { newFolder = await window.electron.openDirectoryDialog(); } state.folderSelectorDialogVisible = false; return newFolder; } async function openUGCFolderSelector() { const path = await folderSelectorDialog(ugcFolderPath.value); await setUGCFolderPath(path); } async function showVRChatConfig() { isVRChatConfigDialogVisible.value = true; if (!gameStore.VRChatUsedCacheSize) { gameStore.getVRChatCacheSize(); } } function promptAutoClearVRCXCacheFrequency() { ElMessageBox.prompt( t('prompt.auto_clear_cache.description'), t('prompt.auto_clear_cache.header'), { distinguishCancelAndClose: true, confirmButtonText: t('prompt.auto_clear_cache.ok'), cancelButtonText: t('prompt.auto_clear_cache.cancel'), inputValue: ( vrcxStore.clearVRCXCacheFrequency / 3600 / 2 ).toString(), inputPattern: /\d+$/, inputErrorMessage: t('prompt.auto_clear_cache.input_error') } ) .then(async ({ value }) => { if (value && !isNaN(parseInt(value, 10))) { vrcxStore.clearVRCXCacheFrequency = Math.trunc( parseInt(value, 10) * 3600 * 2 ); await configRepository.setString( 'VRCX_clearVRCXCacheFrequency', vrcxStore.clearVRCXCacheFrequency.toString() ); } }) .catch(() => {}); } return { state, bioLanguage, enablePrimaryPassword, relaunchVRChatAfterCrash, vrcQuitFix, autoSweepVRChatCache, selfInviteOverride, saveInstancePrints, cropInstancePrints, saveInstanceStickers, avatarRemoteDatabase, enableAppLauncher, enableAppLauncherAutoClose, enableAppLauncherRunProcessOnce, screenshotHelper, screenshotHelperModifyFilename, screenshotHelperCopyToClipboard, youTubeApi, translationApi, youTubeApiKey, translationApiKey, translationApiType, translationApiEndpoint, translationApiModel, translationApiPrompt, progressPie, progressPieFilter, showConfirmationOnSwitchAvatar, gameLogDisabled, sqliteTableSizes, ugcFolderPath, currentUserInventory, autoDeleteOldPrints, notificationOpacity, isVRChatConfigDialogVisible, saveInstanceEmoji, vrcRegistryAutoBackup, vrcRegistryAskRestore, sentryErrorReporting, setEnablePrimaryPasswordConfigRepository, setBioLanguage, setRelaunchVRChatAfterCrash, setVrcQuitFix, setAutoSweepVRChatCache, setSelfInviteOverride, setSaveInstancePrints, setCropInstancePrints, setSaveInstanceStickers, setAvatarRemoteDatabase, setEnableAppLauncher, setEnableAppLauncherAutoClose, setEnableAppLauncherRunProcessOnce, setScreenshotHelper, setScreenshotHelperModifyFilename, setScreenshotHelperCopyToClipboard, setYouTubeApi, setTranslationApi, setYouTubeApiKey, setTranslationApiKey, setTranslationApiType, setTranslationApiEndpoint, setTranslationApiModel, setTranslationApiPrompt, setProgressPie, setProgressPieFilter, setShowConfirmationOnSwitchAvatar, setGameLogDisabled, setUGCFolderPath, cropPrintsChanged, setAutoDeleteOldPrints, setNotificationOpacity, getSqliteTableSizes, handleSetAppLauncherSettings, lookupYouTubeVideo, translateText, resetUGCFolder, openUGCFolder, openUGCFolderSelector, folderSelectorDialog, showVRChatConfig, promptAutoClearVRCXCacheFrequency, setSaveInstanceEmoji, setVrcRegistryAutoBackup, setVrcRegistryAskRestore, setSentryErrorReporting, checkSentryConsent, askDeleteAllScreenshotMetadata }; });