mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-15 12:53:51 +02:00
980 lines
34 KiB
JavaScript
980 lines
34 KiB
JavaScript
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?</br></br>' +
|
|
'• Only collects crash and error information.</br>' +
|
|
'• No personal data or VRChat information is collected.</br>' +
|
|
'• Only enabled in nightly builds.</br>' +
|
|
'• 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
|
|
};
|
|
});
|