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 @@
-
-
+ PC
- A
- iOS
- {{ scope.row.ref.last_platform }}
+ A
+ iOS
+ {{ scope.row.ref.$platform }}
VR