mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-16 05:13:51 +02:00
347 lines
10 KiB
JavaScript
347 lines
10 KiB
JavaScript
import { ref, watch } from 'vue';
|
|
import { defineStore } from 'pinia';
|
|
import { toast } from 'vue-sonner';
|
|
import { useMagicKeys } from '@vueuse/core';
|
|
import { useRouter } from 'vue-router';
|
|
|
|
import { AppDebug } from '../service/appConfig';
|
|
import { refreshCustomCss } from '../shared/utils/base/ui';
|
|
import { updateLocalizedStrings } from '../plugin/i18n';
|
|
import { useAppearanceSettingsStore } from './settings/appearance';
|
|
import { useAvatarStore } from './avatar';
|
|
import { useGroupStore } from './group';
|
|
import { useInstanceStore } from './instance';
|
|
import { useNotificationStore } from './notification';
|
|
import { useSearchStore } from './search';
|
|
import { useUserStore } from './user';
|
|
import { useWorldStore } from './world';
|
|
|
|
export const useUiStore = defineStore('Ui', () => {
|
|
const notificationStore = useNotificationStore();
|
|
const userStore = useUserStore();
|
|
const worldStore = useWorldStore();
|
|
const avatarStore = useAvatarStore();
|
|
const groupStore = useGroupStore();
|
|
const instanceStore = useInstanceStore();
|
|
const router = useRouter();
|
|
const keys = useMagicKeys();
|
|
const { directAccessPaste } = useSearchStore();
|
|
const appearanceSettings = useAppearanceSettingsStore();
|
|
|
|
const ctrlR = keys['Ctrl+R'];
|
|
const ctrlD = keys['Ctrl+D'];
|
|
const metaD = keys['Meta+D'];
|
|
const shift = keys['Shift'];
|
|
const ctrlShiftI = keys['Ctrl+Shift+I'];
|
|
const altShiftR = keys['Alt+Shift+R'];
|
|
|
|
const notifiedMenus = ref([]);
|
|
const shiftHeld = ref(false);
|
|
const trayIconNotify = ref(false);
|
|
const dialogCrumbs = ref([]);
|
|
|
|
watch(ctrlR, (isPressed) => {
|
|
if (isPressed) {
|
|
location.reload();
|
|
}
|
|
});
|
|
|
|
watch(ctrlD, (isPressed) => {
|
|
if (isPressed) {
|
|
directAccessPaste();
|
|
}
|
|
});
|
|
|
|
watch(metaD, (isPressed) => {
|
|
if (isPressed) {
|
|
directAccessPaste();
|
|
}
|
|
});
|
|
|
|
watch(shift, (isHeld) => {
|
|
shiftHeld.value = isHeld;
|
|
});
|
|
|
|
watch(ctrlShiftI, (isPressed) => {
|
|
if (isPressed) {
|
|
showConsole();
|
|
}
|
|
});
|
|
|
|
watch(altShiftR, (isPressed) => {
|
|
if (isPressed) {
|
|
refreshCustomCss();
|
|
updateLocalizedStrings();
|
|
toast.success('Custom CSS and localization strings refreshed');
|
|
}
|
|
});
|
|
|
|
function pushDialogCrumb(data) {
|
|
const { type, id, label } = data;
|
|
if (!type || !id) {
|
|
return;
|
|
}
|
|
const items = dialogCrumbs.value;
|
|
const last = items[items.length - 1];
|
|
if (last && last.type === type && last.id === id) {
|
|
if (label && last.label !== label) {
|
|
last.label = label;
|
|
}
|
|
return;
|
|
}
|
|
const existingIndex = items.findIndex(
|
|
(item) => item.type === type && item.id === id
|
|
);
|
|
if (existingIndex !== -1) {
|
|
items.splice(existingIndex + 1);
|
|
if (label) {
|
|
items[existingIndex].label = label;
|
|
}
|
|
return;
|
|
}
|
|
if (!data.label) {
|
|
data.label = data.id;
|
|
}
|
|
items.push(data);
|
|
}
|
|
|
|
function setDialogCrumbLabel(type, id, label) {
|
|
if (!type || !id || !label) {
|
|
return;
|
|
}
|
|
const item = dialogCrumbs.value.find(
|
|
(entry) => entry.type === type && entry.id === id
|
|
);
|
|
if (item) {
|
|
item.label = label;
|
|
}
|
|
}
|
|
|
|
function jumpDialogCrumb(index) {
|
|
if (index < 0 || index >= dialogCrumbs.value.length) {
|
|
return;
|
|
}
|
|
dialogCrumbs.value.splice(index + 1);
|
|
}
|
|
|
|
function jumpBackDialogCrumb() {
|
|
if (dialogCrumbs.value.length > 0) {
|
|
dialogCrumbs.value.pop();
|
|
}
|
|
if (dialogCrumbs.value.length === 0) {
|
|
closeMainDialog();
|
|
return;
|
|
}
|
|
handleBreadcrumbClick(dialogCrumbs.value.length - 1);
|
|
}
|
|
|
|
function handleBreadcrumbClick(index) {
|
|
const item = dialogCrumbs.value[index];
|
|
if (!item) {
|
|
return;
|
|
}
|
|
jumpDialogCrumb(index);
|
|
if (item.type === 'user') {
|
|
userStore.showUserDialog(item.id);
|
|
return;
|
|
}
|
|
if (item.type === 'world') {
|
|
worldStore.showWorldDialog(item.tag, item.shortName);
|
|
return;
|
|
}
|
|
if (item.type === 'avatar') {
|
|
avatarStore.showAvatarDialog(item.id);
|
|
return;
|
|
}
|
|
if (item.type === 'group') {
|
|
groupStore.showGroupDialog(item.id);
|
|
return;
|
|
}
|
|
if (item.type === 'previous-instances-user') {
|
|
instanceStore.showPreviousInstancesListDialog('user', item.id);
|
|
return;
|
|
}
|
|
if (item.type === 'previous-instances-world') {
|
|
instanceStore.showPreviousInstancesListDialog('world', item.id);
|
|
return;
|
|
}
|
|
if (item.type === 'previous-instances-group') {
|
|
instanceStore.showPreviousInstancesListDialog('group', item.id);
|
|
return;
|
|
}
|
|
if (item.type === 'previous-instances-info') {
|
|
instanceStore.showPreviousInstancesInfoDialog(item.id);
|
|
return;
|
|
}
|
|
console.error(
|
|
`Unknown dialog crumb type: ${item.type}, closing dialog`
|
|
);
|
|
closeMainDialog();
|
|
}
|
|
|
|
function clearDialogCrumbs() {
|
|
dialogCrumbs.value = [];
|
|
}
|
|
|
|
function closeMainDialog() {
|
|
const userStore = useUserStore();
|
|
const worldStore = useWorldStore();
|
|
const avatarStore = useAvatarStore();
|
|
const groupStore = useGroupStore();
|
|
const instanceStore = useInstanceStore();
|
|
|
|
userStore.userDialog.visible = false;
|
|
worldStore.worldDialog.visible = false;
|
|
avatarStore.avatarDialog.visible = false;
|
|
groupStore.groupDialog.visible = false;
|
|
instanceStore.hidePreviousInstancesDialogs();
|
|
clearDialogCrumbs();
|
|
}
|
|
|
|
/**
|
|
* @param {Object} data
|
|
* @param {string} data.type
|
|
* @param {string} data.id
|
|
* @param {string?} data.tag
|
|
* @param {string?} data.shortName
|
|
* @returns {boolean}
|
|
*/
|
|
function openDialog(data) {
|
|
const { type } = data;
|
|
const userStore = useUserStore();
|
|
const worldStore = useWorldStore();
|
|
const avatarStore = useAvatarStore();
|
|
const groupStore = useGroupStore();
|
|
const instanceStore = useInstanceStore();
|
|
const isPrevInfo = type === 'previous-instances-info';
|
|
const isPrevList =
|
|
type &&
|
|
type.startsWith('previous-instances-') &&
|
|
type !== 'previous-instances-info';
|
|
const hadActiveDialog =
|
|
dialogCrumbs.value.length > 0 ||
|
|
userStore.userDialog.visible ||
|
|
worldStore.worldDialog.visible ||
|
|
avatarStore.avatarDialog.visible ||
|
|
groupStore.groupDialog.visible ||
|
|
(instanceStore.previousInstancesInfoDialog.visible &&
|
|
!isPrevInfo) ||
|
|
(instanceStore.previousInstancesListDialog.visible && !isPrevList);
|
|
|
|
if (type !== 'user') {
|
|
userStore.userDialog.visible = false;
|
|
}
|
|
if (type !== 'world') {
|
|
worldStore.worldDialog.visible = false;
|
|
}
|
|
if (type !== 'avatar') {
|
|
avatarStore.avatarDialog.visible = false;
|
|
}
|
|
if (type !== 'group') {
|
|
groupStore.groupDialog.visible = false;
|
|
}
|
|
if (!isPrevInfo) {
|
|
instanceStore.previousInstancesInfoDialog.visible = false;
|
|
}
|
|
if (!isPrevList) {
|
|
instanceStore.previousInstancesListDialog.visible = false;
|
|
}
|
|
if (!hadActiveDialog) {
|
|
clearDialogCrumbs();
|
|
}
|
|
pushDialogCrumb(data);
|
|
return hadActiveDialog;
|
|
}
|
|
|
|
// Make sure file drops outside of the screenshot manager don't navigate to the file path dropped.
|
|
// This issue persists on prompts created with prompt(), unfortunately. Not sure how to fix that.
|
|
document.body.addEventListener('drop', function (e) {
|
|
e.preventDefault();
|
|
});
|
|
|
|
function showConsole() {
|
|
AppApi.ShowDevTools();
|
|
if (
|
|
AppDebug.debug ||
|
|
AppDebug.debugWebRequests ||
|
|
AppDebug.debugWebSocket ||
|
|
AppDebug.debugUserDiff
|
|
) {
|
|
return;
|
|
}
|
|
console.log(
|
|
'%cCareful! This might not do what you think.',
|
|
'background-color: red; color: yellow; font-size: 32px; font-weight: bold'
|
|
);
|
|
console.log(
|
|
'%cIf someone told you to copy-paste something here, it can give them access to your account.',
|
|
'font-size: 20px;'
|
|
);
|
|
}
|
|
|
|
watch(
|
|
() => router.currentRoute.value.name,
|
|
(routeName) => {
|
|
if (routeName) {
|
|
const name = String(routeName);
|
|
removeNotify(name);
|
|
if (name === 'notification') {
|
|
notificationStore.unseenNotifications = [];
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
function notifyMenu(index) {
|
|
const currentRouteName = router.currentRoute.value?.name;
|
|
if (
|
|
index !== currentRouteName &&
|
|
!notifiedMenus.value.includes(index)
|
|
) {
|
|
notifiedMenus.value.push(index);
|
|
updateTrayIconNotify();
|
|
}
|
|
}
|
|
|
|
function removeNotify(index) {
|
|
notifiedMenus.value = notifiedMenus.value.filter((i) => i !== index);
|
|
updateTrayIconNotify();
|
|
}
|
|
|
|
function updateTrayIconNotify(force = false) {
|
|
const newState =
|
|
appearanceSettings.notificationIconDot &&
|
|
(notifiedMenus.value.includes('notification') ||
|
|
notifiedMenus.value.includes('friend-log'));
|
|
|
|
if (trayIconNotify.value !== newState || force) {
|
|
trayIconNotify.value = newState;
|
|
if (LINUX) {
|
|
window.electron.setTrayIconNotification(trayIconNotify.value);
|
|
return;
|
|
}
|
|
AppApi.SetTrayIconNotification(trayIconNotify.value);
|
|
}
|
|
}
|
|
updateTrayIconNotify(true);
|
|
|
|
return {
|
|
notifiedMenus,
|
|
shiftHeld,
|
|
dialogCrumbs,
|
|
|
|
notifyMenu,
|
|
removeNotify,
|
|
showConsole,
|
|
updateTrayIconNotify,
|
|
pushDialogCrumb,
|
|
setDialogCrumbLabel,
|
|
jumpDialogCrumb,
|
|
clearDialogCrumbs,
|
|
closeMainDialog,
|
|
openDialog,
|
|
jumpBackDialogCrumb,
|
|
handleBreadcrumbClick
|
|
};
|
|
});
|