lint: apply pretty import

This commit is contained in:
pa
2025-10-15 09:08:38 +09:00
committed by Natsumi
parent bed76e0ad8
commit afbb6dfa47
203 changed files with 3502 additions and 1441 deletions

View File

@@ -9,5 +9,9 @@
"omnisharp.useModernNet": false, "omnisharp.useModernNet": false,
"[csharp]": { "[csharp]": {
"editor.defaultFormatter": "ms-dotnettools.csharp" "editor.defaultFormatter": "ms-dotnettools.csharp"
} },
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": ["javascript", "vue", "html"]
} }

View File

@@ -1,7 +1,10 @@
import { defineConfig } from 'eslint/config';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import globals from 'globals';
import js from '@eslint/js'; import js from '@eslint/js';
import pluginVue from 'eslint-plugin-vue'; import pluginVue from 'eslint-plugin-vue';
import { defineConfig } from 'eslint/config'; import prettyImport from '@kamiya4047/eslint-plugin-pretty-import';
import globals from 'globals';
export default defineConfig([ export default defineConfig([
{ {
@@ -69,5 +72,19 @@ export default defineConfig([
'vue/no-v-text-v-html-on-component': 'off', 'vue/no-v-text-v-html-on-component': 'off',
'vue/no-use-v-if-with-v-for': 'warn' 'vue/no-use-v-if-with-v-for': 'warn'
} }
} },
{
plugins: { 'pretty-import': prettyImport },
rules: {
'pretty-import/separate-type-imports': 'warn',
'pretty-import/sort-import-groups': [
'warn',
{
groupStyleImports: true
}
],
'pretty-import/sort-import-names': 'warn'
}
},
eslintPluginPrettierRecommended
]); ]);

2516
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -38,6 +38,7 @@
"@fontsource/noto-sans-kr": "^5.2.8", "@fontsource/noto-sans-kr": "^5.2.8",
"@fontsource/noto-sans-sc": "^5.2.8", "@fontsource/noto-sans-sc": "^5.2.8",
"@fontsource/noto-sans-tc": "^5.2.8", "@fontsource/noto-sans-tc": "^5.2.8",
"@kamiya4047/eslint-plugin-pretty-import": "^0.1.6",
"@sentry/vite-plugin": "^4.4.0", "@sentry/vite-plugin": "^4.4.0",
"@sentry/vue": "^10.19.0", "@sentry/vue": "^10.19.0",
"@types/jest": "^30.0.0", "@types/jest": "^30.0.0",
@@ -55,6 +56,7 @@
"esbuild-jest": "^0.5.0", "esbuild-jest": "^0.5.0",
"eslint": "^9.37.0", "eslint": "^9.37.0",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-vue": "^9.33.0", "eslint-plugin-vue": "^9.33.0",
"globals": "^16.4.0", "globals": "^16.4.0",
"jest": "^30.2.0", "jest": "^30.2.0",

View File

@@ -91,8 +91,11 @@
</template> </template>
<script setup> <script setup>
import './app.scss'; import { computed, onBeforeMount, onMounted } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import cs from 'element-plus/es/locale/lang/cs';
import en from 'element-plus/es/locale/lang/en'; import en from 'element-plus/es/locale/lang/en';
import es from 'element-plus/es/locale/lang/es'; import es from 'element-plus/es/locale/lang/es';
import fr from 'element-plus/es/locale/lang/fr'; import fr from 'element-plus/es/locale/lang/fr';
@@ -101,55 +104,52 @@
import ko from 'element-plus/es/locale/lang/ko'; import ko from 'element-plus/es/locale/lang/ko';
import pl from 'element-plus/es/locale/lang/pl'; import pl from 'element-plus/es/locale/lang/pl';
import pt from 'element-plus/es/locale/lang/pt'; 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 ru from 'element-plus/es/locale/lang/ru';
import th from 'element-plus/es/locale/lang/th';
import vi from 'element-plus/es/locale/lang/vi'; import vi from 'element-plus/es/locale/lang/vi';
import zhCN from 'element-plus/es/locale/lang/zh-cn'; import zhCN from 'element-plus/es/locale/lang/zh-cn';
import zhTW from 'element-plus/es/locale/lang/zh-tw'; 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 { createGlobalStores, useAppearanceSettingsStore } from './stores';
import NavMenu from './components/NavMenu.vue'; import { initNoty } from './plugin/noty';
import MacOSTitleBar from './components/TitleBar/MacOSTitleBar.vue'; import { watchState } from './service/watchState';
import Sidebar from './views/Sidebar/Sidebar.vue';
import Feed from './views/Feed/Feed.vue';
import GameLog from './views/GameLog/GameLog.vue';
import PlayerList from './views/PlayerList/PlayerList.vue';
import Search from './views/Search/Search.vue';
import Favorites from './views/Favorites/Favorites.vue';
import FriendLog from './views/FriendLog/FriendLog.vue';
import Moderation from './views/Moderation/Moderation.vue';
import Notification from './views/Notifications/Notification.vue';
import FriendList from './views/FriendList/FriendList.vue';
import Charts from './views/Charts/Charts.vue';
import Tools from './views/Tools/Tools.vue';
import Profile from './views/Profile/Profile.vue';
import Settings from './views/Settings/Settings.vue';
import UserDialog from './components/dialogs/UserDialog/UserDialog.vue';
import WorldDialog from './components/dialogs/WorldDialog/WorldDialog.vue';
import AvatarDialog from './components/dialogs/AvatarDialog/AvatarDialog.vue'; import AvatarDialog from './components/dialogs/AvatarDialog/AvatarDialog.vue';
import GroupDialog from './components/dialogs/GroupDialog/GroupDialog.vue';
import GroupMemberModerationDialog from './components/dialogs/GroupDialog/GroupMemberModerationDialog.vue';
import FullscreenImagePreview from './components/FullscreenImagePreview.vue';
import PreviousInstancesInfoDialog from './components/dialogs/PreviousInstancesDialog/PreviousInstancesInfoDialog.vue';
import LaunchDialog from './components/dialogs/LaunchDialog.vue';
import LaunchOptionsDialog from './views/Settings/dialogs/LaunchOptionsDialog.vue';
import FriendImportDialog from './views/Favorites/dialogs/FriendImportDialog.vue';
import WorldImportDialog from './views/Favorites/dialogs/WorldImportDialog.vue';
import AvatarImportDialog from './views/Favorites/dialogs/AvatarImportDialog.vue'; import AvatarImportDialog from './views/Favorites/dialogs/AvatarImportDialog.vue';
import Charts from './views/Charts/Charts.vue';
import ChooseFavoriteGroupDialog from './components/dialogs/ChooseFavoriteGroupDialog.vue'; import ChooseFavoriteGroupDialog from './components/dialogs/ChooseFavoriteGroupDialog.vue';
import EditInviteMessageDialog from './views/Profile/dialogs/EditInviteMessageDialog.vue'; import EditInviteMessageDialog from './views/Profile/dialogs/EditInviteMessageDialog.vue';
import Favorites from './views/Favorites/Favorites.vue';
import Feed from './views/Feed/Feed.vue';
import FriendImportDialog from './views/Favorites/dialogs/FriendImportDialog.vue';
import FriendList from './views/FriendList/FriendList.vue';
import FriendLog from './views/FriendLog/FriendLog.vue';
import FullscreenImagePreview from './components/FullscreenImagePreview.vue';
import GameLog from './views/GameLog/GameLog.vue';
import GroupDialog from './components/dialogs/GroupDialog/GroupDialog.vue';
import GroupMemberModerationDialog from './components/dialogs/GroupDialog/GroupMemberModerationDialog.vue';
import LaunchDialog from './components/dialogs/LaunchDialog.vue';
import LaunchOptionsDialog from './views/Settings/dialogs/LaunchOptionsDialog.vue';
import Login from './views/Login/Login.vue';
import MacOSTitleBar from './components/TitleBar/MacOSTitleBar.vue';
import Moderation from './views/Moderation/Moderation.vue';
import NavMenu from './components/NavMenu.vue';
import Notification from './views/Notifications/Notification.vue';
import PlayerList from './views/PlayerList/PlayerList.vue';
import PreviousInstancesInfoDialog from './components/dialogs/PreviousInstancesDialog/PreviousInstancesInfoDialog.vue';
import PrimaryPasswordDialog from './views/Settings/dialogs/PrimaryPasswordDialog.vue';
import Profile from './views/Profile/Profile.vue';
import Search from './views/Search/Search.vue';
import Settings from './views/Settings/Settings.vue';
import Sidebar from './views/Sidebar/Sidebar.vue';
import Tools from './views/Tools/Tools.vue';
import UserDialog from './components/dialogs/UserDialog/UserDialog.vue';
import VRCXUpdateDialog from './components/dialogs/VRCXUpdateDialog.vue'; import VRCXUpdateDialog from './components/dialogs/VRCXUpdateDialog.vue';
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 WorldDialog from './components/dialogs/WorldDialog/WorldDialog.vue';
import WorldImportDialog from './views/Favorites/dialogs/WorldImportDialog.vue';
import { onMounted, computed, onBeforeMount } from 'vue'; import './app.scss';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { createGlobalStores, useAppearanceSettingsStore } from './stores';
import { watchState } from './service/watchState';
import { initNoty } from './plugin/noty';
console.log(`isLinux: ${LINUX}`); console.log(`isLinux: ${LINUX}`);

View File

