mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-02 13:06:08 +02:00
refactor: app.js (#1291)
* refactor: frontend * Fix avatar gallery sort * Update .NET dependencies * Update npm dependencies electron v37.1.0 * bulkRefreshFriends * fix dark theme * Remove crowdin * Fix config.json dialog not updating * VRCX log file fixes & add Cef log * Remove SharedVariable, fix startup * Revert init theme change * Logging date not working? Fix WinformThemer designer error * Add Cef request hander, no more escaping main page * clean * fix * fix * clean * uh * Apply thememode at startup, fixes random user colours * Split database into files * Instance info remove empty lines * Open external VRC links with VRCX * Electron fixes * fix userdialog style * ohhhh * fix store * fix store * fix: load all group members after kicking a user * fix: world dialog favorite button style * fix: Clear VRCX Cache Timer input value * clean * Fix VR overlay * Fix VR overlay 2 * Fix Discord discord rich presence for RPC worlds * Clean up age verified user tags * Fix playerList being occupied after program reload * no `this` * Fix login stuck loading * writable: false * Hide dialogs on logout * add flush sync option * rm LOGIN event * rm LOGOUT event * remove duplicate event listeners * remove duplicate event listeners * clean * remove duplicate event listeners * clean * fix theme style * fix t * clearable * clean * fix ipcEvent * Small changes * Popcorn Palace support * Remove checkActiveFriends * Clean up * Fix dragEnterCef * Block API requests when not logged in * Clear state on login & logout * Fix worldDialog instances not updating * use <script setup> * Fix avatar change event, CheckGameRunning at startup * Fix image dragging * fix * Remove PWI * fix updateLoop * add webpack-dev-server to dev environment * rm unnecessary chunks * use <script setup> * webpack-dev-server changes * use <script setup> * use <script setup> * Fix UGC text size * Split login event * t * use <script setup> * fix * Update .gitignore and enable checkJs in jsconfig * fix i18n t * use <script setup> * use <script setup> * clean * global types * fix * use checkJs for debugging * Add watchState for login watchers * fix .vue template * type fixes * rm Vue.filter * Cef v138.0.170, VC++ 2022 * Settings fixes * Remove 'USER:CURRENT' * clean up 2FA callbacks * remove userApply * rm i18n import * notification handling to use notification store methods * refactor favorite handling to use favorite store methods and clean up event emissions * refactor moderation handling to use dedicated functions for player moderation events * refactor friend handling to use dedicated functions for friend events * Fix program startup, move lang init * Fix friend state * Fix status change error * Fix user notes diff * fix * rm group event * rm auth event * rm avatar event * clean * clean * getUser * getFriends * getFavoriteWorlds, getFavoriteAvatars * AvatarGalleryUpload btn style & package.json update * Fix friend requests * Apply user * Apply world * Fix note diff * Fix VR overlay * Fixes * Update build scripts * Apply avatar * Apply instance * Apply group * update hidden VRC+ badge * Fix sameInstance "private" * fix 502/504 API errors * fix 502/504 API errors * clean * Fix friend in same instance on orange showing twice in friends list * Add back in broken friend state repair methods * add types --------- Co-authored-by: Natsumi <cmcooper123@hotmail.com>
This commit is contained in:
@@ -0,0 +1,652 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import { $app } from '../../app';
|
||||
import { t } from '../../plugin';
|
||||
import configRepository from '../../service/config';
|
||||
import { database } from '../../service/database';
|
||||
import webApiService from '../../service/webapi';
|
||||
import { watchState } from '../../service/watchState';
|
||||
import { useGameStore } from '../game';
|
||||
import { useVrcxStore } from '../vrcx';
|
||||
import { AppGlobal } from '../../service/appConfig';
|
||||
|
||||
export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
|
||||
const gameStore = useGameStore();
|
||||
const vrcxStore = useVrcxStore();
|
||||
|
||||
const state = reactive({
|
||||
enablePrimaryPassword: false,
|
||||
relaunchVRChatAfterCrash: false,
|
||||
vrcQuitFix: true,
|
||||
autoSweepVRChatCache: false,
|
||||
saveInstancePrints: false,
|
||||
cropInstancePrints: false,
|
||||
saveInstanceStickers: false,
|
||||
avatarRemoteDatabase: true,
|
||||
enableAppLauncher: true,
|
||||
enableAppLauncherAutoClose: true,
|
||||
screenshotHelper: true,
|
||||
screenshotHelperModifyFilename: false,
|
||||
screenshotHelperCopyToClipboard: false,
|
||||
youTubeApi: false,
|
||||
youTubeApiKey: '',
|
||||
progressPie: false,
|
||||
progressPieFilter: true,
|
||||
showConfirmationOnSwitchAvatar: false,
|
||||
gameLogDisabled: false,
|
||||
sqliteTableSizes: {},
|
||||
ugcFolderPath: '',
|
||||
currentUserInventory: new Map(),
|
||||
autoDeleteOldPrints: false,
|
||||
notificationOpacity: 100,
|
||||
folderSelectorDialogVisible: false,
|
||||
isVRChatConfigDialogVisible: false,
|
||||
saveInstanceEmoji: false,
|
||||
vrcRegistryAutoBackup: true
|
||||
});
|
||||
|
||||
async function initAdvancedSettings() {
|
||||
const [
|
||||
enablePrimaryPassword,
|
||||
relaunchVRChatAfterCrash,
|
||||
vrcQuitFix,
|
||||
autoSweepVRChatCache,
|
||||
saveInstancePrints,
|
||||
cropInstancePrints,
|
||||
saveInstanceStickers,
|
||||
avatarRemoteDatabase,
|
||||
enableAppLauncher,
|
||||
enableAppLauncherAutoClose,
|
||||
screenshotHelper,
|
||||
screenshotHelperModifyFilename,
|
||||
screenshotHelperCopyToClipboard,
|
||||
youTubeApi,
|
||||
youTubeApiKey,
|
||||
progressPie,
|
||||
progressPieFilter,
|
||||
showConfirmationOnSwitchAvatar,
|
||||
gameLogDisabled,
|
||||
ugcFolderPath,
|
||||
autoDeleteOldPrints,
|
||||
notificationOpacity,
|
||||
saveInstanceEmoji,
|
||||
vrcRegistryAutoBackup
|
||||
] = await Promise.all([
|
||||
configRepository.getBool('enablePrimaryPassword', false),
|
||||
configRepository.getBool('VRCX_relaunchVRChatAfterCrash', false),
|
||||
configRepository.getBool('VRCX_vrcQuitFix', true),
|
||||
configRepository.getBool('VRCX_autoSweepVRChatCache', 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_screenshotHelper', true),
|
||||
configRepository.getBool(
|
||||
'VRCX_screenshotHelperModifyFilename',
|
||||
false
|
||||
),
|
||||
configRepository.getBool(
|
||||
'VRCX_screenshotHelperCopyToClipboard',
|
||||
false
|
||||
),
|
||||
configRepository.getBool('VRCX_youtubeAPI', false),
|
||||
configRepository.getString('VRCX_youtubeAPIKey', ''),
|
||||
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)
|
||||
]);
|
||||
|
||||
state.enablePrimaryPassword = enablePrimaryPassword;
|
||||
state.relaunchVRChatAfterCrash = relaunchVRChatAfterCrash;
|
||||
state.vrcQuitFix = vrcQuitFix;
|
||||
state.autoSweepVRChatCache = autoSweepVRChatCache;
|
||||
state.saveInstancePrints = saveInstancePrints;
|
||||
state.cropInstancePrints = cropInstancePrints;
|
||||
state.saveInstanceStickers = saveInstanceStickers;
|
||||
state.avatarRemoteDatabase = avatarRemoteDatabase;
|
||||
state.enableAppLauncher = enableAppLauncher;
|
||||
state.enableAppLauncherAutoClose = enableAppLauncherAutoClose;
|
||||
state.screenshotHelper = screenshotHelper;
|
||||
state.screenshotHelperModifyFilename = screenshotHelperModifyFilename;
|
||||
state.screenshotHelperCopyToClipboard = screenshotHelperCopyToClipboard;
|
||||
state.youTubeApi = youTubeApi;
|
||||
state.youTubeApiKey = youTubeApiKey;
|
||||
state.progressPie = progressPie;
|
||||
state.progressPieFilter = progressPieFilter;
|
||||
state.showConfirmationOnSwitchAvatar = showConfirmationOnSwitchAvatar;
|
||||
state.gameLogDisabled = gameLogDisabled === 'true';
|
||||
state.ugcFolderPath = ugcFolderPath;
|
||||
state.autoDeleteOldPrints = autoDeleteOldPrints;
|
||||
state.notificationOpacity = notificationOpacity;
|
||||
state.saveInstanceEmoji = saveInstanceEmoji;
|
||||
state.vrcRegistryAutoBackup = vrcRegistryAutoBackup;
|
||||
|
||||
handleSetAppLauncherSettings();
|
||||
}
|
||||
|
||||
initAdvancedSettings();
|
||||
|
||||
watch(
|
||||
() => watchState.isLoggedIn,
|
||||
() => {
|
||||
state.currentUserInventory.clear();
|
||||
state.isVRChatConfigDialogVisible = false;
|
||||
},
|
||||
{ flush: 'sync' }
|
||||
);
|
||||
|
||||
const enablePrimaryPassword = computed({
|
||||
get: () => state.enablePrimaryPassword,
|
||||
set: (value) => (state.enablePrimaryPassword = value)
|
||||
});
|
||||
const relaunchVRChatAfterCrash = computed(
|
||||
() => state.relaunchVRChatAfterCrash
|
||||
);
|
||||
const vrcQuitFix = computed(() => state.vrcQuitFix);
|
||||
const autoSweepVRChatCache = computed(() => state.autoSweepVRChatCache);
|
||||
const saveInstancePrints = computed(() => state.saveInstancePrints);
|
||||
const cropInstancePrints = computed(() => state.cropInstancePrints);
|
||||
const saveInstanceStickers = computed(() => state.saveInstanceStickers);
|
||||
const avatarRemoteDatabase = computed(() => state.avatarRemoteDatabase);
|
||||
const enableAppLauncher = computed(() => state.enableAppLauncher);
|
||||
const enableAppLauncherAutoClose = computed(
|
||||
() => state.enableAppLauncherAutoClose
|
||||
);
|
||||
const screenshotHelper = computed(() => state.screenshotHelper);
|
||||
``;
|
||||
const screenshotHelperModifyFilename = computed(
|
||||
() => state.screenshotHelperModifyFilename
|
||||
);
|
||||
const screenshotHelperCopyToClipboard = computed(
|
||||
() => state.screenshotHelperCopyToClipboard
|
||||
);
|
||||
const youTubeApi = computed(() => state.youTubeApi);
|
||||
const youTubeApiKey = computed({
|
||||
get: () => state.youTubeApiKey,
|
||||
set: (value) => (state.youTubeApiKey = value)
|
||||
});
|
||||
const progressPie = computed(() => state.progressPie);
|
||||
const progressPieFilter = computed(() => state.progressPieFilter);
|
||||
const showConfirmationOnSwitchAvatar = computed(
|
||||
() => state.showConfirmationOnSwitchAvatar
|
||||
);
|
||||
const gameLogDisabled = computed(() => state.gameLogDisabled);
|
||||
const sqliteTableSizes = computed(() => state.sqliteTableSizes);
|
||||
const ugcFolderPath = computed(() => state.ugcFolderPath);
|
||||
const autoDeleteOldPrints = computed(() => state.autoDeleteOldPrints);
|
||||
const notificationOpacity = computed(() => state.notificationOpacity);
|
||||
|
||||
const currentUserInventory = computed({
|
||||
get: () => state.currentUserInventory,
|
||||
set: (value) => {
|
||||
state.currentUserInventory = value;
|
||||
}
|
||||
});
|
||||
const isVRChatConfigDialogVisible = computed({
|
||||
get: () => state.isVRChatConfigDialogVisible,
|
||||
set: (value) => (state.isVRChatConfigDialogVisible = value)
|
||||
});
|
||||
|
||||
const saveInstanceEmoji = computed({
|
||||
get: () => state.saveInstanceEmoji,
|
||||
set: (value) => (state.saveInstanceEmoji = value)
|
||||
});
|
||||
const vrcRegistryAutoBackup = computed(() => state.vrcRegistryAutoBackup);
|
||||
|
||||
/**
|
||||
* @param {boolean} value
|
||||
*/
|
||||
function setEnablePrimaryPasswordConfigRepository(value) {
|
||||
configRepository.setBool('enablePrimaryPassword', value);
|
||||
}
|
||||
function setRelaunchVRChatAfterCrash() {
|
||||
state.relaunchVRChatAfterCrash = !state.relaunchVRChatAfterCrash;
|
||||
configRepository.setBool(
|
||||
'VRCX_relaunchVRChatAfterCrash',
|
||||
state.relaunchVRChatAfterCrash
|
||||
);
|
||||
}
|
||||
function setVrcQuitFix() {
|
||||
state.vrcQuitFix = !state.vrcQuitFix;
|
||||
configRepository.setBool('VRCX_vrcQuitFix', state.vrcQuitFix);
|
||||
}
|
||||
function setAutoSweepVRChatCache() {
|
||||
state.autoSweepVRChatCache = !state.autoSweepVRChatCache;
|
||||
configRepository.setBool(
|
||||
'VRCX_autoSweepVRChatCache',
|
||||
state.autoSweepVRChatCache
|
||||
);
|
||||
}
|
||||
function setSaveInstancePrints() {
|
||||
state.saveInstancePrints = !state.saveInstancePrints;
|
||||
configRepository.setBool(
|
||||
'VRCX_saveInstancePrints',
|
||||
state.saveInstancePrints
|
||||
);
|
||||
}
|
||||
function setCropInstancePrints() {
|
||||
state.cropInstancePrints = !state.cropInstancePrints;
|
||||
configRepository.setBool(
|
||||
'VRCX_cropInstancePrints',
|
||||
state.cropInstancePrints
|
||||
);
|
||||
}
|
||||
function setSaveInstanceStickers() {
|
||||
state.saveInstanceStickers = !state.saveInstanceStickers;
|
||||
configRepository.setBool(
|
||||
'VRCX_saveInstanceStickers',
|
||||
state.saveInstanceStickers
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {boolean} value
|
||||
*/
|
||||
function setAvatarRemoteDatabase(value) {
|
||||
state.avatarRemoteDatabase = value;
|
||||
configRepository.setBool(
|
||||
'VRCX_avatarRemoteDatabase',
|
||||
state.avatarRemoteDatabase
|
||||
);
|
||||
}
|
||||
async function setEnableAppLauncher() {
|
||||
state.enableAppLauncher = !state.enableAppLauncher;
|
||||
await configRepository.setBool(
|
||||
'VRCX_enableAppLauncher',
|
||||
state.enableAppLauncher
|
||||
);
|
||||
handleSetAppLauncherSettings();
|
||||
}
|
||||
async function setEnableAppLauncherAutoClose() {
|
||||
state.enableAppLauncherAutoClose = !state.enableAppLauncherAutoClose;
|
||||
await configRepository.setBool(
|
||||
'VRCX_enableAppLauncherAutoClose',
|
||||
state.enableAppLauncherAutoClose
|
||||
);
|
||||
handleSetAppLauncherSettings();
|
||||
}
|
||||
async function setScreenshotHelper() {
|
||||
state.screenshotHelper = !state.screenshotHelper;
|
||||
await configRepository.setBool(
|
||||
'VRCX_screenshotHelper',
|
||||
state.screenshotHelper
|
||||
);
|
||||
}
|
||||
async function setScreenshotHelperModifyFilename() {
|
||||
state.screenshotHelperModifyFilename =
|
||||
!state.screenshotHelperModifyFilename;
|
||||
await configRepository.setBool(
|
||||
'VRCX_screenshotHelperModifyFilename',
|
||||
state.screenshotHelperModifyFilename
|
||||
);
|
||||
}
|
||||
async function setScreenshotHelperCopyToClipboard() {
|
||||
state.screenshotHelperCopyToClipboard =
|
||||
!state.screenshotHelperCopyToClipboard;
|
||||
await configRepository.setBool(
|
||||
'VRCX_screenshotHelperCopyToClipboard',
|
||||
state.screenshotHelperCopyToClipboard
|
||||
);
|
||||
}
|
||||
async function setYouTubeApi() {
|
||||
state.youTubeApi = !state.youTubeApi;
|
||||
await configRepository.setBool('VRCX_youtubeAPI', state.youTubeApi);
|
||||
}
|
||||
/**
|
||||
* @param {string} value
|
||||
*/
|
||||
async function setYouTubeApiKey(value) {
|
||||
state.youTubeApiKey = value;
|
||||
await configRepository.setString(
|
||||
'VRCX_youtubeAPIKey',
|
||||
state.youTubeApiKey
|
||||
);
|
||||
}
|
||||
async function setProgressPie() {
|
||||
state.progressPie = !state.progressPie;
|
||||
await configRepository.setBool('VRCX_progressPie', state.progressPie);
|
||||
}
|
||||
async function setProgressPieFilter() {
|
||||
state.progressPieFilter = !state.progressPieFilter;
|
||||
await configRepository.setBool(
|
||||
'VRCX_progressPieFilter',
|
||||
state.progressPieFilter
|
||||
);
|
||||
}
|
||||
async function setShowConfirmationOnSwitchAvatar() {
|
||||
state.showConfirmationOnSwitchAvatar =
|
||||
!state.showConfirmationOnSwitchAvatar;
|
||||
await configRepository.setBool(
|
||||
'VRCX_showConfirmationOnSwitchAvatar',
|
||||
state.showConfirmationOnSwitchAvatar
|
||||
);
|
||||
}
|
||||
async function setGameLogDisabled() {
|
||||
state.gameLogDisabled = !state.gameLogDisabled;
|
||||
await configRepository.setBool(
|
||||
'VRCX_gameLogDisabled',
|
||||
state.gameLogDisabled
|
||||
);
|
||||
}
|
||||
|
||||
async function setSaveInstanceEmoji() {
|
||||
state.saveInstanceEmoji = !state.saveInstanceEmoji;
|
||||
await configRepository.setBool(
|
||||
'VRCX_saveInstanceEmoji',
|
||||
state.saveInstanceEmoji
|
||||
);
|
||||
}
|
||||
|
||||
async function setUGCFolderPath(path) {
|
||||
if (typeof path !== 'string') {
|
||||
path = '';
|
||||
}
|
||||
state.ugcFolderPath = path;
|
||||
await configRepository.setString('VRCX_userGeneratedContentPath', path);
|
||||
}
|
||||
|
||||
async function setAutoDeleteOldPrints() {
|
||||
state.autoDeleteOldPrints = !state.autoDeleteOldPrints;
|
||||
await configRepository.setBool(
|
||||
'VRCX_autoDeleteOldPrints',
|
||||
state.autoDeleteOldPrints
|
||||
);
|
||||
}
|
||||
|
||||
async function setNotificationOpacity(value) {
|
||||
state.notificationOpacity = value;
|
||||
await configRepository.setInt('VRCX_notificationOpacity', value);
|
||||
}
|
||||
|
||||
async function setVrcRegistryAutoBackup() {
|
||||
state.vrcRegistryAutoBackup = !state.vrcRegistryAutoBackup;
|
||||
await configRepository.setBool(
|
||||
'VRCX_vrcRegistryAutoBackup',
|
||||
state.vrcRegistryAutoBackup
|
||||
);
|
||||
}
|
||||
|
||||
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()
|
||||
]);
|
||||
|
||||
state.sqliteTableSizes = {
|
||||
gps,
|
||||
status,
|
||||
bio,
|
||||
avatar,
|
||||
onlineOffline,
|
||||
friendLogHistory,
|
||||
notification,
|
||||
location,
|
||||
joinLeave,
|
||||
portalSpawn,
|
||||
videoPlay,
|
||||
event,
|
||||
external
|
||||
};
|
||||
}
|
||||
|
||||
function handleSetAppLauncherSettings() {
|
||||
AppApi.SetAppLauncherSettings(
|
||||
state.enableAppLauncher,
|
||||
state.enableAppLauncherAutoClose
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} videoId
|
||||
*/
|
||||
async function lookupYouTubeVideo(videoId) {
|
||||
if (!state.youTubeApi) {
|
||||
console.warn('no Youtube API key configured');
|
||||
return null;
|
||||
}
|
||||
let data = null;
|
||||
let apiKey = '';
|
||||
if (state.youTubeApiKey) {
|
||||
apiKey = state.youTubeApiKey;
|
||||
}
|
||||
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 (AppGlobal.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;
|
||||
}
|
||||
|
||||
function cropPrintsChanged() {
|
||||
if (!state.cropInstancePrints) return;
|
||||
$app.$confirm(
|
||||
t(
|
||||
'view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old'
|
||||
),
|
||||
{
|
||||
confirmButtonText: t(
|
||||
'view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old_confirm'
|
||||
),
|
||||
cancelButtonText: t(
|
||||
'view.settings.advanced.advanced.save_instance_prints_to_file.crop_convert_old_cancel'
|
||||
),
|
||||
type: 'info',
|
||||
showInput: false,
|
||||
callback: async (action) => {
|
||||
if (action === 'confirm') {
|
||||
const msgBox = $app.$message({
|
||||
message: 'Batch print cropping in progress...',
|
||||
type: 'warning',
|
||||
duration: 0
|
||||
});
|
||||
try {
|
||||
await AppApi.CropAllPrints(state.ugcFolderPath);
|
||||
$app.$message({
|
||||
message: 'Batch print cropping complete',
|
||||
type: 'success'
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
$app.$message({
|
||||
message: `Batch print cropping failed: ${err}`,
|
||||
type: 'error'
|
||||
});
|
||||
} finally {
|
||||
msgBox.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function resetUGCFolder() {
|
||||
setUGCFolderPath('');
|
||||
}
|
||||
|
||||
async function openUGCFolder() {
|
||||
if (LINUX && state.ugcFolderPath == null) {
|
||||
resetUGCFolder();
|
||||
}
|
||||
await AppApi.OpenUGCPhotosFolder(state.ugcFolderPath);
|
||||
}
|
||||
|
||||
async function folderSelectorDialog(oldPath) {
|
||||
if (state.folderSelectorDialogVisible) return;
|
||||
if (!oldPath) {
|
||||
oldPath = '';
|
||||
}
|
||||
|
||||
state.folderSelectorDialogVisible = true;
|
||||
let newFolder = '';
|
||||
if (LINUX) {
|
||||
newFolder = await window.electron.openDirectoryDialog();
|
||||
} else {
|
||||
newFolder = await AppApi.OpenFolderSelectorDialog(oldPath);
|
||||
}
|
||||
|
||||
state.folderSelectorDialogVisible = false;
|
||||
return newFolder;
|
||||
}
|
||||
|
||||
async function openUGCFolderSelector() {
|
||||
const path = await folderSelectorDialog(state.ugcFolderPath);
|
||||
await setUGCFolderPath(path);
|
||||
}
|
||||
|
||||
async function showVRChatConfig() {
|
||||
state.isVRChatConfigDialogVisible = true;
|
||||
if (!gameStore.VRChatUsedCacheSize) {
|
||||
gameStore.getVRChatCacheSize();
|
||||
}
|
||||
}
|
||||
|
||||
function promptAutoClearVRCXCacheFrequency() {
|
||||
$app.$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,
|
||||
inputPattern: /\d+$/,
|
||||
inputErrorMessage: t('prompt.auto_clear_cache.input_error'),
|
||||
callback: async (action, instance) => {
|
||||
if (
|
||||
action === 'confirm' &&
|
||||
instance.inputValue &&
|
||||
!isNaN(instance.inputValue)
|
||||
) {
|
||||
vrcxStore.clearVRCXCacheFrequency = Math.trunc(
|
||||
Number(instance.inputValue) * 3600 * 2
|
||||
);
|
||||
await configRepository.setString(
|
||||
'VRCX_clearVRCXCacheFrequency',
|
||||
vrcxStore.clearVRCXCacheFrequency
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
|
||||
enablePrimaryPassword,
|
||||
relaunchVRChatAfterCrash,
|
||||
vrcQuitFix,
|
||||
autoSweepVRChatCache,
|
||||
saveInstancePrints,
|
||||
cropInstancePrints,
|
||||
saveInstanceStickers,
|
||||
avatarRemoteDatabase,
|
||||
enableAppLauncher,
|
||||
enableAppLauncherAutoClose,
|
||||
screenshotHelper,
|
||||
screenshotHelperModifyFilename,
|
||||
screenshotHelperCopyToClipboard,
|
||||
youTubeApi,
|
||||
youTubeApiKey,
|
||||
progressPie,
|
||||
progressPieFilter,
|
||||
showConfirmationOnSwitchAvatar,
|
||||
gameLogDisabled,
|
||||
sqliteTableSizes,
|
||||
ugcFolderPath,
|
||||
currentUserInventory,
|
||||
autoDeleteOldPrints,
|
||||
notificationOpacity,
|
||||
isVRChatConfigDialogVisible,
|
||||
saveInstanceEmoji,
|
||||
vrcRegistryAutoBackup,
|
||||
|
||||
setEnablePrimaryPasswordConfigRepository,
|
||||
setRelaunchVRChatAfterCrash,
|
||||
setVrcQuitFix,
|
||||
setAutoSweepVRChatCache,
|
||||
setSaveInstancePrints,
|
||||
setCropInstancePrints,
|
||||
setSaveInstanceStickers,
|
||||
setAvatarRemoteDatabase,
|
||||
setEnableAppLauncher,
|
||||
setEnableAppLauncherAutoClose,
|
||||
setScreenshotHelper,
|
||||
setScreenshotHelperModifyFilename,
|
||||
setScreenshotHelperCopyToClipboard,
|
||||
setYouTubeApi,
|
||||
setYouTubeApiKey,
|
||||
setProgressPie,
|
||||
setProgressPieFilter,
|
||||
setShowConfirmationOnSwitchAvatar,
|
||||
setGameLogDisabled,
|
||||
setUGCFolderPath,
|
||||
cropPrintsChanged,
|
||||
setAutoDeleteOldPrints,
|
||||
setNotificationOpacity,
|
||||
getSqliteTableSizes,
|
||||
handleSetAppLauncherSettings,
|
||||
lookupYouTubeVideo,
|
||||
resetUGCFolder,
|
||||
openUGCFolder,
|
||||
openUGCFolderSelector,
|
||||
folderSelectorDialog,
|
||||
showVRChatConfig,
|
||||
promptAutoClearVRCXCacheFrequency,
|
||||
setSaveInstanceEmoji,
|
||||
setVrcRegistryAutoBackup
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,780 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import { $app } from '../../app';
|
||||
import { i18n, t } from '../../plugin';
|
||||
import configRepository from '../../service/config';
|
||||
import { database } from '../../service/database';
|
||||
import { watchState } from '../../service/watchState';
|
||||
import {
|
||||
changeAppDarkStyle,
|
||||
changeAppThemeStyle,
|
||||
changeCJKFontsOrder,
|
||||
getNameColour,
|
||||
HueToHex,
|
||||
systemIsDarkMode,
|
||||
updateTrustColorClasses
|
||||
} from '../../shared/utils';
|
||||
import { useFeedStore } from '../feed';
|
||||
import { useFriendStore } from '../friend';
|
||||
import { useGameLogStore } from '../gameLog';
|
||||
import { useModerationStore } from '../moderation';
|
||||
import { useNotificationStore } from '../notification';
|
||||
import { useUserStore } from '../user';
|
||||
import { useVrStore } from '../vr';
|
||||
import { useVrcxStore } from '../vrcx';
|
||||
|
||||
export const useAppearanceSettingsStore = defineStore(
|
||||
'AppearanceSettings',
|
||||
|
||||
() => {
|
||||
const friendStore = useFriendStore();
|
||||
const vrStore = useVrStore();
|
||||
const notificationStore = useNotificationStore();
|
||||
const feedStore = useFeedStore();
|
||||
const moderationStore = useModerationStore();
|
||||
const gameLogStore = useGameLogStore();
|
||||
const vrcxStore = useVrcxStore();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const state = reactive({
|
||||
appLanguage: 'en',
|
||||
themeMode: '',
|
||||
isDarkMode: false,
|
||||
displayVRCPlusIconsAsAvatar: false,
|
||||
hideNicknames: false,
|
||||
hideTooltips: false,
|
||||
isAgeGatedInstancesVisible: false,
|
||||
sortFavorites: true,
|
||||
instanceUsersSortAlphabetical: false,
|
||||
tablePageSize: 15,
|
||||
dtHour12: false,
|
||||
dtIsoFormat: false,
|
||||
sidebarSortMethod1: 'Sort Private to Bottom',
|
||||
sidebarSortMethod2: 'Sort by Time in Instance',
|
||||
sidebarSortMethod3: 'Sort by Last Active',
|
||||
sidebarSortMethods: [
|
||||
'Sort Private to Bottom',
|
||||
'Sort by Time in Instance',
|
||||
'Sort by Last Active'
|
||||
],
|
||||
asideWidth: 300,
|
||||
isSidebarGroupByInstance: true,
|
||||
isHideFriendsInSameInstance: false,
|
||||
isSidebarDivideByFriendGroup: false,
|
||||
hideUserNotes: false,
|
||||
hideUserMemos: false,
|
||||
hideUnfriends: false,
|
||||
randomUserColours: false,
|
||||
trustColor: {
|
||||
untrusted: '#CCCCCC',
|
||||
basic: '#1778FF',
|
||||
known: '#2BCF5C',
|
||||
trusted: '#FF7B42',
|
||||
veteran: '#B18FFF',
|
||||
vip: '#FF2626',
|
||||
troll: '#782F2F'
|
||||
},
|
||||
currentCulture: ''
|
||||
});
|
||||
|
||||
async function initAppearanceSettings() {
|
||||
const [
|
||||
appLanguage,
|
||||
themeMode,
|
||||
displayVRCPlusIconsAsAvatar,
|
||||
hideNicknames,
|
||||
hideTooltips,
|
||||
isAgeGatedInstancesVisible,
|
||||
sortFavorites,
|
||||
instanceUsersSortAlphabetical,
|
||||
tablePageSize,
|
||||
dtHour12,
|
||||
dtIsoFormat,
|
||||
sidebarSortMethods,
|
||||
asideWidth,
|
||||
isSidebarGroupByInstance,
|
||||
isHideFriendsInSameInstance,
|
||||
isSidebarDivideByFriendGroup,
|
||||
hideUserNotes,
|
||||
hideUserMemos,
|
||||
hideUnfriends,
|
||||
randomUserColours,
|
||||
trustColor
|
||||
] = await Promise.all([
|
||||
configRepository.getString('VRCX_appLanguage'),
|
||||
configRepository.getString('VRCX_ThemeMode', 'system'),
|
||||
configRepository.getBool('displayVRCPlusIconsAsAvatar', true),
|
||||
configRepository.getBool('VRCX_hideNicknames', false),
|
||||
configRepository.getBool('VRCX_hideTooltips', false),
|
||||
configRepository.getBool(
|
||||
'VRCX_isAgeGatedInstancesVisible',
|
||||
true
|
||||
),
|
||||
configRepository.getBool('VRCX_sortFavorites', true),
|
||||
configRepository.getBool(
|
||||
'VRCX_instanceUsersSortAlphabetical',
|
||||
false
|
||||
),
|
||||
configRepository.getInt('VRCX_tablePageSize', 15),
|
||||
configRepository.getBool('VRCX_dtHour12', false),
|
||||
configRepository.getBool('VRCX_dtIsoFormat', false),
|
||||
configRepository.getString(
|
||||
'VRCX_sidebarSortMethods',
|
||||
JSON.stringify([
|
||||
'Sort Private to Bottom',
|
||||
'Sort by Time in Instance',
|
||||
'Sort by Last Active'
|
||||
])
|
||||
),
|
||||
configRepository.getInt('VRCX_sidePanelWidth', 300),
|
||||
configRepository.getBool('VRCX_sidebarGroupByInstance', true),
|
||||
configRepository.getBool(
|
||||
'VRCX_hideFriendsInSameInstance',
|
||||
false
|
||||
),
|
||||
configRepository.getBool(
|
||||
'VRCX_sidebarDivideByFriendGroup',
|
||||
true
|
||||
),
|
||||
configRepository.getBool('VRCX_hideUserNotes', false),
|
||||
configRepository.getBool('VRCX_hideUserMemos', false),
|
||||
configRepository.getBool('VRCX_hideUnfriends', false),
|
||||
configRepository.getBool('VRCX_randomUserColours', false),
|
||||
configRepository.getString(
|
||||
'VRCX_trustColor',
|
||||
JSON.stringify({
|
||||
untrusted: '#CCCCCC',
|
||||
basic: '#1778FF',
|
||||
known: '#2BCF5C',
|
||||
trusted: '#FF7B42',
|
||||
veteran: '#B18FFF',
|
||||
vip: '#FF2626',
|
||||
troll: '#782F2F'
|
||||
})
|
||||
)
|
||||
]);
|
||||
|
||||
if (!appLanguage) {
|
||||
const result = await AppApi.CurrentLanguage();
|
||||
|
||||
const lang = result.split('-')[0];
|
||||
i18n.availableLocales.forEach((ref) => {
|
||||
const refLang = ref.split('_')[0];
|
||||
if (refLang === lang) {
|
||||
changeAppLanguage(ref);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
state.appLanguage = appLanguage;
|
||||
}
|
||||
changeCJKFontsOrder(state.appLanguage);
|
||||
|
||||
state.themeMode = themeMode;
|
||||
applyThemeMode(themeMode);
|
||||
|
||||
state.displayVRCPlusIconsAsAvatar = displayVRCPlusIconsAsAvatar;
|
||||
state.hideNicknames = hideNicknames;
|
||||
state.hideTooltips = hideTooltips;
|
||||
state.isAgeGatedInstancesVisible = isAgeGatedInstancesVisible;
|
||||
state.sortFavorites = sortFavorites;
|
||||
state.instanceUsersSortAlphabetical = instanceUsersSortAlphabetical;
|
||||
|
||||
setTablePageSize(tablePageSize);
|
||||
handleSetTablePageSize(state.tablePageSize);
|
||||
|
||||
state.dtHour12 = dtHour12;
|
||||
state.dtIsoFormat = dtIsoFormat;
|
||||
|
||||
state.currentCulture = await AppApi.CurrentCulture();
|
||||
|
||||
state.sidebarSortMethods = JSON.parse(sidebarSortMethods);
|
||||
if (state.sidebarSortMethods?.length === 3) {
|
||||
state.sidebarSortMethod1 = state.sidebarSortMethods[0];
|
||||
state.sidebarSortMethod2 = state.sidebarSortMethods[1];
|
||||
state.sidebarSortMethod3 = state.sidebarSortMethods[2];
|
||||
}
|
||||
|
||||
state.trustColor = JSON.parse(trustColor);
|
||||
state.asideWidth = asideWidth;
|
||||
state.isSidebarGroupByInstance = isSidebarGroupByInstance;
|
||||
state.isHideFriendsInSameInstance = isHideFriendsInSameInstance;
|
||||
state.isSidebarDivideByFriendGroup = isSidebarDivideByFriendGroup;
|
||||
state.hideUserNotes = hideUserNotes;
|
||||
state.hideUserMemos = hideUserMemos;
|
||||
state.hideUnfriends = hideUnfriends;
|
||||
state.randomUserColours = randomUserColours;
|
||||
|
||||
// Migrate old settings
|
||||
// Assume all exist if one does
|
||||
await mergeOldSortMethodsSettings();
|
||||
|
||||
updateTrustColorClasses(state.trustColor);
|
||||
|
||||
vrStore.updateVRConfigVars();
|
||||
}
|
||||
|
||||
initAppearanceSettings();
|
||||
|
||||
const appLanguage = computed(() => state.appLanguage);
|
||||
const themeMode = computed(() => state.themeMode);
|
||||
const isDarkMode = computed(() => state.isDarkMode);
|
||||
const displayVRCPlusIconsAsAvatar = computed(
|
||||
() => state.displayVRCPlusIconsAsAvatar
|
||||
);
|
||||
const hideNicknames = computed(() => state.hideNicknames);
|
||||
const hideTooltips = computed(() => state.hideTooltips);
|
||||
const isAgeGatedInstancesVisible = computed(
|
||||
() => state.isAgeGatedInstancesVisible
|
||||
);
|
||||
const sortFavorites = computed(() => state.sortFavorites);
|
||||
const instanceUsersSortAlphabetical = computed(
|
||||
() => state.instanceUsersSortAlphabetical
|
||||
);
|
||||
const tablePageSize = computed(() => state.tablePageSize);
|
||||
const dtHour12 = computed(() => state.dtHour12);
|
||||
const dtIsoFormat = computed(() => state.dtIsoFormat);
|
||||
const sidebarSortMethod1 = computed(() => state.sidebarSortMethod1);
|
||||
const sidebarSortMethod2 = computed(() => state.sidebarSortMethod2);
|
||||
const sidebarSortMethod3 = computed(() => state.sidebarSortMethod3);
|
||||
const sidebarSortMethods = computed(() => state.sidebarSortMethods);
|
||||
const asideWidth = computed(() => state.asideWidth);
|
||||
const isSidebarGroupByInstance = computed(
|
||||
() => state.isSidebarGroupByInstance
|
||||
);
|
||||
const isHideFriendsInSameInstance = computed(
|
||||
() => state.isHideFriendsInSameInstance
|
||||
);
|
||||
const isSidebarDivideByFriendGroup = computed(
|
||||
() => state.isSidebarDivideByFriendGroup
|
||||
);
|
||||
const hideUserNotes = computed(() => state.hideUserNotes);
|
||||
const hideUserMemos = computed(() => state.hideUserMemos);
|
||||
const hideUnfriends = computed(() => state.hideUnfriends);
|
||||
const randomUserColours = computed(() => state.randomUserColours);
|
||||
const trustColor = computed(() => state.trustColor);
|
||||
const currentCulture = computed(() => state.currentCulture);
|
||||
|
||||
watch(
|
||||
() => watchState.isFriendsLoaded,
|
||||
(isFriendsLoaded) => {
|
||||
if (isFriendsLoaded) {
|
||||
tryInitUserColours();
|
||||
}
|
||||
},
|
||||
{ flush: 'sync' }
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} language
|
||||
*/
|
||||
function changeAppLanguage(language) {
|
||||
setAppLanguage(language);
|
||||
vrStore.updateVRConfigVars();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} language
|
||||
*/
|
||||
function setAppLanguage(language) {
|
||||
console.log('Language changed:', language);
|
||||
state.appLanguage = language;
|
||||
configRepository.setString('VRCX_appLanguage', language);
|
||||
changeCJKFontsOrder(state.appLanguage);
|
||||
i18n.locale = state.appLanguage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} newThemeMode
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function saveThemeMode(newThemeMode) {
|
||||
setThemeMode(newThemeMode);
|
||||
await changeThemeMode();
|
||||
}
|
||||
|
||||
async function changeThemeMode() {
|
||||
await changeAppThemeStyle(state.themeMode);
|
||||
vrStore.updateVRConfigVars();
|
||||
await updateTrustColor();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} field
|
||||
* @param {string} color
|
||||
* @param {boolean} setRandomColor
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function updateTrustColor(field, color, setRandomColor = false) {
|
||||
if (setRandomColor) {
|
||||
setRandomUserColours();
|
||||
}
|
||||
if (typeof userStore.currentUser?.id === 'undefined') {
|
||||
return;
|
||||
}
|
||||
if (field && color) {
|
||||
setTrustColor({
|
||||
...state.trustColor,
|
||||
[field]: color
|
||||
});
|
||||
}
|
||||
if (state.randomUserColours) {
|
||||
const colour = await getNameColour(userStore.currentUser.id);
|
||||
userStore.currentUser.$userColour = colour;
|
||||
userColourInit();
|
||||
} else {
|
||||
applyUserTrustLevel(userStore.currentUser);
|
||||
userStore.cachedUsers.forEach((ref) => {
|
||||
applyUserTrustLevel(ref);
|
||||
});
|
||||
}
|
||||
updateTrustColorClasses(state.trustColor);
|
||||
}
|
||||
|
||||
async function userColourInit() {
|
||||
let dictObject = await AppApi.GetColourBulk(
|
||||
Array.from(userStore.cachedUsers.keys())
|
||||
);
|
||||
if (LINUX) {
|
||||
dictObject = Object.fromEntries(dictObject);
|
||||
}
|
||||
for (const [userId, hue] of Object.entries(dictObject)) {
|
||||
const ref = userStore.cachedUsers.get(userId);
|
||||
if (typeof ref !== 'undefined') {
|
||||
ref.$userColour = HueToHex(hue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} ref
|
||||
*/
|
||||
function applyUserTrustLevel(ref) {
|
||||
ref.$isModerator =
|
||||
ref.developerType && ref.developerType !== 'none';
|
||||
ref.$isTroll = false;
|
||||
ref.$isProbableTroll = false;
|
||||
let trustColor = '';
|
||||
const { tags } = ref;
|
||||
if (tags.includes('admin_moderator')) {
|
||||
ref.$isModerator = true;
|
||||
}
|
||||
if (tags.includes('system_troll')) {
|
||||
ref.$isTroll = true;
|
||||
}
|
||||
if (tags.includes('system_probable_troll') && !ref.$isTroll) {
|
||||
ref.$isProbableTroll = true;
|
||||
}
|
||||
if (tags.includes('system_trust_veteran')) {
|
||||
ref.$trustLevel = 'Trusted User';
|
||||
ref.$trustClass = 'x-tag-veteran';
|
||||
trustColor = 'veteran';
|
||||
ref.$trustSortNum = 5;
|
||||
} else if (tags.includes('system_trust_trusted')) {
|
||||
ref.$trustLevel = 'Known User';
|
||||
ref.$trustClass = 'x-tag-trusted';
|
||||
trustColor = 'trusted';
|
||||
ref.$trustSortNum = 4;
|
||||
} else if (tags.includes('system_trust_known')) {
|
||||
ref.$trustLevel = 'User';
|
||||
ref.$trustClass = 'x-tag-known';
|
||||
trustColor = 'known';
|
||||
ref.$trustSortNum = 3;
|
||||
} else if (tags.includes('system_trust_basic')) {
|
||||
ref.$trustLevel = 'New User';
|
||||
ref.$trustClass = 'x-tag-basic';
|
||||
trustColor = 'basic';
|
||||
ref.$trustSortNum = 2;
|
||||
} else {
|
||||
ref.$trustLevel = 'Visitor';
|
||||
ref.$trustClass = 'x-tag-untrusted';
|
||||
trustColor = 'untrusted';
|
||||
ref.$trustSortNum = 1;
|
||||
}
|
||||
if (ref.$isTroll || ref.$isProbableTroll) {
|
||||
trustColor = 'troll';
|
||||
ref.$trustSortNum += 0.1;
|
||||
}
|
||||
if (ref.$isModerator) {
|
||||
trustColor = 'vip';
|
||||
ref.$trustSortNum += 0.3;
|
||||
}
|
||||
if (state.randomUserColours && watchState.isFriendsLoaded) {
|
||||
if (!ref.$userColour) {
|
||||
getNameColour(ref.id).then((colour) => {
|
||||
ref.$userColour = colour;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
ref.$userColour = state.trustColor[trustColor];
|
||||
}
|
||||
}
|
||||
|
||||
window
|
||||
.matchMedia('(prefers-color-scheme: dark)')
|
||||
.addEventListener('change', async () => {
|
||||
if (state.themeMode === 'system') {
|
||||
await changeThemeMode();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} mode
|
||||
*/
|
||||
function setThemeMode(mode) {
|
||||
state.themeMode = mode;
|
||||
configRepository.setString('VRCX_ThemeMode', mode);
|
||||
applyThemeMode();
|
||||
}
|
||||
function applyThemeMode() {
|
||||
if (state.themeMode === 'light') {
|
||||
setIsDarkMode(false);
|
||||
} else if (state.themeMode === 'system') {
|
||||
setIsDarkMode(systemIsDarkMode());
|
||||
} else {
|
||||
setIsDarkMode(true);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {boolean} isDark
|
||||
*/
|
||||
function setIsDarkMode(isDark) {
|
||||
state.isDarkMode = isDark;
|
||||
changeAppDarkStyle(isDark);
|
||||
}
|
||||
function setDisplayVRCPlusIconsAsAvatar() {
|
||||
state.displayVRCPlusIconsAsAvatar =
|
||||
!state.displayVRCPlusIconsAsAvatar;
|
||||
configRepository.setBool(
|
||||
'displayVRCPlusIconsAsAvatar',
|
||||
state.displayVRCPlusIconsAsAvatar
|
||||
);
|
||||
}
|
||||
function setHideNicknames() {
|
||||
state.hideNicknames = !state.hideNicknames;
|
||||
configRepository.setBool('VRCX_hideNicknames', state.hideNicknames);
|
||||
}
|
||||
function setHideTooltips() {
|
||||
state.hideTooltips = !state.hideTooltips;
|
||||
configRepository.setBool('VRCX_hideTooltips', state.hideTooltips);
|
||||
}
|
||||
function setIsAgeGatedInstancesVisible() {
|
||||
state.isAgeGatedInstancesVisible =
|
||||
!state.isAgeGatedInstancesVisible;
|
||||
configRepository.setBool(
|
||||
'VRCX_isAgeGatedInstancesVisible',
|
||||
state.isAgeGatedInstancesVisible
|
||||
);
|
||||
}
|
||||
function setSortFavorites() {
|
||||
state.sortFavorites = !state.sortFavorites;
|
||||
configRepository.setBool('VRCX_sortFavorites', state.sortFavorites);
|
||||
}
|
||||
function setInstanceUsersSortAlphabetical() {
|
||||
state.instanceUsersSortAlphabetical =
|
||||
!state.instanceUsersSortAlphabetical;
|
||||
configRepository.setBool(
|
||||
'VRCX_instanceUsersSortAlphabetical',
|
||||
state.instanceUsersSortAlphabetical
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {number} size
|
||||
*/
|
||||
function setTablePageSize(size) {
|
||||
state.tablePageSize = size;
|
||||
configRepository.setInt('VRCX_tablePageSize', size);
|
||||
}
|
||||
function setDtHour12() {
|
||||
state.dtHour12 = !state.dtHour12;
|
||||
configRepository.setBool('VRCX_dtHour12', state.dtHour12);
|
||||
}
|
||||
function setDtIsoFormat() {
|
||||
state.dtIsoFormat = !state.dtIsoFormat;
|
||||
configRepository.setBool('VRCX_dtIsoFormat', state.dtIsoFormat);
|
||||
}
|
||||
/**
|
||||
* @param {string} method
|
||||
*/
|
||||
function setSidebarSortMethod1(method) {
|
||||
state.sidebarSortMethod1 = method;
|
||||
handleSaveSidebarSortOrder();
|
||||
}
|
||||
/**
|
||||
* @param {string} method
|
||||
*/
|
||||
function setSidebarSortMethod2(method) {
|
||||
state.sidebarSortMethod2 = method;
|
||||
handleSaveSidebarSortOrder();
|
||||
}
|
||||
/**
|
||||
* @param {string} method
|
||||
*/
|
||||
function setSidebarSortMethod3(method) {
|
||||
state.sidebarSortMethod3 = method;
|
||||
handleSaveSidebarSortOrder();
|
||||
}
|
||||
/**
|
||||
* @param {Array<string>} methods
|
||||
*/
|
||||
function setSidebarSortMethods(methods) {
|
||||
state.sidebarSortMethods = methods;
|
||||
configRepository.setString(
|
||||
'VRCX_sidebarSortMethods',
|
||||
JSON.stringify(methods)
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {number} width
|
||||
*/
|
||||
function setAsideWidth(width) {
|
||||
requestAnimationFrame(() => {
|
||||
state.asideWidth = width;
|
||||
configRepository.setInt('VRCX_sidePanelWidth', width);
|
||||
});
|
||||
}
|
||||
function setIsSidebarGroupByInstance() {
|
||||
state.isSidebarGroupByInstance = !state.isSidebarGroupByInstance;
|
||||
configRepository.setBool(
|
||||
'VRCX_sidebarGroupByInstance',
|
||||
state.isSidebarGroupByInstance
|
||||
);
|
||||
}
|
||||
function setIsHideFriendsInSameInstance() {
|
||||
state.isHideFriendsInSameInstance =
|
||||
!state.isHideFriendsInSameInstance;
|
||||
configRepository.setBool(
|
||||
'VRCX_hideFriendsInSameInstance',
|
||||
state.isHideFriendsInSameInstance
|
||||
);
|
||||
}
|
||||
function setIsSidebarDivideByFriendGroup() {
|
||||
state.isSidebarDivideByFriendGroup =
|
||||
!state.isSidebarDivideByFriendGroup;
|
||||
configRepository.setBool(
|
||||
'VRCX_sidebarDivideByFriendGroup',
|
||||
state.isSidebarDivideByFriendGroup
|
||||
);
|
||||
}
|
||||
function setHideUserNotes() {
|
||||
state.hideUserNotes = !state.hideUserNotes;
|
||||
configRepository.setBool('VRCX_hideUserNotes', state.hideUserNotes);
|
||||
}
|
||||
function setHideUserMemos() {
|
||||
state.hideUserMemos = !state.hideUserMemos;
|
||||
configRepository.setBool('VRCX_hideUserMemos', state.hideUserMemos);
|
||||
}
|
||||
function setHideUnfriends() {
|
||||
state.hideUnfriends = !state.hideUnfriends;
|
||||
configRepository.setBool('VRCX_hideUnfriends', state.hideUnfriends);
|
||||
}
|
||||
function setRandomUserColours() {
|
||||
state.randomUserColours = !state.randomUserColours;
|
||||
configRepository.setBool(
|
||||
'VRCX_randomUserColours',
|
||||
state.randomUserColours
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {object} color
|
||||
*/
|
||||
function setTrustColor(color) {
|
||||
state.trustColor = color;
|
||||
configRepository.setString(
|
||||
'VRCX_trustColor',
|
||||
JSON.stringify(color)
|
||||
);
|
||||
}
|
||||
|
||||
function handleSaveSidebarSortOrder() {
|
||||
if (state.sidebarSortMethod1 === state.sidebarSortMethod2) {
|
||||
state.sidebarSortMethod2 = '';
|
||||
}
|
||||
if (state.sidebarSortMethod1 === state.sidebarSortMethod3) {
|
||||
state.sidebarSortMethod3 = '';
|
||||
}
|
||||
if (state.sidebarSortMethod2 === state.sidebarSortMethod3) {
|
||||
state.sidebarSortMethod3 = '';
|
||||
}
|
||||
if (!state.sidebarSortMethod1) {
|
||||
state.sidebarSortMethod2 = '';
|
||||
}
|
||||
if (!state.sidebarSortMethod2) {
|
||||
state.sidebarSortMethod3 = '';
|
||||
}
|
||||
const sidebarSortMethods = [
|
||||
state.sidebarSortMethod1,
|
||||
state.sidebarSortMethod2,
|
||||
state.sidebarSortMethod3
|
||||
];
|
||||
setSidebarSortMethods(sidebarSortMethods);
|
||||
}
|
||||
|
||||
async function mergeOldSortMethodsSettings() {
|
||||
const orderFriendsGroupPrivate = await configRepository.getBool(
|
||||
'orderFriendGroupPrivate'
|
||||
);
|
||||
if (orderFriendsGroupPrivate !== null) {
|
||||
await configRepository.remove('orderFriendGroupPrivate');
|
||||
|
||||
const orderFriendsGroupStatus = await configRepository.getBool(
|
||||
'orderFriendsGroupStatus'
|
||||
);
|
||||
await configRepository.remove('orderFriendsGroupStatus');
|
||||
|
||||
const orderFriendsGroupGPS = await configRepository.getBool(
|
||||
'orderFriendGroupGPS'
|
||||
);
|
||||
await configRepository.remove('orderFriendGroupGPS');
|
||||
|
||||
const orderOnlineFor =
|
||||
await configRepository.getBool('orderFriendGroup0');
|
||||
await configRepository.remove('orderFriendGroup0');
|
||||
await configRepository.remove('orderFriendGroup1');
|
||||
await configRepository.remove('orderFriendGroup2');
|
||||
await configRepository.remove('orderFriendGroup3');
|
||||
|
||||
const sortOrder = [];
|
||||
if (orderFriendsGroupPrivate) {
|
||||
sortOrder.push('Sort Private to Bottom');
|
||||
}
|
||||
if (orderFriendsGroupStatus) {
|
||||
sortOrder.push('Sort by Status');
|
||||
}
|
||||
if (orderOnlineFor && orderFriendsGroupGPS) {
|
||||
sortOrder.push('Sort by Time in Instance');
|
||||
}
|
||||
if (!orderOnlineFor) {
|
||||
sortOrder.push('Sort Alphabetically');
|
||||
}
|
||||
|
||||
if (sortOrder.length > 0) {
|
||||
while (sortOrder.length < 3) {
|
||||
sortOrder.push('');
|
||||
}
|
||||
state.sidebarSortMethods = sortOrder;
|
||||
state.sidebarSortMethod1 = sortOrder[0];
|
||||
state.sidebarSortMethod2 = sortOrder[1];
|
||||
state.sidebarSortMethod3 = sortOrder[2];
|
||||
}
|
||||
setSidebarSortMethods(sortOrder);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSetTablePageSize(pageSize) {
|
||||
feedStore.feedTable.pageSize = pageSize;
|
||||
gameLogStore.gameLogTable.pageSize = pageSize;
|
||||
friendStore.friendLogTable.pageSize = pageSize;
|
||||
moderationStore.playerModerationTable.pageSize = pageSize;
|
||||
notificationStore.notificationTable.pageSize = pageSize;
|
||||
setTablePageSize(pageSize);
|
||||
}
|
||||
|
||||
function promptMaxTableSizeDialog() {
|
||||
$app.$prompt(
|
||||
t('prompt.change_table_size.description'),
|
||||
t('prompt.change_table_size.header'),
|
||||
{
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: t('prompt.change_table_size.save'),
|
||||
cancelButtonText: t('prompt.change_table_size.cancel'),
|
||||
inputValue: vrcxStore.maxTableSize,
|
||||
inputPattern: /\d+$/,
|
||||
inputErrorMessage: t(
|
||||
'prompt.change_table_size.input_error'
|
||||
),
|
||||
callback: async (action, instance) => {
|
||||
if (action === 'confirm' && instance.inputValue) {
|
||||
if (instance.inputValue > 10000) {
|
||||
instance.inputValue = 10000;
|
||||
}
|
||||
vrcxStore.maxTableSize = instance.inputValue;
|
||||
await configRepository.setString(
|
||||
'VRCX_maxTableSize',
|
||||
vrcxStore.maxTableSize
|
||||
);
|
||||
database.setMaxTableSize(vrcxStore.maxTableSize);
|
||||
feedStore.feedTableLookup();
|
||||
gameLogStore.gameLogTableLookup();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function tryInitUserColours() {
|
||||
if (!state.randomUserColours) {
|
||||
return;
|
||||
}
|
||||
const colour = await getNameColour(userStore.currentUser.id);
|
||||
userStore.currentUser.$userColour = colour;
|
||||
await userColourInit();
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
|
||||
appLanguage,
|
||||
themeMode,
|
||||
isDarkMode,
|
||||
displayVRCPlusIconsAsAvatar,
|
||||
hideNicknames,
|
||||
hideTooltips,
|
||||
isAgeGatedInstancesVisible,
|
||||
sortFavorites,
|
||||
instanceUsersSortAlphabetical,
|
||||
tablePageSize,
|
||||
dtHour12,
|
||||
dtIsoFormat,
|
||||
sidebarSortMethod1,
|
||||
sidebarSortMethod2,
|
||||
sidebarSortMethod3,
|
||||
sidebarSortMethods,
|
||||
asideWidth,
|
||||
isSidebarGroupByInstance,
|
||||
isHideFriendsInSameInstance,
|
||||
isSidebarDivideByFriendGroup,
|
||||
hideUserNotes,
|
||||
hideUserMemos,
|
||||
hideUnfriends,
|
||||
randomUserColours,
|
||||
trustColor,
|
||||
currentCulture,
|
||||
|
||||
setAppLanguage,
|
||||
setDisplayVRCPlusIconsAsAvatar,
|
||||
setHideNicknames,
|
||||
setHideTooltips,
|
||||
setIsAgeGatedInstancesVisible,
|
||||
setSortFavorites,
|
||||
setInstanceUsersSortAlphabetical,
|
||||
setTablePageSize,
|
||||
setDtHour12,
|
||||
setDtIsoFormat,
|
||||
setSidebarSortMethod1,
|
||||
setSidebarSortMethod2,
|
||||
setSidebarSortMethod3,
|
||||
setSidebarSortMethods,
|
||||
setAsideWidth,
|
||||
setIsSidebarGroupByInstance,
|
||||
setIsHideFriendsInSameInstance,
|
||||
setIsSidebarDivideByFriendGroup,
|
||||
setHideUserNotes,
|
||||
setHideUserMemos,
|
||||
setHideUnfriends,
|
||||
setRandomUserColours,
|
||||
setTrustColor,
|
||||
saveThemeMode,
|
||||
tryInitUserColours,
|
||||
updateTrustColor,
|
||||
changeThemeMode,
|
||||
userColourInit,
|
||||
applyUserTrustLevel,
|
||||
changeAppLanguage,
|
||||
handleSetTablePageSize,
|
||||
promptMaxTableSizeDialog
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,358 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { computed, reactive } from 'vue';
|
||||
import { userRequest, worldRequest } from '../../api';
|
||||
import configRepository from '../../service/config';
|
||||
import {
|
||||
getGroupName,
|
||||
getLaunchURL,
|
||||
isRealInstance,
|
||||
isRpcWorld,
|
||||
parseLocation
|
||||
} from '../../shared/utils';
|
||||
import { useGameStore } from '../game';
|
||||
import { useGameLogStore } from '../gameLog';
|
||||
import { useLocationStore } from '../location';
|
||||
import { useUpdateLoopStore } from '../updateLoop';
|
||||
import { useUserStore } from '../user';
|
||||
import { useWorldStore } from '../world';
|
||||
import { useAdvancedSettingsStore } from './advanced';
|
||||
import { ActivityType } from '../../shared/constants/discord';
|
||||
|
||||
export const useDiscordPresenceSettingsStore = defineStore(
|
||||
'DiscordPresenceSettings',
|
||||
() => {
|
||||
const locationStore = useLocationStore();
|
||||
const gameStore = useGameStore();
|
||||
const advancedSettingsStore = useAdvancedSettingsStore();
|
||||
const worldStore = useWorldStore();
|
||||
const gameLogStore = useGameLogStore();
|
||||
const userStore = useUserStore();
|
||||
const updateLoopStore = useUpdateLoopStore();
|
||||
|
||||
const state = reactive({
|
||||
discordActive: false,
|
||||
discordInstance: true,
|
||||
discordHideInvite: true,
|
||||
discordJoinButton: false,
|
||||
discordHideImage: false,
|
||||
isDiscordActive: false
|
||||
});
|
||||
|
||||
async function initDiscordPresenceSettings() {
|
||||
const [
|
||||
discordActive,
|
||||
discordInstance,
|
||||
discordHideInvite,
|
||||
discordJoinButton,
|
||||
discordHideImage
|
||||
] = await Promise.all([
|
||||
configRepository.getBool('discordActive', false),
|
||||
configRepository.getBool('discordInstance', true),
|
||||
configRepository.getBool('discordHideInvite', true),
|
||||
configRepository.getBool('discordJoinButton', false),
|
||||
configRepository.getBool('discordHideImage', false)
|
||||
]);
|
||||
|
||||
state.discordActive = discordActive;
|
||||
state.discordInstance = discordInstance;
|
||||
state.discordHideInvite = discordHideInvite;
|
||||
state.discordJoinButton = discordJoinButton;
|
||||
state.discordHideImage = discordHideImage;
|
||||
}
|
||||
|
||||
const discordActive = computed(() => state.discordActive);
|
||||
const discordInstance = computed(() => state.discordInstance);
|
||||
const discordHideInvite = computed(() => state.discordHideInvite);
|
||||
const discordJoinButton = computed(() => state.discordJoinButton);
|
||||
const discordHideImage = computed(() => state.discordHideImage);
|
||||
|
||||
function setDiscordActive() {
|
||||
state.discordActive = !state.discordActive;
|
||||
configRepository.setBool('discordActive', state.discordActive);
|
||||
}
|
||||
function setDiscordInstance() {
|
||||
state.discordInstance = !state.discordInstance;
|
||||
configRepository.setBool('discordInstance', state.discordInstance);
|
||||
}
|
||||
function setDiscordHideInvite() {
|
||||
state.discordHideInvite = !state.discordHideInvite;
|
||||
configRepository.setBool(
|
||||
'discordHideInvite',
|
||||
state.discordHideInvite
|
||||
);
|
||||
}
|
||||
function setDiscordJoinButton() {
|
||||
state.discordJoinButton = !state.discordJoinButton;
|
||||
configRepository.setBool(
|
||||
'discordJoinButton',
|
||||
state.discordJoinButton
|
||||
);
|
||||
}
|
||||
function setDiscordHideImage() {
|
||||
state.discordHideImage = !state.discordHideImage;
|
||||
configRepository.setBool(
|
||||
'discordHideImage',
|
||||
state.discordHideImage
|
||||
);
|
||||
}
|
||||
|
||||
initDiscordPresenceSettings();
|
||||
|
||||
function updateDiscord() {
|
||||
let platform;
|
||||
let currentLocation = locationStore.lastLocation.location;
|
||||
let timeStamp = locationStore.lastLocation.date;
|
||||
if (locationStore.lastLocation.location === 'traveling') {
|
||||
currentLocation = locationStore.lastLocationDestination;
|
||||
timeStamp = locationStore.lastLocationDestinationTime;
|
||||
}
|
||||
if (
|
||||
!state.discordActive ||
|
||||
(!gameStore.isGameRunning &&
|
||||
!advancedSettingsStore.gameLogDisabled) ||
|
||||
(!currentLocation && !locationStore.lastLocation$.tag)
|
||||
) {
|
||||
setIsDiscordActive(false);
|
||||
return;
|
||||
}
|
||||
setIsDiscordActive(true);
|
||||
let L = locationStore.lastLocation$;
|
||||
if (currentLocation !== locationStore.lastLocation$.tag) {
|
||||
Discord.SetTimestamps(timeStamp, 0);
|
||||
L = parseLocation(currentLocation);
|
||||
L.worldName = '';
|
||||
L.thumbnailImageUrl = '';
|
||||
L.worldCapacity = 0;
|
||||
L.joinUrl = '';
|
||||
L.accessName = '';
|
||||
if (L.worldId) {
|
||||
const ref = worldStore.cachedWorlds.get(L.worldId);
|
||||
if (ref) {
|
||||
L.worldName = ref.name;
|
||||
L.thumbnailImageUrl = ref.thumbnailImageUrl;
|
||||
L.worldCapacity = ref.capacity;
|
||||
} else {
|
||||
worldRequest
|
||||
.getWorld({
|
||||
worldId: L.worldId
|
||||
})
|
||||
.then((args) => {
|
||||
L.worldName = args.ref.name;
|
||||
L.thumbnailImageUrl =
|
||||
args.ref.thumbnailImageUrl;
|
||||
L.worldCapacity = args.ref.capacity;
|
||||
return args;
|
||||
});
|
||||
}
|
||||
if (gameStore.isGameNoVR) {
|
||||
platform = 'Desktop';
|
||||
} else {
|
||||
platform = 'VR';
|
||||
}
|
||||
let groupAccessType = '';
|
||||
if (L.groupAccessType) {
|
||||
if (L.groupAccessType === 'public') {
|
||||
groupAccessType = 'Public';
|
||||
} else if (L.groupAccessType === 'plus') {
|
||||
groupAccessType = 'Plus';
|
||||
}
|
||||
}
|
||||
switch (L.accessType) {
|
||||
case 'public':
|
||||
L.joinUrl = getLaunchURL(L);
|
||||
L.accessName = `Public #${L.instanceName} (${platform})`;
|
||||
break;
|
||||
case 'invite+':
|
||||
L.accessName = `Invite+ #${L.instanceName} (${platform})`;
|
||||
break;
|
||||
case 'invite':
|
||||
L.accessName = `Invite #${L.instanceName} (${platform})`;
|
||||
break;
|
||||
case 'friends':
|
||||
L.accessName = `Friends #${L.instanceName} (${platform})`;
|
||||
break;
|
||||
case 'friends+':
|
||||
L.accessName = `Friends+ #${L.instanceName} (${platform})`;
|
||||
break;
|
||||
case 'group':
|
||||
L.accessName = `Group #${L.instanceName} (${platform})`;
|
||||
getGroupName(L.groupId).then((groupName) => {
|
||||
if (groupName) {
|
||||
L.accessName = `Group${groupAccessType}(${groupName}) #${L.instanceName} (${platform})`;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
locationStore.lastLocation$ = L;
|
||||
}
|
||||
let hidePrivate = false;
|
||||
if (
|
||||
state.discordHideInvite &&
|
||||
(L.accessType === 'invite' ||
|
||||
L.accessType === 'invite+' ||
|
||||
L.groupAccessType === 'members')
|
||||
) {
|
||||
hidePrivate = true;
|
||||
}
|
||||
switch (userStore.currentUser.status) {
|
||||
case 'active':
|
||||
L.statusName = 'Online';
|
||||
L.statusImage = 'active';
|
||||
break;
|
||||
case 'join me':
|
||||
L.statusName = 'Join Me';
|
||||
L.statusImage = 'joinme';
|
||||
break;
|
||||
case 'ask me':
|
||||
L.statusName = 'Ask Me';
|
||||
L.statusImage = 'askme';
|
||||
if (state.discordHideInvite) {
|
||||
hidePrivate = true;
|
||||
}
|
||||
break;
|
||||
case 'busy':
|
||||
L.statusName = 'Do Not Disturb';
|
||||
L.statusImage = 'busy';
|
||||
hidePrivate = true;
|
||||
break;
|
||||
}
|
||||
let activityType = ActivityType.Playing;
|
||||
let appId = '883308884863901717';
|
||||
let bigIcon = 'vrchat';
|
||||
let partyId = `${L.worldId}:${L.instanceName}`;
|
||||
let partySize = locationStore.lastLocation.playerList.size;
|
||||
let partyMaxSize = L.worldCapacity;
|
||||
if (partySize > partyMaxSize) {
|
||||
partyMaxSize = partySize;
|
||||
}
|
||||
let buttonText = 'Join';
|
||||
let buttonUrl = L.joinUrl;
|
||||
if (!state.discordJoinButton) {
|
||||
buttonText = '';
|
||||
buttonUrl = '';
|
||||
}
|
||||
if (!state.discordInstance) {
|
||||
partySize = 0;
|
||||
partyMaxSize = 0;
|
||||
}
|
||||
if (hidePrivate) {
|
||||
partyId = '';
|
||||
partySize = 0;
|
||||
partyMaxSize = 0;
|
||||
buttonText = '';
|
||||
buttonUrl = '';
|
||||
} else if (isRpcWorld(L.tag)) {
|
||||
// custom world rpc
|
||||
if (
|
||||
L.worldId === 'wrld_f20326da-f1ac-45fc-a062-609723b097b1' ||
|
||||
L.worldId === 'wrld_10e5e467-fc65-42ed-8957-f02cace1398c' ||
|
||||
L.worldId === 'wrld_04899f23-e182-4a8d-b2c7-2c74c7c15534'
|
||||
) {
|
||||
activityType = ActivityType.Listening;
|
||||
appId = '784094509008551956';
|
||||
bigIcon = 'pypy';
|
||||
} else if (
|
||||
L.worldId === 'wrld_42377cf1-c54f-45ed-8996-5875b0573a83' ||
|
||||
L.worldId === 'wrld_dd6d2888-dbdc-47c2-bc98-3d631b2acd7c'
|
||||
) {
|
||||
activityType = ActivityType.Listening;
|
||||
appId = '846232616054030376';
|
||||
bigIcon = 'vr_dancing';
|
||||
} else if (
|
||||
L.worldId === 'wrld_52bdcdab-11cd-4325-9655-0fb120846945' ||
|
||||
L.worldId === 'wrld_2d40da63-8f1f-4011-8a9e-414eb8530acd'
|
||||
) {
|
||||
activityType = ActivityType.Listening;
|
||||
appId = '939473404808007731';
|
||||
bigIcon = 'zuwa_zuwa_dance';
|
||||
} else if (
|
||||
L.worldId === 'wrld_74970324-58e8-4239-a17b-2c59dfdf00db' ||
|
||||
L.worldId === 'wrld_db9d878f-6e76-4776-8bf2-15bcdd7fc445' ||
|
||||
L.worldId === 'wrld_435bbf25-f34f-4b8b-82c6-cd809057eb8e' ||
|
||||
L.worldId === 'wrld_f767d1c8-b249-4ecc-a56f-614e433682c8'
|
||||
) {
|
||||
activityType = ActivityType.Watching;
|
||||
appId = '968292722391785512';
|
||||
bigIcon = 'ls_media';
|
||||
} else if (
|
||||
L.worldId === 'wrld_266523e8-9161-40da-acd0-6bd82e075833' ||
|
||||
L.worldId === 'wrld_27c7e6b2-d938-447e-a270-3d1a873e2cf3'
|
||||
) {
|
||||
activityType = ActivityType.Watching;
|
||||
appId = '1095440531821170820';
|
||||
bigIcon = 'popcorn_palace';
|
||||
}
|
||||
if (gameLogStore.nowPlaying.name) {
|
||||
L.worldName = gameLogStore.nowPlaying.name;
|
||||
}
|
||||
if (gameLogStore.nowPlaying.playing) {
|
||||
Discord.SetTimestamps(
|
||||
gameLogStore.nowPlaying.startTime * 1000,
|
||||
(gameLogStore.nowPlaying.startTime +
|
||||
gameLogStore.nowPlaying.length) *
|
||||
1000
|
||||
);
|
||||
}
|
||||
} else if (!state.discordHideImage && L.thumbnailImageUrl) {
|
||||
bigIcon = L.thumbnailImageUrl;
|
||||
}
|
||||
Discord.SetAssets(
|
||||
bigIcon, // big icon
|
||||
'Powered by VRCX', // big icon hover text
|
||||
L.statusImage, // small icon
|
||||
L.statusName, // small icon hover text
|
||||
partyId, // party id
|
||||
partySize, // party size
|
||||
partyMaxSize, // party max size
|
||||
buttonText, // button text
|
||||
buttonUrl, // button url
|
||||
appId, // app id
|
||||
activityType // activity type
|
||||
);
|
||||
// NOTE
|
||||
// 글자 수가 짧으면 업데이트가 안된다..
|
||||
if (L.worldName.length < 2) {
|
||||
L.worldName += '\uFFA0'.repeat(2 - L.worldName.length);
|
||||
}
|
||||
if (hidePrivate) {
|
||||
Discord.SetText('Private', '');
|
||||
Discord.SetTimestamps(0, 0);
|
||||
} else if (state.discordInstance) {
|
||||
Discord.SetText(L.worldName, L.accessName);
|
||||
} else {
|
||||
Discord.SetText(L.worldName, '');
|
||||
}
|
||||
}
|
||||
|
||||
async function setIsDiscordActive(active) {
|
||||
if (active !== state.isDiscordActive) {
|
||||
state.isDiscordActive = await Discord.SetActive(active);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveDiscordOption(configLabel = '') {
|
||||
locationStore.lastLocation$.tag = '';
|
||||
updateLoopStore.nextDiscordUpdate = 3;
|
||||
updateDiscord();
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
|
||||
discordActive,
|
||||
discordInstance,
|
||||
discordHideInvite,
|
||||
discordJoinButton,
|
||||
discordHideImage,
|
||||
|
||||
setDiscordActive,
|
||||
setDiscordInstance,
|
||||
setDiscordHideInvite,
|
||||
setDiscordJoinButton,
|
||||
setDiscordHideImage,
|
||||
updateDiscord,
|
||||
saveDiscordOption
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,321 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { computed, reactive } from 'vue';
|
||||
import * as workerTimers from 'worker-timers';
|
||||
import { $app } from '../../app';
|
||||
import { t } from '../../plugin';
|
||||
import configRepository from '../../service/config';
|
||||
import { useVrcxStore } from '../vrcx';
|
||||
import { useVRCXUpdaterStore } from '../vrcxUpdater';
|
||||
|
||||
export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
|
||||
const vrcxStore = useVrcxStore();
|
||||
const VRCXUpdaterStore = useVRCXUpdaterStore();
|
||||
const state = reactive({
|
||||
isStartAtWindowsStartup: false,
|
||||
isStartAsMinimizedState: false,
|
||||
isCloseToTray: false,
|
||||
disableGpuAcceleration: false,
|
||||
disableVrOverlayGpuAcceleration: false,
|
||||
localFavoriteFriendsGroups: [],
|
||||
udonExceptionLogging: false,
|
||||
logResourceLoad: false,
|
||||
logEmptyAvatars: false,
|
||||
autoStateChangeEnabled: false,
|
||||
autoStateChangeAloneStatus: 'join me',
|
||||
autoStateChangeCompanyStatus: 'busy',
|
||||
autoStateChangeInstanceTypes: [],
|
||||
autoStateChangeNoFriends: false,
|
||||
autoAcceptInviteRequests: 'Off'
|
||||
});
|
||||
|
||||
async function initGeneralSettings() {
|
||||
const [
|
||||
isStartAtWindowsStartup,
|
||||
isStartAsMinimizedState,
|
||||
isCloseToTray,
|
||||
isCloseToTrayConfigBool,
|
||||
disableGpuAccelerationStr,
|
||||
disableVrOverlayGpuAccelerationStr,
|
||||
localFavoriteFriendsGroupsStr,
|
||||
udonExceptionLogging,
|
||||
logResourceLoad,
|
||||
logEmptyAvatars,
|
||||
autoStateChangeEnabled,
|
||||
autoStateChangeAloneStatus,
|
||||
autoStateChangeCompanyStatus,
|
||||
autoStateChangeInstanceTypesStr,
|
||||
autoAcceptInviteRequests
|
||||
] = await Promise.all([
|
||||
configRepository.getBool('VRCX_StartAtWindowsStartup', false),
|
||||
VRCXStorage.Get('VRCX_StartAsMinimizedState'),
|
||||
VRCXStorage.Get('VRCX_CloseToTray'),
|
||||
configRepository.getBool('VRCX_CloseToTray'),
|
||||
VRCXStorage.Get('VRCX_DisableGpuAcceleration'),
|
||||
VRCXStorage.Get('VRCX_DisableVrOverlayGpuAcceleration'),
|
||||
configRepository.getString('VRCX_localFavoriteFriendsGroups', '[]'),
|
||||
configRepository.getBool('VRCX_udonExceptionLogging', false),
|
||||
configRepository.getBool('VRCX_logResourceLoad', false),
|
||||
configRepository.getBool('VRCX_logEmptyAvatars', false),
|
||||
configRepository.getBool('VRCX_autoStateChangeEnabled', false),
|
||||
configRepository.getString(
|
||||
'VRCX_autoStateChangeAloneStatus',
|
||||
'join me'
|
||||
),
|
||||
configRepository.getString(
|
||||
'VRCX_autoStateChangeCompanyStatus',
|
||||
'busy'
|
||||
),
|
||||
configRepository.getString(
|
||||
'VRCX_autoStateChangeInstanceTypes',
|
||||
'[]'
|
||||
),
|
||||
configRepository.getString('VRCX_autoAcceptInviteRequests', 'Off')
|
||||
]);
|
||||
|
||||
state.isStartAtWindowsStartup = isStartAtWindowsStartup;
|
||||
state.isStartAsMinimizedState = isStartAsMinimizedState === 'true';
|
||||
|
||||
if (isCloseToTrayConfigBool) {
|
||||
state.isCloseToTray = isCloseToTrayConfigBool;
|
||||
|
||||
await VRCXStorage.Set(
|
||||
'VRCX_CloseToTray',
|
||||
state.isCloseToTray.toString()
|
||||
);
|
||||
await configRepository.remove('VRCX_CloseToTray');
|
||||
} else {
|
||||
state.isCloseToTray = isCloseToTray === 'true';
|
||||
}
|
||||
|
||||
state.disableGpuAcceleration = disableGpuAccelerationStr === 'true';
|
||||
state.disableVrOverlayGpuAcceleration =
|
||||
disableVrOverlayGpuAccelerationStr === 'true';
|
||||
state.localFavoriteFriendsGroups = JSON.parse(
|
||||
localFavoriteFriendsGroupsStr
|
||||
);
|
||||
state.udonExceptionLogging = udonExceptionLogging;
|
||||
state.logResourceLoad = logResourceLoad;
|
||||
state.logEmptyAvatars = logEmptyAvatars;
|
||||
state.autoStateChangeEnabled = autoStateChangeEnabled;
|
||||
state.autoStateChangeAloneStatus = autoStateChangeAloneStatus;
|
||||
state.autoStateChangeCompanyStatus = autoStateChangeCompanyStatus;
|
||||
state.autoStateChangeInstanceTypes = JSON.parse(
|
||||
autoStateChangeInstanceTypesStr
|
||||
);
|
||||
state.autoAcceptInviteRequests = autoAcceptInviteRequests;
|
||||
}
|
||||
|
||||
initGeneralSettings();
|
||||
|
||||
const isStartAtWindowsStartup = computed(
|
||||
() => state.isStartAtWindowsStartup
|
||||
);
|
||||
const isStartAsMinimizedState = computed(
|
||||
() => state.isStartAsMinimizedState
|
||||
);
|
||||
const disableGpuAcceleration = computed(() => state.disableGpuAcceleration);
|
||||
const isCloseToTray = computed(() => state.isCloseToTray);
|
||||
const disableVrOverlayGpuAcceleration = computed(
|
||||
() => state.disableVrOverlayGpuAcceleration
|
||||
);
|
||||
const localFavoriteFriendsGroups = computed(
|
||||
() => state.localFavoriteFriendsGroups
|
||||
);
|
||||
const udonExceptionLogging = computed(() => state.udonExceptionLogging);
|
||||
const logResourceLoad = computed(() => state.logResourceLoad);
|
||||
const logEmptyAvatars = computed(() => state.logEmptyAvatars);
|
||||
const autoStateChangeEnabled = computed(() => state.autoStateChangeEnabled);
|
||||
const autoStateChangeAloneStatus = computed(
|
||||
() => state.autoStateChangeAloneStatus
|
||||
);
|
||||
const autoStateChangeCompanyStatus = computed(
|
||||
() => state.autoStateChangeCompanyStatus
|
||||
);
|
||||
const autoStateChangeInstanceTypes = computed(
|
||||
() => state.autoStateChangeInstanceTypes
|
||||
);
|
||||
const autoStateChangeNoFriends = computed(
|
||||
() => state.autoStateChangeNoFriends
|
||||
);
|
||||
const autoAcceptInviteRequests = computed(
|
||||
() => state.autoAcceptInviteRequests
|
||||
);
|
||||
|
||||
function setIsStartAtWindowsStartup() {
|
||||
state.isStartAtWindowsStartup = !state.isStartAtWindowsStartup;
|
||||
configRepository.setBool(
|
||||
'VRCX_StartAtWindowsStartup',
|
||||
state.isStartAtWindowsStartup
|
||||
);
|
||||
AppApi.SetStartup(state.isStartAtWindowsStartup);
|
||||
}
|
||||
function setIsStartAsMinimizedState() {
|
||||
state.isStartAsMinimizedState = !state.isStartAsMinimizedState;
|
||||
VRCXStorage.Set(
|
||||
'VRCX_StartAsMinimizedState',
|
||||
state.isStartAsMinimizedState.toString()
|
||||
);
|
||||
}
|
||||
function setIsCloseToTray() {
|
||||
state.isCloseToTray = !state.isCloseToTray;
|
||||
VRCXStorage.Set('VRCX_CloseToTray', state.isCloseToTray.toString());
|
||||
}
|
||||
function setDisableGpuAcceleration() {
|
||||
state.disableGpuAcceleration = !state.disableGpuAcceleration;
|
||||
VRCXStorage.Set(
|
||||
'VRCX_DisableGpuAcceleration',
|
||||
state.disableGpuAcceleration.toString()
|
||||
);
|
||||
}
|
||||
function setDisableVrOverlayGpuAcceleration() {
|
||||
state.disableVrOverlayGpuAcceleration =
|
||||
!state.disableVrOverlayGpuAcceleration;
|
||||
VRCXStorage.Set(
|
||||
'VRCX_DisableVrOverlayGpuAcceleration',
|
||||
state.disableVrOverlayGpuAcceleration.toString()
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {string[]} value
|
||||
*/
|
||||
function setLocalFavoriteFriendsGroups(value) {
|
||||
state.localFavoriteFriendsGroups = value;
|
||||
configRepository.setString(
|
||||
'VRCX_localFavoriteFriendsGroups',
|
||||
JSON.stringify(value)
|
||||
);
|
||||
}
|
||||
function setUdonExceptionLogging() {
|
||||
state.udonExceptionLogging = !state.udonExceptionLogging;
|
||||
configRepository.setBool(
|
||||
'VRCX_udonExceptionLogging',
|
||||
state.udonExceptionLogging
|
||||
);
|
||||
}
|
||||
function setLogResourceLoad() {
|
||||
state.logResourceLoad = !state.logResourceLoad;
|
||||
configRepository.setBool('VRCX_logResourceLoad', state.logResourceLoad);
|
||||
}
|
||||
function setLogEmptyAvatars() {
|
||||
state.logEmptyAvatars = !state.logEmptyAvatars;
|
||||
configRepository.setBool('VRCX_logEmptyAvatars', state.logEmptyAvatars);
|
||||
}
|
||||
function setAutoStateChangeEnabled() {
|
||||
state.autoStateChangeEnabled = !state.autoStateChangeEnabled;
|
||||
configRepository.setBool(
|
||||
'VRCX_autoStateChangeEnabled',
|
||||
state.autoStateChangeEnabled
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {string} value
|
||||
*/
|
||||
function setAutoStateChangeAloneStatus(value) {
|
||||
state.autoStateChangeAloneStatus = value;
|
||||
configRepository.setString(
|
||||
'VRCX_autoStateChangeAloneStatus',
|
||||
state.autoStateChangeAloneStatus
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {string} value
|
||||
*/
|
||||
function setAutoStateChangeCompanyStatus(value) {
|
||||
state.autoStateChangeCompanyStatus = value;
|
||||
configRepository.setString(
|
||||
'VRCX_autoStateChangeCompanyStatus',
|
||||
state.autoStateChangeCompanyStatus
|
||||
);
|
||||
}
|
||||
function setAutoStateChangeInstanceTypes(value) {
|
||||
state.autoStateChangeInstanceTypes = value;
|
||||
configRepository.setString(
|
||||
'VRCX_autoStateChangeInstanceTypes',
|
||||
JSON.stringify(state.autoStateChangeInstanceTypes)
|
||||
);
|
||||
}
|
||||
function setAutoStateChangeNoFriends() {
|
||||
state.autoStateChangeNoFriends = !state.autoStateChangeNoFriends;
|
||||
configRepository.setBool(
|
||||
'VRCX_autoStateChangeNoFriends',
|
||||
state.autoStateChangeNoFriends
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {string} value
|
||||
*/
|
||||
function setAutoAcceptInviteRequests(value) {
|
||||
state.autoAcceptInviteRequests = value;
|
||||
configRepository.setString(
|
||||
'VRCX_autoAcceptInviteRequests',
|
||||
state.autoAcceptInviteRequests
|
||||
);
|
||||
}
|
||||
|
||||
function promptProxySettings() {
|
||||
$app.$prompt(
|
||||
t('prompt.proxy_settings.description'),
|
||||
t('prompt.proxy_settings.header'),
|
||||
{
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: t('prompt.proxy_settings.restart'),
|
||||
cancelButtonText: t('prompt.proxy_settings.close'),
|
||||
inputValue: vrcxStore.proxyServer,
|
||||
inputPlaceholder: t('prompt.proxy_settings.placeholder'),
|
||||
callback: async (action, instance) => {
|
||||
vrcxStore.proxyServer = instance.inputValue;
|
||||
await VRCXStorage.Set(
|
||||
'VRCX_ProxyServer',
|
||||
vrcxStore.proxyServer
|
||||
);
|
||||
await VRCXStorage.Flush();
|
||||
await new Promise((resolve) => {
|
||||
workerTimers.setTimeout(resolve, 100);
|
||||
});
|
||||
if (action === 'confirm') {
|
||||
const { restartVRCX } = VRCXUpdaterStore;
|
||||
const isUpgrade = false;
|
||||
restartVRCX(isUpgrade);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
|
||||
isStartAtWindowsStartup,
|
||||
isStartAsMinimizedState,
|
||||
isCloseToTray,
|
||||
disableGpuAcceleration,
|
||||
disableVrOverlayGpuAcceleration,
|
||||
localFavoriteFriendsGroups,
|
||||
udonExceptionLogging,
|
||||
logResourceLoad,
|
||||
logEmptyAvatars,
|
||||
autoStateChangeEnabled,
|
||||
autoStateChangeAloneStatus,
|
||||
autoStateChangeCompanyStatus,
|
||||
autoStateChangeInstanceTypes,
|
||||
autoStateChangeNoFriends,
|
||||
autoAcceptInviteRequests,
|
||||
|
||||
setIsStartAtWindowsStartup,
|
||||
setIsStartAsMinimizedState,
|
||||
setIsCloseToTray,
|
||||
setDisableGpuAcceleration,
|
||||
setDisableVrOverlayGpuAcceleration,
|
||||
setLocalFavoriteFriendsGroups,
|
||||
setUdonExceptionLogging,
|
||||
setLogResourceLoad,
|
||||
setLogEmptyAvatars,
|
||||
setAutoStateChangeEnabled,
|
||||
setAutoStateChangeAloneStatus,
|
||||
setAutoStateChangeCompanyStatus,
|
||||
setAutoStateChangeInstanceTypes,
|
||||
setAutoStateChangeNoFriends,
|
||||
setAutoAcceptInviteRequests,
|
||||
promptProxySettings
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,518 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { computed, reactive } from 'vue';
|
||||
import { $app } from '../../app';
|
||||
import { t } from '../../plugin';
|
||||
import configRepository from '../../service/config';
|
||||
import { sharedFeedFiltersDefaults } from '../../shared/constants';
|
||||
import { useVrStore } from '../vr';
|
||||
|
||||
export const useNotificationsSettingsStore = defineStore(
|
||||
'NotificationsSettings',
|
||||
() => {
|
||||
const vrStore = useVrStore();
|
||||
const state = reactive({
|
||||
overlayToast: true,
|
||||
openVR: false,
|
||||
overlayNotifications: true,
|
||||
xsNotifications: true,
|
||||
ovrtHudNotifications: true,
|
||||
ovrtWristNotifications: false,
|
||||
imageNotifications: true,
|
||||
desktopToast: 'Never',
|
||||
afkDesktopToast: false,
|
||||
notificationTTS: 'Never',
|
||||
notificationTTSNickName: false,
|
||||
sharedFeedFilters: {
|
||||
noty: {
|
||||
Location: 'Off',
|
||||
OnPlayerJoined: 'VIP',
|
||||
OnPlayerLeft: 'VIP',
|
||||
OnPlayerJoining: 'VIP',
|
||||
Online: 'VIP',
|
||||
Offline: 'VIP',
|
||||
GPS: 'Off',
|
||||
Status: 'Off',
|
||||
invite: 'Friends',
|
||||
requestInvite: 'Friends',
|
||||
inviteResponse: 'Friends',
|
||||
requestInviteResponse: 'Friends',
|
||||
friendRequest: 'On',
|
||||
Friend: 'On',
|
||||
Unfriend: 'On',
|
||||
DisplayName: 'VIP',
|
||||
TrustLevel: 'VIP',
|
||||
boop: 'Off',
|
||||
groupChange: 'On',
|
||||
'group.announcement': 'On',
|
||||
'group.informative': 'On',
|
||||
'group.invite': 'On',
|
||||
'group.joinRequest': 'Off',
|
||||
'group.transfer': 'On',
|
||||
'group.queueReady': 'On',
|
||||
'instance.closed': 'On',
|
||||
PortalSpawn: 'Everyone',
|
||||
Event: 'On',
|
||||
External: 'On',
|
||||
VideoPlay: 'Off',
|
||||
BlockedOnPlayerJoined: 'Off',
|
||||
BlockedOnPlayerLeft: 'Off',
|
||||
MutedOnPlayerJoined: 'Off',
|
||||
MutedOnPlayerLeft: 'Off',
|
||||
AvatarChange: 'Off',
|
||||
ChatBoxMessage: 'Off',
|
||||
Blocked: 'Off',
|
||||
Unblocked: 'Off',
|
||||
Muted: 'Off',
|
||||
Unmuted: 'Off'
|
||||
},
|
||||
wrist: {
|
||||
Location: 'On',
|
||||
OnPlayerJoined: 'Everyone',
|
||||
OnPlayerLeft: 'Everyone',
|
||||
OnPlayerJoining: 'Friends',
|
||||
Online: 'Friends',
|
||||
Offline: 'Friends',
|
||||
GPS: 'Friends',
|
||||
Status: 'Friends',
|
||||
invite: 'Friends',
|
||||
requestInvite: 'Friends',
|
||||
inviteResponse: 'Friends',
|
||||
requestInviteResponse: 'Friends',
|
||||
friendRequest: 'On',
|
||||
Friend: 'On',
|
||||
Unfriend: 'On',
|
||||
DisplayName: 'Friends',
|
||||
TrustLevel: 'Friends',
|
||||
boop: 'On',
|
||||
groupChange: 'On',
|
||||
'group.announcement': 'On',
|
||||
'group.informative': 'On',
|
||||
'group.invite': 'On',
|
||||
'group.joinRequest': 'On',
|
||||
'group.transfer': 'On',
|
||||
'group.queueReady': 'On',
|
||||
'instance.closed': 'On',
|
||||
PortalSpawn: 'Everyone',
|
||||
Event: 'On',
|
||||
External: 'On',
|
||||
VideoPlay: 'On',
|
||||
BlockedOnPlayerJoined: 'Off',
|
||||
BlockedOnPlayerLeft: 'Off',
|
||||
MutedOnPlayerJoined: 'Off',
|
||||
MutedOnPlayerLeft: 'Off',
|
||||
AvatarChange: 'Everyone',
|
||||
ChatBoxMessage: 'Off',
|
||||
Blocked: 'On',
|
||||
Unblocked: 'On',
|
||||
Muted: 'On',
|
||||
Unmuted: 'On'
|
||||
}
|
||||
},
|
||||
isTestTTSVisible: false,
|
||||
notificationTTSVoice: 0,
|
||||
notificationTTSTest: '',
|
||||
TTSvoices: [],
|
||||
notificationPosition: 'topCenter',
|
||||
notificationTimeout: 3000
|
||||
});
|
||||
|
||||
async function initNotificationsSettings() {
|
||||
const [
|
||||
overlayToast,
|
||||
overlayNotifications,
|
||||
openVR,
|
||||
xsNotifications,
|
||||
ovrtHudNotifications,
|
||||
ovrtWristNotifications,
|
||||
imageNotifications,
|
||||
desktopToast,
|
||||
afkDesktopToast,
|
||||
notificationTTS,
|
||||
notificationTTSNickName,
|
||||
sharedFeedFilters,
|
||||
notificationTTSVoice,
|
||||
notificationPosition,
|
||||
notificationTimeout
|
||||
] = await Promise.all([
|
||||
configRepository.getString('VRCX_overlayToast', 'Game Running'),
|
||||
configRepository.getBool('VRCX_overlayNotifications', true),
|
||||
configRepository.getBool('openVR'),
|
||||
configRepository.getBool('VRCX_xsNotifications', true),
|
||||
configRepository.getBool('VRCX_ovrtHudNotifications', true),
|
||||
configRepository.getBool('VRCX_ovrtWristNotifications', false),
|
||||
configRepository.getBool('VRCX_imageNotifications', true),
|
||||
configRepository.getString('VRCX_desktopToast', 'Never'),
|
||||
configRepository.getBool('VRCX_afkDesktopToast', false),
|
||||
configRepository.getString('VRCX_notificationTTS', 'Never'),
|
||||
configRepository.getBool('VRCX_notificationTTSNickName', false),
|
||||
configRepository.getString(
|
||||
'sharedFeedFilters',
|
||||
JSON.stringify(sharedFeedFiltersDefaults)
|
||||
),
|
||||
configRepository.getString('VRCX_notificationTTSVoice', '0'),
|
||||
configRepository.getString(
|
||||
'VRCX_notificationPosition',
|
||||
'topCenter'
|
||||
),
|
||||
configRepository.getString('VRCX_notificationTimeout', '3000')
|
||||
]);
|
||||
|
||||
state.overlayToast = overlayToast;
|
||||
state.openVR = openVR;
|
||||
state.overlayNotifications = overlayNotifications;
|
||||
state.xsNotifications = xsNotifications;
|
||||
state.ovrtHudNotifications = ovrtHudNotifications;
|
||||
state.ovrtWristNotifications = ovrtWristNotifications;
|
||||
state.imageNotifications = imageNotifications;
|
||||
state.desktopToast = desktopToast;
|
||||
state.afkDesktopToast = afkDesktopToast;
|
||||
state.notificationTTS = notificationTTS;
|
||||
state.notificationTTSNickName = notificationTTSNickName;
|
||||
state.sharedFeedFilters = JSON.parse(sharedFeedFilters);
|
||||
state.notificationTTSVoice = notificationTTSVoice;
|
||||
state.TTSvoices = speechSynthesis.getVoices();
|
||||
state.notificationPosition = notificationPosition;
|
||||
state.notificationTimeout = notificationTimeout;
|
||||
|
||||
initSharedFeedFilters();
|
||||
|
||||
if (LINUX) {
|
||||
setTimeout(() => {
|
||||
updateTTSVoices();
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
initNotificationsSettings();
|
||||
|
||||
const overlayToast = computed(() => state.overlayToast);
|
||||
const openVR = computed(() => state.openVR);
|
||||
const overlayNotifications = computed(() => state.overlayNotifications);
|
||||
const xsNotifications = computed(() => state.xsNotifications);
|
||||
const ovrtHudNotifications = computed(() => state.ovrtHudNotifications);
|
||||
const ovrtWristNotifications = computed(
|
||||
() => state.ovrtWristNotifications
|
||||
);
|
||||
const imageNotifications = computed(() => state.imageNotifications);
|
||||
const desktopToast = computed(() => state.desktopToast);
|
||||
const afkDesktopToast = computed(() => state.afkDesktopToast);
|
||||
const notificationTTS = computed(() => state.notificationTTS);
|
||||
const notificationTTSNickName = computed(
|
||||
() => state.notificationTTSNickName
|
||||
);
|
||||
const sharedFeedFilters = computed({
|
||||
get: () => state.sharedFeedFilters,
|
||||
set: (value) => (state.sharedFeedFilters = value)
|
||||
});
|
||||
const isTestTTSVisible = computed({
|
||||
get: () => state.isTestTTSVisible,
|
||||
set: (value) => (state.isTestTTSVisible = value)
|
||||
});
|
||||
const notificationTTSVoice = computed({
|
||||
get: () => state.notificationTTSVoice,
|
||||
set: (value) => (state.notificationTTSVoice = value)
|
||||
});
|
||||
const TTSvoices = computed({
|
||||
get: () => state.TTSvoices,
|
||||
set: (value) => (state.TTSvoices = value)
|
||||
});
|
||||
const notificationTTSTest = computed({
|
||||
get: () => state.notificationTTSTest,
|
||||
set: (value) => (state.notificationTTSTest = value)
|
||||
});
|
||||
const notificationPosition = computed(() => state.notificationPosition);
|
||||
const notificationTimeout = computed({
|
||||
get: () => state.notificationTimeout,
|
||||
set: (value) => (state.notificationTimeout = value)
|
||||
});
|
||||
|
||||
function setOverlayToast(value) {
|
||||
state.overlayToast = value;
|
||||
configRepository.setString('VRCX_overlayToast', value);
|
||||
}
|
||||
function setOverlayNotifications() {
|
||||
state.overlayNotifications = !state.overlayNotifications;
|
||||
configRepository.setBool(
|
||||
'VRCX_overlayNotifications',
|
||||
state.overlayNotifications
|
||||
);
|
||||
}
|
||||
function setOpenVR() {
|
||||
state.openVR = !state.openVR;
|
||||
configRepository.setBool('openVR', state.openVR);
|
||||
}
|
||||
function setXsNotifications() {
|
||||
state.xsNotifications = !state.xsNotifications;
|
||||
configRepository.setBool(
|
||||
'VRCX_xsNotifications',
|
||||
state.xsNotifications
|
||||
);
|
||||
}
|
||||
function setOvrtHudNotifications() {
|
||||
state.ovrtHudNotifications = !state.ovrtHudNotifications;
|
||||
configRepository.setBool(
|
||||
'VRCX_ovrtHudNotifications',
|
||||
state.ovrtHudNotifications
|
||||
);
|
||||
}
|
||||
function setOvrtWristNotifications() {
|
||||
state.ovrtWristNotifications = !state.ovrtWristNotifications;
|
||||
configRepository.setBool(
|
||||
'VRCX_ovrtWristNotifications',
|
||||
state.ovrtWristNotifications
|
||||
);
|
||||
}
|
||||
function setImageNotifications() {
|
||||
state.imageNotifications = !state.imageNotifications;
|
||||
configRepository.setBool(
|
||||
'VRCX_imageNotifications',
|
||||
state.imageNotifications
|
||||
);
|
||||
}
|
||||
|
||||
function changeNotificationPosition(value) {
|
||||
state.notificationPosition = value;
|
||||
configRepository.setString(
|
||||
'VRCX_notificationPosition',
|
||||
state.notificationPosition
|
||||
);
|
||||
vrStore.updateVRConfigVars();
|
||||
}
|
||||
/**
|
||||
* @param {string} value
|
||||
*/
|
||||
function setDesktopToast(value) {
|
||||
state.desktopToast = value;
|
||||
configRepository.setString('VRCX_desktopToast', value);
|
||||
}
|
||||
function setAfkDesktopToast() {
|
||||
state.afkDesktopToast = !state.afkDesktopToast;
|
||||
configRepository.setBool(
|
||||
'VRCX_afkDesktopToast',
|
||||
state.afkDesktopToast
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {string} value
|
||||
*/
|
||||
function setNotificationTTS(value) {
|
||||
state.notificationTTS = value;
|
||||
configRepository.setString('VRCX_notificationTTS', value);
|
||||
}
|
||||
function setNotificationTTSNickName() {
|
||||
state.notificationTTSNickName = !state.notificationTTSNickName;
|
||||
configRepository.setBool(
|
||||
'VRCX_notificationTTSNickName',
|
||||
state.notificationTTSNickName
|
||||
);
|
||||
}
|
||||
function initSharedFeedFilters() {
|
||||
if (!state.sharedFeedFilters.noty.Blocked) {
|
||||
state.sharedFeedFilters.noty.Blocked = 'Off';
|
||||
state.sharedFeedFilters.noty.Unblocked = 'Off';
|
||||
state.sharedFeedFilters.noty.Muted = 'Off';
|
||||
state.sharedFeedFilters.noty.Unmuted = 'Off';
|
||||
state.sharedFeedFilters.wrist.Blocked = 'On';
|
||||
state.sharedFeedFilters.wrist.Unblocked = 'On';
|
||||
state.sharedFeedFilters.wrist.Muted = 'On';
|
||||
state.sharedFeedFilters.wrist.Unmuted = 'On';
|
||||
}
|
||||
if (!state.sharedFeedFilters.noty['group.announcement']) {
|
||||
state.sharedFeedFilters.noty['group.announcement'] = 'On';
|
||||
state.sharedFeedFilters.noty['group.informative'] = 'On';
|
||||
state.sharedFeedFilters.noty['group.invite'] = 'On';
|
||||
state.sharedFeedFilters.noty['group.joinRequest'] = 'Off';
|
||||
state.sharedFeedFilters.wrist['group.announcement'] = 'On';
|
||||
state.sharedFeedFilters.wrist['group.informative'] = 'On';
|
||||
state.sharedFeedFilters.wrist['group.invite'] = 'On';
|
||||
state.sharedFeedFilters.wrist['group.joinRequest'] = 'On';
|
||||
}
|
||||
if (!state.sharedFeedFilters.noty['group.queueReady']) {
|
||||
state.sharedFeedFilters.noty['group.queueReady'] = 'On';
|
||||
state.sharedFeedFilters.wrist['group.queueReady'] = 'On';
|
||||
}
|
||||
if (!state.sharedFeedFilters.noty['instance.closed']) {
|
||||
state.sharedFeedFilters.noty['instance.closed'] = 'On';
|
||||
state.sharedFeedFilters.wrist['instance.closed'] = 'On';
|
||||
}
|
||||
if (!state.sharedFeedFilters.noty.External) {
|
||||
state.sharedFeedFilters.noty.External = 'On';
|
||||
state.sharedFeedFilters.wrist.External = 'On';
|
||||
}
|
||||
if (!state.sharedFeedFilters.noty.groupChange) {
|
||||
state.sharedFeedFilters.noty.groupChange = 'On';
|
||||
state.sharedFeedFilters.wrist.groupChange = 'On';
|
||||
}
|
||||
if (!state.sharedFeedFilters.noty['group.transfer']) {
|
||||
state.sharedFeedFilters.noty['group.transfer'] = 'On';
|
||||
state.sharedFeedFilters.wrist['group.transfer'] = 'On';
|
||||
}
|
||||
if (!state.sharedFeedFilters.noty.boop) {
|
||||
state.sharedFeedFilters.noty.boop = 'Off';
|
||||
state.sharedFeedFilters.wrist.boop = 'On';
|
||||
}
|
||||
}
|
||||
function setNotificationTTSVoice(index) {
|
||||
state.notificationTTSVoice = index;
|
||||
configRepository.setString(
|
||||
'VRCX_notificationTTSVoice',
|
||||
state.notificationTTSVoice
|
||||
);
|
||||
}
|
||||
|
||||
function getTTSVoiceName() {
|
||||
let voices;
|
||||
if (LINUX) {
|
||||
voices = state.TTSvoices;
|
||||
} else {
|
||||
voices = speechSynthesis.getVoices();
|
||||
}
|
||||
if (voices.length === 0) {
|
||||
return '';
|
||||
}
|
||||
if (state.notificationTTSVoice >= voices.length) {
|
||||
setNotificationTTSVoice(0);
|
||||
}
|
||||
return voices[state.notificationTTSVoice].name;
|
||||
}
|
||||
|
||||
async function changeTTSVoice(index) {
|
||||
setNotificationTTSVoice(index);
|
||||
let voices;
|
||||
if (LINUX) {
|
||||
voices = state.TTSvoices;
|
||||
} else {
|
||||
voices = speechSynthesis.getVoices();
|
||||
}
|
||||
if (voices.length === 0) {
|
||||
return;
|
||||
}
|
||||
const voiceName = voices[index].name;
|
||||
speechSynthesis.cancel();
|
||||
speak(voiceName);
|
||||
}
|
||||
|
||||
function updateTTSVoices() {
|
||||
state.TTSvoices = speechSynthesis.getVoices();
|
||||
if (LINUX) {
|
||||
const voices = speechSynthesis.getVoices();
|
||||
let uniqueVoices = [];
|
||||
voices.forEach((voice) => {
|
||||
if (!uniqueVoices.some((v) => v.lang === voice.lang)) {
|
||||
uniqueVoices.push(voice);
|
||||
}
|
||||
});
|
||||
uniqueVoices = uniqueVoices.filter((v) =>
|
||||
v.lang.startsWith('en')
|
||||
);
|
||||
state.TTSvoices = uniqueVoices;
|
||||
}
|
||||
}
|
||||
async function saveNotificationTTS(value) {
|
||||
speechSynthesis.cancel();
|
||||
if (
|
||||
(await configRepository.getString('VRCX_notificationTTS')) ===
|
||||
'Never' &&
|
||||
value !== 'Never'
|
||||
) {
|
||||
speak('Notification text-to-speech enabled');
|
||||
}
|
||||
setNotificationTTS(value);
|
||||
}
|
||||
|
||||
function testNotificationTTS() {
|
||||
speechSynthesis.cancel();
|
||||
speak(state.notificationTTSTest);
|
||||
}
|
||||
|
||||
function speak(text) {
|
||||
const tts = new SpeechSynthesisUtterance();
|
||||
const voices = speechSynthesis.getVoices();
|
||||
if (voices.length === 0) {
|
||||
return;
|
||||
}
|
||||
let index = 0;
|
||||
if (state.notificationTTSVoice < voices.length) {
|
||||
index = state.notificationTTSVoice;
|
||||
}
|
||||
tts.voice = voices[index];
|
||||
tts.text = text;
|
||||
speechSynthesis.speak(tts);
|
||||
}
|
||||
|
||||
function promptNotificationTimeout() {
|
||||
$app.$prompt(
|
||||
t('prompt.notification_timeout.description'),
|
||||
t('prompt.notification_timeout.header'),
|
||||
{
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: t('prompt.notification_timeout.ok'),
|
||||
cancelButtonText: t('prompt.notification_timeout.cancel'),
|
||||
inputValue: state.notificationTimeout / 1000,
|
||||
inputPattern: /\d+$/,
|
||||
inputErrorMessage: t(
|
||||
'prompt.notification_timeout.input_error'
|
||||
),
|
||||
callback: async (action, instance) => {
|
||||
if (
|
||||
action === 'confirm' &&
|
||||
instance.inputValue &&
|
||||
!isNaN(instance.inputValue)
|
||||
) {
|
||||
state.notificationTimeout = Math.trunc(
|
||||
Number(instance.inputValue) * 1000
|
||||
);
|
||||
await configRepository.setString(
|
||||
'VRCX_notificationTimeout',
|
||||
state.notificationTimeout
|
||||
);
|
||||
vrStore.updateVRConfigVars();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
|
||||
overlayToast,
|
||||
openVR,
|
||||
overlayNotifications,
|
||||
xsNotifications,
|
||||
ovrtHudNotifications,
|
||||
ovrtWristNotifications,
|
||||
imageNotifications,
|
||||
desktopToast,
|
||||
afkDesktopToast,
|
||||
notificationTTS,
|
||||
notificationTTSNickName,
|
||||
sharedFeedFilters,
|
||||
isTestTTSVisible,
|
||||
notificationTTSVoice,
|
||||
TTSvoices,
|
||||
notificationTTSTest,
|
||||
notificationPosition,
|
||||
notificationTimeout,
|
||||
|
||||
setOverlayToast,
|
||||
setOpenVR,
|
||||
setOverlayNotifications,
|
||||
setXsNotifications,
|
||||
setOvrtHudNotifications,
|
||||
setOvrtWristNotifications,
|
||||
setImageNotifications,
|
||||
setDesktopToast,
|
||||
setAfkDesktopToast,
|
||||
setNotificationTTS,
|
||||
setNotificationTTSNickName,
|
||||
getTTSVoiceName,
|
||||
changeTTSVoice,
|
||||
saveNotificationTTS,
|
||||
testNotificationTTS,
|
||||
speak,
|
||||
changeNotificationPosition,
|
||||
promptNotificationTimeout
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,173 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { computed, reactive } from 'vue';
|
||||
import configRepository from '../../service/config';
|
||||
|
||||
export const useWristOverlaySettingsStore = defineStore(
|
||||
'WristOverlaySettings',
|
||||
() => {
|
||||
const state = reactive({
|
||||
overlayWrist: true,
|
||||
hidePrivateFromFeed: false,
|
||||
openVRAlways: false,
|
||||
overlaybutton: false,
|
||||
overlayHand: 0,
|
||||
vrBackgroundEnabled: false,
|
||||
minimalFeed: false,
|
||||
hideDevicesFromFeed: false,
|
||||
vrOverlayCpuUsage: false,
|
||||
hideUptimeFromFeed: false,
|
||||
pcUptimeOnFeed: false
|
||||
});
|
||||
|
||||
async function initWristOverlaySettings() {
|
||||
const [
|
||||
overlayWrist,
|
||||
hidePrivateFromFeed,
|
||||
openVRAlways,
|
||||
overlaybutton,
|
||||
overlayHand,
|
||||
vrBackgroundEnabled,
|
||||
minimalFeed,
|
||||
hideDevicesFromFeed,
|
||||
vrOverlayCpuUsage,
|
||||
hideUptimeFromFeed,
|
||||
pcUptimeOnFeed
|
||||
] = await Promise.all([
|
||||
configRepository.getBool('VRCX_overlayWrist', false),
|
||||
configRepository.getBool('VRCX_hidePrivateFromFeed', false),
|
||||
configRepository.getBool('openVRAlways', false),
|
||||
configRepository.getBool('VRCX_overlaybutton', false),
|
||||
configRepository.getInt('VRCX_overlayHand', 0),
|
||||
configRepository.getBool('VRCX_vrBackgroundEnabled', false),
|
||||
configRepository.getBool('VRCX_minimalFeed', false),
|
||||
configRepository.getBool('VRCX_hideDevicesFromFeed', false),
|
||||
configRepository.getBool('VRCX_vrOverlayCpuUsage', false),
|
||||
configRepository.getBool('VRCX_hideUptimeFromFeed', false),
|
||||
configRepository.getBool('VRCX_pcUptimeOnFeed', false)
|
||||
]);
|
||||
|
||||
state.overlayWrist = overlayWrist;
|
||||
state.hidePrivateFromFeed = hidePrivateFromFeed;
|
||||
state.openVRAlways = openVRAlways;
|
||||
state.overlaybutton = overlaybutton;
|
||||
state.overlayHand = overlayHand;
|
||||
state.vrBackgroundEnabled = vrBackgroundEnabled;
|
||||
state.minimalFeed = minimalFeed;
|
||||
state.hideDevicesFromFeed = hideDevicesFromFeed;
|
||||
state.vrOverlayCpuUsage = vrOverlayCpuUsage;
|
||||
state.hideUptimeFromFeed = hideUptimeFromFeed;
|
||||
state.pcUptimeOnFeed = pcUptimeOnFeed;
|
||||
}
|
||||
|
||||
const overlayWrist = computed(() => state.overlayWrist);
|
||||
const hidePrivateFromFeed = computed(() => state.hidePrivateFromFeed);
|
||||
const openVRAlways = computed(() => state.openVRAlways);
|
||||
const overlaybutton = computed(() => state.overlaybutton);
|
||||
const overlayHand = computed(() => state.overlayHand);
|
||||
const vrBackgroundEnabled = computed(() => state.vrBackgroundEnabled);
|
||||
const minimalFeed = computed(() => state.minimalFeed);
|
||||
const hideDevicesFromFeed = computed(() => state.hideDevicesFromFeed);
|
||||
const vrOverlayCpuUsage = computed(() => state.vrOverlayCpuUsage);
|
||||
const hideUptimeFromFeed = computed(() => state.hideUptimeFromFeed);
|
||||
const pcUptimeOnFeed = computed(() => state.pcUptimeOnFeed);
|
||||
|
||||
function setOverlayWrist() {
|
||||
state.overlayWrist = !state.overlayWrist;
|
||||
configRepository.setBool('VRCX_overlayWrist', state.overlayWrist);
|
||||
}
|
||||
function setHidePrivateFromFeed() {
|
||||
state.hidePrivateFromFeed = !state.hidePrivateFromFeed;
|
||||
configRepository.setBool(
|
||||
'VRCX_hidePrivateFromFeed',
|
||||
state.hidePrivateFromFeed
|
||||
);
|
||||
}
|
||||
function setOpenVRAlways() {
|
||||
state.openVRAlways = !state.openVRAlways;
|
||||
configRepository.setBool('openVRAlways', state.openVRAlways);
|
||||
}
|
||||
function setOverlaybutton() {
|
||||
state.overlaybutton = !state.overlaybutton;
|
||||
configRepository.setBool('VRCX_overlaybutton', state.overlaybutton);
|
||||
}
|
||||
/**
|
||||
* @param {string} value
|
||||
*/
|
||||
function setOverlayHand(value) {
|
||||
state.overlayHand = parseInt(value, 10);
|
||||
if (isNaN(state.overlayHand)) {
|
||||
state.overlayHand = 0;
|
||||
}
|
||||
configRepository.setInt('VRCX_overlayHand', value);
|
||||
}
|
||||
function setVrBackgroundEnabled() {
|
||||
state.vrBackgroundEnabled = !state.vrBackgroundEnabled;
|
||||
configRepository.setBool(
|
||||
'VRCX_vrBackgroundEnabled',
|
||||
state.vrBackgroundEnabled
|
||||
);
|
||||
}
|
||||
function setMinimalFeed() {
|
||||
state.minimalFeed = !state.minimalFeed;
|
||||
configRepository.setBool('VRCX_minimalFeed', state.minimalFeed);
|
||||
}
|
||||
function setHideDevicesFromFeed() {
|
||||
state.hideDevicesFromFeed = !state.hideDevicesFromFeed;
|
||||
configRepository.setBool(
|
||||
'VRCX_hideDevicesFromFeed',
|
||||
state.hideDevicesFromFeed
|
||||
);
|
||||
}
|
||||
function setVrOverlayCpuUsage() {
|
||||
state.vrOverlayCpuUsage = !state.vrOverlayCpuUsage;
|
||||
configRepository.setBool(
|
||||
'VRCX_vrOverlayCpuUsage',
|
||||
state.vrOverlayCpuUsage
|
||||
);
|
||||
}
|
||||
function setHideUptimeFromFeed() {
|
||||
state.hideUptimeFromFeed = !state.hideUptimeFromFeed;
|
||||
configRepository.setBool(
|
||||
'VRCX_hideUptimeFromFeed',
|
||||
state.hideUptimeFromFeed
|
||||
);
|
||||
}
|
||||
function setPcUptimeOnFeed() {
|
||||
state.pcUptimeOnFeed = !state.pcUptimeOnFeed;
|
||||
configRepository.setBool(
|
||||
'VRCX_pcUptimeOnFeed',
|
||||
state.pcUptimeOnFeed
|
||||
);
|
||||
}
|
||||
|
||||
initWristOverlaySettings();
|
||||
|
||||
return {
|
||||
state,
|
||||
|
||||
overlayWrist,
|
||||
hidePrivateFromFeed,
|
||||
openVRAlways,
|
||||
overlaybutton,
|
||||
overlayHand,
|
||||
vrBackgroundEnabled,
|
||||
minimalFeed,
|
||||
hideDevicesFromFeed,
|
||||
vrOverlayCpuUsage,
|
||||
hideUptimeFromFeed,
|
||||
pcUptimeOnFeed,
|
||||
|
||||
setOverlayWrist,
|
||||
setHidePrivateFromFeed,
|
||||
setOpenVRAlways,
|
||||
setOverlaybutton,
|
||||
setOverlayHand,
|
||||
setVrBackgroundEnabled,
|
||||
setMinimalFeed,
|
||||
setHideDevicesFromFeed,
|
||||
setVrOverlayCpuUsage,
|
||||
setHideUptimeFromFeed,
|
||||
setPcUptimeOnFeed
|
||||
};
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user