refactor: replace FullscreenImageDialog with FullscreenImagePreview component

This commit is contained in:
pa
2025-09-23 06:55:18 +09:00
committed by Natsumi
parent 34c85b3c9b
commit 485bfcc197
3 changed files with 198 additions and 127 deletions

View File

@@ -60,7 +60,7 @@
<GroupMemberModerationDialog></GroupMemberModerationDialog>
<FullscreenImageDialog></FullscreenImageDialog>
<FullscreenImagePreview></FullscreenImagePreview>
<PreviousInstancesInfoDialog></PreviousInstancesInfoDialog>
@@ -126,7 +126,7 @@
import AvatarDialog from './components/dialogs/AvatarDialog/AvatarDialog.vue';
import GroupDialog from './components/dialogs/GroupDialog/GroupDialog.vue';
import GroupMemberModerationDialog from './components/dialogs/GroupDialog/GroupMemberModerationDialog.vue';
import FullscreenImageDialog from './components/dialogs/FullscreenImageDialog.vue';
import FullscreenImagePreview from './components/FullscreenImagePreview.vue';
import PreviousInstancesInfoDialog from './components/dialogs/PreviousInstancesDialog/PreviousInstancesInfoDialog.vue';
import LaunchDialog from './components/dialogs/LaunchDialog.vue';
import LaunchOptionsDialog from './views/Settings/dialogs/LaunchOptionsDialog.vue';

View File

@@ -0,0 +1,196 @@
<template>
<div
v-if="fullscreenImageDialog.visible"
class="fullscreen-image-overlay"
:style="{ zIndex: overlayZIndex }"
@click.self="closeDialog">
<el-image
v-if="fullscreenImageDialog.imageUrl"
ref="imageRef"
class="fullscreen-image"
:src="fullscreenImageDialog.imageUrl"
:preview-src-list="[fullscreenImageDialog.imageUrl]"
:z-index="100000"
fit="contain"
preview-teleported
hide-on-click-modal
:initial-index="0"
@load="handleImageLoad"
@close="closeDialog">
<template #toolbar="{ actions }">
<el-icon @click="copyImageToClipboard(fullscreenImageDialog.imageUrl)" class="toolbar-icon">
<CopyDocument />
</el-icon>
<el-icon
@click="downloadAndSaveImage(fullscreenImageDialog.imageUrl, fullscreenImageDialog.fileName)"
class="toolbar-icon">
<Download />
</el-icon>
<el-icon @click="actions('zoomOut')" class="toolbar-icon"><ZoomOut /></el-icon>
<el-icon @click="actions('zoomIn')" class="toolbar-icon"><ZoomIn /></el-icon>
<el-icon @click="actions('clockwise')" class="toolbar-icon"><RefreshRight /></el-icon>
<el-icon @click="actions('anticlockwise')" class="toolbar-icon"><RefreshLeft /></el-icon>
</template>
</el-image>
</div>
</template>
<script setup>
import { ElMessage } from 'element-plus';
import { Download, CopyDocument, ZoomIn, ZoomOut, RefreshRight, RefreshLeft } from '@element-plus/icons-vue';
import Noty from 'noty';
import { storeToRefs } from 'pinia';
import { escapeTag, extractFileId } from '../shared/utils';
import { useGalleryStore } from '../stores';
import { ref, nextTick, watch } from 'vue';
import { getNextDialogIndex } from '../shared/utils/base/ui';
const galleryStore = useGalleryStore();
const { fullscreenImageDialog } = storeToRefs(galleryStore);
const imageRef = ref();
const overlayZIndex = ref(4000);
function showPreview() {
nextTick(() => {
imageRef.value?.showPreview?.();
});
}
function handleImageLoad() {
showPreview();
}
watch(
() => fullscreenImageDialog.value.visible,
(visible) => {
if (!visible) {
return;
}
overlayZIndex.value = Math.max(getNextDialogIndex(), 4000);
showPreview();
}
);
watch(
() => fullscreenImageDialog.value.imageUrl,
(url) => {
if (!url || !fullscreenImageDialog.value.visible) {
return;
}
showPreview();
}
);
function closeDialog() {
fullscreenImageDialog.value.visible = false;
}
async function copyImageToClipboard(url) {
if (!url) {
return;
}
const msg = ElMessage({
message: 'Downloading image...',
type: 'info'
});
try {
const response = await webApiService.execute({
url,
method: 'GET'
});
if (response.status !== 200 || !response.data.startsWith('data:image/png')) {
throw new Error(`Error: ${response.data}`);
}
await navigator.clipboard.write([
new ClipboardItem({
'image/png': await (await fetch(response.data)).blob()
})
]);
ElMessage({
message: 'Image copied to clipboard',
type: 'success'
});
} catch (error) {
console.error('Error downloading image:', error);
new Noty({
type: 'error',
text: escapeTag(`Failed to download image. ${url}`)
}).show();
} finally {
msg.close();
}
}
async function downloadAndSaveImage(url, fileName) {
if (!url) {
return;
}
const msg = ElMessage({
message: 'Downloading image...',
type: 'info'
});
try {
const response = await webApiService.execute({
url,
method: 'GET'
});
if (response.status !== 200 || !response.data.startsWith('data:image/png')) {
throw new Error(`Error: ${response.data}`);
}
const link = document.createElement('a');
link.href = response.data;
const fileId = extractFileId(url);
if (!fileName && fileId) {
fileName = `${fileId}.png`;
}
if (!fileName) {
fileName = `${url.split('/').pop()}.png`;
}
if (!fileName) {
fileName = 'image.png';
}
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.error('Error downloading image:', error);
new Noty({
type: 'error',
text: escapeTag(`Failed to download image. ${url}`)
}).show();
} finally {
msg.close();
}
}
</script>
<style scoped lang="scss">
.toolbar-icon:hover {
opacity: 1;
}
.toolbar-icon {
cursor: pointer;
opacity: 0.8;
}
.fullscreen-image-overlay {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 40px;
box-sizing: border-box;
}
.fullscreen-image {
max-width: 100%;
max-height: 100%;
}
:deep(.el-image__preview) {
display: none;
}
</style>

