feat(clipboard): accept dropped content (#3211)

* feat(clipboard): accept dropped content

* fix(clipboard): address drag drop review

* fix(clipboard): preserve multi-file drops
This commit is contained in:
Huỳnh Thiện Lộc
2026-08-28 14:41:28 -04:00
committed by GitHub
parent 97b5641f67
commit f1bbb97b2a
@@ -11,6 +11,7 @@ BasePill {
property bool isActive: false
property bool isAutoHideBar: false
property bool dropConfirmed: false
signal clipboardClicked
signal showSavedItemsRequested
@@ -33,6 +34,52 @@ BasePill {
return Math.max(minValue, Math.min(maxValue, value));
}
function handleDrop(drop) {
if (!ClipboardService.clipboardAvailable)
return;
if (drop.hasUrls && drop.urls.length > 0) {
const fileUrls = drop.urls.map(url => url.toString()).filter(url => url.startsWith("file://"));
if (fileUrls.length > 0) {
DMSService.sendRequest("clipboard.store", {
"data": fileUrls.join("\r\n"),
"mimeType": "text/uri-list"
}, response => {
if (response.error) {
ToastService.showError(I18n.tr("Failed to save dropped file"));
return;
}
root.showDropConfirmation();
});
return;
}
}
if (drop.hasText && drop.text.length > 0) {
DMSService.sendRequest("clipboard.store", {
"data": drop.text,
"mimeType": "text/plain;charset=utf-8"
}, response => {
if (response.error) {
ToastService.showError(I18n.tr("Failed to save dropped text"));
return;
}
root.showDropConfirmation();
});
}
}
function showDropConfirmation() {
dropConfirmed = true;
dropConfirmationTimer.restart();
}
Timer {
id: dropConfirmationTimer
interval: 1200
onTriggered: root.dropConfirmed = false
}
function openContextMenu() {
const screen = root.parentScreen || Screen;
const screenX = screen.x || 0;
@@ -84,12 +131,34 @@ BasePill {
implicitWidth: icon.width
implicitHeight: root.widgetThickness - root.horizontalPadding * 2
property bool draggingOver: false
DropArea {
anchors.fill: parent
anchors.margins: -root.horizontalPadding
onEntered: draggingOver = true
onExited: draggingOver = false
onDropped: drop => {
draggingOver = false;
drop.accept(Qt.CopyAction);
root.handleDrop(drop);
}
}
DankIcon {
id: icon
anchors.centerIn: parent
name: "content_paste"
name: root.dropConfirmed ? "check" : "content_paste"
size: Theme.barIconSize(root.barThickness, -4, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
color: Theme.widgetIconColor
color: root.dropConfirmed || draggingOver ? Theme.primary : Theme.widgetIconColor
scale: draggingOver ? 1.2 : 1.0
Behavior on color {
ColorAnimation { duration: 150 }
}
Behavior on scale {
NumberAnimation { duration: 200; easing.type: Easing.OutBack }
}
}
}
}