diff --git a/Modules/Panels/Launcher/ClipboardPreview.qml b/Modules/Panels/Launcher/ClipboardPreview.qml index 3aa7d3f93..c87bc23c8 100644 --- a/Modules/Panels/Launcher/ClipboardPreview.qml +++ b/Modules/Panels/Launcher/ClipboardPreview.qml @@ -110,32 +110,47 @@ Item { height: width } - Image { - anchors.fill: parent - anchors.margins: Style.marginS - source: imageDataUrl - visible: isImageContent && !loadingFullContent && imageDataUrl !== "" - fillMode: Image.PreserveAspectFit - } - + // Preview for image entry ColumnLayout { anchors.fill: parent anchors.margins: Style.marginS - spacing: Style.marginXS - visible: !isImageContent && !loadingFullContent + spacing: Style.marginS + visible: isImageContent && !loadingFullContent && imageDataUrl !== "" + + Image { + id: previewImage + Layout.fillWidth: true + Layout.fillHeight: true + source: imageDataUrl + fillMode: Image.PreserveAspectFit + } + + NDivider { + Layout.fillWidth: true + Layout.bottomMargin: Style.marginS + } NText { Layout.fillWidth: true - visible: fullContent.length > 0 text: { - const chars = fullContent.length; - const words = fullContent.split(/\s+/).filter(w => w.length > 0).length; - const lines = fullContent.split('\n').length; - return `${chars} chars, ${words} words, ${lines} lines`; + const meta = ClipboardService.parseImageMeta(currentItem?.preview); + if (meta) + return `${meta.fmt} • ${meta.w}×${meta.h} • ${meta.size}`; + // Fallback to basic info + const format = (currentItem?.mime || "image").split("/")[1]?.toUpperCase() || "Image"; + return `${format} • ${previewImage.implicitWidth}×${previewImage.implicitHeight}`; } pointSize: Style.fontSizeS color: Color.mOnSurfaceVariant } + } + + // Preview for text entry + ColumnLayout { + anchors.fill: parent + anchors.margins: Style.marginS + spacing: Style.marginS + visible: !isImageContent && !loadingFullContent NScrollView { Layout.fillWidth: true @@ -152,6 +167,24 @@ Item { color: Color.mOnSurface } } + + NDivider { + Layout.fillWidth: true + Layout.bottomMargin: Style.marginS + } + + NText { + Layout.fillWidth: true + visible: fullContent.length > 0 + text: { + const chars = fullContent.length; + const words = fullContent.split(/\s+/).filter(w => w.length > 0).length; + const lines = fullContent.split('\n').length; + return `${chars} chars, ${words} words, ${lines} lines`; + } + pointSize: Style.fontSizeS + color: Color.mOnSurfaceVariant + } } } } diff --git a/Modules/Panels/Launcher/Launcher.qml b/Modules/Panels/Launcher/Launcher.qml index 0c9e31456..1a9b2b207 100644 --- a/Modules/Panels/Launcher/Launcher.qml +++ b/Modules/Panels/Launcher/Launcher.qml @@ -687,6 +687,13 @@ SmartPanel { } } + Behavior on y { + NumberAnimation { + duration: Style.animationFast + easing.type: Easing.OutCubic + } + } + Loader { id: previewLoader anchors.fill: parent diff --git a/Modules/Panels/Launcher/Providers/ClipboardProvider.qml b/Modules/Panels/Launcher/Providers/ClipboardProvider.qml index 741ab670e..ca537804b 100644 --- a/Modules/Panels/Launcher/Providers/ClipboardProvider.qml +++ b/Modules/Panels/Launcher/Providers/ClipboardProvider.qml @@ -228,7 +228,7 @@ Item { } function formatImageEntry(item) { - const meta = parseImageMeta(item.preview); + const meta = ClipboardService.parseImageMeta(item.preview); return { "name": meta ? `Image ${meta.w}×${meta.h}` : "Image", @@ -283,22 +283,6 @@ Item { }; } - function parseImageMeta(preview) { - const re = /\[\[\s*binary data\s+([\d\.]+\s*(?:KiB|MiB|GiB|B))\s+(\w+)\s+(\d+)x(\d+)\s*\]\]/i; - const match = (preview || "").match(re); - - if (!match) { - return null; - } - - return { - "size": match[1], - "fmt": (match[2] || "").toUpperCase(), - "w": Number(match[3]), - "h": Number(match[4]) - }; - } - function getImageForItem(clipboardId) { return ClipboardService.getImageData ? ClipboardService.getImageData(clipboardId) : null; } diff --git a/Services/Keyboard/ClipboardService.qml b/Services/Keyboard/ClipboardService.qml index dc8474e97..58a61a0bc 100644 --- a/Services/Keyboard/ClipboardService.qml +++ b/Services/Keyboard/ClipboardService.qml @@ -468,4 +468,18 @@ Singleton { revision++; Qt.callLater(() => list()); } + + // Parse image metadata from cliphist preview string + function parseImageMeta(preview) { + const re = /\[\[\s*binary data\s+([\d\.]+\s*(?:KiB|MiB|GiB|B))\s+(\w+)\s+(\d+)x(\d+)\s*\]\]/i; + const match = (preview || "").match(re); + if (!match) + return null; + return { + "size": match[1], + "fmt": (match[2] || "").toUpperCase(), + "w": Number(match[3]), + "h": Number(match[4]) + }; + } }