mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-22 08:13:52 +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:
59
src/shared/utils/base/array.js
Normal file
59
src/shared/utils/base/array.js
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
*
|
||||
* @param {array} array
|
||||
* @param {*} item
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function removeFromArray(array, item) {
|
||||
const { length } = array;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
if (array[i] === item) {
|
||||
array.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {array} a
|
||||
* @param {array} b
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function arraysMatch(a, b) {
|
||||
if (!Array.isArray(a) || !Array.isArray(b)) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
a.length === b.length &&
|
||||
a.every(
|
||||
(element, index) =>
|
||||
JSON.stringify(element) === JSON.stringify(b[index])
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {array} array
|
||||
* @param {number} fromIndex
|
||||
* @param {number} toIndex
|
||||
* @returns {void}
|
||||
*/
|
||||
function moveArrayItem(array, fromIndex, toIndex) {
|
||||
if (!Array.isArray(array) || fromIndex === toIndex) {
|
||||
return;
|
||||
}
|
||||
if (fromIndex < 0 || fromIndex >= array.length) {
|
||||
return;
|
||||
}
|
||||
if (toIndex < 0 || toIndex >= array.length) {
|
||||
return;
|
||||
}
|
||||
const item = array[fromIndex];
|
||||
array.splice(fromIndex, 1);
|
||||
array.splice(toIndex, 0, item);
|
||||
}
|
||||
|
||||
export { removeFromArray, arraysMatch, moveArrayItem };
|
||||
80
src/shared/utils/base/date.js
Normal file
80
src/shared/utils/base/date.js
Normal file
@@ -0,0 +1,80 @@
|
||||
import { useAppearanceSettingsStore } from '../../../stores';
|
||||
|
||||
/**
|
||||
* @param {string} dateStr
|
||||
* @param {'long'|'short'} format
|
||||
* @returns {string}
|
||||
*/
|
||||
function formatDateFilter(dateStr, format) {
|
||||
const appearance = useAppearanceSettingsStore();
|
||||
const {
|
||||
dtIsoFormat: isoFormat,
|
||||
dtHour12: hour12,
|
||||
currentCulture
|
||||
} = appearance;
|
||||
|
||||
if (!dateStr) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
const dt = new Date(dateStr);
|
||||
if (isNaN(dt.getTime())) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
function padZero(num) {
|
||||
return String(num).padStart(2, '0');
|
||||
}
|
||||
|
||||
function toIsoLong(date) {
|
||||
const y = date.getFullYear();
|
||||
const m = padZero(date.getMonth() + 1);
|
||||
const d = padZero(date.getDate());
|
||||
const hh = padZero(date.getHours());
|
||||
const mm = padZero(date.getMinutes());
|
||||
const ss = padZero(date.getSeconds());
|
||||
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
|
||||
}
|
||||
|
||||
function toLocalShort(date) {
|
||||
return date
|
||||
.toLocaleDateString(isoFormat ? 'en-nz' : currentCulture, {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
hourCycle: hour12 ? 'h12' : 'h23'
|
||||
})
|
||||
.replace(' AM', 'am')
|
||||
.replace(' PM', 'pm')
|
||||
.replace(',', '');
|
||||
}
|
||||
|
||||
if (isoFormat) {
|
||||
if (format === 'long') {
|
||||
return toIsoLong(dt);
|
||||
}
|
||||
if (format === 'short') {
|
||||
return toLocalShort(dt);
|
||||
}
|
||||
} else {
|
||||
if (format === 'long') {
|
||||
return dt.toLocaleDateString(currentCulture, {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
second: 'numeric',
|
||||
hourCycle: hour12 ? 'h12' : 'h23'
|
||||
});
|
||||
}
|
||||
if (format === 'short') {
|
||||
return toLocalShort(dt);
|
||||
}
|
||||
}
|
||||
|
||||
return '-';
|
||||
}
|
||||
|
||||
export { formatDateFilter };
|
||||
102
src/shared/utils/base/devtool.js
Normal file
102
src/shared/utils/base/devtool.js
Normal file
@@ -0,0 +1,102 @@
|
||||
import { useAvatarStore, useWorldStore } from '../../../stores';
|
||||
import { compareUnityVersion } from '../avatar';
|
||||
import {
|
||||
extractFileId,
|
||||
extractFileVersion,
|
||||
extractVariantVersion
|
||||
} from '../common';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} input
|
||||
* @returns {Promise<string|null>}
|
||||
*/
|
||||
async function getBundleLocation(input) {
|
||||
const worldStore = useWorldStore();
|
||||
const avatarStore = useAvatarStore();
|
||||
let unityPackage;
|
||||
let unityPackages;
|
||||
let assetUrl = input;
|
||||
let variant = '';
|
||||
if (assetUrl) {
|
||||
// continue
|
||||
} else if (
|
||||
avatarStore.avatarDialog.visible &&
|
||||
avatarStore.avatarDialog.ref.unityPackages.length > 0
|
||||
) {
|
||||
unityPackages = avatarStore.avatarDialog.ref.unityPackages;
|
||||
for (let i = unityPackages.length - 1; i > -1; i--) {
|
||||
unityPackage = unityPackages[i];
|
||||
if (
|
||||
unityPackage.variant &&
|
||||
unityPackage.variant !== 'standard' &&
|
||||
unityPackage.variant !== 'security'
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
unityPackage.platform === 'standalonewindows' &&
|
||||
compareUnityVersion(unityPackage.unitySortNumber)
|
||||
) {
|
||||
assetUrl = unityPackage.assetUrl;
|
||||
if (unityPackage.variant !== 'standard') {
|
||||
variant = unityPackage.variant;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
avatarStore.avatarDialog.visible &&
|
||||
avatarStore.avatarDialog.ref.assetUrl
|
||||
) {
|
||||
assetUrl = avatarStore.avatarDialog.ref.assetUrl;
|
||||
} else if (
|
||||
worldStore.worldDialog.visible &&
|
||||
worldStore.worldDialog.ref.unityPackages.length > 0
|
||||
) {
|
||||
unityPackages = worldStore.worldDialog.ref.unityPackages;
|
||||
for (let i = unityPackages.length - 1; i > -1; i--) {
|
||||
unityPackage = unityPackages[i];
|
||||
if (
|
||||
unityPackage.platform === 'standalonewindows' &&
|
||||
compareUnityVersion(unityPackage.unitySortNumber)
|
||||
) {
|
||||
assetUrl = unityPackage.assetUrl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
worldStore.worldDialog.visible &&
|
||||
worldStore.worldDialog.ref.assetUrl
|
||||
) {
|
||||
assetUrl = worldStore.worldDialog.ref.assetUrl;
|
||||
}
|
||||
if (!assetUrl) {
|
||||
return null;
|
||||
}
|
||||
const fileId = extractFileId(assetUrl);
|
||||
const fileVersion = parseInt(extractFileVersion(assetUrl), 10);
|
||||
const variantVersion = parseInt(extractVariantVersion(assetUrl), 10);
|
||||
const assetLocation = await AssetBundleManager.GetVRChatCacheFullLocation(
|
||||
fileId,
|
||||
fileVersion,
|
||||
variant,
|
||||
variantVersion
|
||||
);
|
||||
const cacheInfo = await AssetBundleManager.CheckVRChatCache(
|
||||
fileId,
|
||||
fileVersion,
|
||||
variant,
|
||||
variantVersion
|
||||
);
|
||||
let inCache = false;
|
||||
if (cacheInfo.Item1 > 0) {
|
||||
inCache = true;
|
||||
}
|
||||
console.log(`InCache: ${inCache}`);
|
||||
const fullAssetLocation = `${assetLocation}\\__data`;
|
||||
console.log(fullAssetLocation);
|
||||
return fullAssetLocation;
|
||||
}
|
||||
|
||||
export { getBundleLocation };
|
||||
97
src/shared/utils/base/format.js
Normal file
97
src/shared/utils/base/format.js
Normal file
@@ -0,0 +1,97 @@
|
||||
import { escapeTag } from './string';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} sec
|
||||
* @param {boolean} isNeedSeconds
|
||||
* @returns {string}
|
||||
*/
|
||||
function timeToText(sec, isNeedSeconds = false) {
|
||||
let n = Number(sec);
|
||||
if (isNaN(n)) {
|
||||
return escapeTag(sec);
|
||||
}
|
||||
n = Math.floor(n / 1000);
|
||||
const arr = [];
|
||||
if (n < 0) {
|
||||
n = -n;
|
||||
}
|
||||
if (n >= 86400) {
|
||||
arr.push(`${Math.floor(n / 86400)}d`);
|
||||
n %= 86400;
|
||||
}
|
||||
if (n >= 3600) {
|
||||
arr.push(`${Math.floor(n / 3600)}h`);
|
||||
n %= 3600;
|
||||
}
|
||||
if (n >= 60) {
|
||||
arr.push(`${Math.floor(n / 60)}m`);
|
||||
n %= 60;
|
||||
}
|
||||
if (isNeedSeconds || (arr.length === 0 && n < 60)) {
|
||||
arr.push(`${n}s`);
|
||||
}
|
||||
return arr.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} duration
|
||||
* @returns {string}
|
||||
*/
|
||||
function formatSeconds(duration) {
|
||||
const pad = function (num, size) {
|
||||
return `000${num}`.slice(size * -1);
|
||||
},
|
||||
time = parseFloat(duration).toFixed(3),
|
||||
hours = Math.floor(time / 60 / 60),
|
||||
minutes = Math.floor(time / 60) % 60,
|
||||
seconds = Math.floor(time - minutes * 60);
|
||||
let hoursOut = '';
|
||||
if (hours > '0') {
|
||||
hoursOut = `${pad(hours, 2)}:`;
|
||||
}
|
||||
return `${hoursOut + pad(minutes, 2)}:${pad(seconds, 2)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} duration
|
||||
* @returns {number}
|
||||
*/
|
||||
function convertYoutubeTime(duration) {
|
||||
let a = duration.match(/\d+/g);
|
||||
if (
|
||||
duration.indexOf('M') >= 0 &&
|
||||
duration.indexOf('H') === -1 &&
|
||||
duration.indexOf('S') === -1
|
||||
) {
|
||||
a = [0, a[0], 0];
|
||||
}
|
||||
if (duration.indexOf('H') >= 0 && duration.indexOf('M') === -1) {
|
||||
a = [a[0], 0, a[1]];
|
||||
}
|
||||
if (
|
||||
duration.indexOf('H') >= 0 &&
|
||||
duration.indexOf('M') === -1 &&
|
||||
duration.indexOf('S') === -1
|
||||
) {
|
||||
a = [a[0], 0, 0];
|
||||
}
|
||||
let length = 0;
|
||||
if (a.length === 3) {
|
||||
length += parseInt(a[0], 10) * 3600;
|
||||
length += parseInt(a[1], 10) * 60;
|
||||
length += parseInt(a[2], 10);
|
||||
}
|
||||
if (a.length === 2) {
|
||||
length += parseInt(a[0], 10) * 60;
|
||||
length += parseInt(a[1], 10);
|
||||
}
|
||||
if (a.length === 1) {
|
||||
length += parseInt(a[0], 10);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
export { timeToText, formatSeconds, convertYoutubeTime };
|
||||
105
src/shared/utils/base/string.js
Normal file
105
src/shared/utils/base/string.js
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
*
|
||||
* @param {string} tag
|
||||
* @returns {string}
|
||||
*/
|
||||
function escapeTag(tag) {
|
||||
const s = String(tag);
|
||||
return s.replace(/["&'<>]/g, (c) => `&#${c.charCodeAt(0)};`);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} obj
|
||||
* @returns {object}
|
||||
*/
|
||||
function escapeTagRecursive(obj) {
|
||||
if (typeof obj === 'string') {
|
||||
return escapeTag(obj);
|
||||
}
|
||||
if (typeof obj === 'object') {
|
||||
for (const key in obj) {
|
||||
obj[key] = escapeTagRecursive(obj[key]);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} text
|
||||
* @returns {string}
|
||||
*/
|
||||
function textToHex(text) {
|
||||
const s = String(text);
|
||||
return s
|
||||
.split('')
|
||||
.map((c) => c.charCodeAt(0).toString(16))
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} num
|
||||
* @returns {string}
|
||||
*/
|
||||
function commaNumber(num) {
|
||||
if (!num) {
|
||||
return '0';
|
||||
}
|
||||
const s = String(Number(num));
|
||||
return s.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {string} search
|
||||
* @param {object} comparer
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function localeIncludes(str, search, comparer) {
|
||||
// These checks are stolen from https://stackoverflow.com/a/69623589/11030436
|
||||
if (search === '') {
|
||||
return true;
|
||||
} else if (!str || !search) {
|
||||
return false;
|
||||
}
|
||||
const strObj = String(str);
|
||||
const searchObj = String(search);
|
||||
|
||||
if (strObj.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (searchObj.length > strObj.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now simply loop through each substring and compare them
|
||||
for (let i = 0; i < str.length - searchObj.length + 1; i++) {
|
||||
const substr = strObj.substring(i, i + searchObj.length);
|
||||
if (comparer.compare(substr, searchObj) === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} text
|
||||
* @returns {string}
|
||||
*/
|
||||
function changeLogRemoveLinks(text) {
|
||||
return text.replace(/([^!])\[[^\]]+\]\([^)]+\)/g, '$1');
|
||||
}
|
||||
|
||||
export {
|
||||
escapeTag,
|
||||
escapeTagRecursive,
|
||||
textToHex,
|
||||
commaNumber,
|
||||
localeIncludes,
|
||||
changeLogRemoveLinks
|
||||
};
|
||||
284
src/shared/utils/base/ui.js
Normal file
284
src/shared/utils/base/ui.js
Normal 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
|
||||
};
|
||||
Reference in New Issue
Block a user