1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-16 08:05:19 -04:00

Fix/clipboard confirmation keyboard safety (#2623)

* fix(clipboard): improve confirmation dialog keyboard focus

* fix(clipboard): require confirmation for clear-all shortcut
This commit is contained in:
jbwfu
2026-06-12 23:34:16 +08:00
committed by GitHub
parent d53809cf2b
commit 0f2f4b96c4
5 changed files with 57 additions and 15 deletions
@@ -7,7 +7,6 @@ Item {
id: clipboardContent id: clipboardContent
required property var modal required property var modal
required property var clearConfirmDialog
property alias searchField: searchField property alias searchField: searchField
property alias clipboardListView: clipboardListView property alias clipboardListView: clipboardListView
@@ -33,14 +32,7 @@ Item {
pinnedCount: modal.pinnedCount pinnedCount: modal.pinnedCount
onKeyboardHintsToggled: modal.showKeyboardHints = !modal.showKeyboardHints onKeyboardHintsToggled: modal.showKeyboardHints = !modal.showKeyboardHints
onTabChanged: tabName => modal.activeTab = tabName onTabChanged: tabName => modal.activeTab = tabName
onClearAllClicked: { onClearAllClicked: modal.confirmClearAll()
const hasPinned = modal.pinnedCount > 0;
const message = hasPinned ? I18n.tr("This will delete all unpinned entries. %1 pinned entries will be kept.").arg(modal.pinnedCount) : I18n.tr("This will permanently delete all clipboard history.");
clearConfirmDialog.show(I18n.tr("Clear History?"), message, function () {
modal.clearAll();
modal.hide();
}, function () {});
}
onCloseClicked: modal.hide() onCloseClicked: modal.hide()
} }
@@ -82,6 +82,15 @@ FocusScope {
ClipboardService.clearAll(); ClipboardService.clearAll();
} }
function confirmClearAll() {
const hasPinned = pinnedCount > 0;
const message = hasPinned ? I18n.tr("This will delete all unpinned entries. %1 pinned entries will be kept.").arg(pinnedCount) : I18n.tr("This will permanently delete all clipboard history.");
clearConfirmDialog.show(I18n.tr("Clear History?"), message, function () {
clearAll();
hide();
}, function () {});
}
function getEntryPreview(entry) { function getEntryPreview(entry) {
return ClipboardService.getEntryPreview(entry); return ClipboardService.getEntryPreview(entry);
} }
@@ -135,7 +144,6 @@ FocusScope {
id: historyContent id: historyContent
anchors.fill: parent anchors.fill: parent
modal: root modal: root
clearConfirmDialog: root.clearConfirmDialog
} }
} }
@@ -77,22 +77,35 @@ DankModal {
id: clearConfirmDialog id: clearConfirmDialog
confirmButtonText: I18n.tr("Clear All") confirmButtonText: I18n.tr("Clear All")
confirmButtonColor: Theme.primary confirmButtonColor: Theme.primary
onVisibleChanged: { onShouldBeVisibleChanged: {
if (visible) { if (shouldBeVisible) {
clipboardHistoryModal.shouldHaveFocus = false; clipboardHistoryModal.shouldHaveFocus = false;
selectedButton = 0;
keyboardNavigation = true;
return; return;
} }
Qt.callLater(function () { Qt.callLater(function () {
if (!clipboardHistoryModal.shouldBeVisible) { if (!clipboardHistoryModal.shouldBeVisible) {
return; return;
} }
clipboardHistoryModal.shouldHaveFocus = true; clipboardHistoryModal.shouldHaveFocus = Qt.binding(() => clipboardHistoryModal.shouldBeVisible);
clipboardHistoryModal.modalFocusScope.forceActiveFocus(); clipboardHistoryModal.modalFocusScope.forceActiveFocus();
if (clipboardHistoryModal.contentLoader.item?.searchField) { if (clipboardHistoryModal.contentLoader.item?.searchField) {
clipboardHistoryModal.contentLoader.item.searchField.forceActiveFocus(); clipboardHistoryModal.contentLoader.item.searchField.forceActiveFocus();
} }
}); });
} }
Connections {
target: clearConfirmDialog.modalFocusScope.Keys
function onPressed(event) {
if (!clearConfirmDialog.shouldBeVisible || event.key !== Qt.Key_Backtab) {
return;
}
clearConfirmDialog.selectedButton = clearConfirmDialog.selectedButton === -1 ? 1 : (clearConfirmDialog.selectedButton - 1 + 2) % 2;
clearConfirmDialog.keyboardNavigation = true;
event.accepted = true;
}
}
} }
content: Component { content: Component {
@@ -1,6 +1,7 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import Quickshell.Wayland
import qs.Common import qs.Common
import qs.Modals.Clipboard import qs.Modals.Clipboard
import qs.Modals.Common import qs.Modals.Common
@@ -95,6 +96,35 @@ DankPopout {
id: clearConfirmDialog id: clearConfirmDialog
confirmButtonText: I18n.tr("Clear All") confirmButtonText: I18n.tr("Clear All")
confirmButtonColor: Theme.primary confirmButtonColor: Theme.primary
onShouldBeVisibleChanged: {
if (shouldBeVisible) {
root.customKeyboardFocus = WlrKeyboardFocus.None;
selectedButton = 0;
keyboardNavigation = true;
return;
}
root.customKeyboardFocus = null;
Qt.callLater(function () {
if (!root.shouldBeVisible || !root.contentLoader.item) {
return;
}
root.contentLoader.item.forceActiveFocus();
if (root.contentLoader.item.searchField) {
root.contentLoader.item.searchField.forceActiveFocus();
}
});
}
Connections {
target: clearConfirmDialog.modalFocusScope.Keys
function onPressed(event) {
if (!clearConfirmDialog.shouldBeVisible || event.key !== Qt.Key_Backtab) {
return;
}
clearConfirmDialog.selectedButton = clearConfirmDialog.selectedButton === -1 ? 1 : (clearConfirmDialog.selectedButton - 1 + 2) % 2;
clearConfirmDialog.keyboardNavigation = true;
event.accepted = true;
}
}
} }
content: Component { content: Component {
@@ -184,8 +184,7 @@ QtObject {
if (event.modifiers & Qt.ShiftModifier) { if (event.modifiers & Qt.ShiftModifier) {
switch (event.key) { switch (event.key) {
case Qt.Key_Delete: case Qt.Key_Delete:
modal.clearAll(); modal.confirmClearAll();
modal.hide();
event.accepted = true; event.accepted = true;
return; return;
case Qt.Key_Return: case Qt.Key_Return: