refactor: app.js (#1291)

* refactor: frontend

* Fix avatar gallery sort

* Update .NET dependencies

* Update npm dependencies

electron v37.1.0

* bulkRefreshFriends

* fix dark theme

* Remove crowdin

* Fix config.json dialog not updating

* VRCX log file fixes & add Cef log

* Remove SharedVariable, fix startup

* Revert init theme change

* Logging date not working? Fix WinformThemer designer error

* Add Cef request hander, no more escaping main page

* clean

* fix

* fix

* clean

* uh

* Apply thememode at startup, fixes random user colours

* Split database into files

* Instance info remove empty lines

* Open external VRC links with VRCX

* Electron fixes

* fix userdialog style

* ohhhh

* fix store

* fix store

* fix: load all group members after kicking a user

* fix: world dialog favorite button style

* fix: Clear VRCX Cache Timer input value

* clean

* Fix VR overlay

* Fix VR overlay 2

* Fix Discord discord rich presence for RPC worlds

* Clean up age verified user tags

* Fix playerList being occupied after program reload

* no `this`

* Fix login stuck loading

* writable: false

* Hide dialogs on logout

* add flush sync option

* rm LOGIN event

* rm LOGOUT event

* remove duplicate event listeners

* remove duplicate event listeners

* clean

* remove duplicate event listeners

* clean

* fix theme style

* fix t

* clearable

* clean

* fix ipcEvent

* Small changes

* Popcorn Palace support

* Remove checkActiveFriends

* Clean up

* Fix dragEnterCef

* Block API requests when not logged in

* Clear state on login & logout

* Fix worldDialog instances not updating

* use <script setup>

* Fix avatar change event, CheckGameRunning at startup

* Fix image dragging

* fix

* Remove PWI

* fix updateLoop

* add webpack-dev-server to dev environment

* rm unnecessary chunks

* use <script setup>

* webpack-dev-server changes

* use <script setup>

* use <script setup>

* Fix UGC text size

* Split login event

* t

* use <script setup>

* fix

* Update .gitignore and enable checkJs in jsconfig

* fix i18n t

* use <script setup>

* use <script setup>

* clean

* global types

* fix

* use checkJs for debugging

* Add watchState for login watchers

* fix .vue template

* type fixes

* rm Vue.filter

* Cef v138.0.170, VC++ 2022

* Settings fixes

* Remove 'USER:CURRENT'

* clean up 2FA callbacks

* remove userApply

* rm i18n import

* notification handling to use notification store methods

* refactor favorite handling to use favorite store methods and clean up event emissions

* refactor moderation handling to use dedicated functions for player moderation events

* refactor friend handling to use dedicated functions for friend events

* Fix program startup, move lang init

* Fix friend state

* Fix status change error

* Fix user notes diff

* fix

* rm group event

* rm auth event

* rm avatar event

* clean

* clean

* getUser

* getFriends

* getFavoriteWorlds, getFavoriteAvatars

* AvatarGalleryUpload btn style & package.json update

* Fix friend requests

* Apply user

* Apply world

* Fix note diff

* Fix VR overlay

* Fixes

* Update build scripts

* Apply avatar

* Apply instance

* Apply group

* update hidden VRC+ badge

* Fix sameInstance "private"

* fix 502/504 API errors

* fix 502/504 API errors

* clean

* Fix friend in same instance on orange showing twice in friends list

* Add back in broken friend state repair methods

* add types

---------

Co-authored-by: Natsumi <cmcooper123@hotmail.com>
This commit is contained in:
pa
2025-07-14 12:00:08 +09:00
committed by GitHub
parent 952fd77ed5
commit f4f78bb5ec
323 changed files with 47745 additions and 43326 deletions

View File

@@ -13,7 +13,7 @@
icon="el-icon-delete"
circle
style="flex: none; margin-left: 10px"
@click="clearSearch"></el-button>
@click="handleClearSearch"></el-button>
</el-tooltip>
</div>
<el-tabs ref="searchTabRef" type="card" style="margin-top: 15px" @tab-click="searchText = ''">
@@ -55,14 +55,14 @@
:disabled="!searchUserParams.offset"
icon="el-icon-back"
size="small"
@click="moreSearchUser(-1)"
@click="handleMoreSearchUser(-1)"
>{{ t('view.search.prev_page') }}</el-button
>
<el-button
:disabled="searchUserResults.length < 10"
icon="el-icon-right"
size="small"
@click="moreSearchUser(1)"
@click="handleMoreSearchUser(1)"
>{{ t('view.search.next_page') }}</el-button
>
</el-button-group>
@@ -81,7 +81,7 @@
></el-button>
<el-dropdown-menu v-slot="dropdown">
<el-dropdown-item
v-for="row in API.cachedConfig.dynamicWorldRows"
v-for="row in cachedConfig.dynamicWorldRows"
:key="row.index"
:command="row"
v-text="row.name"></el-dropdown-item>
@@ -313,79 +313,51 @@
</div>
</template>
<script>
export default {
name: 'SearchTab'
};
</script>
<script setup>
import { inject, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { ref } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { groupRequest, worldRequest } from '../../api';
import utils from '../../classes/utils';
import { convertFileUrlToImageUrl } from '../../composables/shared/utils';
import {
compareByCreatedAt,
compareByName,
compareByUpdatedAt,
convertFileUrlToImageUrl,
replaceBioSymbols,
userImage
} from '../../shared/utils';
import {
useAdvancedSettingsStore,
useAppearanceSettingsStore,
useAuthStore,
useAvatarProviderStore,
useAvatarStore,
useGroupStore,
useSearchStore,
useUiStore,
useUserStore,
useWorldStore
} from '../../stores';
const { hideTooltips, randomUserColours } = storeToRefs(useAppearanceSettingsStore());
const { avatarRemoteDatabase } = storeToRefs(useAdvancedSettingsStore());
const { avatarRemoteDatabaseProviderList, avatarRemoteDatabaseProvider } = storeToRefs(useAvatarProviderStore());
const { setAvatarProvider } = useAvatarProviderStore();
const { userDialog } = storeToRefs(useUserStore());
const { showUserDialog, refreshUserDialogAvatars } = useUserStore();
const { showAvatarDialog, lookupAvatars } = useAvatarStore();
const { cachedAvatars } = storeToRefs(useAvatarStore());
const { cachedWorlds } = storeToRefs(useWorldStore());
const { showWorldDialog } = useWorldStore();
const { showGroupDialog, applyGroup } = useGroupStore();
const { cachedGroups } = storeToRefs(useGroupStore());
const { menuActiveIndex } = storeToRefs(useUiStore());
const { searchText, searchUserResults } = storeToRefs(useSearchStore());
const { clearSearch, moreSearchUser } = useSearchStore();
const { cachedConfig } = storeToRefs(useAuthStore());
const { t } = useI18n();
const API = inject('API');
const showUserDialog = inject('showUserDialog');
const userImage = inject('userImage');
const showWorldDialog = inject('showWorldDialog');
const showAvatarDialog = inject('showAvatarDialog');
const showGroupDialog = inject('showGroupDialog');
const props = defineProps({
menuActiveIndex: {
type: String,
default: ''
},
searchText: {
type: String,
default: ''
},
searchUserResults: {
type: Array,
default: () => []
},
randomUserColours: {
type: Boolean,
default: false
},
avatarRemoteDatabaseProviderList: {
type: Array,
default: () => []
},
avatarRemoteDatabaseProvider: {
type: String,
default: ''
},
hideTooltips: {
type: Boolean,
default: false
},
userDialog: {
type: Object,
default: () => ({})
},
lookupAvatars: {
type: Function,
default: () => () => {}
},
avatarRemoteDatabase: {
type: Boolean,
default: false
}
});
const emit = defineEmits([
'clearSearch',
'setAvatarProvider',
'refreshUserDialogAvatars',
'moreSearchUser',
'update:searchText'
]);
const searchTabRef = ref(null);
const searchUserParams = ref({});
@@ -416,7 +388,7 @@
return convertFileUrlToImageUrl(url);
}
function clearSearch() {
function handleClearSearch() {
searchUserParams.value = {};
searchWorldParams.value = {};
searchWorldResults.value = [];
@@ -425,11 +397,11 @@
searchAvatarPageNum.value = 0;
searchGroupParams.value = {};
searchGroupResults.value = [];
emit('clearSearch');
clearSearch();
}
function updateSearchText(text) {
emit('update:searchText', text);
searchText.value = text;
}
function search() {
@@ -453,16 +425,19 @@
searchUserParams.value = {
n: 10,
offset: 0,
search: props.searchText,
search: searchText.value,
customFields: searchUserByBio.value ? 'bio' : 'displayName',
sort: searchUserSortByLastLoggedIn.value ? 'last_login' : 'relevance'
};
await moreSearchUser();
await handleMoreSearchUser();
}
async function moreSearchUser(go = null) {
emit('moreSearchUser', go, searchUserParams.value);
async function handleMoreSearchUser(go = null) {
isSearchUserLoading.value = true;
await moreSearchUser(go, searchUserParams.value);
isSearchUserLoading.value = false;
}
function searchWorld(ref) {
searchWorldOption.value = '';
const params = {
@@ -508,7 +483,7 @@
break;
default:
params.sort = 'relevance';
params.search = utils.replaceBioSymbols(props.searchText);
params.search = replaceBioSymbols(searchText.value);
break;
}
params.order = ref.sortOrder || 'descending';
@@ -548,7 +523,7 @@
.then((args) => {
const map = new Map();
for (const json of args.json) {
const ref = API.cachedWorlds.get(json.id);
const ref = cachedWorlds.value.get(json.id);
if (typeof ref !== 'undefined') {
map.set(ref.id, ref);
}
@@ -558,13 +533,6 @@
});
}
function setAvatarProvider(provider) {
emit('setAvatarProvider', provider);
}
function refreshUserDialogAvatars(fileId) {
emit('refreshUserDialogAvatars', fileId);
}
async function searchAvatar() {
let ref;
isSearchAvatarLoading.value = true;
@@ -581,10 +549,10 @@
searchAvatarSort.value = 'name';
}
const avatars = new Map();
const query = props.searchText;
const query = searchText.value;
const queryUpper = query.toUpperCase();
if (!query) {
for (ref of API.cachedAvatars.values()) {
for (ref of cachedAvatars.value.values()) {
switch (searchAvatarFilter.value) {
case 'all':
avatars.set(ref.id, ref);
@@ -604,7 +572,7 @@
isSearchAvatarLoading.value = false;
} else {
if (searchAvatarFilterRemote.value === 'all' || searchAvatarFilterRemote.value === 'local') {
for (ref of API.cachedAvatars.values()) {
for (ref of cachedAvatars.value.values()) {
let match = ref.name.toUpperCase().includes(queryUpper);
if (!match && ref.description) {
match = ref.description.toUpperCase().includes(queryUpper);
@@ -633,10 +601,10 @@
}
if (
(searchAvatarFilterRemote.value === 'all' || searchAvatarFilterRemote.value === 'remote') &&
props.avatarRemoteDatabase &&
avatarRemoteDatabase.value &&
query.length >= 3
) {
const data = await props.lookupAvatars('search', query);
const data = await lookupAvatars('search', query);
if (data && typeof data === 'object') {
data.forEach((avatar) => {
avatars.set(avatar.id, avatar);
@@ -649,13 +617,13 @@
if (searchAvatarFilterRemote.value === 'local') {
switch (searchAvatarSort.value) {
case 'updated':
avatarsArray.sort(utils.compareByUpdatedAt);
avatarsArray.sort(compareByUpdatedAt);
break;
case 'created':
avatarsArray.sort(utils.compareByCreatedAt);
avatarsArray.sort(compareByCreatedAt);
break;
case 'name':
avatarsArray.sort(utils.compareByName);
avatarsArray.sort(compareByName);
break;
}
}
@@ -679,7 +647,7 @@
searchGroupParams.value = {
n: 10,
offset: 0,
query: utils.replaceBioSymbols(props.searchText)
query: replaceBioSymbols(searchText.value)
};
await moreSearchGroup();
}
@@ -698,22 +666,10 @@
isSearchGroupLoading.value = false;
})
.then((args) => {
// API.$on('GROUP:SEARCH', function (args) {
for (const json of args.json) {
API.$emit('GROUP', {
json,
params: {
groupId: json.id
}
});
}
// });
const map = new Map();
for (const json of args.json) {
const ref = API.cachedGroups.get(json.id);
if (typeof ref !== 'undefined') {
map.set(ref.id, ref);
}
const ref = applyGroup(json);
map.set(ref.id, ref);
}
searchGroupResults.value = Array.from(map.values());
return args;