mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-07 14:56:06 +02:00
Fix animated emoji in notifications tab
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
<template>
|
||||||
|
<div style="overflow: hidden" :style="{ width: size + 'px', height: size + 'px' }">
|
||||||
|
<div
|
||||||
|
v-if="image.frames"
|
||||||
|
class="avatar"
|
||||||
|
:style="generateEmojiStyle(imageUrl, image.framesOverTime, image.frames, image.loopStyle, size)"></div>
|
||||||
|
<img v-else :src="imageUrl" class="avatar" :style="{ width: size + 'px', height: size + 'px' }" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { extractFileId, generateEmojiStyle } from '../shared/utils';
|
||||||
|
import { useGalleryStore } from '../stores';
|
||||||
|
|
||||||
|
const { getCachedEmoji } = useGalleryStore();
|
||||||
|
const { emojiTable } = useGalleryStore();
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
imageUrl: { type: String, default: '' },
|
||||||
|
size: { type: Number, default: 100 }
|
||||||
|
});
|
||||||
|
|
||||||
|
const image = ref({
|
||||||
|
frames: null,
|
||||||
|
framesOverTime: null,
|
||||||
|
loopStyle: null,
|
||||||
|
versions: []
|
||||||
|
});
|
||||||
|
|
||||||
|
async function update() {
|
||||||
|
const fileId = extractFileId(props.imageUrl);
|
||||||
|
for (const emoji of emojiTable) {
|
||||||
|
if (emoji.id === fileId) {
|
||||||
|
image.value = emoji;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
image.value = await getCachedEmoji(fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.imageUrl, update);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -150,24 +150,8 @@
|
|||||||
image.versions[image.versions.length - 1].file.url
|
image.versions[image.versions.length - 1].file.url
|
||||||
"
|
"
|
||||||
class="x-popover-image"
|
class="x-popover-image"
|
||||||
style="overflow: hidden; width: 100px; height: 100px; padding: 8px">
|
style="padding: 8px">
|
||||||
<div
|
<Emoji :imageUrl="image.versions[image.versions.length - 1].file.url" :size="100"></Emoji>
|
||||||
v-if="image.frames"
|
|
||||||
class="avatar"
|
|
||||||
:style="
|
|
||||||
generateEmojiStyle(
|
|
||||||
image.versions[image.versions.length - 1].file.url,
|
|
||||||
image.framesOverTime,
|
|
||||||
image.frames,
|
|
||||||
image.loopStyle,
|
|
||||||
100
|
|
||||||
)
|
|
||||||
"></div>
|
|
||||||
<img
|
|
||||||
v-else
|
|
||||||
:src="image.versions[image.versions.length - 1].file.url"
|
|
||||||
class="avatar"
|
|
||||||
style="width: 100px; height: 100px" />
|
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -194,7 +178,7 @@
|
|||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import { generateEmojiStyle, userImage, userStatusClass } from '../../shared/utils';
|
import { userImage, userStatusClass } from '../../shared/utils';
|
||||||
import { miscRequest } from '../../api';
|
import { miscRequest } from '../../api';
|
||||||
import { notificationRequest } from '../../api';
|
import { notificationRequest } from '../../api';
|
||||||
import { photonEmojis } from '../../shared/constants/photon.js';
|
import { photonEmojis } from '../../shared/constants/photon.js';
|
||||||
@@ -204,6 +188,8 @@
|
|||||||
import { useNotificationStore } from '../../stores';
|
import { useNotificationStore } from '../../stores';
|
||||||
import { useUserStore } from '../../stores/user.js';
|
import { useUserStore } from '../../stores/user.js';
|
||||||
|
|
||||||
|
import Emoji from '../Emoji.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const { sendBoopDialog } = storeToRefs(useUserStore());
|
const { sendBoopDialog } = storeToRefs(useUserStore());
|
||||||
|
|||||||
+25
-1
@@ -20,6 +20,8 @@ import { handleImageUploadInput } from '../shared/utils/imageUpload';
|
|||||||
import { useAdvancedSettingsStore } from './settings/advanced';
|
import { useAdvancedSettingsStore } from './settings/advanced';
|
||||||
import { watchState } from '../service/watchState';
|
import { watchState } from '../service/watchState';
|
||||||
|
|
||||||
|
import miscReq from '../api/misc';
|
||||||
|
|
||||||
import * as workerTimers from 'worker-timers';
|
import * as workerTimers from 'worker-timers';
|
||||||
|
|
||||||
export const useGalleryStore = defineStore('Gallery', () => {
|
export const useGalleryStore = defineStore('Gallery', () => {
|
||||||
@@ -35,6 +37,8 @@ export const useGalleryStore = defineStore('Gallery', () => {
|
|||||||
instanceInventoryQueueWorker: null
|
instanceInventoryQueueWorker: null
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const cachedEmoji = new Map();
|
||||||
|
|
||||||
const galleryTable = ref([]);
|
const galleryTable = ref([]);
|
||||||
|
|
||||||
const galleryDialogVisible = ref(false);
|
const galleryDialogVisible = ref(false);
|
||||||
@@ -78,6 +82,7 @@ export const useGalleryStore = defineStore('Gallery', () => {
|
|||||||
watch(
|
watch(
|
||||||
() => watchState.isLoggedIn,
|
() => watchState.isLoggedIn,
|
||||||
(isLoggedIn) => {
|
(isLoggedIn) => {
|
||||||
|
cachedEmoji.clear();
|
||||||
galleryTable.value = [];
|
galleryTable.value = [];
|
||||||
VRCPlusIconsTable.value = [];
|
VRCPlusIconsTable.value = [];
|
||||||
stickerTable.value = [];
|
stickerTable.value = [];
|
||||||
@@ -500,6 +505,23 @@ export const useGalleryStore = defineStore('Gallery', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getCachedEmoji(fileId) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let ref = cachedEmoji.get(fileId);
|
||||||
|
if (typeof ref !== 'undefined') {
|
||||||
|
resolve(ref);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
miscReq
|
||||||
|
.getFile({ fileId })
|
||||||
|
.then((args) => {
|
||||||
|
cachedEmoji.set(fileId, args.json);
|
||||||
|
resolve(args.json);
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
|
|
||||||
@@ -521,6 +543,7 @@ export const useGalleryStore = defineStore('Gallery', () => {
|
|||||||
emojiTable,
|
emojiTable,
|
||||||
inventoryTable,
|
inventoryTable,
|
||||||
fullscreenImageDialog,
|
fullscreenImageDialog,
|
||||||
|
cachedEmoji,
|
||||||
|
|
||||||
showGalleryDialog,
|
showGalleryDialog,
|
||||||
refreshGalleryTable,
|
refreshGalleryTable,
|
||||||
@@ -538,6 +561,7 @@ export const useGalleryStore = defineStore('Gallery', () => {
|
|||||||
handleStickerAdd,
|
handleStickerAdd,
|
||||||
handleGalleryImageAdd,
|
handleGalleryImageAdd,
|
||||||
handleFilesList,
|
handleFilesList,
|
||||||
queueCheckInstanceInventory
|
queueCheckInstanceInventory,
|
||||||
|
getCachedEmoji
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -126,13 +126,12 @@
|
|||||||
<el-table-column :label="t('table.notification.photo')" width="100" prop="photo">
|
<el-table-column :label="t('table.notification.photo')" width="100" prop="photo">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template v-if="scope.row.type === 'boop'">
|
<template v-if="scope.row.type === 'boop'">
|
||||||
<img
|
<Emoji
|
||||||
v-if="scope.row.details?.imageUrl && !scope.row.details.imageUrl.startsWith('default_')"
|
|
||||||
class="x-link"
|
class="x-link"
|
||||||
:src="getSmallThumbnailUrl(scope.row.details.imageUrl)"
|
|
||||||
style="flex: none; height: 50px; border-radius: 4px"
|
|
||||||
@click="showFullscreenImageDialog(scope.row.details.imageUrl)"
|
@click="showFullscreenImageDialog(scope.row.details.imageUrl)"
|
||||||
loading="lazy" />
|
v-if="scope.row.details?.imageUrl && !scope.row.details.imageUrl.startsWith('default_')"
|
||||||
|
:imageUrl="scope.row.details.imageUrl"
|
||||||
|
:size="50"></Emoji>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="scope.row.details && scope.row.details.imageUrl">
|
<template v-else-if="scope.row.details && scope.row.details.imageUrl">
|
||||||
<img
|
<img
|
||||||
@@ -432,6 +431,7 @@
|
|||||||
import { friendRequest, notificationRequest, worldRequest } from '../../api';
|
import { friendRequest, notificationRequest, worldRequest } from '../../api';
|
||||||
import { database } from '../../service/database';
|
import { database } from '../../service/database';
|
||||||
|
|
||||||
|
import Emoji from '../../components/Emoji.vue';
|
||||||
import SendInviteRequestResponseDialog from './dialogs/SendInviteRequestResponseDialog.vue';
|
import SendInviteRequestResponseDialog from './dialogs/SendInviteRequestResponseDialog.vue';
|
||||||
import SendInviteResponseDialog from './dialogs/SendInviteResponseDialog.vue';
|
import SendInviteResponseDialog from './dialogs/SendInviteResponseDialog.vue';
|
||||||
import configRepository from '../../service/config';
|
import configRepository from '../../service/config';
|
||||||
|
|||||||
@@ -260,25 +260,7 @@
|
|||||||
getEmojiFileName(image)
|
getEmojiFileName(image)
|
||||||
)
|
)
|
||||||
">
|
">
|
||||||
<template v-if="image.frames">
|
<Emoji :imageUrl="image.versions[image.versions.length - 1].file.url" :size="200"></Emoji>
|
||||||
<div
|
|
||||||
class="avatar"
|
|
||||||
:style="
|
|
||||||
generateEmojiStyle(
|
|
||||||
image.versions[image.versions.length - 1].file.url,
|
|
||||||
image.framesOverTime,
|
|
||||||
image.frames,
|
|
||||||
image.loopStyle,
|
|
||||||
200
|
|
||||||
)
|
|
||||||
"></div>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<img
|
|
||||||
class="avatar"
|
|
||||||
:src="image.versions[image.versions.length - 1].file.url"
|
|
||||||
loading="lazy" />
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: inline-block; margin: 5px">
|
<div style="display: inline-block; margin: 5px">
|
||||||
<span v-if="image.loopStyle === 'pingpong'">
|
<span v-if="image.loopStyle === 'pingpong'">
|
||||||
@@ -553,19 +535,15 @@
|
|||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import {
|
|
||||||
extractFileId,
|
|
||||||
formatDateFilter,
|
|
||||||
generateEmojiStyle,
|
|
||||||
getEmojiFileName,
|
|
||||||
getPrintFileName
|
|
||||||
} from '../../../shared/utils';
|
|
||||||
import { inventoryRequest, miscRequest, userRequest, vrcPlusIconRequest, vrcPlusImageRequest } from '../../../api';
|
import { inventoryRequest, miscRequest, userRequest, vrcPlusIconRequest, vrcPlusImageRequest } from '../../../api';
|
||||||
|
import { extractFileId, formatDateFilter, getEmojiFileName, getPrintFileName } from '../../../shared/utils';
|
||||||
import { useAdvancedSettingsStore, useAuthStore, useGalleryStore, useUserStore } from '../../../stores';
|
import { useAdvancedSettingsStore, useAuthStore, useGalleryStore, useUserStore } from '../../../stores';
|
||||||
import { emojiAnimationStyleList, emojiAnimationStyleUrl } from '../../../shared/constants';
|
import { emojiAnimationStyleList, emojiAnimationStyleUrl } from '../../../shared/constants';
|
||||||
import { AppDebug } from '../../../service/appConfig';
|
import { AppDebug } from '../../../service/appConfig';
|
||||||
import { handleImageUploadInput } from '../../../shared/utils/imageUpload';
|
import { handleImageUploadInput } from '../../../shared/utils/imageUpload';
|
||||||
|
|
||||||
|
import Emoji from '../../../components/Emoji.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
Reference in New Issue
Block a user