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:
pa
2025-07-14 12:00:08 +09:00
committed by GitHub
parent 952fd77ed5
commit f4f78bb5ec
323 changed files with 47745 additions and 43326 deletions

284
src/shared/utils/base/ui.js Normal file
View File

@@ -0,0 +1,284 @@
import { storeToRefs } from 'pinia';
import { useAppearanceSettingsStore } from '../../../stores';
/**
*
* @returns {boolean}
*/
function systemIsDarkMode() {
return window.matchMedia('(prefers-color-scheme: dark)').matches;
}
/**
*
* @param {boolean}isDark
*/
function changeAppDarkStyle(isDark) {
if (isDark) {
AppApi.ChangeTheme(1);
} else {
AppApi.ChangeTheme(0);
}
}
/**
*
* @param {string} themeMode
* @returns
*/
function changeAppThemeStyle(themeMode) {
const themeStyle = {};
switch (themeMode) {
case 'light':
themeStyle.href = '';
break;
case 'dark':
themeStyle.href = '';
break;
case 'darkvanillaold':
themeStyle.href = 'theme.darkvanillaold.css';
break;
case 'darkvanilla':
themeStyle.href = 'theme.darkvanilla.css';
break;
case 'pink':
themeStyle.href = 'theme.pink.css';
break;
case 'material3':
themeStyle.href = 'theme.material3.css';
break;
case 'system':
themeStyle.href = '';
break;
}
/**
* prevents flickering
* giving absolute paths does prevent flickering
* when switching from another dark theme to 'dark' theme
* <del>works on my machine</del>
*/
let filePathPrefix = 'file://vrcx/';
if (LINUX) {
filePathPrefix = './';
}
let $appThemeStyle = document.getElementById('app-theme-style');
if (!$appThemeStyle) {
$appThemeStyle = document.createElement('link');
$appThemeStyle.setAttribute('id', 'app-theme-style');
$appThemeStyle.rel = 'stylesheet';
document.head.appendChild($appThemeStyle);
}
$appThemeStyle.href = themeStyle.href
? `${filePathPrefix}${themeStyle.href}`
: '';
let $appThemeDarkStyle = document.getElementById('app-theme-dark-style');
const darkThemeCssPath = `${filePathPrefix}theme.dark.css`;
if (!$appThemeDarkStyle && themeMode !== 'light') {
if (themeMode === 'system' && !systemIsDarkMode()) {
return;
}
$appThemeDarkStyle = document.createElement('link');
$appThemeDarkStyle.setAttribute('id', 'app-theme-dark-style');
$appThemeDarkStyle.rel = 'stylesheet';
$appThemeDarkStyle.href = darkThemeCssPath;
document.head.insertBefore($appThemeDarkStyle, $appThemeStyle);
} else {
if (themeMode === 'system' && systemIsDarkMode()) {
if ($appThemeDarkStyle.href === darkThemeCssPath) {
return;
}
$appThemeDarkStyle.href = darkThemeCssPath;
} else if (themeMode !== 'light' && themeMode !== 'system') {
if ($appThemeDarkStyle.href === darkThemeCssPath) {
return;
}
$appThemeDarkStyle.href = darkThemeCssPath;
} else {
$appThemeDarkStyle && $appThemeDarkStyle.remove();
}
}
}
/**
* CJK character in Japanese, Korean, Chinese are different
* so change font-family order when users change language to display CJK character correctly
* @param {string} lang
*/
function changeCJKFontsOrder(lang) {
const otherFonts = window
.getComputedStyle(document.body)
.fontFamily.split(',')
.filter((item) => !item.includes('Noto Sans'))
.join(', ');
const notoSans = 'Noto Sans';
const fontFamilies = {
ja_JP: ['JP', 'KR', 'TC', 'SC'],
ko: ['KR', 'JP', 'TC', 'SC'],
zh_TW: ['TC', 'JP', 'KR', 'SC'],
zh_CN: ['SC', 'JP', 'KR', 'TC']
};
if (fontFamilies[lang]) {
const CJKFamily = fontFamilies[lang]
.map((item) => `${notoSans} ${item}`)
.join(', ');
document.body.style.fontFamily = `${CJKFamily}, ${otherFonts}`;
}
}
/**
*
* @param {object} trustColor
*/
function updateTrustColorClasses(trustColor) {
if (document.getElementById('trustColor') !== null) {
document.getElementById('trustColor').outerHTML = '';
}
const style = document.createElement('style');
style.id = 'trustColor';
style.type = 'text/css';
let newCSS = '';
for (const rank in trustColor) {
newCSS += `.x-tag-${rank} { color: ${trustColor[rank]} !important; border-color: ${trustColor[rank]} !important; } `;
}
style.innerHTML = newCSS;
document.getElementsByTagName('head')[0].appendChild(style);
}
function refreshCustomCss() {
if (document.contains(document.getElementById('app-custom-style'))) {
document.getElementById('app-custom-style').remove();
}
AppApi.CustomCssPath().then((customCss) => {
const head = document.head;
if (customCss) {
const $appCustomStyle = document.createElement('link');
$appCustomStyle.setAttribute('id', 'app-custom-style');
$appCustomStyle.rel = 'stylesheet';
$appCustomStyle.href = `file://${customCss}?_=${Date.now()}`;
head.appendChild($appCustomStyle);
}
});
}
function refreshCustomScript() {
if (document.contains(document.getElementById('app-custom-script'))) {
document.getElementById('app-custom-script').remove();
}
AppApi.CustomScriptPath().then((customScript) => {
const head = document.head;
if (customScript) {
const $appCustomScript = document.createElement('script');
$appCustomScript.setAttribute('id', 'app-custom-script');
$appCustomScript.src = `file://${customScript}?_=${Date.now()}`;
head.appendChild($appCustomScript);
}
});
}
/**
*
* @param {number} hue
* @returns {string}
*/
function HueToHex(hue) {
const appSettingsStore = useAppearanceSettingsStore();
const { isDarkMode } = storeToRefs(appSettingsStore);
// this.HSVtoRGB(hue / 65535, .8, .8);
if (isDarkMode.value) {
return HSVtoRGB(hue / 65535, 0.6, 1);
}
return HSVtoRGB(hue / 65535, 1, 0.7);
}
/**
*
* @param {number} h
* @param {number} s
* @param {number} v
* @returns {string}
*/
function HSVtoRGB(h, s, v) {
let r = 0;
let g = 0;
let b = 0;
if (arguments.length === 1) {
s = h.s;
v = h.v;
h = h.h;
}
const i = Math.floor(h * 6);
const f = h * 6 - i;
const p = v * (1 - s);
const q = v * (1 - f * s);
const t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
const red = Math.round(r * 255);
const green = Math.round(g * 255);
const blue = Math.round(b * 255);
const decColor = 0x1000000 + blue + 0x100 * green + 0x10000 * red;
return `#${decColor.toString(16).substr(1)}`;
}
function adjustDialogZ(el) {
let z = 0;
document.querySelectorAll('.v-modal,.el-dialog__wrapper').forEach((v) => {
const _z = Number(v.style.zIndex) || 0;
if (_z && _z > z && v !== el) {
z = _z;
}
});
if (z) {
el.style.zIndex = z + 1;
}
}
export {
systemIsDarkMode,
changeAppDarkStyle,
changeAppThemeStyle,
changeCJKFontsOrder,
updateTrustColorClasses,
refreshCustomCss,
refreshCustomScript,
HueToHex,
HSVtoRGB,
adjustDialogZ
};