@@ -1302,8 +1308,14 @@
const { hideUserNotes, hideUserMemos } = storeToRefs(useAppearanceSettingsStore());
const { avatarRemoteDatabase } = storeToRefs(useAdvancedSettingsStore());
const { userDialog, languageDialog, currentUser, isLocalUserVrcPlusSupporter } = storeToRefs(useUserStore());
- const { cachedUsers, showUserDialog, sortUserDialogAvatars, refreshUserDialogAvatars, refreshUserDialogTreeData } =
- useUserStore();
+ const {
+ cachedUsers,
+ showUserDialog,
+ sortUserDialogAvatars,
+ refreshUserDialogAvatars,
+ refreshUserDialogTreeData,
+ showSendBoopDialog
+ } = useUserStore();
const { favoriteLimits } = storeToRefs(useFavoriteStore());
const { showFavoriteDialog, handleFavoriteWorldList } = useFavoriteStore();
const { showAvatarDialog, lookupAvatars, showAvatarAuthorDialog } = useAvatarStore();
@@ -1749,8 +1761,8 @@
redirectToToolsTab();
} else if (command === 'Invite To Group') {
showInviteGroupDialog('', D.id);
- // } else if (command === 'Send Boop') {
- // this.showSendBoopDialog(D.id);
+ } else if (command === 'Send Boop') {
+ showSendBoopDialog(D.id);
} else if (command === 'Group Moderation') {
showModerateGroupDialog(D.id);
} else if (command === 'Hide Avatar') {
@@ -2273,6 +2285,12 @@
});
}
+ function toggleAllowBooping() {
+ userRequest.saveCurrentUser({
+ isBoopingEnabled: !currentUser.value.isBoopingEnabled
+ });
+ }
+
function resetHome() {
ElMessageBox.confirm('Continue? Reset Home', 'Confirm', {
confirmButtonText: 'Confirm',
diff --git a/src/shared/utils/common.js b/src/shared/utils/common.js
index 674b046f..7bff391d 100644
--- a/src/shared/utils/common.js
+++ b/src/shared/utils/common.js
@@ -9,6 +9,7 @@ import {
useSearchStore,
useWorldStore
} from '../../stores';
+import { AppDebug } from '../../service/appConfig.js';
import { compareUnityVersion } from './avatar';
import { escapeTag } from './base/string';
import { miscRequest } from '../../api';
@@ -213,7 +214,7 @@ function convertFileUrlToImageUrl(url, resolution = 128) {
if (match) {
const fileId = match[1];
const version = match[2];
- return `https://api.vrchat.cloud/api/1/image/file_${fileId}/${version}/${resolution}`;
+ return `${AppDebug.endpointDomain}/image/file_${fileId}/${version}/${resolution}`;
}
// no match return origin url
return url;
diff --git a/src/shared/utils/gallery.js b/src/shared/utils/gallery.js
index 939b8367..a434a822 100644
--- a/src/shared/utils/gallery.js
+++ b/src/shared/utils/gallery.js
@@ -54,4 +54,34 @@ function getEmojiFileName(emoji) {
}
}
-export { getPrintLocalDate, getPrintFileName, getEmojiFileName };
+/**
+ * @param {string} url
+ * @param {number} fps
+ * @param {number} frameCount
+ * @param {string} loopStyle
+ */
+function generateEmojiStyle(url, fps, frameCount, loopStyle) {
+ let framesPerLine = 2;
+ if (frameCount > 4) framesPerLine = 4;
+ if (frameCount > 16) framesPerLine = 8;
+ const animationDurationMs = (1000 / fps) * frameCount;
+ const frameSize = 1024 / framesPerLine;
+ const scale = 100 / (frameSize / 200);
+ const animStyle = loopStyle === 'pingpong' ? 'alternate' : 'none';
+ const style = `
+ transform: scale(${scale / 100});
+ transform-origin: top left;
+ width: ${frameSize}px;
+ height: ${frameSize}px;
+ background: url('${url}') 0 0;
+ animation: ${animationDurationMs}ms steps(1) 0s infinite ${animStyle} running animated-emoji-${frameCount};
+ `;
+ return style;
+}
+
+export {
+ getPrintLocalDate,
+ getPrintFileName,
+ getEmojiFileName,
+ generateEmojiStyle
+};
diff --git a/src/stores/notification.js b/src/stores/notification.js
index 92e657e6..7d662dff 100644
--- a/src/stores/notification.js
+++ b/src/stores/notification.js
@@ -413,6 +413,15 @@ export const useNotificationStore = defineStore('Notification', () => {
}
ref.details = details;
}
+ if (ref.type === 'boop') {
+ ref.message = ref.title;
+ if (ref.details?.emojiId.startsWith('default_')) {
+ ref.details.imageUrl = ref.details.emojiId;
+ ref.message += ` ${ref.details.emojiId.replace('default_', '')}`;
+ } else {
+ ref.details.imageUrl = `${AppDebug.endpointDomain}/file/${ref.details.emojiId}/${ref.details.emojiVersion}`;
+ }
+ }
return ref;
}
diff --git a/src/stores/photon.js b/src/stores/photon.js
index ecc60a1a..c921ee7c 100644
--- a/src/stores/photon.js
+++ b/src/stores/photon.js
@@ -1115,7 +1115,7 @@ export const usePhotonStore = defineStore('Photon', () => {
} else if (type === 1) {
emojiName = 'Custom';
var fileId = data.Parameters[245][1];
- imageUrl = `https://api.vrchat.cloud/api/1/file/${fileId}/1/`;
+ imageUrl = `${AppDebug.endpointDomain}/file/${fileId}/1/`;
}
addEntryPhotonEvent({
photonId,
diff --git a/src/stores/user.js b/src/stores/user.js
index a42ee47a..ff60c807 100644
--- a/src/stores/user.js
+++ b/src/stores/user.js
@@ -269,6 +269,10 @@ export const useUserStore = defineStore('User', () => {
languageChoice: false,
languages: []
});
+ const sendBoopDialog = ref({
+ visible: false,
+ userId: ''
+ });
const pastDisplayNameTable = ref({
data: [],
tableProps: {
@@ -1960,6 +1964,11 @@ export const useUserStore = defineStore('User', () => {
return ref;
}
+ function showSendBoopDialog(userId) {
+ sendBoopDialog.value.userId = userId;
+ sendBoopDialog.value.visible = true;
+ }
+
return {
state,
@@ -1968,6 +1977,7 @@ export const useUserStore = defineStore('User', () => {
userDialog,
subsetOfLanguages,
languageDialog,
+ sendBoopDialog,
pastDisplayNameTable,
showUserDialogHistory,
customUserTags,
@@ -1986,7 +1996,7 @@ export const useUserStore = defineStore('User', () => {
initUserNotes,
getCurrentUser,
handleConfig,
-
+ showSendBoopDialog,
checkNote
};
});
diff --git a/src/views/Notifications/Notification.vue b/src/views/Notifications/Notification.vue
index 5b4c9bf7..a8d963eb 100644
--- a/src/views/Notifications/Notification.vue
+++ b/src/views/Notifications/Notification.vue
@@ -125,7 +125,16 @@
-
+
+
+
+
+
-
-
-
-
-
-
-
+
4) framesPerLine = 4;
- if (frameCount > 16) framesPerLine = 8;
- const animationDurationMs = (1000 / fps) * frameCount;
- const frameSize = 1024 / framesPerLine;
- const scale = 100 / (frameSize / 200);
- const animStyle = loopStyle === 'pingpong' ? 'alternate' : 'none';
- const style = `
- transform: scale(${scale / 100});
- transform-origin: top left;
- width: ${frameSize}px;
- height: ${frameSize}px;
- background: url('${url}') 0 0;
- animation: ${animationDurationMs}ms steps(1) 0s infinite ${animStyle} running animated-emoji-${frameCount};
- `;
- return style;
- }
-
function deleteEmoji(fileId) {
miscRequest.deleteFile(fileId).then((args) => {
const array = emojiTable.value;