@@ -1,5 +1,5 @@
import { request } from '../service/request';
import { useFavoriteStore, useUserStore } from '../stores'; import { useFavoriteStore, useUserStore } from '../stores';
import { request } from '../service/request';
function getCurrentUserId() { function getCurrentUserId() {
return useUserStore().currentUser.id; return useUserStore().currentUser.id;

View File

@@ -1,5 +1,5 @@
import { useGroupStore, useUserStore } from '../stores';
import { request } from '../service/request'; import { request } from '../service/request';
import { useUserStore, useGroupStore } from '../stores';
function getCurrentUserId() { function getCurrentUserId() {
return useUserStore().currentUser.id; return useUserStore().currentUser.id;

View File

@@ -1,5 +1,5 @@
import { request } from '../service/request';
import { useAvatarStore, useWorldStore } from '../stores'; import { useAvatarStore, useWorldStore } from '../stores';
import { request } from '../service/request';
const imageReq = { const imageReq = {
async uploadAvatarFailCleanup(id) { async uploadAvatarFailCleanup(id) {
@@ -12,10 +12,12 @@ const imageReq = {
const fileVersion = json.versions[json.versions.length - 1].version; const fileVersion = json.versions[json.versions.length - 1].version;
request(`file/${fileId}/${fileVersion}/signature/finish`, { request(`file/${fileId}/${fileVersion}/signature/finish`, {
method: 'PUT' method: 'PUT'
}).catch(err => console.error('Failed to finish signature:', err)); }).catch((err) =>
console.error('Failed to finish signature:', err)
);
request(`file/${fileId}/${fileVersion}/file/finish`, { request(`file/${fileId}/${fileVersion}/file/finish`, {
method: 'PUT' method: 'PUT'
}).catch(err => console.error('Failed to finish file:', err)); }).catch((err) => console.error('Failed to finish file:', err));
} catch (error) { } catch (error) {
console.error('Failed to cleanup avatar upload:', error); console.error('Failed to cleanup avatar upload:', error);
} }
@@ -143,10 +145,12 @@ const imageReq = {
const fileVersion = json.versions[json.versions.length - 1].version; const fileVersion = json.versions[json.versions.length - 1].version;
request(`file/${fileId}/${fileVersion}/signature/finish`, { request(`file/${fileId}/${fileVersion}/signature/finish`, {
method: 'PUT' method: 'PUT'
}).catch(err => console.error('Failed to finish signature:', err)); }).catch((err) =>
console.error('Failed to finish signature:', err)
);
request(`file/${fileId}/${fileVersion}/file/finish`, { request(`file/${fileId}/${fileVersion}/file/finish`, {
method: 'PUT' method: 'PUT'
}).catch(err => console.error('Failed to finish file:', err)); }).catch((err) => console.error('Failed to finish file:', err));
} catch (error) { } catch (error) {
console.error('Failed to cleanup world upload:', error); console.error('Failed to cleanup world upload:', error);
} }

View File

@@ -4,24 +4,25 @@
*/ */
import { request } from '../service/request'; import { request } from '../service/request';
import userRequest from './user';
import worldRequest from './world'; import authRequest from './auth';
import instanceRequest from './instance';
import friendRequest from './friend';
import avatarRequest from './avatar';
import notificationRequest from './notification';
import playerModerationRequest from './playerModeration';
import avatarModerationRequest from './avatarModeration'; import avatarModerationRequest from './avatarModeration';
import avatarRequest from './avatar';
import favoriteRequest from './favorite'; import favoriteRequest from './favorite';
import vrcPlusIconRequest from './vrcPlusIcon'; import friendRequest from './friend';
import vrcPlusImageRequest from './vrcPlusImage'; import groupRequest from './group';
import imageRequest from './image';
import instanceRequest from './instance';
import inventoryRequest from './inventory';
import inviteMessagesRequest from './inviteMessages'; import inviteMessagesRequest from './inviteMessages';
import miscRequest from './misc'; import miscRequest from './misc';
import groupRequest from './group'; import notificationRequest from './notification';
import authRequest from './auth'; import playerModerationRequest from './playerModeration';
import inventoryRequest from './inventory';
import propRequest from './prop'; import propRequest from './prop';
import imageRequest from './image'; import userRequest from './user';
import vrcPlusIconRequest from './vrcPlusIcon';
import vrcPlusImageRequest from './vrcPlusImage';
import worldRequest from './world';
window.request = { window.request = {
request, request,

View File

@@ -1,4 +1,5 @@
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { i18n } from '../plugin/i18n'; import { i18n } from '../plugin/i18n';
import { request } from '../service/request'; import { request } from '../service/request';
import { useInstanceStore } from '../stores'; import { useInstanceStore } from '../stores';

View File

@@ -1,5 +1,5 @@
import { request } from '../service/request';
import { useGalleryStore, useNotificationStore } from '../stores'; import { useGalleryStore, useNotificationStore } from '../stores';
import { request } from '../service/request';
/** /**
* @returns {any} * @returns {any}

View File

@@ -5,9 +5,12 @@
// 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 { pinia } from './stores';
import { initPlugins, i18n, initComponents, initSentry } from './plugin';
import ElementPlus from 'element-plus'; import ElementPlus from 'element-plus';
import { i18n, initComponents, initPlugins, initSentry } from './plugin';
import { pinia } from './stores';
import App from './App.vue'; import App from './App.vue';
await initPlugins(); await initPlugins();

View File

@@ -8,6 +8,7 @@
<script setup> <script setup>
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { useAvatarStore } from '../stores'; import { useAvatarStore } from '../stores';
const avatarStore = useAvatarStore(); const avatarStore = useAvatarStore();

View File

@@ -4,9 +4,11 @@
<script setup> <script setup>
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'; import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
import * as workerTimers from 'worker-timers';
import { timeToText } from '../shared/utils'; import { timeToText } from '../shared/utils';
import * as workerTimers from 'worker-timers';
const props = defineProps({ const props = defineProps({
datetime: { type: String, default: '' }, datetime: { type: String, default: '' },
hours: { type: Number, default: 1 } hours: { type: Number, default: 1 }

View File

@@ -27,7 +27,7 @@
</template> </template>
<script> <script>
import { computed, ref, watch, toRefs } from 'vue'; import { computed, ref, toRefs, watch } from 'vue';
export default { export default {
name: 'DataTable', name: 'DataTable',

View File

@@ -4,8 +4,9 @@
<script setup> <script setup>
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { userRequest } from '../api';
import { useUserStore } from '../stores'; import { useUserStore } from '../stores';
import { userRequest } from '../api';
const userStore = useUserStore(); const userStore = useUserStore();

View File

@@ -58,12 +58,13 @@
</template> </template>
<script setup> <script setup>
import { WarningFilled, Close, Loading } from '@element-plus/icons-vue'; import { Close, Loading, WarningFilled } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { computed } from 'vue'; import { computed } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { userImage, userStatusClass } from '../shared/utils';
import { useAppearanceSettingsStore, useFriendStore } from '../stores'; import { useAppearanceSettingsStore, useFriendStore } from '../stores';
import { userImage, userStatusClass } from '../shared/utils';
const props = defineProps({ const props = defineProps({
friend: { type: Object, required: true }, friend: { type: Object, required: true },

View File

@@ -36,17 +36,16 @@
</template> </template>
<script setup> <script setup>
import { CopyDocument, Download, RefreshLeft, RefreshRight, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
import { nextTick, ref, watch } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { Download, CopyDocument, ZoomIn, ZoomOut, RefreshRight, RefreshLeft } from '@element-plus/icons-vue'; import { storeToRefs } from 'pinia';
import Noty from 'noty'; import Noty from 'noty';
import { storeToRefs } from 'pinia';
import { escapeTag, extractFileId } from '../shared/utils'; import { escapeTag, extractFileId } from '../shared/utils';
import { useGalleryStore } from '../stores';
import { ref, nextTick, watch } from 'vue';
import { getNextDialogIndex } from '../shared/utils/base/ui'; import { getNextDialogIndex } from '../shared/utils/base/ui';
import { useGalleryStore } from '../stores';
const galleryStore = useGalleryStore(); const galleryStore = useGalleryStore();
const { fullscreenImageDialog } = storeToRefs(galleryStore); const { fullscreenImageDialog } = storeToRefs(galleryStore);

View File

@@ -60,12 +60,13 @@
<script setup> <script setup>
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { CaretBottom } from '@element-plus/icons-vue';
import { reactive, watch } from 'vue'; import { reactive, watch } from 'vue';
import { CaretBottom } from '@element-plus/icons-vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { miscRequest } from '../api';
import { formatDateFilter, hasGroupPermission } from '../shared/utils';
import { useGroupStore, useInstanceStore, useLocationStore, useUserStore } from '../stores'; import { useGroupStore, useInstanceStore, useLocationStore, useUserStore } from '../stores';
import { formatDateFilter, hasGroupPermission } from '../shared/utils';
import { miscRequest } from '../api';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -18,14 +18,15 @@
</template> </template>
<script setup> <script setup>
import { ElMessage } from 'element-plus';
import { Loading, Message } from '@element-plus/icons-vue'; import { Loading, Message } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { computed } from 'vue'; import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { instanceRequest } from '../api'; import { useI18n } from 'vue-i18n';
import { checkCanInviteSelf, parseLocation } from '../shared/utils'; import { checkCanInviteSelf, parseLocation } from '../shared/utils';
import { useInviteStore, useLaunchStore } from '../stores'; import { useInviteStore, useLaunchStore } from '../stores';
import { instanceRequest } from '../api';
const props = defineProps({ const props = defineProps({
location: String, location: String,

View File

@@ -10,10 +10,11 @@
</template> </template>
<script setup> <script setup>
import { ref, watch } from 'vue';
import { Location } from '@element-plus/icons-vue'; import { Location } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useInstanceStore } from '../stores'; import { useInstanceStore } from '../stores';
const { instanceJoinHistory } = storeToRefs(useInstanceStore()); const { instanceJoinHistory } = storeToRefs(useInstanceStore());

View File

@@ -10,6 +10,7 @@
import { SwitchButton } from '@element-plus/icons-vue'; import { SwitchButton } from '@element-plus/icons-vue';
import { computed } from 'vue'; import { computed } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { checkCanInviteSelf } from '../shared/utils'; import { checkCanInviteSelf } from '../shared/utils';
import { useLaunchStore } from '../stores'; import { useLaunchStore } from '../stores';

View File

@@ -22,11 +22,13 @@
<script setup> <script setup>
import { Loading, Lock, WarnTriangleFilled } from '@element-plus/icons-vue'; import { Loading, Lock, WarnTriangleFilled } from '@element-plus/icons-vue';
import { ref, watchEffect, watch } from 'vue'; import { ref, watch, watchEffect } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { getGroupName, getWorldName, parseLocation } from '../shared/utils';
import { useGroupStore, useInstanceStore, useSearchStore, useWorldStore } from '../stores';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useGroupStore, useInstanceStore, useSearchStore, useWorldStore } from '../stores';
import { getGroupName, getWorldName, parseLocation } from '../shared/utils';
const { t } = useI18n(); const { t } = useI18n();
const { cachedWorlds, showWorldDialog } = useWorldStore(); const { cachedWorlds, showWorldDialog } = useWorldStore();

View File

@@ -17,9 +17,11 @@
import { Lock, Unlock, WarnTriangleFilled } from '@element-plus/icons-vue'; import { Lock, Unlock, WarnTriangleFilled } from '@element-plus/icons-vue';
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { getGroupName, parseLocation } from '../shared/utils';
import { useGroupStore, useLaunchStore, useInstanceStore } from '../stores';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useGroupStore, useInstanceStore, useLaunchStore } from '../stores';
import { getGroupName, parseLocation } from '../shared/utils';
const { t } = useI18n(); const { t } = useI18n();
const { cachedInstances } = useInstanceStore(); const { cachedInstances } = useInstanceStore();
const { lastInstanceApplied } = storeToRefs(useInstanceStore()); const { lastInstanceApplied } = storeToRefs(useInstanceStore());

View File

@@ -41,6 +41,7 @@
import { Download } from '@element-plus/icons-vue'; import { Download } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useUiStore, useVRCXUpdaterStore } from '../stores'; import { useUiStore, useVRCXUpdaterStore } from '../stores';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -3,6 +3,7 @@
</template> </template>
<script setup> <script setup>
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'; import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
import { timeToText } from '../shared/utils'; import { timeToText } from '../shared/utils';
const props = defineProps({ const props = defineProps({

View File

@@ -571,50 +571,49 @@
</template> </template>
<script setup> <script setup>
import { ElMessage, ElMessageBox } from 'element-plus';
import { import {
Delete, Back,
Star,
StarFilled,
Check, Check,
MoreFilled,
Refresh,
Share,
CircleCheck, CircleCheck,
CircleClose, CircleClose,
Picture,
User,
Edit,
Download,
Upload,
Back,
Right,
CopyDocument, CopyDocument,
Delete,
Download,
Edit,
MoreFilled,
Picture,
Refresh,
Right,
Share,
Star,
StarFilled,
Upload,
User,
Warning Warning
} from '@element-plus/icons-vue'; } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { computed, defineAsyncComponent, nextTick, reactive, ref, watch } from 'vue'; import { computed, defineAsyncComponent, nextTick, reactive, ref, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { avatarModerationRequest, avatarRequest, favoriteRequest, miscRequest } from '../../../api';
import { database } from '../../../service/database';
import { import {
buildTreeData, buildTreeData,
commaNumber, commaNumber,
copyToClipboard, copyToClipboard,
downloadAndSaveJson, downloadAndSaveJson,
extractFileId, extractFileId,
formatDateFilter,
moveArrayItem,
openExternalLink, openExternalLink,
openFolderGeneric, openFolderGeneric,
replaceVrcPackageUrl, replaceVrcPackageUrl,
timeToText, timeToText
moveArrayItem,
formatDateFilter
} from '../../../shared/utils'; } from '../../../shared/utils';
import { handleImageUploadInput } from '../../../shared/utils/imageUpload';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
import { useAvatarStore, useFavoriteStore, useGalleryStore, useGameStore, useUserStore } from '../../../stores'; import { useAvatarStore, useFavoriteStore, useGalleryStore, useGameStore, useUserStore } from '../../../stores';
import { avatarModerationRequest, avatarRequest, favoriteRequest, miscRequest } from '../../../api';
import { database } from '../../../service/database';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
import { handleImageUploadInput } from '../../../shared/utils/imageUpload';
const ChangeAvatarImageDialog = defineAsyncComponent(() => import('./ChangeAvatarImageDialog.vue')); const ChangeAvatarImageDialog = defineAsyncComponent(() => import('./ChangeAvatarImageDialog.vue'));
const SetAvatarStylesDialog = defineAsyncComponent(() => import('./SetAvatarStylesDialog.vue')); const SetAvatarStylesDialog = defineAsyncComponent(() => import('./SetAvatarStylesDialog.vue'));

View File

@@ -44,15 +44,16 @@
<script setup> <script setup>
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { Upload } from '@element-plus/icons-vue'; import { Upload } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { ref } from 'vue'; import { ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { avatarRequest, imageRequest } from '../../../api'; import { avatarRequest, imageRequest } from '../../../api';
import { handleImageUploadInput } from '../../../shared/utils/imageUpload';
import { useAvatarStore } from '../../../stores';
import { $throw } from '../../../service/request'; import { $throw } from '../../../service/request';
import { AppDebug } from '../../../service/appConfig'; import { AppDebug } from '../../../service/appConfig';
import { extractFileId } from '../../../shared/utils'; import { extractFileId } from '../../../shared/utils';
import { handleImageUploadInput } from '../../../shared/utils/imageUpload';
import { useAvatarStore } from '../../../stores';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -60,13 +60,13 @@
</template> </template>
<script setup> <script setup>
import { ElMessage } from 'element-plus';
import { useI18n } from 'vue-i18n';
import { watch } from 'vue'; import { watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { arraysMatch } from '../../../shared/utils'; import { arraysMatch } from '../../../shared/utils';
import { avatarRequest } from '../../../api'; import { avatarRequest } from '../../../api';
import { useAvatarStore } from '../../../stores'; import { useAvatarStore } from '../../../stores';
import { ElMessage } from 'element-plus';
const { t } = useI18n(); const { t } = useI18n();
const { applyAvatar } = useAvatarStore(); const { applyAvatar } = useAvatarStore();

View File

@@ -92,11 +92,11 @@
</template> </template>
<script setup> <script setup>
import { Loading } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { Loading } from '@element-plus/icons-vue';
import { watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { watch } from 'vue';
import { avatarRequest } from '../../../api'; import { avatarRequest } from '../../../api';
import { useAvatarStore } from '../../../stores'; import { useAvatarStore } from '../../../stores';

View File

@@ -62,15 +62,16 @@
</template> </template>
<script setup> <script setup>
import { computed, nextTick, ref, watch } from 'vue';
import { Check } from '@element-plus/icons-vue'; import { Check } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import Noty from 'noty'; import Noty from 'noty';
import { storeToRefs } from 'pinia';
import { computed, nextTick, ref, watch } from 'vue'; import { useFavoriteStore, useUserStore } from '../../stores';
import { useI18n } from 'vue-i18n';
import { favoriteRequest } from '../../api'; import { favoriteRequest } from '../../api';
import { getNextDialogIndex } from '../../shared/utils/base/ui'; import { getNextDialogIndex } from '../../shared/utils/base/ui';
import { useFavoriteStore, useUserStore } from '../../stores';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -53,14 +53,13 @@
</template> </template>
<script setup> <script setup>
import { ElMessage } from 'element-plus';
import { Close, Refresh, Upload } from '@element-plus/icons-vue'; import { Close, Refresh, Upload } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { vrcPlusImageRequest } from '../../../api';
import { useGalleryStore, useUserStore } from '../../../stores'; import { useGalleryStore, useUserStore } from '../../../stores';
import { vrcPlusImageRequest } from '../../../api';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -1121,61 +1121,62 @@
</template> </template>
<script setup> <script setup>
import { ElMessage, ElMessageBox } from 'element-plus';
import { import {
ArrowDown,
ChatLineSquare,
Check, Check,
View,
Star,
StarFilled,
Close,
Message,
MoreFilled,
Refresh,
Share,
Tickets,
Delete,
CircleCheck, CircleCheck,
CircleClose, CircleClose,
Edit, Close,
CopyDocument,
Download,
Operation,
Loading,
Warning,
ArrowDown,
CollectionTag, CollectionTag,
ChatLineSquare CopyDocument,
Delete,
Download,
Edit,
Loading,
Message,
MoreFilled,
Operation,
Refresh,
Share,
Star,
StarFilled,
Tickets,
View,
Warning
} from '@element-plus/icons-vue'; } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { nextTick, reactive, ref, watch } from 'vue'; import { nextTick, reactive, ref, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import * as workerTimers from 'worker-timers';
import { groupRequest } from '../../../api';
import { groupDialogFilterOptions, groupDialogSortingOptions } from '../../../shared/constants';
import { import {
buildTreeData, buildTreeData,
copyToClipboard, copyToClipboard,
debounce,
downloadAndSaveJson, downloadAndSaveJson,
formatDateFilter,
getFaviconUrl, getFaviconUrl,
hasGroupPermission,
hasGroupModerationPermission, hasGroupModerationPermission,
hasGroupPermission,
languageClass, languageClass,
openExternalLink, openExternalLink,
refreshInstancePlayerCount, refreshInstancePlayerCount,
removeFromArray, removeFromArray,
userImage, userImage,
userStatusClass, userStatusClass
formatDateFilter,
debounce
} from '../../../shared/utils'; } from '../../../shared/utils';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
import { useGalleryStore, useGroupStore, useLocationStore, useUserStore } from '../../../stores'; import { useGalleryStore, useGroupStore, useLocationStore, useUserStore } from '../../../stores';
import InviteGroupDialog from '../InviteGroupDialog.vue'; import { groupDialogFilterOptions, groupDialogSortingOptions } from '../../../shared/constants';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
import { groupRequest } from '../../../api';
import GroupPostEditDialog from './GroupPostEditDialog.vue'; import GroupPostEditDialog from './GroupPostEditDialog.vue';
import InviteGroupDialog from '../InviteGroupDialog.vue';
import PreviousInstancesGroupDialog from '../PreviousInstancesDialog/PreviousInstancesGroupDialog.vue'; import PreviousInstancesGroupDialog from '../PreviousInstancesDialog/PreviousInstancesGroupDialog.vue';
import * as workerTimers from 'worker-timers';
const { t } = useI18n(); const { t } = useI18n();
const { showUserDialog } = useUserStore(); const { showUserDialog } = useUserStore();

View File

@@ -861,19 +861,21 @@
</template> </template>
<script setup> <script setup>
import { Refresh, Delete, ArrowDown, Warning, Loading } from '@element-plus/icons-vue'; import { ArrowDown, Delete, Loading, Refresh, Warning } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia';
import { reactive, ref, watch } from 'vue'; import { reactive, ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import * as workerTimers from 'worker-timers';
import { groupRequest, userRequest } from '../../../api'; import { debounce, formatDateFilter, hasGroupPermission, userImage, userImageFull } from '../../../shared/utils';
import { groupDialogFilterOptions, groupDialogSortingOptions } from '../../../shared/constants';
import { hasGroupPermission, userImage, userImageFull, formatDateFilter, debounce } from '../../../shared/utils';
import { useAppearanceSettingsStore, useGalleryStore, useGroupStore, useUserStore } from '../../../stores'; import { useAppearanceSettingsStore, useGalleryStore, useGroupStore, useUserStore } from '../../../stores';
import { groupDialogFilterOptions, groupDialogSortingOptions } from '../../../shared/constants';
import { groupRequest, userRequest } from '../../../api';
import GroupMemberModerationExportDialog from './GroupMemberModerationExportDialog.vue'; import GroupMemberModerationExportDialog from './GroupMemberModerationExportDialog.vue';
import * as workerTimers from 'worker-timers';
const { randomUserColours } = storeToRefs(useAppearanceSettingsStore()); const { randomUserColours } = storeToRefs(useAppearanceSettingsStore());
const { showUserDialog } = useUserStore(); const { showUserDialog } = useUserStore();
const { currentUser } = storeToRefs(useUserStore()); const { currentUser } = storeToRefs(useUserStore());

View File

@@ -32,6 +32,7 @@
<script setup> <script setup>
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { copyToClipboard } from '../../../shared/utils'; import { copyToClipboard } from '../../../shared/utils';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -98,11 +98,13 @@
</template> </template>
<script setup> <script setup>
import { computed, ref } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { ref, computed } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { groupRequest, vrcPlusIconRequest } from '../../../api'; import { groupRequest, vrcPlusIconRequest } from '../../../api';
import { useGalleryStore, useGroupStore } from '../../../stores'; import { useGalleryStore, useGroupStore } from '../../../stores';
import GallerySelectDialog from './GallerySelectDialog.vue'; import GallerySelectDialog from './GallerySelectDialog.vue';
const props = defineProps({ const props = defineProps({

View File

@@ -35,9 +35,10 @@
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { instanceRequest, inviteMessagesRequest, notificationRequest } from '../../../api'; import { instanceRequest, inviteMessagesRequest, notificationRequest } from '../../../api';
import { parseLocation } from '../../../shared/utils';
import { useGalleryStore, useUserStore } from '../../../stores'; import { useGalleryStore, useUserStore } from '../../../stores';
import { parseLocation } from '../../../shared/utils';
const { t } = useI18n(); const { t } = useI18n();
const { uploadImage } = storeToRefs(useGalleryStore()); const { uploadImage } = storeToRefs(useGalleryStore());

View File

@@ -169,13 +169,14 @@
<script setup> <script setup>
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { storeToRefs } from 'pinia';
import { ref } from 'vue'; import { ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { instanceRequest, notificationRequest } from '../../../api';
import { parseLocation, userImage, userStatusClass } from '../../../shared/utils';
import { useFriendStore, useGalleryStore, useInviteStore, useUserStore } from '../../../stores'; import { useFriendStore, useGalleryStore, useInviteStore, useUserStore } from '../../../stores';
import { parseLocation, userImage, userStatusClass } from '../../../shared/utils';
import { instanceRequest, notificationRequest } from '../../../api';
import SendInviteDialog from './SendInviteDialog.vue'; import SendInviteDialog from './SendInviteDialog.vue';
const { vipFriends, onlineFriends, activeFriends } = storeToRefs(useFriendStore()); const { vipFriends, onlineFriends, activeFriends } = storeToRefs(useFriendStore());

View File

@@ -25,9 +25,10 @@
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { instanceRequest, notificationRequest } from '../../../api'; import { instanceRequest, notificationRequest } from '../../../api';
import { parseLocation } from '../../../shared/utils';
import { useGalleryStore, useUserStore } from '../../../stores'; import { useGalleryStore, useUserStore } from '../../../stores';
import { parseLocation } from '../../../shared/utils';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -91,11 +91,12 @@
<script setup> <script setup>
import { Edit } from '@element-plus/icons-vue'; import { Edit } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { ref } from 'vue'; import { ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useGalleryStore, useInviteStore, useUserStore } from '../../../stores'; import { useGalleryStore, useInviteStore, useUserStore } from '../../../stores';
import EditAndSendInviteDialog from './EditAndSendInviteDialog.vue'; import EditAndSendInviteDialog from './EditAndSendInviteDialog.vue';
import SendInviteConfirmDialog from './SendInviteConfirmDialog.vue'; import SendInviteConfirmDialog from './SendInviteConfirmDialog.vue';

View File

@@ -165,15 +165,17 @@
</template> </template>
<script setup> <script setup>
import { computed, nextTick, ref, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { ref, watch, nextTick, computed } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { groupRequest, userRequest } from '../../api';
import configRepository from '../../service/config';
import { hasGroupPermission, userImage, userStatusClass } from '../../shared/utils'; import { hasGroupPermission, userImage, userStatusClass } from '../../shared/utils';
import { getNextDialogIndex } from '../../shared/utils/base/ui'; import { groupRequest, userRequest } from '../../api';
import { useFriendStore, useGroupStore } from '../../stores'; import { useFriendStore, useGroupStore } from '../../stores';
import { getNextDialogIndex } from '../../shared/utils/base/ui';
import configRepository from '../../service/config';
const { vipFriends, onlineFriends, activeFriends, offlineFriends } = storeToRefs(useFriendStore()); const { vipFriends, onlineFriends, activeFriends, offlineFriends } = storeToRefs(useFriendStore());
const { currentUserGroups, inviteGroupDialog } = storeToRefs(useGroupStore()); const { currentUserGroups, inviteGroupDialog } = storeToRefs(useGroupStore());

View File

@@ -97,18 +97,19 @@
</template> </template>
<script setup> <script setup>
import { computed, nextTick, ref, watch } from 'vue';
import { CopyDocument, Warning } from '@element-plus/icons-vue'; import { CopyDocument, Warning } from '@element-plus/icons-vue';
import { ref, computed, nextTick, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { instanceRequest, worldRequest } from '../../api';
import configRepository from '../../service/config'; import { useFriendStore, useGameStore, useInviteStore, useLaunchStore, useLocationStore } from '../../stores';
import { checkCanInvite, getLaunchURL, isRealInstance, parseLocation } from '../../shared/utils'; import { checkCanInvite, getLaunchURL, isRealInstance, parseLocation } from '../../shared/utils';
import { instanceRequest, worldRequest } from '../../api';
import { getNextDialogIndex } from '../../shared/utils/base/ui'; import { getNextDialogIndex } from '../../shared/utils/base/ui';
import { useFriendStore, useInviteStore, useLaunchStore, useLocationStore, useGameStore } from '../../stores';
import InviteDialog from './InviteDialog/InviteDialog.vue'; import InviteDialog from './InviteDialog/InviteDialog.vue';
import configRepository from '../../service/config';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -60,9 +60,10 @@
</template> </template>
<script setup> <script setup>
import { ref, watch, nextTick, computed } from 'vue'; import { computed, nextTick, ref, watch } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { groupRequest, userRequest } from '../../api'; import { groupRequest, userRequest } from '../../api';
import { hasGroupModerationPermission, userImage } from '../../shared/utils'; import { hasGroupModerationPermission, userImage } from '../../shared/utils';
import { getNextDialogIndex } from '../../shared/utils/base/ui'; import { getNextDialogIndex } from '../../shared/utils/base/ui';

View File

@@ -473,12 +473,11 @@
</template> </template>
<script setup> <script setup>
import { ref, watch, nextTick, computed } from 'vue'; import { computed, nextTick, ref, watch } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { groupRequest, instanceRequest, worldRequest } from '../../api'; import { useI18n } from 'vue-i18n';
import configRepository from '../../service/config';
import { import {
copyToClipboard, copyToClipboard,
getLaunchURL, getLaunchURL,
@@ -488,17 +487,20 @@
userImage, userImage,
userStatusClass userStatusClass
} from '../../shared/utils'; } from '../../shared/utils';
import { getNextDialogIndex } from '../../shared/utils/base/ui';
import { import {
useFriendStore, useFriendStore,
useGroupStore, useGroupStore,
useInstanceStore, useInstanceStore,
useInviteStore,
useLaunchStore, useLaunchStore,
useLocationStore, useLocationStore,
useUserStore, useUserStore
useInviteStore
} from '../../stores'; } from '../../stores';
import { groupRequest, instanceRequest, worldRequest } from '../../api';
import { getNextDialogIndex } from '../../shared/utils/base/ui';
import InviteDialog from './InviteDialog/InviteDialog.vue'; import InviteDialog from './InviteDialog/InviteDialog.vue';
import configRepository from '../../service/config';
const props = defineProps({ const props = defineProps({
newInstanceDialogLocationTag: { newInstanceDialogLocationTag: {

View File

@@ -62,21 +62,21 @@
</template> </template>
<script setup> <script setup>
import { DataLine, Close } from '@element-plus/icons-vue'; import { computed, nextTick, reactive, ref, watch } from 'vue';
import { Close, DataLine } from '@element-plus/icons-vue';
import { ElMessageBox } from 'element-plus'; import { ElMessageBox } from 'element-plus';
import { ref, reactive, computed, watch, nextTick } from 'vue';
import {
parseLocation,
compareByCreatedAt,
timeToText,
removeFromArray,
formatDateFilter
} from '../../../shared/utils';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
import { database } from '../../../service/database';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import {
compareByCreatedAt,
formatDateFilter,
parseLocation,
removeFromArray,
timeToText
} from '../../../shared/utils';
import { useInstanceStore, useUiStore } from '../../../stores'; import { useInstanceStore, useUiStore } from '../../../stores';
import { database } from '../../../service/database';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
const { showPreviousInstancesInfoDialog } = useInstanceStore(); const { showPreviousInstancesInfoDialog } = useInstanceStore();
const { shiftHeld } = useUiStore(); const { shiftHeld } = useUiStore();

View File

@@ -59,13 +59,14 @@
</template> </template>
<script setup> <script setup>
import { ref, watch, nextTick } from 'vue'; import { nextTick, ref, watch } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { database } from '../../../service/database';
import { compareByCreatedAt, parseLocation, timeToText, formatDateFilter } from '../../../shared/utils'; import { compareByCreatedAt, formatDateFilter, parseLocation, timeToText } from '../../../shared/utils';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
import { useGameLogStore, useInstanceStore, useUserStore } from '../../../stores'; import { useGameLogStore, useInstanceStore, useUserStore } from '../../../stores';
import { database } from '../../../service/database';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
const { lookupUser } = useUserStore(); const { lookupUser } = useUserStore();
const { previousInstancesInfoDialogVisible, previousInstancesInfoDialogInstanceId } = const { previousInstancesInfoDialogVisible, previousInstancesInfoDialogInstanceId } =

View File

@@ -69,22 +69,22 @@
</template> </template>
<script setup> <script setup>
import { DataLine, Close } from '@element-plus/icons-vue'; import { computed, nextTick, reactive, ref, watch } from 'vue';
import { Close, DataLine } from '@element-plus/icons-vue';
import { ElMessageBox } from 'element-plus'; import { ElMessageBox } from 'element-plus';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed, nextTick, reactive, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { database } from '../../../service/database';
import { import {
compareByCreatedAt, compareByCreatedAt,
formatDateFilter,
parseLocation, parseLocation,
removeFromArray, removeFromArray,
timeToText, timeToText
formatDateFilter
} from '../../../shared/utils'; } from '../../../shared/utils';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
import { useInstanceStore, useUiStore, useUserStore } from '../../../stores'; import { useInstanceStore, useUiStore, useUserStore } from '../../../stores';
import { database } from '../../../service/database';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -47,13 +47,12 @@
</template> </template>
<script setup> <script setup>
import { ElMessage } from 'element-plus';
import { Delete } from '@element-plus/icons-vue'; import { Delete } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { userRequest } from '../../../api';
import { getFaviconUrl } from '../../../shared/utils'; import { getFaviconUrl } from '../../../shared/utils';
import { userRequest } from '../../../api';
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ const props = defineProps({

View File

@@ -45,9 +45,10 @@
<script setup> <script setup>
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { userRequest } from '../../../api';
import { languageClass } from '../../../shared/utils'; import { languageClass } from '../../../shared/utils';
import { useUserStore } from '../../../stores'; import { useUserStore } from '../../../stores';
import { userRequest } from '../../../api';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -72,22 +72,22 @@
</template> </template>
<script setup> <script setup>
import { SwitchButton, DataLine, Close } from '@element-plus/icons-vue'; import { computed, nextTick, reactive, ref, watch } from 'vue';
import { Close, DataLine, SwitchButton } from '@element-plus/icons-vue';
import { ElMessageBox } from 'element-plus'; import { ElMessageBox } from 'element-plus';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { computed, nextTick, reactive, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { database } from '../../../service/database';
import { import {
compareByCreatedAt, compareByCreatedAt,
formatDateFilter,
parseLocation, parseLocation,
removeFromArray, removeFromArray,
timeToText, timeToText
formatDateFilter
} from '../../../shared/utils'; } from '../../../shared/utils';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
import { useInstanceStore, useLaunchStore, useUiStore } from '../../../stores'; import { useInstanceStore, useLaunchStore, useUiStore } from '../../../stores';
import { database } from '../../../service/database';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
const props = defineProps({ const props = defineProps({
previousInstancesUserDialog: { previousInstancesUserDialog: {

View File

@@ -27,6 +27,7 @@
<script setup> <script setup>
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { userRequest } from '../../../api'; import { userRequest } from '../../../api';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -64,11 +64,12 @@
<script setup> <script setup>
import { Edit } from '@element-plus/icons-vue'; import { Edit } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { ref } from 'vue'; import { ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useGalleryStore, useInviteStore, useUserStore } from '../../../stores'; import { useGalleryStore, useInviteStore, useUserStore } from '../../../stores';
import EditAndSendInviteDialog from '../InviteDialog/EditAndSendInviteDialog.vue'; import EditAndSendInviteDialog from '../InviteDialog/EditAndSendInviteDialog.vue';
import SendInviteConfirmDialog from '../InviteDialog/SendInviteConfirmDialog.vue'; import SendInviteConfirmDialog from '../InviteDialog/SendInviteConfirmDialog.vue';

View File

@@ -58,11 +58,11 @@
<script setup> <script setup>
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { userRequest } from '../../../api';
import { useUserStore } from '../../../stores'; import { useUserStore } from '../../../stores';
import { userRequest } from '../../../api';
const { t } = useI18n(); const { t } = useI18n();
const { currentUser } = storeToRefs(useUserStore()); const { currentUser } = storeToRefs(useUserStore());

View File

@@ -1690,72 +1690,59 @@
</template> </template>
<script setup> <script setup>
import { ElMessage, ElMessageBox } from 'element-plus';
import { import {
Delete, ArrowDown,
Bottom,
CaretBottom,
ChatDotRound,
ChatLineRound,
Check, Check,
Star,
StarFilled,
MoreFilled,
Refresh,
Share,
Picture,
Edit,
SwitchButton,
Message,
Close,
Plus,
DataLine,
CircleCheck, CircleCheck,
CircleClose, CircleClose,
User, Close,
Flag,
CopyDocument,
Setting,
Download,
CaretBottom,
UserFilled,
Postcard,
Operation,
Microphone,
Mute,
ChatLineRound,
ChatDotRound,
Pointer,
Loading,
More,
Warning,
ArrowDown,
Top,
Bottom,
CollectionTag, CollectionTag,
View CopyDocument,
DataLine,
Delete,
Download,
Edit,
Flag,
Loading,
Message,
Microphone,
More,
MoreFilled,
Mute,
Operation,
Picture,
Plus,
Pointer,
Postcard,
Refresh,
Setting,
Share,
Star,
StarFilled,
SwitchButton,
Top,
User,
UserFilled,
View,
Warning
} from '@element-plus/icons-vue'; } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { computed, defineAsyncComponent, nextTick, ref, watch } from 'vue'; import { computed, defineAsyncComponent, nextTick, ref, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import {
favoriteRequest,
friendRequest,
groupRequest,
miscRequest,
notificationRequest,
playerModerationRequest,
userRequest,
worldRequest
} from '../../../api';
import { database } from '../../../service/database';
import { processBulk, request } from '../../../service/request';
import { userDialogGroupSortingOptions } from '../../../shared/constants';
import { userDialogWorldOrderOptions, userDialogWorldSortingOptions } from '../../../shared/constants/';
import { import {
checkCanInvite, checkCanInvite,
compareByMemberCount, compareByMemberCount,
compareByName, compareByName,
copyToClipboard, copyToClipboard,
downloadAndSaveJson, downloadAndSaveJson,
formatDateFilter,
getFaviconUrl,
isFriendOnline, isFriendOnline,
isRealInstance, isRealInstance,
languageClass, languageClass,
@@ -1768,11 +1755,8 @@
userImage, userImage,
userOnlineFor, userOnlineFor,
userOnlineForTimestamp, userOnlineForTimestamp,
userStatusClass, userStatusClass
formatDateFilter,
getFaviconUrl
} from '../../../shared/utils'; } from '../../../shared/utils';
import { getNextDialogIndex, redirectToToolsTab } from '../../../shared/utils/base/ui';
import { import {
useAdvancedSettingsStore, useAdvancedSettingsStore,
useAppearanceSettingsStore, useAppearanceSettingsStore,
@@ -1786,12 +1770,28 @@
useInviteStore, useInviteStore,
useLocationStore, useLocationStore,
useModerationStore, useModerationStore,
useUiStore,
useUserStore, useUserStore,
useWorldStore, useWorldStore
useUiStore
} from '../../../stores'; } from '../../../stores';
import SendInviteDialog from '../InviteDialog/SendInviteDialog.vue'; import {
favoriteRequest,
friendRequest,
groupRequest,
miscRequest,
notificationRequest,
playerModerationRequest,
userRequest,
worldRequest
} from '../../../api';
import { getNextDialogIndex, redirectToToolsTab } from '../../../shared/utils/base/ui';
import { processBulk, request } from '../../../service/request';
import { userDialogWorldOrderOptions, userDialogWorldSortingOptions } from '../../../shared/constants/';
import { database } from '../../../service/database';
import { userDialogGroupSortingOptions } from '../../../shared/constants';
import InviteGroupDialog from '../InviteGroupDialog.vue'; import InviteGroupDialog from '../InviteGroupDialog.vue';
import SendInviteDialog from '../InviteDialog/SendInviteDialog.vue';
const BioDialog = defineAsyncComponent(() => import('./BioDialog.vue')); const BioDialog = defineAsyncComponent(() => import('./BioDialog.vue'));
const LanguageDialog = defineAsyncComponent(() => import('./LanguageDialog.vue')); const LanguageDialog = defineAsyncComponent(() => import('./LanguageDialog.vue'));

View File

@@ -58,9 +58,10 @@
</template> </template>
<script setup> <script setup>
import { storeToRefs } from 'pinia';
import { nextTick, ref, watch } from 'vue'; import { nextTick, ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { branches } from '../../shared/constants'; import { branches } from '../../shared/constants';
import { getNextDialogIndex } from '../../shared/utils/base/ui'; import { getNextDialogIndex } from '../../shared/utils/base/ui';
import { useVRCXUpdaterStore } from '../../stores'; import { useVRCXUpdaterStore } from '../../stores';

View File

@@ -44,15 +44,16 @@
<script setup> <script setup>
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { Upload } from '@element-plus/icons-vue'; import { Upload } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { ref } from 'vue'; import { ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { worldRequest, imageRequest } from '../../../api';
import { handleImageUploadInput } from '../../../shared/utils/imageUpload'; import { imageRequest, worldRequest } from '../../../api';
import { useWorldStore } from '../../../stores';
import { $throw } from '../../../service/request'; import { $throw } from '../../../service/request';
import { AppDebug } from '../../../service/appConfig'; import { AppDebug } from '../../../service/appConfig';
import { extractFileId } from '../../../shared/utils'; import { extractFileId } from '../../../shared/utils';
import { handleImageUploadInput } from '../../../shared/utils/imageUpload';
import { useWorldStore } from '../../../stores';
const { t } = useI18n(); const { t } = useI18n();

View File

@@ -85,11 +85,12 @@
</template> </template>
<script setup> <script setup>
import { ref, computed, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { worldRequest } from '../../../api';
import { useWorldStore } from '../../../stores'; import { useWorldStore } from '../../../stores';
import { worldRequest } from '../../../api';
const props = defineProps({ const props = defineProps({
oldTags: { oldTags: {

View File

@@ -27,12 +27,11 @@
</template> </template>
<script setup> <script setup>
import { computed, ref, watch } from 'vue';
import { Delete } from '@element-plus/icons-vue'; import { Delete } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { ref, computed, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { worldRequest } from '../../../api'; import { worldRequest } from '../../../api';
const props = defineProps({ const props = defineProps({

View File

@@ -746,55 +746,51 @@
<script setup> <script setup>
import { import {
HomeFilled, ArrowDown,
Check,
CopyDocument,
DataLine,
Delete, Delete,
Download,
Edit,
Flag,
HomeFilled,
Loading,
MagicStick,
Message,
MoreFilled, MoreFilled,
Picture,
Refresh, Refresh,
Share, Share,
Flag,
Message,
MagicStick,
Picture,
Upload,
Edit,
Download,
View,
DataLine,
CopyDocument,
Warning,
Star, Star,
StarFilled, StarFilled,
Upload,
User, User,
Check, UserFilled,
Loading, View,
ArrowDown, Warning
UserFilled
} from '@element-plus/icons-vue'; } from '@element-plus/icons-vue';
import { computed, defineAsyncComponent, nextTick, ref, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { computed, ref, watch, nextTick, defineAsyncComponent } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { favoriteRequest, miscRequest, userRequest, worldRequest } from '../../../api';
import { database } from '../../../service/database.js';
import { import {
buildTreeData, buildTreeData,
commaNumber,
copyToClipboard,
deleteVRChatCache,
downloadAndSaveJson, downloadAndSaveJson,
formatDateFilter,
openExternalLink, openExternalLink,
openFolderGeneric,
refreshInstancePlayerCount, refreshInstancePlayerCount,
replaceVrcPackageUrl, replaceVrcPackageUrl,
textToHex,
timeToText, timeToText,
userImage, userImage,
userStatusClass, userStatusClass
openFolderGeneric,
deleteVRChatCache,
commaNumber,
formatDateFilter,
textToHex,
copyToClipboard
} from '../../../shared/utils'; } from '../../../shared/utils';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
import { import {
useAppearanceSettingsStore, useAppearanceSettingsStore,
useFavoriteStore, useFavoriteStore,
@@ -806,6 +802,9 @@
useUserStore, useUserStore,
useWorldStore useWorldStore
} from '../../../stores'; } from '../../../stores';
import { favoriteRequest, miscRequest, userRequest, worldRequest } from '../../../api';
import { database } from '../../../service/database.js';
import { getNextDialogIndex } from '../../../shared/utils/base/ui';
const NewInstanceDialog = defineAsyncComponent(() => import('../NewInstanceDialog.vue')); const NewInstanceDialog = defineAsyncComponent(() => import('../NewInstanceDialog.vue'));
const PreviousInstancesWorldDialog = defineAsyncComponent( const PreviousInstancesWorldDialog = defineAsyncComponent(

View File

@@ -1,33 +1,41 @@
class InteropApi { class InteropApi {
constructor() { constructor() {
return new Proxy(this, { return new Proxy(this, {
get(target, prop) { get(target, prop) {
if (WINDOWS) { if (WINDOWS) {
return undefined; return undefined;
} }
// If the property is not a method of InteropApi, // If the property is not a method of InteropApi,
// treat it as a .NET class name // treat it as a .NET class name
if (typeof prop === 'string' && !target[prop]) { if (typeof prop === 'string' && !target[prop]) {
return new Proxy({}, { return new Proxy(
get(_, methodName) { {},
// Return a method that calls the .NET method dynamically {
return async (...args) => { get(_, methodName) {
return await target.callMethod(prop, methodName, ...args); // Return a method that calls the .NET method dynamically
}; return async (...args) => {
} return await target.callMethod(
}); prop,
} methodName,
return target[prop]; ...args
} );
}); };
}
}
);
}
return target[prop];
}
});
} }
async callMethod(className, methodName, ...args) { async callMethod(className, methodName, ...args) {
return window.interopApi.callDotNetMethod(className, methodName, args) return window.interopApi
.then(result => { .callDotNetMethod(className, methodName, args)
return result; .then((result) => {
}); return result;
});
} }
} }
export default new InteropApi(); export default new InteropApi();

View File

@@ -1,24 +1,28 @@
// Because this isn't a package (just a loose js file), we have to use require // Because this isn't a package (just a loose js file), we have to use require
// statements // statements
const process = require("node:process") const process = require('node:process');
const fs = require('node:fs'); const fs = require('node:fs');
const path = require('node:path'); const path = require('node:path');
const yargs = require("yargs/yargs"); const yargs = require('yargs/yargs');
const { hideBin } = require("yargs/helpers") const { hideBin } = require('yargs/helpers');
const getLocalizationObjects = function* () { const getLocalizationObjects = function* () {
const localeFolder = './src/localization'; const localeFolder = './src/localization';
const folders = fs.readdirSync(localeFolder, { withFileTypes: true }).filter(file => file.isDirectory()); const folders = fs
.readdirSync(localeFolder, { withFileTypes: true })
.filter((file) => file.isDirectory());
for (const folder of folders) { for (const folder of folders) {
const filePath = path.join(localeFolder, folder.name, "en.json"); const filePath = path.join(localeFolder, folder.name, 'en.json');
const jsonStr = fs.readFileSync(filePath); const jsonStr = fs.readFileSync(filePath);
yield [filePath, JSON.parse(jsonStr)]; yield [filePath, JSON.parse(jsonStr)];
} }
} };
const addKey = function (obj, objects, value, above_key) { const addKey = function (obj, objects, value, above_key) {
console.log(`Adding key to ${obj.language} at path '${objects.join('.')}' with value '${value}' above key '${above_key}'`); console.log(
`Adding key to ${obj.language} at path '${objects.join('.')}' with value '${value}' above key '${above_key}'`
);
let currentObj = obj; let currentObj = obj;
let i = 0; let i = 0;
@@ -32,12 +36,12 @@ const addKey = function (obj, objects, value, above_key) {
currentObj = currentObj[objects[i]]; currentObj = currentObj[objects[i]];
} }
InsertKeyInObj(currentObj, objects[i], value, above_key); InsertKeyInObj(currentObj, objects[i], value, above_key);
} };
// Shamelessly stolen from https://stackoverflow.com/a/55017155/11030436 // Shamelessly stolen from https://stackoverflow.com/a/55017155/11030436
const InsertKeyInObj = (obj, key, value, above_key) => { const InsertKeyInObj = (obj, key, value, above_key) => {
const keys = Object.keys(obj); const keys = Object.keys(obj);
if (keys.length === 0 || !(Object.hasOwn(obj, above_key))) { if (keys.length === 0 || !Object.hasOwn(obj, above_key)) {
obj[key] = value; obj[key] = value;
return obj; return obj;
} }
@@ -58,7 +62,7 @@ const InsertKeyInObj = (obj, key, value, above_key) => {
} }
return newObj; return newObj;
}, {}) }, {});
delete ret.dummy; delete ret.dummy;
// Clear keys on old object // Clear keys on old object
@@ -68,7 +72,7 @@ const InsertKeyInObj = (obj, key, value, above_key) => {
// Assign new properties to old object // Assign new properties to old object
Object.assign(obj, ret); Object.assign(obj, ret);
} };
const addLocalizationKey = (key, value, above_key) => { const addLocalizationKey = (key, value, above_key) => {
const objects = key.split('.'); const objects = key.split('.');
@@ -79,11 +83,13 @@ const addLocalizationKey = (key, value, above_key) => {
} }
console.log(`\`${key}:${value}\` added to every localization file!`); console.log(`\`${key}:${value}\` added to every localization file!`);
} };
const removeKey = (obj, objects, i = 0) => { const removeKey = (obj, objects, i = 0) => {
console.log(`Removing key from ${obj.language} at path '${objects.join('.')}'`); console.log(
if (!(Object.hasOwn(obj, objects[i]))) { `Removing key from ${obj.language} at path '${objects.join('.')}'`
);
if (!Object.hasOwn(obj, objects[i])) {
return; return;
} }
@@ -95,7 +101,7 @@ const removeKey = (obj, objects, i = 0) => {
delete obj[objects[i]]; delete obj[objects[i]];
} }
} }
} };
const removeLocalizationKey = (key) => { const removeLocalizationKey = (key) => {
const objects = key.split('.'); const objects = key.split('.');
@@ -108,12 +114,14 @@ const removeLocalizationKey = (key) => {
} }
console.log(`\`${key}\` removed from every localization file!`); console.log(`\`${key}\` removed from every localization file!`);
} };
// Yes this code is extremely slow, but it doesn't run very often so. // Yes this code is extremely slow, but it doesn't run very often so.
const Validate = function () { const Validate = function () {
const files = [...getLocalizationObjects()]; const files = [...getLocalizationObjects()];
const enIndex = files.findIndex(file => path.dirname(file[0]).endsWith("en")); const enIndex = files.findIndex((file) =>
path.dirname(file[0]).endsWith('en')
);
const [_, enObj] = files.splice(enIndex, 1)[0]; const [_, enObj] = files.splice(enIndex, 1)[0];
const traverse = function (obj, predicate, pathes = []) { const traverse = function (obj, predicate, pathes = []) {
@@ -124,16 +132,16 @@ const Validate = function () {
traverse(obj[key], predicate, [...pathes, key]); traverse(obj[key], predicate, [...pathes, key]);
} }
} }
} };
let hasRemoved = false; let hasRemoved = false;
for (const [_, localeObj] of files) { for (const [_, localeObj] of files) {
toRemove = [] toRemove = [];
traverse(localeObj, (_, key, pathes) => { traverse(localeObj, (_, key, pathes) => {
let currObj = enObj; let currObj = enObj;
for (const pathSegment of pathes) { for (const pathSegment of pathes) {
if (Object.hasOwn(currObj, pathSegment)) { if (Object.hasOwn(currObj, pathSegment)) {
currObj = currObj[pathSegment] currObj = currObj[pathSegment];
} else { } else {
toRemove.push([...pathes, key]); toRemove.push([...pathes, key]);
return; return;
@@ -151,10 +159,14 @@ const Validate = function () {
} }
} }
toAdd = [] toAdd = [];
traverse(enObj, (obj, key, pathes) => { traverse(enObj, (obj, key, pathes) => {
// Add above_key to the toAdd entry // Add above_key to the toAdd entry
if (toAdd.length > 0 && typeof toAdd.at(-1)[3] === 'undefined' && toAdd.at(-1)[1].at(-2) === pathes.at(-1)) { if (
toAdd.length > 0 &&
typeof toAdd.at(-1)[3] === 'undefined' &&
toAdd.at(-1)[1].at(-2) === pathes.at(-1)
) {
toAdd.at(-1)[3] = key; toAdd.at(-1)[3] = key;
} }
@@ -164,7 +176,12 @@ const Validate = function () {
if (Object.hasOwn(currObj, pathSegment)) { if (Object.hasOwn(currObj, pathSegment)) {
currObj = currObj[pathSegment]; currObj = currObj[pathSegment];
} else { } else {
toAdd.push([localeObj, [...pathes, key], obj[key], undefined]); toAdd.push([
localeObj,
[...pathes, key],
obj[key],
undefined
]);
return; return;
} }
} }
@@ -181,20 +198,23 @@ const Validate = function () {
if (toAdd.length > 0 || hasRemoved) { if (toAdd.length > 0 || hasRemoved) {
for (const [localePath, localeObj] of files) { for (const [localePath, localeObj] of files) {
fs.writeFileSync(localePath, `${JSON.stringify(localeObj, null, 4)}\n`); fs.writeFileSync(
localePath,
`${JSON.stringify(localeObj, null, 4)}\n`
);
} }
} else { } else {
console.log("validation passed!"); console.log('validation passed!');
} }
};
}
const cliParser = yargs(hideBin(process.argv)) const cliParser = yargs(hideBin(process.argv))
.command({ .command({
command: 'add <key> <value> [above_key]', command: 'add <key> <value> [above_key]',
aliases: ['a', 'replace', 'r'], aliases: ['a', 'replace', 'r'],
desc: 'adds or replaces a key and value to all localization files above `above_key`', desc: 'adds or replaces a key and value to all localization files above `above_key`',
handler: (argv) => addLocalizationKey(argv.key, argv.value, argv.above_key) handler: (argv) =>
addLocalizationKey(argv.key, argv.value, argv.above_key)
}) })
.command({ .command({
command: 'remove <key>', command: 'remove <key>',
@@ -205,17 +225,20 @@ const cliParser = yargs(hideBin(process.argv))
.command({ .command({
command: 'validate', command: 'validate',
aliases: [], aliases: [],
desc: 'removes keys from other languages that don\'t exist in the en translation and adds keys that don\'t exist in other languages', desc: "removes keys from other languages that don't exist in the en translation and adds keys that don't exist in other languages",
handler: Validate handler: Validate
}) })
.demandCommand(1) .demandCommand(1)
.example([ .example([
['$0 add foo.bar "I\'m adding a key!"', 'Adding a key as `foo.bar`'], ['$0 add foo.bar "I\'m adding a key!"', 'Adding a key as `foo.bar`'],
['$0 remove foo.bar', 'removes the foo.bar key'], ['$0 remove foo.bar', 'removes the foo.bar key'],
['$0 add foo.bar "I\'m adding a key!" baz', 'Adding a key aboe the existing `foo.baz` key'] [
'$0 add foo.bar "I\'m adding a key!" baz',
'Adding a key aboe the existing `foo.baz` key'
]
]) ])
.help(false) .help(false)
.version(false) .version(false);
cliParser cliParser
.wrap(cliParser.terminalWidth()) .wrap(cliParser.terminalWidth())
@@ -226,4 +249,4 @@ cliParser
handler: () => cliParser.showHelp() handler: () => cliParser.showHelp()
}) })
.fail(() => cliParser.showHelp()) .fail(() => cliParser.showHelp())
.parse() .parse();

View File

@@ -1,5 +1,6 @@
import AvatarInfo from '../components/AvatarInfo.vue'; import AvatarInfo from '../components/AvatarInfo.vue';
import CountdownTimer from '../components/CountdownTimer.vue'; import CountdownTimer from '../components/CountdownTimer.vue';
import DataTable from '../components/DataTable.vue';
import DisplayName from '../components/DisplayName.vue'; import DisplayName from '../components/DisplayName.vue';
import InstanceInfo from '../components/InstanceInfo.vue'; import InstanceInfo from '../components/InstanceInfo.vue';
import InviteYourself from '../components/InviteYourself.vue'; import InviteYourself from '../components/InviteYourself.vue';
@@ -8,7 +9,6 @@ import Launch from '../components/Launch.vue';
import Location from '../components/Location.vue'; import Location from '../components/Location.vue';
import LocationWorld from '../components/LocationWorld.vue'; import LocationWorld from '../components/LocationWorld.vue';
import Timer from '../components/Timer.vue'; import Timer from '../components/Timer.vue';
import DataTable from '../components/DataTable.vue';
export function initComponents(app) { export function initComponents(app) {
app.component('Location', Location); app.component('Location', Location);

View File

@@ -1,10 +1,10 @@
import customParseFormat from 'dayjs/plugin/customParseFormat';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration'; import duration from 'dayjs/plugin/duration';
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'; import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
import localizedFormat from 'dayjs/plugin/localizedFormat';
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';
export function initDayjs() { export function initDayjs() {
dayjs.extend(duration); dayjs.extend(duration);

View File

@@ -1,4 +1,5 @@
import { createI18n } from 'vue-i18n'; import { createI18n } from 'vue-i18n';
import * as localizedStrings from '../localization/localizedStrings'; import * as localizedStrings from '../localization/localizedStrings';
const i18n = createI18n({ const i18n = createI18n({

View File

@@ -1,5 +1,5 @@
import { initInteropApi } from './interopApi';
import { initDayjs } from './dayjs'; import { initDayjs } from './dayjs';
import { initInteropApi } from './interopApi';
import { initNoty } from './noty'; import { initNoty } from './noty';
import { initUi } from './ui'; import { initUi } from './ui';

View File

@@ -1,6 +1,7 @@
import * as Sentry from '@sentry/vue';
import configRepository from '../service/config'; import configRepository from '../service/config';
import * as Sentry from '@sentry/vue';
export async function initSentry(app) { export async function initSentry(app) {
const enabled = await configRepository.getString( const enabled = await configRepository.getString(
'VRCX_SentryEnabled', 'VRCX_SentryEnabled',

View File

@@ -1,14 +1,15 @@
import configRepository from '../service/config';
import { import {
changeAppDarkStyle, changeAppDarkStyle,
changeAppThemeStyle, changeAppThemeStyle,
getThemeMode,
refreshCustomCss, refreshCustomCss,
refreshCustomScript, refreshCustomScript,
setLoginContainerStyle, setLoginContainerStyle
getThemeMode
} from '../shared/utils/base/ui'; } from '../shared/utils/base/ui';
import { i18n } from './i18n'; import { i18n } from './i18n';
import configRepository from '../service/config';
export async function initUi() { export async function initUi() {
try { try {
// @ts-ignore // @ts-ignore

View File

@@ -1,5 +1,7 @@
import { reactive } from 'vue'; import { reactive } from 'vue';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import * as utils from '../shared/utils'; import * as utils from '../shared/utils';
const AppDebug = reactive({ const AppDebug = reactive({

View File

@@ -31,36 +31,81 @@ const charToConfusables = new Map([
['pi', 'ᒆ'], ['pi', 'ᒆ'],
['Nj', 'Nj'], ['Nj', 'Nj'],
['AE', 'ᴁ'], ['AE', 'ᴁ'],
['A', '𝑨𝔄ᗄ𝖠𝗔ꓯ𝞐🄐🄰Ꭿ𐊠𝕬𝜜𝐴ꓮᎪ𝚨ꭺ𝝖🅐Å∀🇦₳🅰𝒜𝘈𝐀𝔸дǺᗅⒶAΑᾋᗩĂÃÅǍȀȂĀȺĄʌΛλƛᴀᴬДАልÄₐᕱªǞӒΆẠẢẦẨẬẮẰẲẴẶᾸᾹᾺΆᾼᾈᾉᾊᾌᾍᾎᾏἈἉἊἋἌἍἎἏḀȦǠӐÀÁÂẤẪ𝛢𝓐𝙰𝘼ᗩ'], [
['a', '∂⍺ⓐձǟᵃᶏ⒜аɒaαȃȁคǎმäɑāɐąᾄẚạảǡầẵḁȧӑӓãåάὰάăẩằẳặᾀᾁᾂᾃᾅᾆᾰᾱᾲᾳᾴᶐᾶᾷἀἁἂἃἄἅἆἇᾇậắàáâấẫǻⱥ𝐚𝑎𝒂𝒶𝓪𝔞𝕒𝖆𝖺𝗮𝘢𝙖𝚊𝛂𝛼𝜶𝝰𝞪⍶'], 'A',
['B', '🄑𝔙𝖁ꞵ𝛃𝛽𝜷𝝱𝞫Ᏸ𐌁𝑩𝕭🄱𐊡𝖡𝘽ꓐ𝗕𝘉𝜝𐊂𝚩𝐁𝛣𝝗𝐵𝙱𝔹Ᏼᏼ𝞑Ꞵ𝔅🅑฿𝓑ᗿᗾᗽ🅱ⒷBвϐᗷƁ乃ßცჩ๖βɮБՅ๒ᙖʙᴮᵇጌḄℬΒВẞḂḆɃദᗹᗸᵝᙞᙟᙝᛒᙗᙘᴃ🇧'], '𝑨𝔄ᗄ𝖠𝗔ꓯ𝞐🄐🄰Ꭿ𐊠𝕬𝜜𝐴ꓮᎪ𝚨ꭺ𝝖🅐Å∀🇦₳🅰𝒜𝘈𝐀𝔸дǺᗅⒶAΑᾋᗩĂÃÅǍȀȂĀȺĄʌΛλƛᴀᴬДАልÄₐᕱªǞӒΆẠẢẦẨẬẮẰẲẴẶᾸᾹᾺΆᾼᾈᾉᾊᾌᾍᾎᾏἈἉἊἋἌἍἎἏḀȦǠӐÀÁÂẤẪ𝛢𝓐𝙰𝘼ᗩ'
],
[
'a',
'∂⍺ⓐձǟᵃᶏ⒜аɒaαȃȁคǎმäɑāɐąᾄẚạảǡầẵḁȧӑӓãåάὰάăẩằẳặᾀᾁᾂᾃᾅᾆᾰᾱᾲᾳᾴᶐᾶᾷἀἁἂἃἄἅἆἇᾇậắàáâấẫǻⱥ𝐚𝑎𝒂𝒶𝓪𝔞𝕒𝖆𝖺𝗮𝘢𝙖𝚊𝛂𝛼𝜶𝝰𝞪⍶'
],
[
'B',
'🄑𝔙𝖁ꞵ𝛃𝛽𝜷𝝱𝞫Ᏸ𐌁𝑩𝕭🄱𐊡𝖡𝘽ꓐ𝗕𝘉𝜝𐊂𝚩𝐁𝛣𝝗𝐵𝙱𝔹Ᏼᏼ𝞑Ꞵ𝔅🅑฿𝓑ᗿᗾᗽ🅱ⒷBвϐᗷƁ乃ßცჩ๖βɮБՅ๒ᙖʙᴮᵇጌḄℬΒВẞḂḆɃദᗹᗸᵝᙞᙟᙝᛒᙗᙘᴃ🇧'
],
['b', 'ꮟᏏ𝐛𝘣𝒷𝔟𝓫𝖇𝖻𝑏𝙗𝕓𝒃𝗯𝚋♭ᑳᒈbᖚᕹᕺⓑḃḅҍъḇƃɓƅᖯƄЬᑲþƂ⒝ЪᶀᑿᒀᒂᒁᑾьƀҌѢѣᔎ'], ['b', 'ꮟᏏ𝐛𝘣𝒷𝔟𝓫𝖇𝖻𝑏𝙗𝕓𝒃𝗯𝚋♭ᑳᒈbᖚᕹᕺⓑḃḅҍъḇƃɓƅᖯƄЬᑲþƂ⒝ЪᶀᑿᒀᒂᒁᑾьƀҌѢѣᔎ'],
['C', 'ꞆႠ℃🄒ᏟⲤ🄲ꓚ𐊢𐌂🅲𐐕🅒☾ČÇⒸCↃƇᑕㄈ¢८↻ĈϾՇȻᙅᶜ⒞ĆҀĊ©टƆℂℭϹС匚ḈҪʗᑖᑡᑢᑣᑤᑥⅭ𝐂𝐶𝑪𝒞𝓒𝕮𝖢𝗖𝘊𝘾ᔍ'], [
['c', '🝌cⅽ𝐜𝑐𝒄𝒸𝓬𝔠𝕔𝖈𝖼𝗰𝘤𝙘𝚌ᴄϲⲥсꮯ𐐽ⲥ𐐽ꮯĉcⓒćčċçҁƈḉȼↄсርᴄϲҫ꒝ςɽϛ𝙲ᑦ᧚𝐜𝑐𝒄𝒸𝓬𝔠𝕔𝖈𝖼𝗰𝘤𝙘𝚌₵🇨ᥴᒼⅽ'], 'C',
'ꞆႠ℃🄒ᏟⲤ🄲ꓚ𐊢𐌂🅲𐐕🅒☾ČÇⒸCↃƇᑕㄈ¢८↻ĈϾՇȻᙅᶜ⒞ĆҀĊ©टƆℂℭϹС匚ḈҪʗᑖᑡᑢᑣᑤᑥⅭ𝐂𝐶𝑪𝒞𝓒𝕮𝖢𝗖𝘊𝘾ᔍ'
],
[
'c',
'🝌cⅽ𝐜𝑐𝒄𝒸𝓬𝔠𝕔𝖈𝖼𝗰𝘤𝙘𝚌ᴄϲⲥсꮯ𐐽ⲥ𐐽ꮯĉcⓒćčċçҁƈḉȼↄсርᴄϲҫ꒝ςɽϛ𝙲ᑦ᧚𝐜𝑐𝒄𝒸𝓬𝔠𝕔𝖈𝖼𝗰𝘤𝙘𝚌₵🇨ᥴᒼⅽ'
],
['D', '🄓Ꭰ🄳𝔡𝖉𝔻𝗗𝘋𝙳𝐷𝓓𝐃𝑫𝕯𝖣𝔇𝘿ꭰⅅ𝒟ꓓ🅳🅓ⒹDƉᗪƊÐԺᴅᴰↁḊĐÞⅮᗞᑯĎḌḐḒḎᗫᗬᗟᗠᶛᴆ🇩'], ['D', '🄓Ꭰ🄳𝔡𝖉𝔻𝗗𝘋𝙳𝐷𝓓𝐃𝑫𝕯𝖣𝔇𝘿ꭰⅅ𝒟ꓓ🅳🅓ⒹDƉᗪƊÐԺᴅᴰↁḊĐÞⅮᗞᑯĎḌḐḒḎᗫᗬᗟᗠᶛᴆ🇩'],
['d', 'Ꮷ𝔡𝖉ᑯꓒ𝓭ᵭ₫ԃⓓdḋďḍḑḓḏđƌɖɗᵈ⒟ԁⅾᶁԀᑺᑻᑼᑽᒄᑰᑱᶑ𝕕𝖽𝑑𝘥𝒅𝙙𝐝𝗱𝚍ⅆ𝒹ʠժ'], ['d', 'Ꮷ𝔡𝖉ᑯꓒ𝓭ᵭ₫ԃⓓdḋďḍḑḓḏđƌɖɗᵈ⒟ԁⅾᶁԀᑺᑻᑼᑽᒄᑰᑱᶑ𝕕𝖽𝑑𝘥𝒅𝙙𝐝𝗱𝚍ⅆ𝒹ʠժ'],
['E', '£ᙓ⋿∃ⴺꓱ𝐄𝐸𝔈𝕰𝖤𝘌𝙴𝛦𝜠ꭼ🄔🄴𝙀𝔼𐊆𝚬ꓰ𝝚𝞔𝓔𝑬𝗘🅴🅔ⒺΈEƎἝᕮƐモЄᴇᴱᵉÉ乇ЁɆꂅ€ÈℰΕЕⴹᎬĒĔĖĘĚÊËԐỀẾỄỂẼḔḖẺȄȆẸỆȨḜḘḚἘἙἚἛἜῈΈӖὲέЀϵ🇪'], [
['e', 'əәⅇꬲꞓ⋴𝛆𝛜𝜀𝜖𝜺𝝐𝝴𝞊𝞮𝟄ⲉꮛ𐐩ꞒⲈ⍷𝑒𝓮𝕖𝖊𝘦𝗲𝚎𝙚𝒆𝔢𝖾𝐞Ҿҿⓔe⒠èᧉéᶒêɘἔềếễ૯ǝєεēҽɛểẽḕḗĕėëẻěȅȇẹệȩɇₑęḝḙḛ℮еԑѐӗᥱёἐἑἒἓἕℯ'], 'E',
'£ᙓ⋿∃ⴺꓱ𝐄𝐸𝔈𝕰𝖤𝘌𝙴𝛦𝜠ꭼ🄔🄴𝙀𝔼𐊆𝚬ꓰ𝝚𝞔𝓔𝑬𝗘🅴🅔ⒺΈEƎἝᕮƐモЄᴇᴱᵉÉ乇ЁɆꂅ€ÈℰΕЕⴹᎬĒĔĖĘĚÊËԐỀẾỄỂẼḔḖẺȄȆẸỆȨḜḘḚἘἙἚἛἜῈΈӖὲέЀϵ🇪'
],
[
'e',
'əәⅇꬲꞓ⋴𝛆𝛜𝜀𝜖𝜺𝝐𝝴𝞊𝞮𝟄ⲉꮛ𐐩ꞒⲈ⍷𝑒𝓮𝕖𝖊𝘦𝗲𝚎𝙚𝒆𝔢𝖾𝐞Ҿҿⓔe⒠èᧉéᶒêɘἔềếễ૯ǝєεēҽɛểẽḕḗĕėëẻěȅȇẹệȩɇₑęḝḙḛ℮еԑѐӗᥱёἐἑἒἓἕℯ'
],
['F', 'ᖵꘘꓞꟻᖷ𝐅𝐹𝑭𝔽𝕱𝖥𝗙𝙁𝙵𝟊℉🄕🄵𐊇𝔉𝘍𐊥ꓝꞘ🅵🅕𝓕ⒻFғҒᖴƑԲϝቻḞℱϜ₣🇫Ⅎ'], ['F', 'ᖵꘘꓞꟻᖷ𝐅𝐹𝑭𝔽𝕱𝖥𝗙𝙁𝙵𝟊℉🄕🄵𐊇𝔉𝘍𐊥ꓝꞘ🅵🅕𝓕ⒻFғҒᖴƑԲϝቻḞℱϜ₣🇫Ⅎ'],
['f', '𝐟ᵮ𝑓𝒇𝒻𝓯𝔣𝕗𝖿𝗳𝙛𝚏ꬵꞙẝ𝖋ⓕfƒḟʃբᶠ⒡ſꊰʄ∱ᶂ𝘧'], ['f', '𝐟ᵮ𝑓𝒇𝒻𝓯𝔣𝕗𝖿𝗳𝙛𝚏ꬵꞙẝ𝖋ⓕfƒḟʃբᶠ⒡ſꊰʄ∱ᶂ𝘧'],
['G', '𝗚𝘎🄖ꓖᏳ🄶Ꮐᏻ𝔾𝓖𝑮𝕲ꮐ𝒢𝙂𝖦𝙶𝔊𝐺𝐆🅶🅖ⒼGɢƓʛĢᘜᴳǴĠԌĜḠĞǦǤԍ₲🇬⅁'], ['G', '𝗚𝘎🄖ꓖᏳ🄶Ꮐᏻ𝔾𝓖𝑮𝕲ꮐ𝒢𝙂𝖦𝙶𝔊𝐺𝐆🅶🅖ⒼGɢƓʛĢᘜᴳǴĠԌĜḠĞǦǤԍ₲🇬⅁'],
['g', 'ᶃᶢⓖgǵĝḡğġǧģց૭ǥɠﻭﻮᵍ⒢ℊɡᧁ𝐠𝑔𝒈𝓰𝔤𝕘𝖌𝗀𝗴𝘨𝙜𝚐'], ['g', 'ᶃᶢⓖgǵĝḡğġǧģց૭ǥɠﻭﻮᵍ⒢ℊɡᧁ𝐠𝑔𝒈𝓰𝔤𝕘𝖌𝗀𝗴𝘨𝙜𝚐'],
['H', 'Ἤ🄗𝆦🄷𝜢ꓧ𝘏𝐻𝝜𝖧𐋏𝗛ꮋℍᎻℌⲎ𝑯𝞖🅷🅗ዞǶԋⒽHĤᚺḢḦȞḤḨḪĦⱧҢңҤῊΉῌἨἩἪἫἭἮἯᾘᾙᾚᾛᾜᾝᾞᾟӉӈҥΉн卄♓𝓗ℋН𝐇𝙃𝙷ʜ𝛨Η𝚮ᕼӇᴴᵸ🇭'], [
'H',
'Ἤ🄗𝆦🄷𝜢ꓧ𝘏𝐻𝝜𝖧𐋏𝗛ꮋℍᎻℌⲎ𝑯𝞖🅷🅗ዞǶԋⒽHĤᚺḢḦȞḤḨḪĦⱧҢңҤῊΉῌἨἩἪἫἭἮἯᾘᾙᾚᾛᾜᾝᾞᾟӉӈҥΉн卄♓𝓗ℋН𝐇𝙃𝙷ʜ𝛨Η𝚮ᕼӇᴴᵸ🇭'
],
['h', 'ꞕ৸𝕳ꚕᏲℏӊԊꜧᏂҺ⒣ђⓗhĥḣḧȟḥḩḫẖħⱨհһከኩኪካɦℎ𝐡𝒉𝒽𝓱𝔥𝕙𝖍𝗁𝗵𝘩𝙝𝚑իʰᑋᗁɧんɥ'], ['h', 'ꞕ৸𝕳ꚕᏲℏӊԊꜧᏂҺ⒣ђⓗhĥḣḧȟḥḩḫẖħⱨհһከኩኪካɦℎ𝐡𝒉𝒽𝓱𝔥𝕙𝖍𝗁𝗵𝘩𝙝𝚑իʰᑋᗁɧんɥ'],
['I', 'ⲒἿ🄘🄸ЇꀤᏆ🅸🅘إﺇٳأﺃٲٵⒾI៸ÌÍÎĨĪĬİÏḮỈǏȈȊỊĮḬƗェエῘῙῚΊἸἹἺἻἼἽἾⅠΪΊɪᶦᑊᥣ𝛪𝐈𝙄𝙸𝓵𝙡𝐼ᴵ𝚰𝑰🇮'], [
['i', '⍳ℹⅈ𝑖𝒊𝒾ı𝚤ɩιιͺ𝛊𝜄𝜾𝞲ꙇӏꭵᎥⓘiìíîĩīĭïḯỉǐȉȋịḭῐῑῒΐῖῗἰἱἲⅰⅼ∣ⵏ│׀ا١۱ߊᛁἳἴἵɨіὶίᶖ𝔦𝚒𝝸𝗂𝐢𝕚𝖎𝗶𝘪𝙞ίⁱᵢ𝓲⒤'], 'I',
'ⲒἿ🄘🄸ЇꀤᏆ🅸🅘إﺇٳأﺃٲٵⒾI៸ÌÍÎĨĪĬİÏḮỈǏȈȊỊĮḬƗェエῘῙῚΊἸἹἺἻἼἽἾⅠΪΊɪᶦᑊᥣ𝛪𝐈𝙄𝙸𝓵𝙡𝐼ᴵ𝚰𝑰🇮'
],
[
'i',
'⍳ℹⅈ𝑖𝒊𝒾ı𝚤ɩιιͺ𝛊𝜄𝜾𝞲ꙇӏꭵᎥⓘiìíîĩīĭïḯỉǐȉȋịḭῐῑῒΐῖῗἰἱἲⅰⅼ∣ⵏ│׀ا١۱ߊᛁἳἴἵɨіὶίᶖ𝔦𝚒𝝸𝗂𝐢𝕚𝖎𝗶𝘪𝙞ίⁱᵢ𝓲⒤'
],
['J', '𝐉𝐽𝑱𝒥𝓙𝔍𝕁𝕵𝖩𝗝𝘑𝙅𝙹ꞲͿꓙ🄙🄹🅹🅙ⒿJЈʝᒍנフĴʆวلյʖᴊᴶﻝጋɈⱼՂๅႱįᎫȷ丿ℐℑᒘᒙᒚᒛᒴᒵᒎᒏ🇯'], ['J', '𝐉𝐽𝑱𝒥𝓙𝔍𝕁𝕵𝖩𝗝𝘑𝙅𝙹ꞲͿꓙ🄙🄹🅹🅙ⒿJЈʝᒍנフĴʆวلյʖᴊᴶﻝጋɈⱼՂๅႱįᎫȷ丿ℐℑᒘᒙᒚᒛᒴᒵᒎᒏ🇯'],
['j', '𝚥ꭻⅉⓙjϳʲ⒥ɉĵǰјڶᶨ𝒿𝘫𝗷𝑗𝙟𝔧𝒋𝗃𝓳𝕛𝚓𝖏𝐣'], ['j', '𝚥ꭻⅉⓙjϳʲ⒥ɉĵǰјڶᶨ𝒿𝘫𝗷𝑗𝙟𝔧𝒋𝗃𝓳𝕛𝚓𝖏𝐣'],
['K', '𝐊ꝄꝀ𝐾𝑲𝓚𝕶𝖪𝙺𝚱𝝟🄚𝗞🄺𝜥𝘒ꓗ𝙆𝕂Ⲕ𝔎𝛫Ꮶ𝞙𝒦🅺🅚₭ⓀKĸḰќƘкҠκқҟӄʞҚКҡᴋᴷᵏ⒦ᛕЌጕḲΚKҜҝҞĶḴǨⱩϗӃ🇰'], ['K', '𝐊ꝄꝀ𝐾𝑲𝓚𝕶𝖪𝙺𝚱𝝟🄚𝗞🄺𝜥𝘒ꓗ𝙆𝕂Ⲕ𝔎𝛫Ꮶ𝞙𝒦🅺🅚₭ⓀKĸḰќƘкҠκқҟӄʞҚКҡᴋᴷᵏ⒦ᛕЌጕḲΚKҜҝҞĶḴǨⱩϗӃ🇰'],
['k', 'ⓚꝁkḱǩḳķḵƙⱪᶄ𝐤𝘬𝗄𝕜𝜅𝜘𝜿𝝒𝝹𝞌𝞳𝙠𝚔𝑘𝒌ϰ𝛋𝛞𝟆𝗸𝓴𝓀'], ['k', 'ⓚꝁkḱǩḳķḵƙⱪᶄ𝐤𝘬𝗄𝕜𝜅𝜘𝜿𝝒𝝹𝞌𝞳𝙠𝚔𝑘𝒌ϰ𝛋𝛞𝟆𝗸𝓴𝓀'],
['L', '𝐋𝐿𝔏𝕃𝕷𝖫𝗟𝘓𝙇ﴼ🄛🄻𐐛Ⳑ𝑳𝙻𐑃𝓛ⳑꮮᏞꓡ🅻🅛ﺈ└ⓁւLĿᒪ乚ՆʟꓶιԼᴸˡĹረḶₗΓլĻᄂⅬℒⱢᥧᥨᒻᒶᒷᶫﺎᒺᒹᒸᒫ⎳ㄥŁⱠﺄȽ🇱'], [
'L',
'𝐋𝐿𝔏𝕃𝕷𝖫𝗟𝘓𝙇ﴼ🄛🄻𐐛Ⳑ𝑳𝙻𐑃𝓛ⳑꮮᏞꓡ🅻🅛ﺈ└ⓁւLĿᒪ乚ՆʟꓶιԼᴸˡĹረḶₗΓլĻᄂⅬℒⱢᥧᥨᒻᒶᒷᶫﺎᒺᒹᒸᒫ⎳ㄥŁⱠﺄȽ🇱'
],
['l', 'ⓛlŀĺľḷḹļӀℓḽḻłレɭƚɫⱡ|Ɩ⒧ʅǀוןΙІ|ᶩӏ𝓘𝕀𝖨𝗜𝘐𝐥𝑙𝒍𝓁𝔩𝕝𝖑𝗅𝗹𝘭𝚕𝜤𝝞ı𝚤ɩι𝛊𝜄𝜾𝞲'], ['l', 'ⓛlŀĺľḷḹļӀℓḽḻłレɭƚɫⱡ|Ɩ⒧ʅǀוןΙІ|ᶩӏ𝓘𝕀𝖨𝗜𝘐𝐥𝑙𝒍𝓁𝔩𝕝𝖑𝗅𝗹𝘭𝚕𝜤𝝞ı𝚤ɩι𝛊𝜄𝜾𝞲'],
['M', 'ꮇ🄜🄼𐌑𐊰ꓟⲘᎷ🅼🅜ⓂMмṂ൱ᗰ州ᘻო๓♏ʍᙏᴍᴹᵐ⒨ḾМṀ௱ⅯℳΜϺᛖӍӎ𝐌𝑀𝑴𝓜𝔐𝕄𝕸𝖬𝗠𝘔𝙈𝙼𝚳𝛭𝜧𝝡𝞛🇲'], ['M', 'ꮇ🄜🄼𐌑𐊰ꓟⲘᎷ🅼🅜ⓂMмṂ൱ᗰ州ᘻო๓♏ʍᙏᴍᴹᵐ⒨ḾМṀ௱ⅯℳΜϺᛖӍӎ𝐌𝑀𝑴𝓜𝔐𝕄𝕸𝖬𝗠𝘔𝙈𝙼𝚳𝛭𝜧𝝡𝞛🇲'],
['m', '₥ᵯ𝖒𝐦𝗆𝔪𝕞𝓂ⓜmനᙢ൩ḿṁⅿϻṃጠɱ៳ᶆ𝙢𝓶𝚖𝑚𝗺᧕᧗'], ['m', '₥ᵯ𝖒𝐦𝗆𝔪𝕞𝓂ⓜmനᙢ൩ḿṁⅿϻṃጠɱ៳ᶆ𝙢𝓶𝚖𝑚𝗺᧕᧗'],
['N', '𝇙𝇚𝇜🄝𝆧𝙉🄽ℕꓠ𝛮𝝢𝙽𝚴𝑵𝑁Ⲛ𝐍𝒩𝞜𝗡𝘕𝜨𝓝𝖭🅽₦🅝ЙЍⓃҋ៷NᴎɴƝᑎ几иՈռИהЛπᴺᶰŃ刀ክṄⁿÑПΝᴨոϖǸŇṆŅṊṈทŊӢӣӤӥћѝйᥢҊᴻ🇳'], [
['n', 'ոռח𝒏𝓷𝙣𝑛𝖓𝔫𝗇𝚗𝗻ᥒⓝήnǹᴒńñᾗηṅňṇɲņṋṉղຖՌƞŋ⒩ภกɳпʼnлԉȠἠἡῃդᾐᾑᾒᾓᾔᾕᾖῄῆῇῂἢἣἤἥἦἧὴήበቡቢባቤብቦȵ𝛈𝜂𝜼𝝶𝞰𝕟𝘯𝐧𝓃ᶇᵰᥥ∩'], 'N',
['O', '𝜽⭘🔿ꭴ⭕⏺🄁🄀Ꭴ𝚯𝚹𝛩𝛳𝜣𝜭𝝝𝝧𝞗𝞡ⴱᎾᏫ⍬𝞱𝝷𝛉𝟎𝜃θ𝟘𝑂𝑶𝓞𝔒𝕆𝕺𝗢𝘖𝙊𝛰㈇ꄲ🄞🔾🄾𐊒𝟬ꓳⲞ𐐄𐊫𐓂𝞞🅞⍥◯ⵁ⊖0⊝𝝤Ѳϴ𝚶𝜪ѺӦӨӪΌʘ𝐎ǑÒŎÓÔÕȌȎㇿ❍ⓄOὋロ❤૦⊕ØФԾΘƠᴼᵒ⒪ŐÖₒ¤◊Φ〇ΟОՕଠഠ௦סỒỐỖỔṌȬṎŌṐṒȮȰȪỎỜỚỠỞỢỌỘǪǬǾƟⵔ߀៰⍜⎔⎕⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁⧂⧃ὈὉὊὌὍ'], '𝇙𝇚𝇜🄝𝆧𝙉🄽ℕꓠ𝛮𝝢𝙽𝚴𝑵𝑁Ⲛ𝐍𝒩𝞜𝗡𝘕𝜨𝓝𝖭🅽₦🅝ЙЍⓃҋ៷NᴎɴƝᑎ几иՈռИהЛπᴺᶰŃ刀ክṄⁿÑПΝᴨոϖǸŇṆŅṊṈทŊӢӣӤӥћѝйᥢҊᴻ🇳'
['o', 'ంಂംං૦௦۵ℴ𝑜𝒐𝖔ꬽ𝝄𝛔𝜎𝝈𝞂ჿ𝚘০୦ዐ𝛐𝗈𝞼ဝⲟ𝙤၀𐐬𝔬𐓪𝓸🇴⍤○ϙ🅾𝒪𝖮𝟢𝟶𝙾𝘰𝗼𝕠𝜊𝐨𝝾𝞸ᐤⓞѳ᧐ᥲðoఠᦞՓòөӧóºōôǒȏŏồốȍỗổõσṍȭṏὄṑṓȯȫ๏ᴏőöѻоዐǭȱ০୦٥౦೦൦๐໐οօᴑ०੦ỏơờớỡởợọộǫøǿɵծὀὁόὸόὂὃὅ'], ],
[
'n',
'ոռח𝒏𝓷𝙣𝑛𝖓𝔫𝗇𝚗𝗻ᥒⓝήnǹᴒńñᾗηṅňṇɲņṋṉղຖՌƞŋ⒩ภกɳпʼnлԉȠἠἡῃդᾐᾑᾒᾓᾔᾕᾖῄῆῇῂἢἣἤἥἦἧὴήበቡቢባቤብቦȵ𝛈𝜂𝜼𝝶𝞰𝕟𝘯𝐧𝓃ᶇᵰᥥ∩'
],
[
'O',
'𝜽⭘🔿ꭴ⭕⏺🄁🄀Ꭴ𝚯𝚹𝛩𝛳𝜣𝜭𝝝𝝧𝞗𝞡ⴱᎾᏫ⍬𝞱𝝷𝛉𝟎𝜃θ𝟘𝑂𝑶𝓞𝔒𝕆𝕺𝗢𝘖𝙊𝛰㈇ꄲ🄞🔾🄾𐊒𝟬ꓳⲞ𐐄𐊫𐓂𝞞🅞⍥◯ⵁ⊖0⊝𝝤Ѳϴ𝚶𝜪ѺӦӨӪΌʘ𝐎ǑÒŎÓÔÕȌȎㇿ❍ⓄOὋロ❤૦⊕ØФԾΘƠᴼᵒ⒪ŐÖₒ¤◊Φ〇ΟОՕଠഠ௦סỒỐỖỔṌȬṎŌṐṒȮȰȪỎỜỚỠỞỢỌỘǪǬǾƟⵔ߀៰⍜⎔⎕⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧀⧁⧂⧃ὈὉὊὌὍ'
],
[
'o',
'ంಂംං૦௦۵ℴ𝑜𝒐𝖔ꬽ𝝄𝛔𝜎𝝈𝞂ჿ𝚘০୦ዐ𝛐𝗈𝞼ဝⲟ𝙤၀𐐬𝔬𐓪𝓸🇴⍤○ϙ🅾𝒪𝖮𝟢𝟶𝙾𝘰𝗼𝕠𝜊𝐨𝝾𝞸ᐤⓞѳ᧐ᥲðoఠᦞՓòөӧóºōôǒȏŏồốȍỗổõσṍȭṏὄṑṓȯȫ๏ᴏőöѻоዐǭȱ০୦٥౦೦൦๐໐οօᴑ०੦ỏơờớỡởợọộǫøǿɵծὀὁόὸόὂὃὅ'
],
['P', '🄟🄿ꓑ𝚸𝙿𝞠𝙋ꮲⲢ𝒫𝝦𝑃𝑷𝗣𝐏𐊕𝜬𝘗𝓟𝖯𝛲Ꮲ🅟Ҏ🅿ⓅPƤᑭ尸Ṗրφքᴘᴾᵖ⒫ṔアקРየᴩⱣℙΡῬᑸᑶᑷᑹᑬᑮ🇵₱'], ['P', '🄟🄿ꓑ𝚸𝙿𝞠𝙋ꮲⲢ𝒫𝝦𝑃𝑷𝗣𝐏𐊕𝜬𝘗𝓟𝖯𝛲Ꮲ🅟Ҏ🅿ⓅPƤᑭ尸Ṗրφքᴘᴾᵖ⒫ṔアקРየᴩⱣℙΡῬᑸᑶᑷᑹᑬᑮ🇵₱'],
['p', 'ⲣҏ℗ⓟpṕṗƥᵽῥρрƿǷῤ⍴𝓹𝓅𝐩𝑝𝒑𝔭𝕡𝖕𝗉𝗽𝘱𝙥𝚙𝛒𝝆𝞺𝜌𝞀'], ['p', 'ⲣҏ℗ⓟpṕṗƥᵽῥρрƿǷῤ⍴𝓹𝓅𝐩𝑝𝒑𝔭𝕡𝖕𝗉𝗽𝘱𝙥𝚙𝛒𝝆𝞺𝜌𝞀'],
['Q', '🅀🄠Ꝗ🆀🅠ⓆQℚⵕԚ𝐐𝑄𝑸𝒬𝓠𝚀𝘘𝙌𝖰𝕼𝔔𝗤🇶'], ['Q', '🅀🄠Ꝗ🆀🅠ⓆQℚⵕԚ𝐐𝑄𝑸𝒬𝓠𝚀𝘘𝙌𝖰𝕼𝔔𝗤🇶'],
@@ -69,26 +114,43 @@ const charToConfusables = new Map([
['r', '𝚛ꭇᣴℾ𝚪𝛤𝜞𝝘𝞒ⲄГᎱᒥꭈⲅꮁⓡrŕṙřȑȓṛṝŗгՐɾᥬṟɍʳ⒭ɼѓᴦᶉ𝐫𝑟𝒓𝓇𝓻𝔯𝕣𝖗𝗋𝗿𝘳𝙧ᵲґᵣ'], ['r', '𝚛ꭇᣴℾ𝚪𝛤𝜞𝝘𝞒ⲄГᎱᒥꭈⲅꮁⓡrŕṙřȑȓṛṝŗгՐɾᥬṟɍʳ⒭ɼѓᴦᶉ𝐫𝑟𝒓𝓇𝓻𝔯𝕣𝖗𝗋𝗿𝘳𝙧ᵲґᵣ'],
['S', '🅂🄪🄢ꇙ𝓢𝗦Ꮪ𝒮Ꮥ𝚂𝐒ꓢ𝖲𝔖𝙎𐊖𝕾𐐠𝘚𝕊𝑆𝑺🆂🅢ⓈSṨŞֆՏȘˢ⒮ЅṠŠŚṤŜṦṢടᔕᔖᔢᔡᔣᔤ'], ['S', '🅂🄪🄢ꇙ𝓢𝗦Ꮪ𝒮Ꮥ𝚂𝐒ꓢ𝖲𝔖𝙎𐊖𝕾𐐠𝘚𝕊𝑆𝑺🆂🅢ⓈSṨŞֆՏȘˢ⒮ЅṠŠŚṤŜṦṢടᔕᔖᔢᔡᔣᔤ'],
['s', 'ᣵⓢꜱ𐑈ꮪsśṥŝṡšṧʂṣṩѕşșȿᶊక𝐬𝑠𝒔𝓈𝓼𝔰𝕤𝖘𝗌𝘀𝘴𝙨𝚜ގ🇸'], ['s', 'ᣵⓢꜱ𐑈ꮪsśṥŝṡšṧʂṣṩѕşșȿᶊక𝐬𝑠𝒔𝓈𝓼𝔰𝕤𝖘𝗌𝘀𝘴𝙨𝚜ގ🇸'],
['T', '🅃🄣七ፒ𝜯🆃𐌕𝚻𝛵𝕋𝕿𝑻𐊱𐊗𝖳𝙏🝨𝝩𝞣𝚃𝘛𝑇ꓔ⟙𝐓Ⲧ𝗧⊤𝔗Ꭲꭲ𝒯🅣⏇⏉ⓉTтҬҭƬイŦԵτᴛᵀイፕϮŤ⊥ƮΤТ下ṪṬȚŢṰṮ丅丁ᐪ𝛕𝜏𝝉𝞃𝞽𝓣ㄒ🇹ጥ'], [
'T',
'🅃🄣七ፒ𝜯🆃𐌕𝚻𝛵𝕋𝕿𝑻𐊱𐊗𝖳𝙏🝨𝝩𝞣𝚃𝘛𝑇ꓔ⟙𝐓Ⲧ𝗧⊤𝔗Ꭲꭲ𝒯🅣⏇⏉ⓉTтҬҭƬイŦԵτᴛᵀイፕϮŤ⊥ƮΤТ下ṪṬȚŢṰṮ丅丁ᐪ𝛕𝜏𝝉𝞃𝞽𝓣ㄒ🇹ጥ'
],
['t', 'ⓣtṫẗťṭțȶ੮էʇ†ţṱṯƭŧᵗ⒯ʈեƫ𝐭𝑡𝒕𝓉𝓽𝔱𝕥𝖙𝗍𝘁𝘵𝙩𝚝ナ'], ['t', 'ⓣtṫẗťṭțȶ੮էʇ†ţṱṯƭŧᵗ⒯ʈեƫ𝐭𝑡𝒕𝓉𝓽𝔱𝕥𝖙𝗍𝘁𝘵𝙩𝚝ナ'],
['U', '🅄Џ🄤ሀꓴ𐓎꒤🆄🅤ŨŬŮᑗᑘǓǕǗǙⓊUȖᑌ凵ƱմԱꓵЦŪՄƲᙀᵁᵘ⒰ŰપÜՍÙÚÛṸṺǛỦȔƯỪỨỮỬỰỤṲŲṶṴɄᥩᑧ∪ᘮ⋃𝐔𝑈𝑼𝒰𝓤𝔘𝕌𝖀𝖴𝗨𝘜𝙐𝚄🇺'], [
['u', '𝘂𝘶𝙪𝚞ꞟꭎꭒ𝛖𝜐𝝊𝞄𝞾𐓶ὺύⓤuùũūừṷṹŭǖữᥙǚǜὗυΰนսʊǘǔúůᴜűųยûṻцሁüᵾᵤµʋủȕȗưứửựụṳṵʉῠῡῢΰῦῧὐὑϋύὒὓὔὕὖᥔ𝐮𝑢𝒖𝓊𝓾𝔲𝕦𝖚𝗎ᶙ'], 'U',
'🅄Џ🄤ሀꓴ𐓎꒤🆄🅤ŨŬŮᑗᑘǓǕǗǙⓊUȖᑌ凵ƱմԱꓵЦŪՄƲᙀᵁᵘ⒰ŰપÜՍÙÚÛṸṺǛỦȔƯỪỨỮỬỰỤṲŲṶṴɄᥩᑧ∪ᘮ⋃𝐔𝑈𝑼𝒰𝓤𝔘𝕌𝖀𝖴𝗨𝘜𝙐𝚄🇺'
],
[
'u',
'𝘂𝘶𝙪𝚞ꞟꭎꭒ𝛖𝜐𝝊𝞄𝞾𐓶ὺύⓤuùũūừṷṹŭǖữᥙǚǜὗυΰนսʊǘǔúůᴜűųยûṻцሁüᵾᵤµʋủȕȗưứửựụṳṵʉῠῡῢΰῦῧὐὑϋύὒὓὔὕὖᥔ𝐮𝑢𝒖𝓊𝓾𝔲𝕦𝖚𝗎ᶙ'
],
['V', '𝑉𝒱𝕍𝗩🄥🅅ꓦ𝑽𝖵𝘝Ꮩ𝚅𝙑𝐕🆅🅥ⓋVᐯѴᵛ⒱۷ṾⅴⅤṼ٧ⴸѶᐺᐻ🇻𝓥'], ['V', '𝑉𝒱𝕍𝗩🄥🅅ꓦ𝑽𝖵𝘝Ꮩ𝚅𝙑𝐕🆅🅥ⓋVᐯѴᵛ⒱۷ṾⅴⅤṼ٧ⴸѶᐺᐻ🇻𝓥'],
['v', '∨⌄⋁ⅴ𝐯𝑣𝒗𝓋𝔳𝕧𝖛𝗏ꮩሀⓥv𝜐𝝊ṽṿ౮งѵעᴠνטᵥѷ៴ᘁ𝙫𝚟𝛎𝜈𝝂𝝼𝞶𝘷𝘃𝓿'], ['v', '∨⌄⋁ⅴ𝐯𝑣𝒗𝓋𝔳𝕧𝖛𝗏ꮩሀⓥv𝜐𝝊ṽṿ౮งѵעᴠνטᵥѷ៴ᘁ𝙫𝚟𝛎𝜈𝝂𝝼𝞶𝘷𝘃𝓿'],
['W', '𝐖𝑊𝓦𝔚𝕎𝖂𝖶𝗪𝙒𝚆🄦🅆ᏔᎳ𝑾ꓪ𝒲𝘞🆆Ⓦ🅦wWẂᾧᗯᥕ山ѠຟచաЩШώщฬшᙎᵂʷ⒲ฝሠẄԜẀŴẆẈധᘺѿᙡƜ₩🇼'], ['W', '𝐖𝑊𝓦𝔚𝕎𝖂𝖶𝗪𝙒𝚆🄦🅆ᏔᎳ𝑾ꓪ𝒲𝘞🆆Ⓦ🅦wWẂᾧᗯᥕ山ѠຟచաЩШώщฬшᙎᵂʷ⒲ฝሠẄԜẀŴẆẈധᘺѿᙡƜ₩🇼'],
['w', '𝐰ꝡ𝑤𝒘𝓌𝔀𝔴𝕨𝖜𝗐𝘄𝘸𝙬𝚠աẁꮃẃⓦ⍵ŵẇẅẘẉⱳὼὠὡὢὣωὤὥὦὧῲῳῴῶῷⱲѡԝᴡώᾠᾡᾢᾣᾤᾥᾦɯ𝝕𝟉𝞏'], ['w', '𝐰ꝡ𝑤𝒘𝓌𝔀𝔴𝕨𝖜𝗐𝘄𝘸𝙬𝚠աẁꮃẃⓦ⍵ŵẇẅẘẉⱳὼὠὡὢὣωὤὥὦὧῲῳῴῶῷⱲѡԝᴡώᾠᾡᾢᾣᾤᾥᾦɯ𝝕𝟉𝞏'],
['X', 'ꭓꭕ𝛘𝜒𝝌𝞆𝟀ⲭ🞨𝑿𝛸🄧🞩🞪🅇🞫🞬𐌗Ⲭꓫ𝖃𝞦𝘟𐊐𝚾𝝬𝜲Ꭓ𐌢𝖷𝑋𝕏𝔛𐊴𝗫🆇🅧❌Ⓧ𝓧XẊ᙭χㄨ𝒳ӾჯӼҳЖΧҲᵡˣ⒳אሸẌꊼⅩХ╳᙮ᕁᕽⅹᚷⵝ𝙓𝚇乂𝐗🇽'], [
'X',
'ꭓꭕ𝛘𝜒𝝌𝞆𝟀ⲭ🞨𝑿𝛸🄧🞩🞪🅇🞫🞬𐌗Ⲭꓫ𝖃𝞦𝘟𐊐𝚾𝝬𝜲Ꭓ𐌢𝖷𝑋𝕏𝔛𐊴𝗫🆇🅧❌Ⓧ𝓧XẊ᙭χㄨ𝒳ӾჯӼҳЖΧҲᵡˣ⒳אሸẌꊼⅩХ╳᙮ᕁᕽⅹᚷⵝ𝙓𝚇乂𝐗🇽'
],
['x', '᙮ⅹ𝑥𝒙𝓍𝔵𝕩𝖝𝗑𝘅ᕁᕽⓧxхẋ×ₓ⤫⤬⨯ẍᶍ𝙭ӽ𝘹𝐱𝚡⨰メ𝔁'], ['x', '᙮ⅹ𝑥𝒙𝓍𝔵𝕩𝖝𝗑𝘅ᕁᕽⓧxхẋ×ₓ⤫⤬⨯ẍᶍ𝙭ӽ𝘹𝐱𝚡⨰メ𝔁'],
['Y', '𝒴🄨𝓨𝔜𝖄𝖸𝘠𝙔𝚼𝛶𝝪𝞤УᎩᎽⲨ𝚈𝑌𝗬𝐘ꓬ𝒀𝜰𐊲🆈🅨ⓎYὛƳㄚʏ⅄ϔ¥¥ՎϓγץӲЧЎሃŸɎϤΥϒҮỲÝŶỸȲẎỶỴῨῩῪΎὙὝὟΫΎӮӰҰұ𝕐🇾'], [
'Y',
'𝒴🄨𝓨𝔜𝖄𝖸𝘠𝙔𝚼𝛶𝝪𝞤УᎩᎽⲨ𝚈𝑌𝗬𝐘ꓬ𝒀𝜰𐊲🆈🅨ⓎYὛƳㄚʏ⅄ϔ¥¥ՎϓγץӲЧЎሃŸɎϤΥϒҮỲÝŶỸȲẎỶỴῨῩῪΎὙὝὟΫΎӮӰҰұ𝕐🇾'
],
['y', '𝐲𝑦𝒚𝓎𝔂𝔶𝕪𝖞𝗒𝘆𝘺𝙮𝚢ʏỿꭚγℽ𝛄𝛾𝜸𝝲𝞬🅈ᎽᎩⓨyỳýŷỹȳẏÿỷуყẙỵƴɏᵞɣʸᶌү⒴ӳӱӯўУʎ'], ['y', '𝐲𝑦𝒚𝓎𝔂𝔶𝕪𝖞𝗒𝘆𝘺𝙮𝚢ʏỿꭚγℽ𝛄𝛾𝜸𝝲𝞬🅈ᎽᎩⓨyỳýŷỹȳẏÿỷуყẙỵƴɏᵞɣʸᶌү⒴ӳӱӯўУʎ'],
['Z', '🄩🅉ꓜ𝗭𝐙☡Ꮓ𝘡🆉🅩ⓏZẔƵ乙ẐȤᶻ⒵ŹℤΖŻŽẒⱫ🇿'], ['Z', '🄩🅉ꓜ𝗭𝐙☡Ꮓ𝘡🆉🅩ⓏZẔƵ乙ẐȤᶻ⒵ŹℤΖŻŽẒⱫ🇿'],
['z', '𝑍𝒁𝒵𝓩𝖹𝙕𝚉𝚭𝛧𝜡𝝛𝞕ᵶꮓ𝐳𝑧𝒛𝓏𝔃𝔷𝕫𝖟𝗓𝘇𝘻𝙯𝚣ⓩzźẑżžẓẕƶȥɀᴢጊʐⱬᶎʑᙆ'] ['z', '𝑍𝒁𝒵𝓩𝖹𝙕𝚉𝚭𝛧𝜡𝝛𝞕ᵶꮓ𝐳𝑧𝒛𝓏𝔃𝔷𝕫𝖟𝗓𝘇𝘻𝙯𝚣ⓩzźẑżžẓẕƶȥɀᴢጊʐⱬᶎʑᙆ']
]); ]);
/** @copyright Mathias Bynens <https://mathiasbynens.be/>. MIT license. */ /** @copyright Mathias Bynens <https://mathiasbynens.be/>. MIT license. */
const regexLineBreakCombiningMarks = /[\0-\x08\x0E-\x1F\x7F-\x84\x86-\x9F\u0300-\u034E\u0350-\u035B\u0363-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u061C\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D4-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F7E\u0F80-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFB-\u1DFF\u200C\u200E\u200F\u202A-\u202E\u2066-\u206F\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3035\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFFF9-\uFFFB]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDDCA-\uDDCC\uDE2C-\uDE37\uDE3E\uDEDF-\uDEEA\uDF00-\uDF03\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC35-\uDC46\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDDDC\uDDDD\uDE30-\uDE40\uDEAB-\uDEB7]|\uD807[\uDC2F-\uDC36\uDC38-\uDC3F\uDC92-\uDCA7\uDCA9-\uDCB6]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF51-\uDF7E\uDF8F-\uDF92]|\uD82F[\uDC9D\uDC9E\uDCA0-\uDCA3]|\uD834[\uDD65-\uDD69\uDD6D-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD4A]|\uDB40[\uDC01\uDC20-\uDC7F\uDD00-\uDDEF]/g; const regexLineBreakCombiningMarks =
/[\0-\x08\x0E-\x1F\x7F-\x84\x86-\x9F\u0300-\u034E\u0350-\u035B\u0363-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u061C\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D4-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F7E\u0F80-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFB-\u1DFF\u200C\u200E\u200F\u202A-\u202E\u2066-\u206F\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3035\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFFF9-\uFFFB]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDDCA-\uDDCC\uDE2C-\uDE37\uDE3E\uDEDF-\uDEEA\uDF00-\uDF03\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC35-\uDC46\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDDDC\uDDDD\uDE30-\uDE40\uDEAB-\uDEB7]|\uD807[\uDC2F-\uDC36\uDC38-\uDC3F\uDC92-\uDCA7\uDCA9-\uDCB6]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF51-\uDF7E\uDF8F-\uDF92]|\uD82F[\uDC9D\uDC9E\uDCA0-\uDCA3]|\uD834[\uDD65-\uDD69\uDD6D-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD4A]|\uDB40[\uDC01\uDC20-\uDC7F\uDD00-\uDDEF]/g;
/** @copyright Mathias Bynens <https://mathiasbynens.be/>. MIT license. */ /** @copyright Mathias Bynens <https://mathiasbynens.be/>. MIT license. */
const regexSymbolWithCombiningMarks = /([\0-\u02FF\u0370-\u1AAF\u1B00-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uE000-\uFE1F\uFE30-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])([\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]+)/g; const regexSymbolWithCombiningMarks =
/([\0-\u02FF\u0370-\u1AAF\u1B00-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uE000-\uFE1F\uFE30-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])([\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]+)/g;
const confusablesToChar = new Map(); const confusablesToChar = new Map();
for (const [char_, confusables] of charToConfusables) { for (const [char_, confusables] of charToConfusables) {
@@ -105,15 +167,24 @@ const removeConfusables = function (a) {
} }
let ret = ''; let ret = '';
for (const char_ of a.normalize().replace(regexLineBreakCombiningMarks, '').replace(regexSymbolWithCombiningMarks, '$1').replace(/\s/g, '')) { for (const char_ of a
.normalize()
.replace(regexLineBreakCombiningMarks, '')
.replace(regexSymbolWithCombiningMarks, '$1')
.replace(/\s/g, '')) {
ret += confusablesToChar.get(char_) || char_; ret += confusablesToChar.get(char_) || char_;
} }
return ret; return ret;
} };
const removeWhitespace = function (a) { const removeWhitespace = function (a) {
return a.replace(/\s/g, ''); return a.replace(/\s/g, '');
} };
export { removeConfusables as default, confusablesToChar, charToConfusables, removeWhitespace }; export {
removeConfusables as default,
confusablesToChar,
charToConfusables,
removeWhitespace
};

View File

@@ -1,17 +1,17 @@
import sqliteService from './sqlite.js';
import { feed } from './database/feed.js';
import { gameLog } from './database/gameLog.js';
import { notifications } from './database/notifications.js';
import { moderation } from './database/moderation.js';
import { friendLogHistory } from './database/friendLogHistory.js';
import { friendLogCurrent } from './database/friendLogCurrent.js';
import { memos } from './database/memos.js';
import { avatarFavorites } from './database/avatarFavorites.js'; import { avatarFavorites } from './database/avatarFavorites.js';
import { worldFavorites } from './database/worldFavorites.js'; import { feed } from './database/feed.js';
import { friendLogCurrent } from './database/friendLogCurrent.js';
import { friendLogHistory } from './database/friendLogHistory.js';
import { gameLog } from './database/gameLog.js';
import { memos } from './database/memos.js';
import { moderation } from './database/moderation.js';
import { notifications } from './database/notifications.js';
import { tableAlter } from './database/tableAlter.js'; import { tableAlter } from './database/tableAlter.js';
import { tableFixes } from './database/tableFixes.js'; import { tableFixes } from './database/tableFixes.js';
import { tableSize } from './database/tableSize.js'; import { tableSize } from './database/tableSize.js';
import { worldFavorites } from './database/worldFavorites.js';
import sqliteService from './sqlite.js';
const dbVars = { const dbVars = {
userId: '', userId: '',

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const avatarFavorites = { const avatarFavorites = {
addAvatarToCache(entry) { addAvatarToCache(entry) {
sqliteService.executeNonQuery( sqliteService.executeNonQuery(

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const feed = { const feed = {
async getFeedDatabase() { async getFeedDatabase() {
var feedDatabase = []; var feedDatabase = [];

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const friendLogCurrent = { const friendLogCurrent = {
async getFriendLogCurrent() { async getFriendLogCurrent() {
var friendLogCurrent = []; var friendLogCurrent = [];

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const friendLogHistory = { const friendLogHistory = {
async getFriendLogHistory() { async getFriendLogHistory() {
var friendLogHistory = []; var friendLogHistory = [];

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const gameLog = { const gameLog = {
async getGamelogDatabase() { async getGamelogDatabase() {
var gamelogDatabase = []; var gamelogDatabase = [];

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const memos = { const memos = {
// user memos // user memos

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const moderation = { const moderation = {
async getModeration(userId) { async getModeration(userId) {
var row = {}; var row = {};

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const notifications = { const notifications = {
async getNotifications() { async getNotifications() {
var notifications = []; var notifications = [];

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const tableAlter = { const tableAlter = {
async upgradeDatabaseVersion() { async upgradeDatabaseVersion() {
// var version = 0; // var version = 0;

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const tableFixes = { const tableFixes = {
async cleanLegendFromFriendLog() { async cleanLegendFromFriendLog() {
await sqliteService.executeNonQuery( await sqliteService.executeNonQuery(

View File

@@ -1,6 +1,7 @@
import sqliteService from '../sqlite.js';
import { dbVars } from '../database'; import { dbVars } from '../database';
import sqliteService from '../sqlite.js';
const tableSize = { const tableSize = {
async getMaxFriendLogNumber() { async getMaxFriendLogNumber() {
var friendNumber = 0; var friendNumber = 0;

View File

@@ -1,5 +1,5 @@
import * as workerTimers from 'worker-timers'; import * as workerTimers from 'worker-timers';
/* eslint-disable no-unused-vars */
let VRCXStorage = {}; let VRCXStorage = {};
export default class { export default class {

View File

@@ -1,8 +1,7 @@
import { ElMessage, ElMessageBox } from 'element-plus';
import Noty from 'noty'; import Noty from 'noty';
import { ElMessageBox, ElMessage } from 'element-plus';
import { i18n } from '../plugin/i18n';
import { statusCodes } from '../shared/constants/api.js';
import { escapeTag } from '../shared/utils';
import { import {
useAuthStore, useAuthStore,
useAvatarStore, useAvatarStore,
@@ -11,9 +10,13 @@ import {
useUserStore useUserStore
} from '../stores'; } from '../stores';
import { AppDebug } from './appConfig.js'; import { AppDebug } from './appConfig.js';
import webApiService from './webapi.js'; import { escapeTag } from '../shared/utils';
import { i18n } from '../plugin/i18n';
import { statusCodes } from '../shared/constants/api.js';
import { watchState } from './watchState'; import { watchState } from './watchState';
import webApiService from './webapi.js';
const pendingGetRequests = new Map(); const pendingGetRequests = new Map();
export let failedGetRequests = new Map(); export let failedGetRequests = new Map();

View File

@@ -1,7 +1,5 @@
import Noty from 'noty'; import Noty from 'noty';
import * as workerTimers from 'worker-timers';
import { groupRequest } from '../api';
import { escapeTag, parseLocation } from '../shared/utils';
import { import {
useFriendStore, useFriendStore,
useGalleryStore, useGalleryStore,
@@ -13,10 +11,14 @@ import {
useUiStore, useUiStore,
useUserStore useUserStore
} from '../stores'; } from '../stores';
import { escapeTag, parseLocation } from '../shared/utils';
import { AppDebug } from './appConfig'; import { AppDebug } from './appConfig';
import { groupRequest } from '../api';
import { request } from './request'; import { request } from './request';
import { watchState } from './watchState'; import { watchState } from './watchState';
import * as workerTimers from 'worker-timers';
let webSocket = null; let webSocket = null;
let lastWebSocketMessage = ''; let lastWebSocketMessage = '';

View File

@@ -1,9 +1,6 @@
import amoled from '../../assets/scss/themes/theme.amoled.scss?url';
import dark from '../../assets/scss/themes/theme.dark.scss?url'; import dark from '../../assets/scss/themes/theme.dark.scss?url';
import darkblue from '../../assets/scss/themes/theme.darkblue.scss?url'; import darkblue from '../../assets/scss/themes/theme.darkblue.scss?url';
import amoled from '../../assets/scss/themes/theme.amoled.scss?url';
// import darkvanillaold from '../../assets/scss/themes/theme.darkvanillaold.scss?url';
// import darkvanilla from '../../assets/scss/themes/theme.darkvanilla.scss?url';
// import pink from '../../assets/scss/themes/theme.pink.scss?url';
import material3 from '../../assets/scss/themes/theme.material3.scss?url'; import material3 from '../../assets/scss/themes/theme.material3.scss?url';
export const THEME_CONFIG = { export const THEME_CONFIG = {

View File

@@ -1,16 +1,16 @@
import { import {
compareByName,
compareByCreatedAt, compareByCreatedAt,
compareByCreatedAtAscending, compareByCreatedAtAscending,
compareByUpdatedAt,
compareByDisplayName, compareByDisplayName,
compareByMemberCount,
compareByPrivate,
compareByStatus,
compareByLastActive, compareByLastActive,
compareByLastSeen, compareByLastSeen,
compareByLocation,
compareByLocationAt, compareByLocationAt,
compareByLocation compareByMemberCount,
compareByName,
compareByPrivate,
compareByStatus,
compareByUpdatedAt
} from '../compare'; } from '../compare';
describe('Compare Functions', () => { describe('Compare Functions', () => {

View File

@@ -1,4 +1,4 @@
import { sortStatus, isFriendOnline } from '../friend'; import { isFriendOnline, sortStatus } from '../friend';
describe('Friend Utils', () => { describe('Friend Utils', () => {
describe('sortStatus', () => { describe('sortStatus', () => {

View File

@@ -1,7 +1,7 @@
import { import {
getEmojiFileName,
getPrintFileName, getPrintFileName,
getPrintLocalDate, getPrintLocalDate
getEmojiFileName
} from '../gallery'; } from '../gallery';
describe('Gallery Utils', () => { describe('Gallery Utils', () => {

View File

@@ -1,4 +1,4 @@
import { parseLocation, displayLocation } from '../location'; import { displayLocation, parseLocation } from '../location';
describe('Location Utils', () => { describe('Location Utils', () => {
describe('parseLocation', () => { describe('parseLocation', () => {

View File

@@ -1,5 +1,5 @@
import { useAuthStore } from '../../stores';
import { replaceBioSymbols } from './common'; import { replaceBioSymbols } from './common';
import { useAuthStore } from '../../stores';
/** /**
* *

View File

@@ -1,10 +1,10 @@
import { import {
changeLogRemoveLinks,
commaNumber,
escapeTag, escapeTag,
escapeTagRecursive, escapeTagRecursive,
textToHex,
commaNumber,
localeIncludes, localeIncludes,
changeLogRemoveLinks textToHex
} from '../string'; } from '../string';
describe('String Utils', () => { describe('String Utils', () => {

View File

@@ -1,10 +1,10 @@
import { useAvatarStore, useWorldStore } from '../../../stores';
import { compareUnityVersion } from '../avatar';
import { import {
extractFileId, extractFileId,
extractFileVersion, extractFileVersion,
extractVariantVersion extractVariantVersion
} from '../common'; } from '../common';
import { useAvatarStore, useWorldStore } from '../../../stores';
import { compareUnityVersion } from '../avatar';
/** /**
* *

View File

@@ -1,7 +1,8 @@
import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useAppearanceSettingsStore, useUiStore } from '../../../stores'; import { useAppearanceSettingsStore, useUiStore } from '../../../stores';
import { THEME_CONFIG } from '../../constants'; import { THEME_CONFIG } from '../../constants';
import { ElMessage } from 'element-plus';
import { i18n } from '../../../plugin/i18n'; import { i18n } from '../../../plugin/i18n';
/** /**

View File

@@ -1,15 +1,17 @@
import Noty from 'noty'; import { ElMessage, ElMessageBox } from 'element-plus';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { ElMessageBox, ElMessage } from 'element-plus';
import { miscRequest } from '../../api'; import Noty from 'noty';
import { import {
useAvatarStore, useAvatarStore,
useInstanceStore, useInstanceStore,
useWorldStore, useSearchStore,
useSearchStore useWorldStore
} from '../../stores'; } from '../../stores';
import { compareUnityVersion } from './avatar'; import { compareUnityVersion } from './avatar';
import { escapeTag } from './base/string'; import { escapeTag } from './base/string';
import { miscRequest } from '../../api';
/** /**
* *

View File

@@ -96,10 +96,7 @@ function compareByDisplayName(a, b) {
* @returns * @returns
*/ */
function compareById(a, b) { function compareById(a, b) {
if ( if (typeof a.id !== 'string' || typeof b.id !== 'string') {
typeof a.id !== 'string' ||
typeof b.id !== 'string'
) {
return 0; return 0;
} }
return a.id.localeCompare(b.id); return a.id.localeCompare(b.id);

View File

@@ -47,7 +47,10 @@ export function handleImageUploadInput(event, options = {}) {
const file = files[0]; const file = files[0];
if (file.size >= maxSize) { if (file.size >= maxSize) {
if (tooLargeMessage) { if (tooLargeMessage) {
ElMessage({ message: resolveMessage(tooLargeMessage), type: 'error' }); ElMessage({
message: resolveMessage(tooLargeMessage),
type: 'error'
});
} }
clearInput(); clearInput();
return { file: null, clearInput }; return { file: null, clearInput };
@@ -55,12 +58,18 @@ export function handleImageUploadInput(event, options = {}) {
let acceptRegex = null; let acceptRegex = null;
if (acceptPattern) { if (acceptPattern) {
acceptRegex = acceptPattern instanceof RegExp ? acceptPattern : new RegExp(acceptPattern); acceptRegex =
acceptPattern instanceof RegExp
? acceptPattern
: new RegExp(acceptPattern);
} }
if (acceptRegex && !acceptRegex.test(file.type)) { if (acceptRegex && !acceptRegex.test(file.type)) {
if (invalidTypeMessage) { if (invalidTypeMessage) {
ElMessage({ message: resolveMessage(invalidTypeMessage), type: 'error' }); ElMessage({
message: resolveMessage(invalidTypeMessage),
type: 'error'
});
} }
clearInput(); clearInput();
return { file: null, clearInput }; return { file: null, clearInput };

View File

@@ -1,8 +1,8 @@
import { useAppearanceSettingsStore, useUserStore } from '../../stores'; import { useAppearanceSettingsStore, useUserStore } from '../../stores';
import { languageMappings } from '../constants';
import { timeToText } from './base/format';
import { HueToHex } from './base/ui'; import { HueToHex } from './base/ui';
import { convertFileUrlToImageUrl } from './common'; import { convertFileUrlToImageUrl } from './common';
import { languageMappings } from '../constants';
import { timeToText } from './base/format';
/** /**
* *

View File

@@ -1,6 +1,7 @@
import { worldRequest } from '../../api';
import { parseLocation } from './location'; import { parseLocation } from './location';
import { rpcWorlds } from '../constants'; import { rpcWorlds } from '../constants';
import { worldRequest } from '../../api';
/** /**
* *
* @param {string} location * @param {string} location

View File

@@ -1,23 +1,26 @@
import Noty from 'noty'; import { reactive, ref, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { ref, reactive, watch } from 'vue';
import { ElMessageBox, ElMessage } from 'element-plus';
import { authRequest } from '../api';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import configRepository from '../service/config';
import { database } from '../service/database'; import Noty from 'noty';
import { AppDebug } from '../service/appConfig';
import { request } from '../service/request';
import security from '../service/security';
import webApiService from '../service/webapi';
import { closeWebSocket, initWebsocket } from '../service/websocket'; import { closeWebSocket, initWebsocket } from '../service/websocket';
import { watchState } from '../service/watchState'; import { AppDebug } from '../service/appConfig';
import { authRequest } from '../api';
import { database } from '../service/database';
import { escapeTag } from '../shared/utils'; import { escapeTag } from '../shared/utils';
import { useNotificationStore } from './notification'; import { request } from '../service/request';
import { useAdvancedSettingsStore } from './settings/advanced'; import { useAdvancedSettingsStore } from './settings/advanced';
import { useNotificationStore } from './notification';
import { useUpdateLoopStore } from './updateLoop'; import { useUpdateLoopStore } from './updateLoop';
import { useUserStore } from './user'; import { useUserStore } from './user';
import { useVrcxStore } from './vrcx'; import { useVrcxStore } from './vrcx';
import { watchState } from '../service/watchState';
import configRepository from '../service/config';
import security from '../service/security';
import webApiService from '../service/webapi';
export const useAuthStore = defineStore('Auth', () => { export const useAuthStore = defineStore('Auth', () => {
const advancedSettingsStore = useAdvancedSettingsStore(); const advancedSettingsStore = useAdvancedSettingsStore();

View File

@@ -1,11 +1,7 @@
import { defineStore } from 'pinia'; import { nextTick, ref, watch } from 'vue';
import { ref, watch, nextTick } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { avatarRequest, miscRequest } from '../api'; import { defineStore } from 'pinia';
import { database } from '../service/database';
import { AppDebug } from '../service/appConfig';
import webApiService from '../service/webapi';
import { watchState } from '../service/watchState';
import { import {
checkVRChatCache, checkVRChatCache,
extractFileId, extractFileId,
@@ -15,11 +11,17 @@ import {
replaceBioSymbols, replaceBioSymbols,
storeAvatarImage storeAvatarImage
} from '../shared/utils'; } from '../shared/utils';
import { avatarRequest, miscRequest } from '../api';
import { AppDebug } from '../service/appConfig';
import { database } from '../service/database';
import { useAdvancedSettingsStore } from './settings/advanced';
import { useAvatarProviderStore } from './avatarProvider'; import { useAvatarProviderStore } from './avatarProvider';
import { useFavoriteStore } from './favorite'; import { useFavoriteStore } from './favorite';
import { useAdvancedSettingsStore } from './settings/advanced';
import { useUserStore } from './user'; import { useUserStore } from './user';
import { useVRCXUpdaterStore } from './vrcxUpdater'; import { useVRCXUpdaterStore } from './vrcxUpdater';
import { watchState } from '../service/watchState';
import webApiService from '../service/webapi';
export const useAvatarStore = defineStore('Avatar', () => { export const useAvatarStore = defineStore('Avatar', () => {
const favoriteStore = useFavoriteStore(); const favoriteStore = useFavoriteStore();

Some files were not shown because too many files have changed in this diff Show More