View File

@@ -1,125 +0,0 @@
<template>
<el-dialog class="x-dialog" v-model="fullscreenImageDialog.visible" append-to-body width="97vw">
<div>
<div style="margin: 0 0 5px 5px">
<el-tooltip :content="t('dialog.fullscreen_image.copy_image_to_clipboard')" placement="top">
<el-button
size="small"
:icon="CopyDocument"
circle
@click="copyImageToClipboard(fullscreenImageDialog.imageUrl)"></el-button>
</el-tooltip>
<el-tooltip :content="t('dialog.fullscreen_image.download_and_save_image')" placement="top">
<el-button
type="default"
size="small"
:icon="Download"
circle
style="margin-left: 5px"
:disabled="!fullscreenImageDialog.imageUrl.startsWith('http')"
@click="
downloadAndSaveImage(fullscreenImageDialog.imageUrl, fullscreenImageDialog.fileName)
"></el-button>
</el-tooltip>
</div>
<img
:src="fullscreenImageDialog.imageUrl"
style="width: 100%; height: 85vh; object-fit: contain"
loading="lazy" />
</div>
</el-dialog>
</template>
<script setup>
import { ElMessage } from 'element-plus';
import { Download, CopyDocument } from '@element-plus/icons-vue';
import Noty from 'noty';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { escapeTag, extractFileId } from '../../shared/utils';
import { useGalleryStore } from '../../stores';
const { t } = useI18n();
const { fullscreenImageDialog } = storeToRefs(useGalleryStore());
async function copyImageToClipboard(url) {
if (!url) {
return;
}
const msg = ElMessage({
message: 'Downloading image...',
type: 'info'
});
try {
const response = await webApiService.execute({
url,
method: 'GET'
});
if (response.status !== 200 || !response.data.startsWith('data:image/png')) {
throw new Error(`Error: ${response.data}`);
}
await navigator.clipboard.write([
new ClipboardItem({
'image/png': await (await fetch(response.data)).blob()
})
]);
ElMessage({
message: 'Image copied to clipboard',
type: 'success'
});
} catch (error) {
console.error('Error downloading image:', error);
new Noty({
type: 'error',
text: escapeTag(`Failed to download image. ${url}`)
}).show();
} finally {
msg.close();
}
}
async function downloadAndSaveImage(url, fileName) {
if (!url) {
return;
}
const msg = ElMessage({
message: 'Downloading image...',
type: 'info'
});
try {
const response = await webApiService.execute({
url,
method: 'GET'
});
if (response.status !== 200 || !response.data.startsWith('data:image/png')) {
throw new Error(`Error: ${response.data}`);
}
const link = document.createElement('a');
link.href = response.data;
const fileId = extractFileId(url);
if (!fileName && fileId) {
fileName = `${fileId}.png`;
}
if (!fileName) {
fileName = `${url.split('/').pop()}.png`;
}
if (!fileName) {
fileName = 'image.png';
}
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.error('Error downloading image:', error);
new Noty({
type: 'error',
text: escapeTag(`Failed to download image. ${url}`)
}).show();
} finally {
msg.close();
}
}
</script>