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

@@ -18,7 +18,7 @@
icon="el-icon-refresh"
:loading="isGroupMembersLoading"
circle
@click="loadAllGroupMembers"></el-button>
@click="loadAllGroupMembers" />
<span style="font-size: 14px; margin-left: 5px; margin-right: 5px">
{{ groupMemberModerationTable.data.length }}/{{
groupMemberModeration.groupRef.memberCount
@@ -40,7 +40,7 @@
@click.native.stop>
<el-button size="mini">
<span
>{{ groupDialog.memberSortOrder.name }}
>{{ t(groupDialog.memberSortOrder.name) }}
<i class="el-icon-arrow-down el-icon--right"></i
></span>
</el-button>
@@ -49,7 +49,7 @@
v-for="item in groupDialogSortingOptions"
:key="item.name"
@click.native="setGroupMemberSortOrder(item)">
{{ item.name }}
{{ t(item.name) }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
@@ -68,7 +68,7 @@
@click.native.stop>
<el-button size="mini">
<span
>{{ groupDialog.memberFilter.name }}
>{{ t(groupDialog.memberFilter.name) }}
<i class="el-icon-arrow-down el-icon--right"></i
></span>
</el-button>
@@ -77,7 +77,7 @@
v-for="item in groupDialogFilterOptions"
:key="item.name"
@click.native="setGroupMemberFilter(item)"
v-text="item.name"></el-dropdown-item>
v-text="t(item.name)"></el-dropdown-item>
<el-dropdown-item
v-for="item in groupDialog.ref.roles"
v-if="!item.defaultRole"
@@ -147,12 +147,11 @@
<el-table-column :label="t('dialog.group_member_moderation.roles')" prop="roleIds" sortable>
<template slot-scope="scope">
<template v-for="(roleId, index) in scope.row.roleIds">
<span
v-for="(role, rIndex) in groupMemberModeration.groupRef.roles"
v-if="role?.id === roleId"
:key="rIndex"
>{{ role.name
}}<span v-if="index < scope.row.roleIds.length - 1">, </span></span
<template v-for="(role, rIndex) in groupMemberModeration.groupRef.roles">
<span v-if="role?.id === roleId" :key="roleId + rIndex"
>{{ role.name
}}<span v-if="index < scope.row.roleIds.length - 1">, </span></span
></template
>
</template>
</template>
@@ -171,7 +170,7 @@
prop="joinedAt"
sortable>
<template slot-scope="scope">
<span>{{ scope.row.joinedAt | formatDate('long') }}</span>
<span>{{ formatDateFilter(scope.row.joinedAt, 'long') }}</span>
</template>
</el-table-column>
<el-table-column
@@ -284,7 +283,7 @@
prop="joinedAt"
sortable>
<template slot-scope="scope">
<span>{{ scope.row.joinedAt | formatDate('long') }}</span>
<span>{{ formatDateFilter(scope.row.joinedAt, 'long') }}</span>
</template>
</el-table-column>
<el-table-column
@@ -293,7 +292,7 @@
prop="bannedAt"
sortable>
<template slot-scope="scope">
<span>{{ scope.row.bannedAt | formatDate('long') }}</span>
<span>{{ formatDateFilter(scope.row.bannedAt, 'long') }}</span>
</template>
</el-table-column>
</data-tables>
@@ -629,7 +628,7 @@
prop="created_at"
sortable>
<template slot-scope="scope">
<span>{{ scope.row.created_at | formatDate('long') }}</span>
<span>{{ formatDateFilter(scope.row.created_at, 'long') }}</span>
</template>
</el-table-column>
<el-table-column
@@ -656,7 +655,7 @@
:label="t('dialog.group_member_moderation.description')"
prop="description">
<template slot-scope="scope">
<location
<Location
v-if="scope.row?.targetId.startsWith('wrld_')"
:location="scope.row.targetId" />
<span v-text="scope.row.description"></span>
@@ -810,45 +809,165 @@
</template>
<script setup>
import Location from '../../Location.vue';
import { getCurrentInstance, inject, ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { getCurrentInstance, reactive, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { groupRequest, userRequest } from '../../../api';
import { useModerationTable, useSelectedUsers } from '../../../composables/group/useGroupMemberModeration';
import { hasGroupPermission } from '../../../composables/group/utils';
import { groupDialogFilterOptions, groupDialogSortingOptions } from '../../../shared/constants';
import { hasGroupPermission, userImage, userImageFull, formatDateFilter } from '../../../shared/utils';
import { useAppearanceSettingsStore, useGalleryStore, useGroupStore, useUserStore } from '../../../stores';
import GroupMemberModerationExportDialog from './GroupMemberModerationExportDialog.vue';
const API = inject('API');
const showUserDialog = inject('showUserDialog');
const userImage = inject('userImage');
const userImageFull = inject('userImageFull');
const showFullscreenImageDialog = inject('showFullscreenImageDialog');
const { randomUserColours } = storeToRefs(useAppearanceSettingsStore());
const { showUserDialog } = useUserStore();
const { currentUser } = storeToRefs(useUserStore());
const { groupDialog } = storeToRefs(useGroupStore());
const { applyGroupMember, handleGroupMemberProps } = useGroupStore();
const { showFullscreenImageDialog } = useGalleryStore();
const { t } = useI18n();
const instance = getCurrentInstance();
const $message = instance.proxy.$message;
const selectedUsers = reactive({});
const selectedUsersArray = ref([]);
function setSelectedUsers(usersId, user) {
if (!user) {
return;
}
selectedUsers[usersId] = user;
selectedUsersArray.value = Object.values(selectedUsers);
}
function deselectedUsers(userId, isAll = false) {
if (isAll) {
for (const id in selectedUsers) {
if (Object.prototype.hasOwnProperty.call(selectedUsers, id)) {
delete selectedUsers[id];
}
}
} else {
if (Object.prototype.hasOwnProperty.call(selectedUsers, userId)) {
delete selectedUsers[userId];
}
}
selectedUsersArray.value = Object.values(selectedUsers);
}
function groupMemberModerationTableSelectionChange(row) {
if (row.$selected && !selectedUsers[row.userId]) {
setSelectedUsers(row.userId, row);
} else if (!row.$selected && selectedUsers[row.userId]) {
deselectedUsers(row.userId);
}
}
const groupInvitesModerationTable = reactive({
data: [],
tableProps: { stripe: true, size: 'mini' },
pageSize: 15,
paginationProps: {
small: true,
layout: 'sizes,prev,pager,next,total',
pageSizes: [10, 15, 20, 25, 50, 100]
}
});
const groupJoinRequestsModerationTable = reactive({
data: [],
tableProps: { stripe: true, size: 'mini' },
pageSize: 15,
paginationProps: {
small: true,
layout: 'sizes,prev,pager,next,total',
pageSizes: [10, 15, 20, 25, 50, 100]
}
});
const groupBlockedModerationTable = reactive({
data: [],
tableProps: { stripe: true, size: 'mini' },
pageSize: 15,
paginationProps: {
small: true,
layout: 'sizes,prev,pager,next,total',
pageSizes: [10, 15, 20, 25, 50, 100]
}
});
const groupLogsModerationTable = reactive({
data: [],
filters: [{ prop: ['description'], value: '' }],
tableProps: { stripe: true, size: 'mini' },
pageSize: 15,
paginationProps: {
small: true,
layout: 'sizes,prev,pager,next,total',
pageSizes: [10, 15, 20, 25, 50, 100]
}
});
const groupBansModerationTable = reactive({
data: [],
filters: [{ prop: ['$displayName'], value: '' }],
tableProps: { stripe: true, size: 'mini' },
pageSize: 15,
paginationProps: {
small: true,
layout: 'sizes,prev,pager,next,total',
pageSizes: [10, 15, 20, 25, 50, 100]
}
});
const groupMemberModerationTable = reactive({
data: [],
tableProps: { stripe: true, size: 'mini' },
pageSize: 15,
paginationProps: {
small: true,
layout: 'sizes,prev,pager,next,total',
pageSizes: [10, 15, 20, 25, 50, 100]
}
});
async function initializePageSize() {
try {
const { tablePageSize } = storeToRefs(useAppearanceSettingsStore());
groupMemberModerationTable.pageSize = tablePageSize.value;
groupBansModerationTable.pageSize = tablePageSize.value;
groupLogsModerationTable.pageSize = tablePageSize.value;
groupInvitesModerationTable.pageSize = tablePageSize.value;
groupJoinRequestsModerationTable.pageSize = tablePageSize.value;
groupBlockedModerationTable.pageSize = tablePageSize.value;
} catch (error) {
console.error('Failed to initialize table page size:', error);
}
}
function deselectGroupMember(userId) {
const deselectInTable = (tableData) => {
if (userId) {
const row = tableData.find((item) => item.userId === userId);
if (row) {
row.$selected = false;
}
} else {
tableData.forEach((row) => {
if (row.$selected) {
row.$selected = false;
}
});
}
};
deselectInTable(groupMemberModerationTable.data);
deselectInTable(groupBansModerationTable.data);
deselectInTable(groupInvitesModerationTable.data);
deselectInTable(groupJoinRequestsModerationTable.data);
deselectInTable(groupBlockedModerationTable.data);
}
const props = defineProps({
isGroupMembersLoading: {
type: Boolean,
default: false
},
groupDialog: {
type: Object,
required: true
},
groupDialogSortingOptions: {
type: Object,
required: true
},
groupDialogFilterOptions: {
type: Object,
required: true
},
randomUserColours: {
type: Boolean,
default: false
},
groupMemberModeration: {
type: Object,
required: true
@@ -864,25 +983,6 @@
'group-members-search'
]);
const {
groupInvitesModerationTable,
groupJoinRequestsModerationTable,
groupBlockedModerationTable,
groupLogsModerationTable,
groupBansModerationTable,
groupMemberModerationTable,
initializePageSize,
deselectGroupMember
} = useModerationTable();
const {
selectedUsers,
selectedUsersArray,
groupMemberModerationTableSelectionChange,
deselectedUsers,
setSelectedUsers
} = useSelectedUsers();
const selectUserId = ref('');
const progressCurrent = ref(0);
const progressTotal = ref(0);
@@ -895,7 +995,7 @@
() => props.groupMemberModeration.visible,
(newVal) => {
if (newVal) {
if (props.groupMemberModeration.id !== props.groupDialog.id) {
if (props.groupMemberModeration.id !== groupDialog.value.id) {
return;
}
groupMemberModerationTable.data = [];
@@ -905,6 +1005,7 @@
groupBlockedModerationTable.data = [];
groupLogsModerationTable.data = [];
Object.assign(selectedUsers, {});
selectedUsersArray.value = [];
selectUserId.value = '';
selectedRoles.value = [];
note.value = '';
@@ -913,7 +1014,7 @@
);
watch(
() => props.groupDialog.members,
() => groupDialog.value.members,
(newVal) => {
if (newVal) {
setGroupMemberModerationTable(newVal);
@@ -923,7 +1024,7 @@
);
watch(
() => props.groupDialog.memberSearchResults,
() => groupDialog.value.memberSearchResults,
(newVal) => {
if (newVal) {
setGroupMemberModerationTable(newVal);
@@ -965,9 +1066,8 @@
}
function handleGroupMemberRoleChange(args) {
// 'GROUP:MEMBER:ROLE:CHANGE'
if (props.groupDialog.id === args.params.groupId) {
props.groupDialog.members.forEach((member) => {
if (groupDialog.value.id === args.params.groupId) {
groupDialog.value.members.forEach((member) => {
if (member.userId === args.params.userId) {
member.roleIds = args.json;
return true;
@@ -988,7 +1088,7 @@
}
const user = users[i];
progressCurrent.value = i + 1;
if (user.userId === API.currentUser.id) {
if (user.userId === currentUser.value.id) {
continue;
}
console.log(`Deleting group invite ${user.userId} ${i + 1}/${memberCount}`);
@@ -1014,7 +1114,7 @@
}
progressCurrent.value = 0;
progressTotal.value = 0;
getAllGroupInvites(D.id, groupInvitesModerationTable);
getAllGroupInvites(D.id);
}
function selectAllGroupMembers() {
@@ -1038,7 +1138,7 @@
continue;
}
args.json.forEach((json) => {
const ref = API.applyGroupMember(json);
const ref = applyGroupMember(json);
fetchedBans.push(ref);
});
if (args.json.length < params.n) {
@@ -1076,7 +1176,7 @@
if (!progressTotal.value) break;
const user = users[i];
progressCurrent.value = i + 1;
if (user.userId === API.currentUser.id) continue;
if (user.userId === currentUser.value.id) continue;
console.log(`Banning ${user.userId} ${i + 1}/${memberCount}`);
try {
await groupRequest.banGroupMember({ groupId: D.id, userId: user.userId });
@@ -1105,7 +1205,7 @@
if (!progressTotal.value) break;
const user = users[i];
progressCurrent.value = i + 1;
if (user.userId === API.currentUser.id) continue;
if (user.userId === currentUser.value.id) continue;
console.log(`Unbanning ${user.userId} ${i + 1}/${memberCount}`);
try {
await groupRequest.unbanGroupMember({ groupId: D.id, userId: user.userId });
@@ -1138,7 +1238,7 @@
if (!progressTotal.value) break;
const user = users[i];
progressCurrent.value = i + 1;
if (user.userId === API.currentUser.id) continue;
if (user.userId === currentUser.value.id) continue;
console.log(`Kicking ${user.userId} ${i + 1}/${memberCount}`);
try {
@@ -1158,6 +1258,7 @@
progressCurrent.value = 0;
progressTotal.value = 0;
deselectedUsers(null, true);
loadAllGroupMembers();
}
async function groupMembersSaveNote() {
@@ -1176,7 +1277,8 @@
}
console.log(`Setting note ${noteToSave} for ${user.userId} ${i + 1}/${memberCount}`);
try {
await groupRequest.setGroupMemberProps(user.userId, D.id, { managerNotes: noteToSave });
const args = await groupRequest.setGroupMemberProps(user.userId, D.id, { managerNotes: noteToSave });
handleGroupMemberProps(args);
} catch (err) {
console.error(err);
$message({
@@ -1334,7 +1436,7 @@
let member = {};
const memberArgs = await groupRequest.getGroupMember({ groupId: D.id, userId });
if (memberArgs && memberArgs.json) {
member = API.applyGroupMember(memberArgs.json);
member = applyGroupMember(memberArgs.json);
}
if (member && member.user) {
setSelectedUsers(member.userId, member);
@@ -1400,7 +1502,7 @@
const user = users[i];
progressCurrent.value = i + 1;
if (user.userId === API.currentUser.id) {
if (user.userId === currentUser.value.id) {
continue;
}
@@ -1424,7 +1526,7 @@
}
progressCurrent.value = 0;
progressTotal.value = 0;
getAllGroupInvitesAndJoinRequests();
getAllGroupInvitesAndJoinRequests(D.id);
deselectedUsers(null, true);
}
@@ -1438,7 +1540,7 @@
if (!progressTotal.value) break;
const user = users[i];
progressCurrent.value = i + 1;
if (user.userId === API.currentUser.id) continue;
if (user.userId === currentUser.value.id) continue;
console.log(`Blocking group join request from ${user.userId} ${i + 1}/${memberCount}`);
try {
@@ -1460,7 +1562,7 @@
}
progressCurrent.value = 0;
progressTotal.value = 0;
getAllGroupInvitesAndJoinRequests();
getAllGroupInvitesAndJoinRequests(D.id);
deselectedUsers(null, true);
}
@@ -1475,7 +1577,7 @@
if (!progressTotal.value) break;
const user = users[i];
progressCurrent.value = i + 1;
if (user.userId === API.currentUser.id) continue;
if (user.userId === currentUser.value.id) continue;
console.log(`Rejecting group join request from ${user.userId} ${i + 1}/${memberCount}`);
try {
@@ -1497,7 +1599,7 @@
}
progressCurrent.value = 0;
progressTotal.value = 0;
getAllGroupInvitesAndJoinRequests();
getAllGroupInvitesAndJoinRequests(D.id);
deselectedUsers(null, true);
}
@@ -1511,7 +1613,7 @@
if (!progressTotal.value) break;
const user = users[i];
progressCurrent.value = i + 1;
if (user.userId === API.currentUser.id) continue;
if (user.userId === currentUser.value.id) continue;
console.log(`Accepting group join request from ${user.userId} ${i + 1}/${memberCount}`);
try {
@@ -1533,7 +1635,7 @@
}
progressCurrent.value = 0;
progressTotal.value = 0;
getAllGroupInvitesAndJoinRequests();
getAllGroupInvitesAndJoinRequests(D.id);
deselectedUsers(null, true);
}
@@ -1565,7 +1667,7 @@
? groupBlockedModerationTable
: groupJoinRequestsModerationTable;
for (const json of args.json) {
const ref = API.applyGroupMember(json);
const ref = applyGroupMember(json);
targetTable.data.push(ref);
}
params.offset += params.n;
@@ -1598,7 +1700,7 @@
? groupBlockedModerationTable
: groupJoinRequestsModerationTable;
for (const json of args.json) {
const ref = API.applyGroupMember(json);
const ref = applyGroupMember(json);
targetTable.data.push(ref);
}
params.offset += params.n;
@@ -1631,7 +1733,7 @@
}
for (const json of args.json) {
const ref = API.applyGroupMember(json);
const ref = applyGroupMember(json);
groupInvitesModerationTable.data.push(ref);
}
}
@@ -1649,7 +1751,7 @@
type: 'error'
});
} finally {
updateIsGroupMembersLoading(false); // Use emit
updateIsGroupMembersLoading(false);
}
}