Organize bootstrap.js

This commit is contained in:
pa
2025-09-14 16:36:02 +09:00
committed by Natsumi
parent 875459689f
commit b2b8e6ba3f
16 changed files with 221 additions and 192 deletions
+30 -21
View File
@@ -84,10 +84,22 @@
</template> </template>
<script setup> <script setup>
import { onMounted, computed } from 'vue'; import './app.scss';
import { useI18n } from 'vue-i18n';
import { createGlobalStores } from './stores'; import en from 'element-plus/es/locale/lang/en';
import { watchState } from './service/watchState'; import es from 'element-plus/es/locale/lang/es';
import fr from 'element-plus/es/locale/lang/fr';
import hu from 'element-plus/es/locale/lang/hu';
import ja from 'element-plus/es/locale/lang/ja';
import ko from 'element-plus/es/locale/lang/ko';
import pl from 'element-plus/es/locale/lang/pl';
import pt from 'element-plus/es/locale/lang/pt';
import cs from 'element-plus/es/locale/lang/cs';
import ru from 'element-plus/es/locale/lang/ru';
import vi from 'element-plus/es/locale/lang/vi';
import zhCN from 'element-plus/es/locale/lang/zh-cn';
import zhTW from 'element-plus/es/locale/lang/zh-tw';
import th from 'element-plus/es/locale/lang/th';
import Login from './views/Login/Login.vue'; import Login from './views/Login/Login.vue';
import NavMenu from './components/NavMenu.vue'; import NavMenu from './components/NavMenu.vue';
@@ -124,20 +136,17 @@
import VRChatConfigDialog from './views/Settings/dialogs/VRChatConfigDialog.vue'; import VRChatConfigDialog from './views/Settings/dialogs/VRChatConfigDialog.vue';
import PrimaryPasswordDialog from './views/Settings/dialogs/PrimaryPasswordDialog.vue'; import PrimaryPasswordDialog from './views/Settings/dialogs/PrimaryPasswordDialog.vue';
import en from 'element-plus/es/locale/lang/en'; import { onMounted, computed, onBeforeMount } from 'vue';
import es from 'element-plus/es/locale/lang/es'; import { createGlobalStores } from './stores';
import fr from 'element-plus/es/locale/lang/fr'; import { watchState } from './service/watchState';
import hu from 'element-plus/es/locale/lang/hu'; import { useI18n } from 'vue-i18n';
import ja from 'element-plus/es/locale/lang/ja'; import { initNoty } from './plugin/noty';
import ko from 'element-plus/es/locale/lang/ko';
import pl from 'element-plus/es/locale/lang/pl'; console.log(`isLinux: ${LINUX}`);
import pt from 'element-plus/es/locale/lang/pt';
import cs from 'element-plus/es/locale/lang/cs'; const { locale } = useI18n();
import ru from 'element-plus/es/locale/lang/ru';
import vi from 'element-plus/es/locale/lang/vi'; initNoty();
import zhCN from 'element-plus/es/locale/lang/zh-cn';
import zhTW from 'element-plus/es/locale/lang/zh-tw';
import th from 'element-plus/es/locale/lang/th';
const langMap = { const langMap = {
en: en, en: en,
@@ -160,15 +169,15 @@
return langMap[locale.value] || en; return langMap[locale.value] || en;
}); });
const { locale } = useI18n();
const store = createGlobalStores(); const store = createGlobalStores();
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
window.$pinia = store; window.$pinia = store;
} }
store.updateLoop.updateLoop(); onBeforeMount(() => {
store.updateLoop.updateLoop();
});
onMounted(async () => { onMounted(async () => {
store.gameLog.getGameLogTable(); store.gameLog.getGameLogTable();
+12 -16
View File
@@ -5,28 +5,24 @@
// For a copy, see <https://opensource.org/licenses/MIT>. // For a copy, see <https://opensource.org/licenses/MIT>.
import { createApp } from 'vue'; import { createApp } from 'vue';
import './bootstrap';
import { i18n } from './plugin/i18n';
import App from './App.vue';
import { pinia } from './stores'; import { pinia } from './stores';
import { initPlugins } from './plugin';
import { i18n } from './plugin/i18n';
import { initComponents } from './plugin/components';
import ElementPlus from 'element-plus'; import ElementPlus from 'element-plus';
import App from './App.vue';
import './app.scss'; initPlugins();
import registerComponents from './plugin/components';
console.log(`isLinux: ${LINUX}`);
// #region | Hey look it's most of VRCX! // #region | Hey look it's most of VRCX!
// prompt: 'Please clean up and refactor the VRCX codebase.'
const $app = createApp(App); const app = createApp(App);
$app.use(pinia);
$app.use(i18n);
$app.use(ElementPlus);
registerComponents($app); app.use(pinia);
app.use(i18n);
app.use(ElementPlus);
initComponents(app);
$app.mount('#root'); app.mount('#root');
window.$app = $app; window.$app = app;
export { $app };
+13 -4
View File
@@ -12,10 +12,19 @@
@use './assets/scss/animated-emoji.scss'; @use './assets/scss/animated-emoji.scss';
@use 'element-plus/theme-chalk/src/index.scss' as *; @use 'element-plus/theme-chalk/src/index.scss' as *;
@import 'element-plus/theme-chalk/src/dark/css-vars.scss'; @use '@fontsource/noto-sans-kr/korean.css';
@import 'animate.css/animate.min.css'; @use '@fontsource/noto-sans-jp/japanese.css';
@import 'noty/lib/noty.css'; @use '@fontsource/noto-sans-sc/chinese-simplified.css';
@import 'remixicon/fonts/remixicon.css'; @use '@fontsource/noto-sans-tc/chinese-traditional.css';
@use '@fontsource/noto-sans-kr';
@use '@fontsource/noto-sans-jp';
@use '@fontsource/noto-sans-sc';
@use '@fontsource/noto-sans-tc';
@use 'element-plus/theme-chalk/src/dark/css-vars.scss';
@use 'animate.css/animate.min.css';
@use 'noty/lib/noty.css';
@use 'remixicon/fonts/remixicon.css';
.color-palettes { .color-palettes {
background: #409eff; background: #409eff;
-96
View File
@@ -1,96 +0,0 @@
import '@fontsource/noto-sans-kr/korean.css';
import '@fontsource/noto-sans-jp/japanese.css';
import '@fontsource/noto-sans-sc/chinese-simplified.css';
import '@fontsource/noto-sans-tc/chinese-traditional.css';
import '@fontsource/noto-sans-kr';
import '@fontsource/noto-sans-jp';
import '@fontsource/noto-sans-sc';
import '@fontsource/noto-sans-tc';
import configRepository from './service/config';
import vrcxJsonStorage from './service/jsonStorage';
import {
changeAppDarkStyle,
changeAppThemeStyle,
refreshCustomCss,
refreshCustomScript,
systemIsDarkMode
} from './shared/utils/base/ui';
import { i18n } from './plugin/i18n';
import { initNoty } from './plugin/noty';
import './plugin/ipc';
import './plugin/dayjs';
initNoty(false);
configRepository.init();
AppApi.SetUserAgent();
// prevent flicker on login page
function setLoginContainerStyle(isDarkMode) {
const loginContainerStyle = document.createElement('style');
loginContainerStyle.id = 'login-container-style';
loginContainerStyle.type = 'text/css';
const backgroundColor = isDarkMode ? '#101010' : '#ffffff';
const inputBackgroundColor = isDarkMode ? '#333333' : '#ffffff';
const inputBorder = isDarkMode ? '1px solid #3b3b3b' : '1px solid #DCDFE6';
loginContainerStyle.innerHTML = `
.x-login-container {
background-color: ${backgroundColor} !important;
transition: background-color 0.3s ease;
}
.x-login-container .el-input__inner {
background-color: ${inputBackgroundColor} !important;
border: ${inputBorder} !important;
transition: background-color 0.3s ease, border-color 0.3s ease;
}
`;
document.head.insertBefore(loginContainerStyle, document.head.firstChild);
}
async function getThemeMode() {
const initThemeMode = await configRepository.getString(
'VRCX_ThemeMode',
'system'
);
let isDarkMode;
if (initThemeMode === 'light') {
isDarkMode = false;
} else if (initThemeMode === 'system') {
isDarkMode = systemIsDarkMode();
} else {
isDarkMode = true;
}
return { initThemeMode, isDarkMode };
}
try {
// @ts-ignore
i18n.locale = await configRepository.getString('VRCX_appLanguage', 'en');
const { initThemeMode, isDarkMode } = await getThemeMode();
setLoginContainerStyle(isDarkMode);
changeAppDarkStyle(isDarkMode);
changeAppThemeStyle(initThemeMode);
} catch (error) {
console.error('Error initializing locale and theme:', error);
}
refreshCustomCss();
refreshCustomScript();
new vrcxJsonStorage(VRCXStorage);
// some workaround for failing to get voice list first run
speechSynthesis.getVoices();
+1 -1
View File
@@ -11,7 +11,7 @@ import SimpleSwitch from '../components/SimpleSwitch.vue';
import Timer from '../components/Timer.vue'; import Timer from '../components/Timer.vue';
import DataTable from '../components/DataTable.vue'; import DataTable from '../components/DataTable.vue';
export default function registerComponents(app) { export function initComponents(app) {
app.component('SimpleSwitch', SimpleSwitch); app.component('SimpleSwitch', SimpleSwitch);
app.component('Location', Location); app.component('Location', Location);
app.component('Timer', Timer); app.component('Timer', Timer);
+10 -4
View File
@@ -3,8 +3,14 @@ import duration from 'dayjs/plugin/duration';
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'; import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
import timezone from 'dayjs/plugin/timezone'; import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc'; import utc from 'dayjs/plugin/utc';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.extend(duration); export function initDayjs() {
dayjs.extend(utc); dayjs.extend(duration);
dayjs.extend(timezone); dayjs.extend(utc);
dayjs.extend(isSameOrAfter); dayjs.extend(timezone);
dayjs.extend(isSameOrAfter);
dayjs.extend(localizedFormat);
dayjs.extend(customParseFormat);
}
+13
View File
@@ -0,0 +1,13 @@
import { initInteropApi } from './interopApi';
import { initDayjs } from './dayjs';
import { initNoty } from './noty';
import { initUi } from './ui';
export async function initPlugins(isVrOverlay = false) {
await initInteropApi(isVrOverlay);
if (!isVrOverlay) {
await initUi();
}
initDayjs();
initNoty(isVrOverlay);
}
+42
View File
@@ -0,0 +1,42 @@
// @ts-nocheck
import InteropApi from '../ipc-electron/interopApi.js';
import configRepository from '../service/config';
import vrcxJsonStorage from '../service/jsonStorage';
export async function initInteropApi(isVrOverlay = false) {
if (isVrOverlay) {
if (WINDOWS) {
await CefSharp.BindObjectAsync('AppApiVr');
} else {
// @ts-ignore
window.AppApiVr = InteropApi.AppApiVrElectron;
}
} else {
// #region | Init Cef C# bindings
if (WINDOWS) {
await CefSharp.BindObjectAsync(
'AppApi',
'WebApi',
'VRCXStorage',
'SQLite',
'LogWatcher',
'Discord',
'AssetBundleManager'
);
} else {
window.AppApi = InteropApi.AppApiElectron;
window.WebApi = InteropApi.WebApi;
window.VRCXStorage = InteropApi.VRCXStorage;
window.SQLite = InteropApi.SQLite;
window.LogWatcher = InteropApi.LogWatcher;
window.Discord = InteropApi.Discord;
window.AssetBundleManager = InteropApi.AssetBundleManager;
window.AppApiVrElectron = InteropApi.AppApiVrElectron;
}
configRepository.init();
new vrcxJsonStorage(VRCXStorage);
AppApi.SetUserAgent();
}
}
-24
View File
@@ -1,24 +0,0 @@
// @ts-nocheck
import InteropApi from '../ipc-electron/interopApi.js';
// #region | Init Cef C# bindings
if (WINDOWS) {
await CefSharp.BindObjectAsync(
'AppApi',
'WebApi',
'VRCXStorage',
'SQLite',
'LogWatcher',
'Discord',
'AssetBundleManager'
);
} else {
window.AppApi = InteropApi.AppApiElectron;
window.WebApi = InteropApi.WebApi;
window.VRCXStorage = InteropApi.VRCXStorage;
window.SQLite = InteropApi.SQLite;
window.LogWatcher = InteropApi.LogWatcher;
window.Discord = InteropApi.Discord;
window.AssetBundleManager = InteropApi.AssetBundleManager;
window.AppApiVrElectron = InteropApi.AppApiVrElectron;
}
+1 -3
View File
@@ -1,6 +1,6 @@
import Noty from 'noty'; import Noty from 'noty';
function initNoty(isVrOverlay) { export function initNoty(isVrOverlay = false) {
if (isVrOverlay) { if (isVrOverlay) {
Noty.overrideDefaults({ Noty.overrideDefaults({
animation: { animation: {
@@ -23,5 +23,3 @@ function initNoty(isVrOverlay) {
}); });
} }
} }
export { initNoty };
+32
View File
@@ -0,0 +1,32 @@
import configRepository from '../service/config';
import {
changeAppDarkStyle,
changeAppThemeStyle,
refreshCustomCss,
refreshCustomScript,
setLoginContainerStyle,
getThemeMode
} from '../shared/utils/base/ui';
import { i18n } from './i18n';
export async function initUi() {
try {
// @ts-ignore
i18n.locale = await configRepository.getString(
'VRCX_appLanguage',
'en'
);
const { initThemeMode, isDarkMode } =
await getThemeMode(configRepository);
setLoginContainerStyle(isDarkMode);
changeAppDarkStyle(isDarkMode);
changeAppThemeStyle(initThemeMode);
} catch (error) {
console.error('Error initializing locale and theme:', error);
}
refreshCustomCss();
refreshCustomScript();
}
-5
View File
@@ -1,11 +1,6 @@
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import customParseFormat from 'dayjs/plugin/customParseFormat';
import { useAppearanceSettingsStore } from '../../../stores'; import { useAppearanceSettingsStore } from '../../../stores';
dayjs.extend(localizedFormat);
dayjs.extend(customParseFormat);
/** /**
* @param {string} dateStr * @param {string} dateStr
* @param {'long'|'short'} format * @param {'long'|'short'} format
+48 -1
View File
@@ -222,6 +222,51 @@ function changeHtmlLangAttribute(language) {
htmlElement.setAttribute('lang', language); htmlElement.setAttribute('lang', language);
} }
// prevent flicker on login page
function setLoginContainerStyle(isDarkMode) {
const loginContainerStyle = document.createElement('style');
loginContainerStyle.id = 'login-container-style';
loginContainerStyle.type = 'text/css';
const backgroundColor = isDarkMode ? '#101010' : '#ffffff';
const inputBackgroundColor = isDarkMode ? '#333333' : '#ffffff';
const inputBorder = isDarkMode ? '1px solid #3b3b3b' : '1px solid #DCDFE6';
loginContainerStyle.innerHTML = `
.x-login-container {
background-color: ${backgroundColor} !important;
transition: background-color 0.3s ease;
}
.x-login-container .el-input__inner {
background-color: ${inputBackgroundColor} !important;
border: ${inputBorder} !important;
transition: background-color 0.3s ease, border-color 0.3s ease;
}
`;
document.head.insertBefore(loginContainerStyle, document.head.firstChild);
}
async function getThemeMode(configRepository) {
const initThemeMode = await configRepository.getString(
'VRCX_ThemeMode',
'system'
);
let isDarkMode;
if (initThemeMode === 'light') {
isDarkMode = false;
} else if (initThemeMode === 'system') {
isDarkMode = systemIsDarkMode();
} else {
isDarkMode = true;
}
return { initThemeMode, isDarkMode };
}
export { export {
systemIsDarkMode, systemIsDarkMode,
changeAppDarkStyle, changeAppDarkStyle,
@@ -232,5 +277,7 @@ export {
HueToHex, HueToHex,
HSVtoRGB, HSVtoRGB,
getNextDialogIndex, getNextDialogIndex,
changeHtmlLangAttribute changeHtmlLangAttribute,
setLoginContainerStyle,
getThemeMode
}; };
+2
View File
@@ -185,6 +185,8 @@ export const useNotificationsSettingsStore = defineStore(
}, 5000); }, 5000);
} }
} }
// some workaround for failing to get voice list first run
speechSynthesis.getVoices();
initNotificationsSettings(); initNotificationsSettings();
+5 -14
View File
@@ -5,22 +5,13 @@
// For a copy, see <https://opensource.org/licenses/MIT>. // For a copy, see <https://opensource.org/licenses/MIT>.
import { createApp } from 'vue'; import { createApp } from 'vue';
import { initNoty } from '../plugin/noty'; import { initPlugins } from '../plugin';
import { i18n } from '../plugin/i18n'; import { i18n } from '../plugin/i18n';
import InteropApi from '../ipc-electron/interopApi.js';
import Vr from './Vr.vue'; import Vr from './Vr.vue';
initNoty(true); initPlugins(true);
if (WINDOWS) { const vr = createApp(Vr);
await CefSharp.BindObjectAsync('AppApiVr'); vr.use(i18n);
} else {
// @ts-ignore
window.AppApiVr = InteropApi.AppApiVrElectron;
}
const $app = createApp(Vr); vr.mount('#root');
$app.use(i18n);
$app.mount('#root');
+12 -3
View File
@@ -10,9 +10,18 @@
@use '../assets/scss/flags.scss'; @use '../assets/scss/flags.scss';
@import 'animate.css/animate.min.css'; @use '@fontsource/noto-sans-kr/korean.css';
@import 'noty/lib/noty.css'; @use '@fontsource/noto-sans-jp/japanese.css';
@import 'remixicon/fonts/remixicon.css'; @use '@fontsource/noto-sans-sc/chinese-simplified.css';
@use '@fontsource/noto-sans-tc/chinese-traditional.css';
@use '@fontsource/noto-sans-kr';
@use '@fontsource/noto-sans-jp';
@use '@fontsource/noto-sans-sc';
@use '@fontsource/noto-sans-tc';
@use 'animate.css/animate.min.css';
@use 'noty/lib/noty.css';
@use 'remixicon/fonts/remixicon.css';
/* /*
마지노선인듯 마지노선인듯