1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-30 00:12:50 -05:00

keyboard navigation on clipboard history

This commit is contained in:
bbedward
2025-08-16 12:34:36 -04:00
parent 4135250bb7
commit 7dfb2b6a99
3 changed files with 818 additions and 611 deletions

View File

@@ -8,7 +8,6 @@ import qs.Services
import qs.Widgets import qs.Widgets
DankModal { DankModal {
id: clipboardHistoryModal id: clipboardHistoryModal
property int totalCount: 0 property int totalCount: 0
@@ -16,122 +15,110 @@ DankModal {
property bool showClearConfirmation: false property bool showClearConfirmation: false
property var clipboardEntries: [] property var clipboardEntries: []
property string searchText: "" property string searchText: ""
property int selectedIndex: 0
property bool keyboardNavigationActive: false
property bool showKeyboardHints: false
property Component clipboardContent
function updateFilteredModel() { function updateFilteredModel() {
filteredClipboardModel.clear() filteredClipboardModel.clear();
for (var i = 0; i < clipboardModel.count; i++) { for (var i = 0; i < clipboardModel.count; i++) {
const entry = clipboardModel.get(i).entry const entry = clipboardModel.get(i).entry;
if (searchText.trim().length === 0) { if (searchText.trim().length === 0) {
filteredClipboardModel.append({ filteredClipboardModel.append({
"entry": entry "entry": entry
}) });
} else { } else {
const content = getEntryPreview(entry).toLowerCase() const content = getEntryPreview(entry).toLowerCase();
if (content.includes(searchText.toLowerCase())) if (content.includes(searchText.toLowerCase()))
filteredClipboardModel.append({ filteredClipboardModel.append({
"entry": entry "entry": entry
}) });
} }
} }
clipboardHistoryModal.totalCount = filteredClipboardModel.count clipboardHistoryModal.totalCount = filteredClipboardModel.count;
} }
function toggle() { function toggle() {
if (visible) if (visible)
hide() hide();
else else
show() show();
} }
function show() { function show() {
clipboardHistoryModal.visible = true clipboardHistoryModal.visible = true;
initializeThumbnailSystem() initializeThumbnailSystem();
refreshClipboard() refreshClipboard();
keyboardController.reset();
Qt.callLater(function() {
if (contentLoader.item) {
const content = contentLoader.item
if (content.children && content.children.length > 1) {
const searchField = content.children[1]
if (searchField && searchField.forceActiveFocus) {
searchField.text = ""
searchField.forceActiveFocus()
}
}
}
})
} }
function hide() { function hide() {
clipboardHistoryModal.visible = false clipboardHistoryModal.visible = false;
clipboardHistoryModal.searchText = "" clipboardHistoryModal.searchText = "";
cleanupTempFiles() keyboardController.reset();
cleanupTempFiles();
} }
function initializeThumbnailSystem() {// No initialization needed - using direct image display function initializeThumbnailSystem() {
} }
function cleanupTempFiles() { function cleanupTempFiles() {
Quickshell.execDetached(["sh", "-c", "rm -f /tmp/clipboard_*.png"]) Quickshell.execDetached(["sh", "-c", "rm -f /tmp/clipboard_*.png"]);
} }
function generateThumbnails() {// No thumbnail generation needed - using direct image display function generateThumbnails() {
} }
function refreshClipboard() { function refreshClipboard() {
clipboardProcess.running = true clipboardProcess.running = true;
} }
function copyEntry(entry) { function copyEntry(entry) {
const entryId = entry.split('\t')[0] const entryId = entry.split('\t')[0];
Quickshell.execDetached( Quickshell.execDetached(["sh", "-c", `cliphist decode ${entryId} | wl-copy`]);
["sh", "-c", `cliphist decode ${entryId} | wl-copy`]) ToastService.showInfo("Copied to clipboard");
clipboardHistoryModal.hide();
ToastService.showInfo("Copied to clipboard")
clipboardHistoryModal.hide()
} }
function deleteEntry(entry) { function deleteEntry(entry) {
deleteProcess.command = ["sh", "-c", `echo '${entry.replace( deleteProcess.command = ["sh", "-c", `echo '${entry.replace(
/'/g, "'\\''")}' | cliphist delete`] /'/g, "'\\''")}' | cliphist delete`];
deleteProcess.running = true deleteProcess.running = true;
} }
function clearAll() { function clearAll() {
clearProcess.running = true clearProcess.running = true;
} }
function getEntryPreview(entry) { function getEntryPreview(entry) {
let content = entry.replace(/^\s*\d+\s+/, "") let content = entry.replace(/^\s*\d+\s+/, "");
if (content.includes("image/") || content.includes("binary data") if (content.includes("image/") || content.includes("binary data") || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(content)) {
|| /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(content)) { const dimensionMatch = content.match(/(\d+)x(\d+)/);
const dimensionMatch = content.match(/(\d+)x(\d+)/)
if (dimensionMatch) if (dimensionMatch)
return `Image ${dimensionMatch[1]}×${dimensionMatch[2]}` return `Image ${dimensionMatch[1]}×${dimensionMatch[2]}`;
const typeMatch = content.match(/\b(png|jpg|jpeg|gif|bmp|webp)\b/i) const typeMatch = content.match(/\b(png|jpg|jpeg|gif|bmp|webp)\b/i);
if (typeMatch) if (typeMatch)
return `Image (${typeMatch[1].toUpperCase()})` return `Image (${typeMatch[1].toUpperCase()})`;
return "Image" return "Image";
} }
if (content.length > 100) if (content.length > 100)
return content.substring(0, 100) + "..." return content.substring(0, 100) + "...";
return content return content;
} }
function getEntryType(entry) { function getEntryType(entry) {
if (entry.includes("image/") || entry.includes("binary data") if (entry.includes("image/") || entry.includes("binary data") || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(entry) || /\b(png|jpg|jpeg|gif|bmp|webp)\b/i.test(entry))
|| /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(entry) return "image";
|| /\b(png|jpg|jpeg|gif|bmp|webp)\b/i.test(entry))
return "image"
if (entry.length > 200) if (entry.length > 200)
return "long_text" return "long_text";
return "text" return "text";
} }
visible: false visible: false
@@ -144,7 +131,125 @@ DankModal {
borderWidth: 1 borderWidth: 1
enableShadow: true enableShadow: true
onBackgroundClicked: { onBackgroundClicked: {
hide() hide();
}
modalFocusScope.Keys.onPressed: function(event) {
keyboardController.handleKey(event);
}
content: clipboardContent
QtObject {
id: keyboardController
function reset() {
selectedIndex = 0;
keyboardNavigationActive = false;
showKeyboardHints = false;
if (typeof clipboardListView !== 'undefined' && clipboardListView)
clipboardListView.keyboardActive = false;
}
function selectNext() {
if (filteredClipboardModel.count === 0)
return ;
keyboardNavigationActive = true;
selectedIndex = Math.min(selectedIndex + 1, filteredClipboardModel.count - 1);
}
function selectPrevious() {
if (filteredClipboardModel.count === 0)
return ;
keyboardNavigationActive = true;
selectedIndex = Math.max(selectedIndex - 1, 0);
}
function copySelected() {
if (filteredClipboardModel.count === 0 || selectedIndex < 0 || selectedIndex >= filteredClipboardModel.count)
return ;
var selectedEntry = filteredClipboardModel.get(selectedIndex).entry;
copyEntry(selectedEntry);
}
function deleteSelected() {
if (filteredClipboardModel.count === 0 || selectedIndex < 0 || selectedIndex >= filteredClipboardModel.count)
return ;
var selectedEntry = filteredClipboardModel.get(selectedIndex).entry;
deleteEntry(selectedEntry);
if (selectedIndex >= filteredClipboardModel.count && filteredClipboardModel.count > 0)
selectedIndex = filteredClipboardModel.count - 1;
}
function ensureVisible() {
}
function handleKey(event) {
if (event.key === Qt.Key_Escape) {
if (keyboardNavigationActive) {
keyboardNavigationActive = false;
if (typeof clipboardListView !== 'undefined' && clipboardListView)
clipboardListView.keyboardActive = false;
event.accepted = true;
} else {
hide();
event.accepted = true;
}
} else if (event.key === Qt.Key_Down) {
if (!keyboardNavigationActive) {
keyboardNavigationActive = true;
selectedIndex = 0;
if (typeof clipboardListView !== 'undefined' && clipboardListView)
clipboardListView.keyboardActive = true;
event.accepted = true;
} else {
selectNext();
event.accepted = true;
}
} else if (event.key === Qt.Key_Up) {
if (!keyboardNavigationActive) {
keyboardNavigationActive = true;
selectedIndex = 0;
if (typeof clipboardListView !== 'undefined' && clipboardListView)
clipboardListView.keyboardActive = true;
event.accepted = true;
} else if (selectedIndex === 0) {
keyboardNavigationActive = false;
if (typeof clipboardListView !== 'undefined' && clipboardListView)
clipboardListView.keyboardActive = false;
event.accepted = true;
} else {
selectPrevious();
event.accepted = true;
}
} else if (keyboardNavigationActive) {
if (event.key === Qt.Key_C && (event.modifiers & Qt.ControlModifier)) {
copySelected();
event.accepted = true;
} else if (event.key === Qt.Key_Delete) {
if (event.modifiers & Qt.ShiftModifier) {
showClearConfirmation = true;
event.accepted = true;
} else {
deleteSelected();
event.accepted = true;
}
}
}
if (event.key === Qt.Key_F10) {
showKeyboardHints = !showKeyboardHints;
event.accepted = true;
}
}
} }
DankModal { DankModal {
@@ -155,7 +260,7 @@ DankModal {
height: 150 height: 150
keyboardFocus: "ondemand" keyboardFocus: "ondemand"
onBackgroundClicked: { onBackgroundClicked: {
showClearConfirmation = false showClearConfirmation = false;
} }
content: Component { content: Component {
@@ -211,6 +316,7 @@ DankModal {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: showClearConfirmation = false onClicked: showClearConfirmation = false
} }
} }
Rectangle { Rectangle {
@@ -234,16 +340,22 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
clearAll() clearAll();
showClearConfirmation = false showClearConfirmation = false;
hide() hide();
} }
} }
} }
} }
} }
} }
} }
} }
ListModel { ListModel {
@@ -262,28 +374,30 @@ DankModal {
stdout: StdioCollector { stdout: StdioCollector {
onStreamFinished: { onStreamFinished: {
clipboardModel.clear() clipboardModel.clear();
const lines = text.trim().split('\n') const lines = text.trim().split('\n');
for (const line of lines) { for (const line of lines) {
if (line.trim().length > 0) if (line.trim().length > 0)
clipboardModel.append({ clipboardModel.append({
"entry": line "entry": line
}) });
} }
updateFilteredModel() updateFilteredModel();
} }
} }
} }
Process { Process {
id: deleteProcess id: deleteProcess
running: false running: false
onExited: exitCode => { onExited: (exitCode) => {
if (exitCode === 0) if (exitCode === 0)
refreshClipboard() refreshClipboard();
else else
console.warn("Failed to delete clipboard entry") console.warn("Failed to delete clipboard entry");
} }
} }
@@ -292,51 +406,44 @@ DankModal {
command: ["cliphist", "wipe"] command: ["cliphist", "wipe"]
running: false running: false
onExited: exitCode => { onExited: (exitCode) => {
if (exitCode === 0) { if (exitCode === 0) {
clipboardModel.clear() clipboardModel.clear();
filteredClipboardModel.clear() filteredClipboardModel.clear();
totalCount = 0 totalCount = 0;
} else { } else {
} }
} }
} }
IpcHandler { IpcHandler {
function open() { function open() {
clipboardHistoryModal.show();
clipboardHistoryModal.show() return "CLIPBOARD_OPEN_SUCCESS";
return "CLIPBOARD_OPEN_SUCCESS"
} }
function close() { function close() {
clipboardHistoryModal.hide();
clipboardHistoryModal.hide() return "CLIPBOARD_CLOSE_SUCCESS";
return "CLIPBOARD_CLOSE_SUCCESS"
} }
function toggle() { function toggle() {
clipboardHistoryModal.toggle();
clipboardHistoryModal.toggle() return "CLIPBOARD_TOGGLE_SUCCESS";
return "CLIPBOARD_TOGGLE_SUCCESS"
} }
target: "clipboard" target: "clipboard"
} }
property Component clipboardContent: Component { clipboardContent: Component {
Item {
anchors.fill: parent
Column { Column {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingL anchors.margins: Theme.spacingL
spacing: Theme.spacingL spacing: Theme.spacingL
focus: true focus: false
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
hide()
event.accepted = true
}
}
Item { Item {
width: parent.width width: parent.width
@@ -361,6 +468,7 @@ DankModal {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Row { Row {
@@ -368,13 +476,23 @@ DankModal {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS spacing: Theme.spacingS
DankActionButton {
iconName: "help"
iconSize: Theme.iconSize - 4
iconColor: showKeyboardHints ? Theme.primary : Theme.surfaceText
hoverColor: Theme.primaryHover
onClicked: {
showKeyboardHints = !showKeyboardHints;
}
}
DankActionButton { DankActionButton {
iconName: "delete_sweep" iconName: "delete_sweep"
iconSize: Theme.iconSize iconSize: Theme.iconSize
iconColor: Theme.error iconColor: Theme.error
hoverColor: Theme.errorHover hoverColor: Theme.errorHover
onClicked: { onClicked: {
showClearConfirmation = true showClearConfirmation = true;
} }
} }
@@ -385,7 +503,9 @@ DankModal {
hoverColor: Theme.errorHover hoverColor: Theme.errorHover
onClicked: hide() onClicked: hide()
} }
} }
} }
DankTextField { DankTextField {
@@ -395,9 +515,21 @@ DankModal {
placeholderText: "Search clipboard history..." placeholderText: "Search clipboard history..."
leftIconName: "search" leftIconName: "search"
showClearButton: true showClearButton: true
focus: true
ignoreLeftRightKeys: true
keyForwardTargets: [modalFocusScope]
onTextChanged: { onTextChanged: {
clipboardHistoryModal.searchText = text clipboardHistoryModal.searchText = text;
updateFilteredModel() updateFilteredModel();
}
Keys.onEscapePressed: function(event) {
clipboardHistoryModal.hide();
event.accepted = true;
}
Component.onCompleted: {
Qt.callLater(function() {
forceActiveFocus();
});
} }
} }
@@ -417,17 +549,17 @@ DankModal {
anchors.margins: Theme.spacingS anchors.margins: Theme.spacingS
clip: true clip: true
model: filteredClipboardModel model: filteredClipboardModel
currentIndex: selectedIndex
spacing: Theme.spacingXS spacing: Theme.spacingXS
// Qt 6.9+ scrolling: flickDeceleration/maximumFlickVelocity only affect touch now
interactive: true interactive: true
flickDeceleration: 1500 // Touch only in Qt 6.9+ // Lower = more momentum, longer scrolling flickDeceleration: 1500
maximumFlickVelocity: 2000 // Touch only in Qt 6.9+ // Higher = faster maximum scroll speed maximumFlickVelocity: 2000
boundsBehavior: Flickable.DragAndOvershootBounds boundsBehavior: Flickable.DragAndOvershootBounds
boundsMovement: Flickable.FollowBoundsBehavior boundsMovement: Flickable.FollowBoundsBehavior
pressDelay: 0 pressDelay: 0
flickableDirection: Flickable.VerticalFlick flickableDirection: Flickable.VerticalFlick
StyledText { StyledText {
text: "No clipboard entries found" text: "No clipboard entries found"
anchors.centerIn: parent anchors.centerIn: parent
@@ -452,17 +584,26 @@ DankModal {
property alias thumbnailImageSource: thumbnailImageSource property alias thumbnailImageSource: thumbnailImageSource
width: clipboardListView.width width: clipboardListView.width
height: Math.max(entryType === "image" ? 72 : 60, height: Math.max(entryType === "image" ? 72 : 60, contentText.contentHeight + Theme.spacingL)
contentText.contentHeight + Theme.spacingL)
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: mouseArea.containsMouse ? Theme.primaryHover : Theme.primaryBackground color: {
border.color: Theme.outlineStrong if (keyboardNavigationActive && index === selectedIndex)
border.width: 1 return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2);
return mouseArea.containsMouse ? Theme.primaryHover : Theme.primaryBackground;
}
border.color: {
if (keyboardNavigationActive && index === selectedIndex)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.5);
return Theme.outlineStrong;
}
border.width: keyboardNavigationActive && index === selectedIndex ? 1.5 : 1
Row { Row {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingM anchors.margins: Theme.spacingM
anchors.rightMargin: Theme.spacingS // Reduced right margin anchors.rightMargin: Theme.spacingS
spacing: Theme.spacingL spacing: Theme.spacingL
Rectangle { Rectangle {
@@ -479,11 +620,12 @@ DankModal {
font.weight: Font.Bold font.weight: Font.Bold
color: Theme.primary color: Theme.primary
} }
} }
Row { Row {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: parent.width - 68 // Account for index (24) + spacing (16) + delete button (32) - small margin width: parent.width - 68
spacing: Theme.spacingM spacing: Theme.spacingM
Item { Item {
@@ -493,18 +635,20 @@ DankModal {
CachingImage { CachingImage {
id: thumbnailImageSource id: thumbnailImageSource
anchors.fill: parent
property string entryId: model.entry.split('\t')[0] property string entryId: model.entry.split('\t')[0]
source: entryType === "image"
&& imageLoader.imageData ? `data:image/png;base64,${imageLoader.imageData}` : "" anchors.fill: parent
source: entryType === "image" && imageLoader.imageData ? `data:image/png;base64,${imageLoader.imageData}` : ""
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
smooth: true smooth: true
cache: true cache: true
visible: false // Hide the original image visible: false
asynchronous: true asynchronous: true
Process { Process {
id: imageLoader id: imageLoader
property string imageData: "" property string imageData: ""
command: ["sh", "-c", `cliphist decode ${thumbnailImageSource.entryId} | base64 -w 0`] command: ["sh", "-c", `cliphist decode ${thumbnailImageSource.entryId} | base64 -w 0`]
@@ -512,10 +656,12 @@ DankModal {
stdout: StdioCollector { stdout: StdioCollector {
onStreamFinished: { onStreamFinished: {
imageLoader.imageData = text.trim() imageLoader.imageData = text.trim();
} }
} }
} }
} }
MultiEffect { MultiEffect {
@@ -524,8 +670,7 @@ DankModal {
source: thumbnailImageSource source: thumbnailImageSource
maskEnabled: true maskEnabled: true
maskSource: clipboardCircularMask maskSource: clipboardCircularMask
visible: entryType === "image" visible: entryType === "image" && thumbnailImageSource.status === Image.Ready
&& thumbnailImageSource.status === Image.Ready
maskThresholdMin: 0.5 maskThresholdMin: 0.5
maskSpreadAtMin: 1 maskSpreadAtMin: 1
} }
@@ -545,41 +690,41 @@ DankModal {
color: "black" color: "black"
antialiasing: true antialiasing: true
} }
} }
DankIcon { DankIcon {
visible: !(entryType === "image" visible: !(entryType === "image" && thumbnailImageSource.status === Image.Ready)
&& thumbnailImageSource.status === Image.Ready)
name: { name: {
if (entryType === "image") if (entryType === "image")
return "image" return "image";
if (entryType === "long_text") if (entryType === "long_text")
return "subject" return "subject";
return "content_copy" return "content_copy";
} }
size: Theme.iconSize size: Theme.iconSize
color: Theme.primary color: Theme.primary
anchors.centerIn: parent anchors.centerIn: parent
} }
} }
Column { Column {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: parent.width - (entryType === "image" ? 48 : Theme.iconSize) width: parent.width - (entryType === "image" ? 48 : Theme.iconSize) - Theme.spacingM
- Theme.spacingM
spacing: Theme.spacingXS spacing: Theme.spacingXS
StyledText { StyledText {
text: { text: {
switch (entryType) { switch (entryType) {
case "image": case "image":
return "Image • " + entryPreview return "Image • " + entryPreview;
case "long_text": case "long_text":
return "Long Text" return "Long Text";
default: default:
return "Text" return "Text";
} }
} }
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
@@ -600,8 +745,11 @@ DankModal {
maximumLineCount: entryType === "long_text" ? 3 : 1 maximumLineCount: entryType === "long_text" ? 3 : 1
elide: Text.ElideRight elide: Text.ElideRight
} }
} }
} }
} }
DankActionButton { DankActionButton {
@@ -613,8 +761,7 @@ DankModal {
iconColor: Theme.error iconColor: Theme.error
hoverColor: Theme.errorHover hoverColor: Theme.errorHover
onClicked: { onClicked: {
deleteEntry(model.entry);
deleteEntry(model.entry)
} }
} }
@@ -622,22 +769,79 @@ DankModal {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: 40 // Enough space to avoid delete button (32 + 8 margin) anchors.rightMargin: 40
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: copyEntry(model.entry) onClicked: copyEntry(model.entry)
} }
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}
}
} }
content: clipboardContent }
}
Item {
width: parent.width
height: showKeyboardHints ? 80 + Theme.spacingL : 0
Behavior on height {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
Rectangle {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: Theme.spacingL
height: 80
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95)
border.color: Theme.primary
border.width: 2
opacity: showKeyboardHints ? 1 : 0
z: 100
Column {
anchors.centerIn: parent
spacing: 2
StyledText {
text: "↑/↓: Navigate • Ctrl+C: Copy • Del: Delete • F10: Help"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: "Shift+Del: Clear All • Esc: Close"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
}
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}
} }

View File

@@ -478,7 +478,7 @@ QtObject {
} }
} }
if (event.key === Qt.Key_Question || event.key === Qt.Key_H) { if (event.key === Qt.Key_F10) {
showKeyboardHints = !showKeyboardHints showKeyboardHints = !showKeyboardHints
event.accepted = true event.accepted = true
} }

View File

@@ -15,13 +15,6 @@ Rectangle {
opacity: showHints ? 1 : 0 opacity: showHints ? 1 : 0
z: 100 z: 100
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
spacing: 2 spacing: 2
@@ -34,10 +27,20 @@ Rectangle {
} }
StyledText { StyledText {
text: "Del: Clear • Shift+Del: Clear All • 1-9: Actions • ?: Help • Esc: Close" text: "Del: Clear • Shift+Del: Clear All • 1-9: Actions • F10: Help • Esc: Close"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
} }
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
} }