From a7df2c689a437f8f887eea24208da97c0fc862c8 Mon Sep 17 00:00:00 2001 From: CrescentLeaf Date: Sun, 9 Nov 2025 16:01:38 +0800 Subject: [PATCH] =?UTF-8?q?ui:=20=E7=A7=BB=E9=99=A4=E5=AF=B9=E5=AA=92?= =?UTF-8?q?=E4=BD=93=E6=96=87=E4=BB=B6=E7=9A=84=E6=98=BE=E7=A4=BA=E5=9C=86?= =?UTF-8?q?=E8=A7=92,=20=E5=B9=B6=E4=BF=AE=E6=AD=A3=E5=A4=A7=E5=B0=8F=20(?= =?UTF-8?q?=E5=9D=97=E7=BA=A7=E5=85=83=E7=B4=A0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/ui/custom-elements/chat-file.ts | 2 +- client/ui/custom-elements/chat-image.ts | 68 ++++++++++++++++--------- client/ui/custom-elements/chat-video.ts | 32 ++++++++---- 3 files changed, 67 insertions(+), 35 deletions(-) diff --git a/client/ui/custom-elements/chat-file.ts b/client/ui/custom-elements/chat-file.ts index 7929789..6807b18 100644 --- a/client/ui/custom-elements/chat-file.ts +++ b/client/ui/custom-elements/chat-file.ts @@ -7,7 +7,7 @@ customElements.define('chat-file', class extends HTMLElement { connectedCallback() { const e = new DOMParser().parseFromString(` - + diff --git a/client/ui/custom-elements/chat-image.ts b/client/ui/custom-elements/chat-image.ts index c3078a1..b1e6aa2 100644 --- a/client/ui/custom-elements/chat-image.ts +++ b/client/ui/custom-elements/chat-image.ts @@ -1,39 +1,59 @@ import openImageViewer from "../openImageViewer.ts" -import { snackbar } from "../snackbar.ts" import { $ } from 'mdui/jq' customElements.define('chat-image', class extends HTMLElement { + static observedAttributes = ['src', 'show-error'] + declare img: HTMLImageElement + declare error: HTMLElement constructor() { super() + + this.attachShadow({ mode: 'open' }) + } + update() { + if (this.img == null) return + + this.img.src = $(this).attr('src') as string + + const error = $(this).attr('show-error') == 'true' + this.img.style.display = error ? 'none' : 'block' + this.error.style.display = error ? '' : 'none' + } + attributeChangedCallback(_name: string, _oldValue: unknown, _newValue: unknown) { + this.update() } connectedCallback() { - this.style.display = 'block' - const e = new Image() - e.style.maxWidth = "400px" - e.style.maxHeight = "300px" - e.style.marginTop = '5px' - e.style.marginBottom = '5px' - e.style.borderRadius = "var(--mdui-shape-corner-medium)" - e.alt = $(this).attr('alt') || "" - e.onerror = () => { - const src = $(this).attr('src') - $(this).html(``) - $(this).attr('alt', '无法加载: ' + $(this).attr('alt')) - $(this).on('click', () => { - snackbar({ - message: `图片 (${src}) 无法加载!`, - placement: 'top' - }) - }) - } - e.src = $(this).attr('src') as string - e.onclick = (event) => { + this.img = new Image() + this.img.style.width = '100%' + this.img.style.maxHeight = "300px" + this.img.style.objectFit = 'cover' + // this.img.style.borderRadius = "var(--mdui-shape-corner-medium)" + this.shadowRoot!.appendChild(this.img) + + this.error = new DOMParser().parseFromString(``, 'text/html').body.firstChild as HTMLElement + this.shadowRoot!.appendChild(this.error) + + this.img.addEventListener('error', () => { + $(this).attr('show-error', 'true') + }) + this.error.addEventListener('click', (event) => { + event.stopPropagation() + const img = this.img + this.img = new Image() + this.img.style.width = '100%' + this.img.style.maxHeight = "300px" + this.img.style.objectFit = 'cover' + this.shadowRoot!.replaceChild(img, this.img) + $(this).attr('show-error', undefined) + }) + this.img.addEventListener('click', (event) => { event.stopPropagation() openImageViewer($(this).attr('src') as string) - } - this.appendChild(e) + }) + + this.update() } }) diff --git a/client/ui/custom-elements/chat-video.ts b/client/ui/custom-elements/chat-video.ts index 2710d49..be2a808 100644 --- a/client/ui/custom-elements/chat-video.ts +++ b/client/ui/custom-elements/chat-video.ts @@ -1,19 +1,31 @@ import { $ } from 'mdui/jq' customElements.define('chat-video', class extends HTMLElement { + static observedAttributes = ['src'] + declare video: HTMLVideoElement constructor() { super() + + this.attachShadow({ mode: 'open' }) + } + update() { + if (this.video == null) return + + this.video.src = $(this).attr('src') as string + } + attributeChangedCallback(_name: string, _oldValue: unknown, _newValue: unknown) { + this.update() } connectedCallback() { - this.style.display = 'block' - const e = new DOMParser().parseFromString(``, 'text/html').body.firstChild as HTMLVideoElement - e.style.maxWidth = "400px" - e.style.maxHeight = "300px" - e.style.width = "100%" - e.style.height = "100%" - e.style.borderRadius = "var(--mdui-shape-corner-medium)" - e.src = $(this).attr('src') as string - e.onclick = (e) => e.stopPropagation() - this.appendChild(e) + this.video = new DOMParser().parseFromString(``, 'text/html').body.firstChild as HTMLVideoElement + this.video.style.maxWidth = "400px" + this.video.style.maxHeight = "300px" + this.video.style.width = "100%" + this.video.style.height = "100%" + this.video.style.display = 'block' + // e.style.borderRadius = "var(--mdui-shape-corner-medium)" + + this.video.onclick = (e) => e.stopPropagation() + this.shadowRoot!.appendChild(this.video) } })