diff --git a/src/app.scss b/src/app.scss index 580cb199..0e67b43a 100644 --- a/src/app.scss +++ b/src/app.scss @@ -847,6 +847,7 @@ i.x-status-icon.red { .el-dialog, .el-message-box { border-radius: 28px; + word-break: break-word; } .el-tabs__nav-wrap::after { diff --git a/src/components/dialogs/UserDialog/UserDialog.vue b/src/components/dialogs/UserDialog/UserDialog.vue index 9876bf25..7ce2ce6f 100644 --- a/src/components/dialogs/UserDialog/UserDialog.vue +++ b/src/components/dialogs/UserDialog/UserDialog.vue @@ -2392,8 +2392,6 @@ D.isBlock = true; } else if (ref.type === 'mute') { D.isMute = true; - } else if (ref.type === 'hideAvatar') { - D.isHideAvatar = true; } else if (ref.type === 'interactOff') { D.isInteractOff = true; } else if (ref.type === 'muteChat') { diff --git a/src/stores/friend.js b/src/stores/friend.js index 6c37c4c9..48df3b27 100644 --- a/src/stores/friend.js +++ b/src/stores/friend.js @@ -440,6 +440,34 @@ export const useFriendStore = defineStore('Friend', () => { if (typeof ref !== 'undefined') { location = ref.location; $location_at = ref.$location_at; + + // wtf, fetch user if offline in an instance + if ( + ctx.state !== 'online' && + isRealInstance(ref.location) && + ref.$lastFetch < Date.now() - 10000 // 10 seconds + ) { + console.log( + `Fetching offline friend in an instance ${ctx.name}` + ); + userRequest.getUser({ + userId: id + }); + } + // wtf, fetch user if online in an offline location + if ( + ctx.state === 'online' && + ref.location === 'offline' && + ref.$lastFetch < Date.now() - 10000 // 10 seconds + ) { + console.log( + `Fetching online friend in an offline location ${ctx.name}` + ); + userRequest.getUser({ + userId: id + }); + return; + } } if (typeof stateInput === 'undefined' || ctx.state === stateInput) { // this is should be: undefined -> user @@ -489,20 +517,6 @@ export const useFriendStore = defineStore('Friend', () => { state.sortOfflineFriends = true; } } - // wtf, fetch user if offline in an instance - if ( - ctx.state !== 'online' && - typeof ref !== 'undefined' && - isRealInstance(ref.location) && - ref.$lastFetch < Date.now() - 10000 // 10 seconds - ) { - console.log( - `Fetching offline friend in an instance ${ctx.name}` - ); - userRequest.getUser({ - userId: id - }); - } } else if ( ctx.state === 'online' && (stateInput === 'active' || stateInput === 'offline') diff --git a/src/stores/instance.js b/src/stores/instance.js index 0e528821..2f7ac8de 100644 --- a/src/stores/instance.js +++ b/src/stores/instance.js @@ -1080,8 +1080,12 @@ export const useInstanceStore = defineStore('Instance', () => { function updatePlayerListDebounce() { const users = []; const pushUser = function (ref) { - let photonId = ''; + let photonId = -1; let isFriend = false; + let isBlocked = false; + let isMuted = false; + let isAvatarInteractionDisabled = false; + let isChatBoxMuted = false; photonStore.photonLobbyCurrent.forEach((ref1, id) => { if (typeof ref1 !== 'undefined') { if ( @@ -1138,6 +1142,11 @@ export const useInstanceStore = defineStore('Instance', () => { } }); } + isBlocked = ref.$moderations.isBlocked; + isMuted = ref.$moderations.isMuted; + isAvatarInteractionDisabled = + ref.$moderations.isAvatarInteractionDisabled; + isChatBoxMuted = ref.$moderations.isChatBoxMuted; } users.push({ ref, diff --git a/src/stores/moderation.js b/src/stores/moderation.js index 8c4fa6e7..a9615d99 100644 --- a/src/stores/moderation.js +++ b/src/stores/moderation.js @@ -1,16 +1,13 @@ import { defineStore } from 'pinia'; -import Vue, { computed, reactive, watch } from 'vue'; +import { computed, reactive, watch } from 'vue'; import { avatarModerationRequest, playerModerationRequest } from '../api'; -import { $app } from '../app'; import { watchState } from '../service/watchState'; import { useAvatarStore } from './avatar'; import { useUserStore } from './user'; -import { useI18n } from 'vue-i18n-bridge'; export const useModerationStore = defineStore('Moderation', () => { const avatarStore = useAvatarStore(); const userStore = useUserStore(); - const { t } = useI18n(); const state = reactive({ cachedPlayerModerations: new Map(), @@ -66,6 +63,23 @@ export const useModerationStore = defineStore('Moderation', () => { function handlePlayerModerationAtDelete(args) { const { ref } = args; + + let hasModeration = false; + for (const ref of state.cachedPlayerModerations.values()) { + if (ref.targetUserId === ref.targetUserId) { + hasModeration = true; + break; + } + } + if (!hasModeration) { + state.cachedPlayerModerationsUserIds.delete(ref.targetUserId); + } + + const userRef = userStore.cachedUsers.get(ref.targetUserId); + if (typeof userRef !== 'undefined') { + userRef.$moderations = getUserModerations(ref.targetUserId); + } + const D = userStore.userDialog; if ( D.visible === false || @@ -91,7 +105,7 @@ export const useModerationStore = defineStore('Moderation', () => { for (let i = 0; i < length; ++i) { if (array[i].id === ref.id) { array.splice(i, 1); - return; + break; } } } @@ -112,9 +126,9 @@ export const useModerationStore = defineStore('Moderation', () => { playerModerationId: ref.id } }); + break; } } - state.cachedPlayerModerationsUserIds.delete(moderated); } /** @@ -153,6 +167,10 @@ export const useModerationStore = defineStore('Moderation', () => { } else { array.push(ref); } + const userRef = userStore.cachedUsers.get(ref.targetUserId); + if (typeof userRef !== 'undefined') { + userRef.$moderations = getUserModerations(ref.targetUserId); + } return ref; } @@ -213,6 +231,44 @@ export const useModerationStore = defineStore('Moderation', () => { }); } + /** + * Get user moderations + * @param {string} userId + * @return {object} moderations + * @property {boolean} isBlocked + * @property {boolean} isMuted + * @property {boolean} isAvatarInteractionDisabled + * @property {boolean} isChatBoxMuted + */ + function getUserModerations(userId) { + let moderations = { + isBlocked: false, + isMuted: false, + isAvatarInteractionDisabled: false, + isChatBoxMuted: false + }; + for (let ref of state.cachedPlayerModerations.values()) { + if (ref.targetUserId !== userId) { + continue; + } + switch (ref.type) { + case 'block': + moderations.isBlocked = true; + break; + case 'mute': + moderations.isMuted = true; + break; + case 'interactOff': + moderations.isAvatarInteractionDisabled = true; + break; + case 'muteChat': + moderations.isChatBoxMuted = true; + break; + } + } + return moderations; + } + return { state, cachedPlayerModerations, @@ -222,6 +278,7 @@ export const useModerationStore = defineStore('Moderation', () => { refreshPlayerModerations, applyPlayerModeration, - handlePlayerModerationDelete + handlePlayerModerationDelete, + getUserModerations }; }); diff --git a/src/stores/user.js b/src/stores/user.js index 51adf765..52a340c0 100644 --- a/src/stores/user.js +++ b/src/stores/user.js @@ -524,6 +524,7 @@ export const useUserStore = defineStore('User', () => { $customTagColour: '', $friendNumber: 0, $platform: '', + $moderations: {}, // ...json }; @@ -594,6 +595,7 @@ export const useUserStore = defineStore('User', () => { } Object.assign(ref, json); } + ref.$moderations = moderationStore.getUserModerations(ref.id); ref.$isVRCPlus = ref.tags.includes('system_supporter'); appearanceSettingsStore.applyUserTrustLevel(ref); applyUserLanguage(ref); @@ -846,8 +848,6 @@ export const useUserStore = defineStore('User', () => { D.isBlock = true; } else if (ref.type === 'mute') { D.isMute = true; - } else if (ref.type === 'hideAvatar') { - D.isHideAvatar = true; } else if (ref.type === 'interactOff') { D.isInteractOff = true; } else if (ref.type === 'muteChat') { diff --git a/src/types/api/instance.d.ts b/src/types/api/instance.d.ts index a53134db..9e45e780 100644 --- a/src/types/api/instance.d.ts +++ b/src/types/api/instance.d.ts @@ -14,9 +14,9 @@ export type CreateInstance = (params: { type: string; region: string; ownerId: string; - roleIds: string[]; - groupAccessType: string; - queueEnabled: boolean; + roleIds?: string[]; + groupAccessType?: string; + queueEnabled?: boolean; }) => Promise<{ json: any; params: any; @@ -84,4 +84,4 @@ interface GetInstanceResponse { interface GetInstanceShortNameResponse { secureName: string; shortName: string; -} \ No newline at end of file +} diff --git a/src/types/api/user.d.ts b/src/types/api/user.d.ts index b113ce82..48446d31 100644 --- a/src/types/api/user.d.ts +++ b/src/types/api/user.d.ts @@ -61,6 +61,14 @@ export interface VrcxUser extends GetUserResponse { $customTagColour: string; $friendNumber: number; $lastFetch: number; + $moderations: moderations; +} + +export interface moderations { + isBlocked: boolean; + isMuted: boolean; + isAvatarInteractionDisabled: boolean; + isChatBoxMuted: boolean; } export interface VrcxCurrentUser extends GetCurrentUserResponse { diff --git a/src/views/PlayerList/PlayerList.vue b/src/views/PlayerList/PlayerList.vue index dd68a93a..9b8ef951 100644 --- a/src/views/PlayerList/PlayerList.vue +++ b/src/views/PlayerList/PlayerList.vue @@ -708,6 +708,22 @@ 💚 + + + + + + + + + + + + 🔴{{ scope.row.timeoutTime }}s @@ -715,17 +731,13 @@