From 549a43ac7f2ae8d60f6d1ce3896856295e94a650 Mon Sep 17 00:00:00 2001 From: marepallisanthosh999333 <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sat, 8 Nov 2025 20:29:14 +0530 Subject: [PATCH 01/27] feat: add sticky overlay functionality --- .../ii/modules/common/Directories.qml | 6 +- .../ii/modules/common/Persistent.qml | 8 + .../quickshell/ii/modules/overlay/Overlay.qml | 5 +- .../ii/modules/overlay/OverlayContext.qml | 5 +- .../overlay/OverlayWidgetDelegateChooser.qml | 6 + .../modules/overlay/stickypad/Stickypad.qml | 23 ++ .../overlay/stickypad/StickypadContent.qml | 363 ++++++++++++++++++ .../ii/modules/overlay/stickypad/qmldir | 4 + 8 files changed, 417 insertions(+), 3 deletions(-) create mode 100644 dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml create mode 100644 dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml create mode 100644 dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir diff --git a/dots/.config/quickshell/ii/modules/common/Directories.qml b/dots/.config/quickshell/ii/modules/common/Directories.qml index 59f3dab53..7f1694f45 100644 --- a/dots/.config/quickshell/ii/modules/common/Directories.qml +++ b/dots/.config/quickshell/ii/modules/common/Directories.qml @@ -31,7 +31,11 @@ Singleton { property string shellConfig: FileUtils.trimFileProtocol(`${Directories.config}/illogical-impulse`) property string shellConfigName: "config.json" property string shellConfigPath: `${Directories.shellConfig}/${Directories.shellConfigName}` - property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`) + property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`) + // CUSTOM: Stickypad integration - START + property string stickypadPath: FileUtils.trimFileProtocol(`${Directories.state}/user/stickypad.txt`) + // CUSTOM: Stickypad integration - END + property string conflictCachePath: FileUtils.trimFileProtocol(`${Directories.cache}/conflict-killer`) property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`) property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`) property string generatedWallpaperCategoryPath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/wallpaper/category.txt`) diff --git a/dots/.config/quickshell/ii/modules/common/Persistent.qml b/dots/.config/quickshell/ii/modules/common/Persistent.qml index 5848b1683..ee5d327cc 100644 --- a/dots/.config/quickshell/ii/modules/common/Persistent.qml +++ b/dots/.config/quickshell/ii/modules/common/Persistent.qml @@ -113,6 +113,14 @@ Singleton { property real x: 1576 property real y: 630 } + // CUSTOM: Stickypad integration - START + property JsonObject stickypad: JsonObject { + property bool pinned: true + property bool clickthrough: false + property real x: 100 + property real y: 100 + } + // CUSTOM: Stickypad integration - END } property JsonObject timer: JsonObject { diff --git a/dots/.config/quickshell/ii/modules/overlay/Overlay.qml b/dots/.config/quickshell/ii/modules/overlay/Overlay.qml index 71ba510c6..12e3d6b44 100644 --- a/dots/.config/quickshell/ii/modules/overlay/Overlay.qml +++ b/dots/.config/quickshell/ii/modules/overlay/Overlay.qml @@ -25,7 +25,10 @@ Scope { exclusionMode: ExclusionMode.Ignore WlrLayershell.namespace: "quickshell:overlay" WlrLayershell.layer: WlrLayer.Overlay - WlrLayershell.keyboardFocus: GlobalStates.overlayOpen ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None + // CUSTOM: Stickypad keyboard focus fix - START + // Use OnDemand for pinned widgets to allow focus switching with mouse clicks + WlrLayershell.keyboardFocus: GlobalStates.overlayOpen ? WlrKeyboardFocus.Exclusive : (OverlayContext.clickableWidgets.length > 0 ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None) + // CUSTOM: Stickypad keyboard focus fix - END visible: true color: "transparent" diff --git a/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml b/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml index b228deda6..4eed3e5b5 100644 --- a/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml +++ b/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml @@ -10,7 +10,10 @@ Singleton { { identifier: "volumeMixer", materialSymbol: "volume_up" }, { identifier: "crosshair", materialSymbol: "point_scan" }, { identifier: "fpsLimiter", materialSymbol: "animation" }, - { identifier: "resources", materialSymbol: "browse_activity" } + { identifier: "resources", materialSymbol: "browse_activity" }, + // CUSTOM: Stickypad integration - START + { identifier: "stickypad", materialSymbol: "note_stack" } + // CUSTOM: Stickypad integration - END ] readonly property bool hasPinnedWidgets: root.pinnedWidgetIdentifiers.length > 0 diff --git a/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml b/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml index fc75d1455..823b5d488 100644 --- a/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml +++ b/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml @@ -11,6 +11,9 @@ import qs.modules.overlay.volumeMixer import qs.modules.overlay.fpsLimiter import qs.modules.overlay.recorder import qs.modules.overlay.resources +// CUSTOM: Stickypad integration - START +import qs.modules.overlay.stickypad +// CUSTOM: Stickypad integration - END DelegateChooser { id: root @@ -21,4 +24,7 @@ DelegateChooser { DelegateChoice { roleValue: "fpsLimiter"; FpsLimiter {} } DelegateChoice { roleValue: "recorder"; Recorder {} } DelegateChoice { roleValue: "resources"; Resources {} } + // CUSTOM: Stickypad integration - START + DelegateChoice { roleValue: "stickypad"; Stickypad {} } + // CUSTOM: Stickypad integration - END } diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml new file mode 100644 index 000000000..149b65ac0 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml @@ -0,0 +1,23 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs.modules.common +import qs.modules.overlay + +StyledOverlayWidget { + id: root + title: "Stickypad" + minWidth: 440 + showCenterButton: true + + // Override opacity to always stay fully opaque, even in clickthrough mode + opacity: 1.0 + + contentItem: StickypadContent { + implicitWidth: 440 + implicitHeight: 380 + // CUSTOM: Pass clickthrough state to content - START + isClickthrough: root.clickthrough + // CUSTOM: Pass clickthrough state to content - END + } +} diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml new file mode 100644 index 000000000..db57ab40a --- /dev/null +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml @@ -0,0 +1,363 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import qs.modules.common +import qs.modules.common.widgets + +Rectangle { + id: root + + readonly property real panelPadding: 20 + property string stickypadContents: "" + property bool pendingReload: false + property var copylistEntries: [] + property string lastParsedCopylistText: "" + property var parsedCopylistLines: [] + // CUSTOM: Track clickthrough state to disable text editing - START + property bool isClickthrough: false + // CUSTOM: Track clickthrough state to disable text editing - END + + color: Appearance.colors.colLayer0 + radius: Appearance.rounding.windowRounding - 6 + + Component.onCompleted: { + stickypadFile.reload() + updateCopylistEntries() + } + + function saveStickypad() { + if (!stickypadInput) + return + stickypadContents = stickypadInput.text + stickypadFile.setText(stickypadContents) + } + + function focusStickypadAtEnd() { + if (!stickypadInput) + return + stickypadInput.forceActiveFocus() + const endPos = stickypadInput.text.length + applySelection(endPos, endPos) + } + + function applySelection(cursorPos, anchorPos) { + if (!stickypadInput) + return + const textLength = stickypadInput.text.length + const cursor = Math.max(0, Math.min(cursorPos, textLength)) + const anchor = Math.max(0, Math.min(anchorPos, textLength)) + stickypadInput.select(anchor, cursor) + if (cursor === anchor) + stickypadInput.deselect() + } + + function scheduleCopylistUpdate(immediate = false) { + if (!stickypadInput) + return + if (immediate) { + copylistDebounce.stop() + updateCopylistEntries() + } else { + copylistDebounce.restart() + } + } + + function updateCopylistEntries() { + if (!stickypadInput) + return + const textValue = stickypadInput.text + if (!textValue || textValue.length === 0) { + lastParsedCopylistText = "" + parsedCopylistLines = [] + copylistEntries = [] + return + } + + if (textValue !== lastParsedCopylistText) { + const lineRegex = /(.*?)(\r?\n|$)/g + let match = null + const parsed = [] + while ((match = lineRegex.exec(textValue)) !== null) { + const lineText = match[1] + const newlineText = match[2] + const lineStart = match.index + const lineEnd = lineStart + lineText.length + const bulletMatch = lineText.match(/^\s*-\s+(.*\S)\s*$/) + if (bulletMatch) { + parsed.push({ + content: bulletMatch[1].trim(), + start: lineStart, + end: lineEnd + }) + } + if (newlineText === "") + break + } + lastParsedCopylistText = textValue + parsedCopylistLines = parsed + if (parsed.length === 0) { + copylistEntries = [] + return + } + } + + updateCopylistPositions() + } + + function updateCopylistPositions() { + if (!stickypadInput || parsedCopylistLines.length === 0) + return + + const rawSelectionStart = stickypadInput.selectionStart + const rawSelectionEnd = stickypadInput.selectionEnd + const selectionStart = rawSelectionStart === -1 ? stickypadInput.cursorPosition : rawSelectionStart + const selectionEnd = rawSelectionEnd === -1 ? stickypadInput.cursorPosition : rawSelectionEnd + const rangeStart = Math.min(selectionStart, selectionEnd) + const rangeEnd = Math.max(selectionStart, selectionEnd) + + const entries = parsedCopylistLines.map(line => { + const caretIntersects = rangeEnd > line.start && rangeStart <= line.end + if (caretIntersects) + return null + const startRect = stickypadInput.positionToRectangle(line.start) + let endRect = stickypadInput.positionToRectangle(line.end) + if (!isFinite(startRect.y)) + return null + if (!isFinite(endRect.y)) + endRect = startRect + const lineBottom = endRect.y + endRect.height + const rectHeight = Math.max(lineBottom - startRect.y, stickypadInput.font.pixelSize + 8) + return { + content: line.content, + y: startRect.y, + height: rectHeight + } + }).filter(entry => entry !== null) + + copylistEntries = entries + } + + ColumnLayout { + id: stickypadLayout + anchors { + fill: parent + margins: panelPadding + } + spacing: 14 + + ScrollView { + id: editorScrollView + Layout.fillWidth: true + Layout.fillHeight: true + Layout.minimumHeight: 200 + clip: true + ScrollBar.vertical.policy: ScrollBar.AsNeeded + onWidthChanged: root.scheduleCopylistUpdate(true) + + StyledTextArea { + id: stickypadInput + wrapMode: TextEdit.Wrap + placeholderText: Translation.tr("Write...") + selectByMouse: true + persistentSelection: true + textFormat: TextEdit.PlainText + background: null + rightPadding: 44 + // CUSTOM: Adapt text color to theme (light/dark mode) - START + color: Appearance.colors.colOnLayer0 + // CUSTOM: Adapt text color to theme (light/dark mode) - END + // CUSTOM: Disable text area when clickthrough enabled - START + // Allow editing when overlay is open OR when clickthrough is disabled + enabled: GlobalStates.overlayOpen || !root.isClickthrough + activeFocusOnTab: GlobalStates.overlayOpen || !root.isClickthrough + + // Release focus when clickthrough is enabled and overlay closes + Connections { + target: root + function onIsClickthroughChanged() { + if (root.isClickthrough && !GlobalStates.overlayOpen && stickypadInput.activeFocus) { + stickypadInput.focus = false + } + } + } + + Connections { + target: GlobalStates + function onOverlayOpenChanged() { + if (!GlobalStates.overlayOpen && root.isClickthrough && stickypadInput.activeFocus) { + stickypadInput.focus = false + } + } + } + // CUSTOM: Disable text area when clickthrough enabled - END + + Keys.onPressed: (event) => { + if (event.key === Qt.Key_Escape && event.modifiers === Qt.NoModifier) { + Persistent.states.overlay.open = Persistent.states.overlay.open.filter(type => type !== "stickypad") + event.accepted = true + return + } + } + onTextChanged: { + if (stickypadInput.activeFocus) { + saveDebounce.restart() + } + root.scheduleCopylistUpdate(true) + } + onCursorPositionChanged: root.scheduleCopylistUpdate() + onSelectionStartChanged: root.scheduleCopylistUpdate() + onSelectionEndChanged: root.scheduleCopylistUpdate() + onHeightChanged: root.scheduleCopylistUpdate(true) + onContentHeightChanged: root.scheduleCopylistUpdate(true) + } + + Item { + anchors.fill: stickypadInput + visible: copylistEntries.length > 0 + clip: true + + Repeater { + model: copylistEntries + delegate: Item { + readonly property real lineHeight: Math.max(modelData.height, Appearance.font.pixelSize.normal + 6) + readonly property real iconSizeLocal: Appearance.font.pixelSize.normal + readonly property real hitPadding: 6 + + width: iconSizeLocal + hitPadding * 2 + height: lineHeight + y: modelData.y + x: Math.max(stickypadInput.width - width - 8, 0) + z: 5 + + Rectangle { + id: feedbackFlash + anchors.centerIn: iconItem + width: iconSizeLocal + hitPadding + height: width + radius: width / 2 + color: Appearance.colors.colLayer2 + opacity: 0 + z: -1 + } + + MaterialSymbol { + id: iconItem + anchors.centerIn: parent + text: "content_copy" + iconSize: iconSizeLocal + color: Appearance.colors.colOnLayer1 + opacity: mouseArea.containsMouse ? 1 : 0.85 + scale: 1 + Behavior on scale { + NumberAnimation { + duration: 120 + easing.type: Easing.OutQuad + } + } + Behavior on opacity { + NumberAnimation { + duration: 120 + } + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + anchors.margins: hitPadding + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onPressed: iconItem.scale = 0.85 + onReleased: iconItem.scale = 1 + onCanceled: iconItem.scale = 1 + onClicked: { + feedbackFlash.opacity = 0.6 + feedbackFade.restart() + Quickshell.clipboardText = modelData.content + } + } + + NumberAnimation { + id: feedbackFade + target: feedbackFlash + property: "opacity" + to: 0 + duration: 200 + easing.type: Easing.OutQuad + } + } + } + } + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 28 + Layout.minimumHeight: 28 + color: "transparent" + + StyledText { + id: statusLabel + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + rightMargin: 8 + } + text: saveDebounce.running ? "Saving..." : "Saved" + color: saveDebounce.running ? Appearance.colors.colAccent : Appearance.colors.colSubtext + font.pixelSize: Appearance.font.pixelSize.small + font.weight: Font.Medium + } + } + } + + Timer { + id: saveDebounce + interval: 500 + repeat: false + onTriggered: saveStickypad() + } + + Timer { + id: copylistDebounce + interval: 100 + repeat: false + onTriggered: updateCopylistPositions() + } + + FileView { + id: stickypadFile + path: Qt.resolvedUrl(Directories.stickypadPath) + onLoaded: { + stickypadContents = stickypadFile.text() + if (stickypadInput && stickypadInput.text !== stickypadContents) { + const previousCursor = stickypadInput.cursorPosition + const previousAnchor = stickypadInput.selectionStart + stickypadInput.text = stickypadContents + applySelection(previousCursor, previousAnchor) + } + if (pendingReload) { + pendingReload = false + Qt.callLater(focusStickypadAtEnd) + } + Qt.callLater(root.updateCopylistEntries) + } + onLoadFailed: (error) => { + if (error === FileViewError.FileNotFound) { + stickypadContents = "" + stickypadFile.setText(stickypadContents) + if (stickypadInput) + stickypadInput.text = stickypadContents + if (pendingReload) { + pendingReload = false + Qt.callLater(focusStickypadAtEnd) + } + Qt.callLater(root.updateCopylistEntries) + } else { + console.log("[Stickypad] Error loading file: " + error) + } + } + } +} diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir b/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir new file mode 100644 index 000000000..13d756392 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir @@ -0,0 +1,4 @@ +module qs.modules.overlay.stickypad + +Stickypad 1.0 Stickypad.qml +StickypadContent 1.0 StickypadContent.qml From c035427e6ad2c02a418b4fad64cef99135c7bda5 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 10:49:52 +0530 Subject: [PATCH 02/27] removed unnecessary comments --- dots/.config/quickshell/ii/modules/common/Directories.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Directories.qml b/dots/.config/quickshell/ii/modules/common/Directories.qml index 7f1694f45..fa25fedba 100644 --- a/dots/.config/quickshell/ii/modules/common/Directories.qml +++ b/dots/.config/quickshell/ii/modules/common/Directories.qml @@ -32,9 +32,7 @@ Singleton { property string shellConfigName: "config.json" property string shellConfigPath: `${Directories.shellConfig}/${Directories.shellConfigName}` property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`) - // CUSTOM: Stickypad integration - START property string stickypadPath: FileUtils.trimFileProtocol(`${Directories.state}/user/stickypad.txt`) - // CUSTOM: Stickypad integration - END property string conflictCachePath: FileUtils.trimFileProtocol(`${Directories.cache}/conflict-killer`) property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`) property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`) From cd452c256e3e02baef1a1a2fb2b3a59be402f120 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 10:59:51 +0530 Subject: [PATCH 03/27] Delete dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir --- dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir b/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir deleted file mode 100644 index 13d756392..000000000 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir +++ /dev/null @@ -1,4 +0,0 @@ -module qs.modules.overlay.stickypad - -Stickypad 1.0 Stickypad.qml -StickypadContent 1.0 StickypadContent.qml From 5820106e31dee7c273d8e57e9b83213e0d998066 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:11:17 +0530 Subject: [PATCH 04/27] removed overriding opacity, as one can change in their config, current default is 0.7 --- .../quickshell/ii/modules/overlay/stickypad/Stickypad.qml | 3 --- 1 file changed, 3 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml index 149b65ac0..cc42e754a 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml @@ -10,9 +10,6 @@ StyledOverlayWidget { minWidth: 440 showCenterButton: true - // Override opacity to always stay fully opaque, even in clickthrough mode - opacity: 1.0 - contentItem: StickypadContent { implicitWidth: 440 implicitHeight: 380 From 631d4960018682fd7e30ed7515c8848fb74ad1d3 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:20:19 +0530 Subject: [PATCH 05/27] removed unnecessary keyboard focus and ESC handler, as they are handled by overlay --- .../overlay/stickypad/StickypadContent.qml | 35 +++---------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml index db57ab40a..d84dff509 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml @@ -165,41 +165,14 @@ Rectangle { textFormat: TextEdit.PlainText background: null rightPadding: 44 - // CUSTOM: Adapt text color to theme (light/dark mode) - START + // Adapt text color to theme (light/dark mode) - START color: Appearance.colors.colOnLayer0 - // CUSTOM: Adapt text color to theme (light/dark mode) - END - // CUSTOM: Disable text area when clickthrough enabled - START - // Allow editing when overlay is open OR when clickthrough is disabled + // Adapt text color to theme (light/dark mode) - END + // Disable text area when clickthrough enabled - START enabled: GlobalStates.overlayOpen || !root.isClickthrough activeFocusOnTab: GlobalStates.overlayOpen || !root.isClickthrough + // Disable text area when clickthrough enabled - END - // Release focus when clickthrough is enabled and overlay closes - Connections { - target: root - function onIsClickthroughChanged() { - if (root.isClickthrough && !GlobalStates.overlayOpen && stickypadInput.activeFocus) { - stickypadInput.focus = false - } - } - } - - Connections { - target: GlobalStates - function onOverlayOpenChanged() { - if (!GlobalStates.overlayOpen && root.isClickthrough && stickypadInput.activeFocus) { - stickypadInput.focus = false - } - } - } - // CUSTOM: Disable text area when clickthrough enabled - END - - Keys.onPressed: (event) => { - if (event.key === Qt.Key_Escape && event.modifiers === Qt.NoModifier) { - Persistent.states.overlay.open = Persistent.states.overlay.open.filter(type => type !== "stickypad") - event.accepted = true - return - } - } onTextChanged: { if (stickypadInput.activeFocus) { saveDebounce.restart() From 77e626456876f47059184c6b4231c0b386949575 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:34:00 +0530 Subject: [PATCH 06/27] removed unnecessary comments --- dots/.config/quickshell/ii/modules/common/Persistent.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Persistent.qml b/dots/.config/quickshell/ii/modules/common/Persistent.qml index ee5d327cc..7585e6c62 100644 --- a/dots/.config/quickshell/ii/modules/common/Persistent.qml +++ b/dots/.config/quickshell/ii/modules/common/Persistent.qml @@ -113,14 +113,12 @@ Singleton { property real x: 1576 property real y: 630 } - // CUSTOM: Stickypad integration - START property JsonObject stickypad: JsonObject { property bool pinned: true property bool clickthrough: false property real x: 100 property real y: 100 } - // CUSTOM: Stickypad integration - END } property JsonObject timer: JsonObject { From 9c1c97a7ecdaa23619a10d7368a2da24bb204214 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:35:14 +0530 Subject: [PATCH 07/27] removed unnecessary comments --- dots/.config/quickshell/ii/modules/overlay/Overlay.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/Overlay.qml b/dots/.config/quickshell/ii/modules/overlay/Overlay.qml index 12e3d6b44..65901ea13 100644 --- a/dots/.config/quickshell/ii/modules/overlay/Overlay.qml +++ b/dots/.config/quickshell/ii/modules/overlay/Overlay.qml @@ -25,10 +25,8 @@ Scope { exclusionMode: ExclusionMode.Ignore WlrLayershell.namespace: "quickshell:overlay" WlrLayershell.layer: WlrLayer.Overlay - // CUSTOM: Stickypad keyboard focus fix - START // Use OnDemand for pinned widgets to allow focus switching with mouse clicks WlrLayershell.keyboardFocus: GlobalStates.overlayOpen ? WlrKeyboardFocus.Exclusive : (OverlayContext.clickableWidgets.length > 0 ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None) - // CUSTOM: Stickypad keyboard focus fix - END visible: true color: "transparent" From 8a5852f61a0e83a9afc890e06d73afd78a4bf9ca Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:36:04 +0530 Subject: [PATCH 08/27] removed unnecessary comments --- dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml b/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml index 4eed3e5b5..7570d7312 100644 --- a/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml +++ b/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml @@ -11,9 +11,7 @@ Singleton { { identifier: "crosshair", materialSymbol: "point_scan" }, { identifier: "fpsLimiter", materialSymbol: "animation" }, { identifier: "resources", materialSymbol: "browse_activity" }, - // CUSTOM: Stickypad integration - START { identifier: "stickypad", materialSymbol: "note_stack" } - // CUSTOM: Stickypad integration - END ] readonly property bool hasPinnedWidgets: root.pinnedWidgetIdentifiers.length > 0 From 935a8ee4112a1d7d015cadc679e3cddff0be787d Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:37:32 +0530 Subject: [PATCH 09/27] removed unnecessary comments --- .../ii/modules/overlay/OverlayWidgetDelegateChooser.qml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml b/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml index 823b5d488..42a2d7e4b 100644 --- a/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml +++ b/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml @@ -11,9 +11,7 @@ import qs.modules.overlay.volumeMixer import qs.modules.overlay.fpsLimiter import qs.modules.overlay.recorder import qs.modules.overlay.resources -// CUSTOM: Stickypad integration - START import qs.modules.overlay.stickypad -// CUSTOM: Stickypad integration - END DelegateChooser { id: root @@ -24,7 +22,5 @@ DelegateChooser { DelegateChoice { roleValue: "fpsLimiter"; FpsLimiter {} } DelegateChoice { roleValue: "recorder"; Recorder {} } DelegateChoice { roleValue: "resources"; Resources {} } - // CUSTOM: Stickypad integration - START DelegateChoice { roleValue: "stickypad"; Stickypad {} } - // CUSTOM: Stickypad integration - END } From ee94828d9711bd6fd6a5b304fdc35614562b8f9b Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:39:23 +0530 Subject: [PATCH 10/27] removed unnecessary comments --- .../ii/modules/overlay/stickypad/StickypadContent.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml index d84dff509..881116a66 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml @@ -15,9 +15,7 @@ Rectangle { property var copylistEntries: [] property string lastParsedCopylistText: "" property var parsedCopylistLines: [] - // CUSTOM: Track clickthrough state to disable text editing - START property bool isClickthrough: false - // CUSTOM: Track clickthrough state to disable text editing - END color: Appearance.colors.colLayer0 radius: Appearance.rounding.windowRounding - 6 From 819735169bcfa59dc77f85e442ce01e56fd4593b Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:40:53 +0530 Subject: [PATCH 11/27] removed unnecessary comments --- .../quickshell/ii/modules/overlay/stickypad/Stickypad.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml index cc42e754a..cd1ccbfc8 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml @@ -13,8 +13,6 @@ StyledOverlayWidget { contentItem: StickypadContent { implicitWidth: 440 implicitHeight: 380 - // CUSTOM: Pass clickthrough state to content - START isClickthrough: root.clickthrough - // CUSTOM: Pass clickthrough state to content - END } } From 61a9d406f21c06fbd09cebb94c1f0a3a0368bbf5 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 09:52:22 +0100 Subject: [PATCH 12/27] fix not launching --- .../quickshell/ii/modules/overlay/stickypad/Stickypad.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml index cd1ccbfc8..74b68fdf4 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml @@ -7,7 +7,6 @@ import qs.modules.overlay StyledOverlayWidget { id: root title: "Stickypad" - minWidth: 440 showCenterButton: true contentItem: StickypadContent { From 42147b2117b785c94f2ae0cfd9445a7edb078b5d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 09:56:57 +0100 Subject: [PATCH 13/27] stickypad: fix imports --- .../ii/modules/overlay/stickypad/StickypadContent.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml index 881116a66..d8473ea33 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml @@ -3,6 +3,8 @@ import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Io +import qs +import qs.services import qs.modules.common import qs.modules.common.widgets From 98ef819feeee075494fdbbef6a1e1591794f94a0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 09:57:11 +0100 Subject: [PATCH 14/27] stickypad: unfuck window size --- dots/.config/quickshell/ii/modules/common/Persistent.qml | 2 ++ .../quickshell/ii/modules/overlay/stickypad/Stickypad.qml | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Persistent.qml b/dots/.config/quickshell/ii/modules/common/Persistent.qml index fbb52071c..afa554d26 100644 --- a/dots/.config/quickshell/ii/modules/common/Persistent.qml +++ b/dots/.config/quickshell/ii/modules/common/Persistent.qml @@ -128,6 +128,8 @@ Singleton { property bool clickthrough: false property real x: 100 property real y: 100 + property real width: 350 + property real height: 600 } } diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml index 74b68fdf4..1db5f6693 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml @@ -10,8 +10,7 @@ StyledOverlayWidget { showCenterButton: true contentItem: StickypadContent { - implicitWidth: 440 - implicitHeight: 380 + anchors.fill: parent isClickthrough: root.clickthrough } } From f46835c9a1ad0cec52f5ac50059fe1d02274868a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:07:07 +0100 Subject: [PATCH 15/27] stickypad: moves files to correct place --- .../ii/modules/{ => ii}/overlay/stickypad/Stickypad.qml | 2 +- .../{ => ii}/overlay/stickypad/StickypadContent.qml | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) rename dots/.config/quickshell/ii/modules/{ => ii}/overlay/stickypad/Stickypad.qml (90%) rename dots/.config/quickshell/ii/modules/{ => ii}/overlay/stickypad/StickypadContent.qml (98%) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml similarity index 90% rename from dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml rename to dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml index 1db5f6693..b702f9b94 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Layouts import Quickshell import qs.modules.common -import qs.modules.overlay +import qs.modules.ii.overlay StyledOverlayWidget { id: root diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml similarity index 98% rename from dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml rename to dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index d8473ea33..adc7724d0 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -7,8 +7,9 @@ import qs import qs.services import qs.modules.common import qs.modules.common.widgets +import qs.modules.ii.overlay -Rectangle { +OverlayBackground { id: root readonly property real panelPadding: 20 @@ -19,9 +20,6 @@ Rectangle { property var parsedCopylistLines: [] property bool isClickthrough: false - color: Appearance.colors.colLayer0 - radius: Appearance.rounding.windowRounding - 6 - Component.onCompleted: { stickypadFile.reload() updateCopylistEntries() @@ -279,7 +277,7 @@ Rectangle { rightMargin: 8 } text: saveDebounce.running ? "Saving..." : "Saved" - color: saveDebounce.running ? Appearance.colors.colAccent : Appearance.colors.colSubtext + color: Appearance.colors.colSubtext font.pixelSize: Appearance.font.pixelSize.small font.weight: Font.Medium } From c8c4642c6140ae1e510632df62aa08261d2e8f67 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:28:09 +0100 Subject: [PATCH 16/27] call stickypad notes --- .../quickshell/ii/modules/common/Persistent.qml | 14 +++++++------- .../ii/modules/ii/overlay/OverlayContext.qml | 2 +- .../ii/overlay/OverlayWidgetDelegateChooser.qml | 2 +- .../ii/modules/ii/overlay/stickypad/Stickypad.qml | 5 +++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Persistent.qml b/dots/.config/quickshell/ii/modules/common/Persistent.qml index 5774912a2..478cadd10 100644 --- a/dots/.config/quickshell/ii/modules/common/Persistent.qml +++ b/dots/.config/quickshell/ii/modules/common/Persistent.qml @@ -131,13 +131,13 @@ Singleton { property real height: 600 property int tabIndex: 0 } - property JsonObject stickypad: JsonObject { - property bool pinned: true - property bool clickthrough: false - property real x: 100 - property real y: 100 - property real width: 350 - property real height: 600 + property JsonObject notes: JsonObject { + property bool pinned: false + property bool clickthrough: true + property real x: 1400 + property real y: 42 + property real width: 460 + property real height: 330 } } diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml index 7cdc938bf..bb68cefc3 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml @@ -11,7 +11,7 @@ Singleton { { identifier: "floatingImage", materialSymbol: "imagesmode" }, { identifier: "recorder", materialSymbol: "screen_record" }, { identifier: "resources", materialSymbol: "browse_activity" }, - { identifier: "stickypad", materialSymbol: "note_stack" }, + { identifier: "notes", materialSymbol: "note_stack" }, { identifier: "volumeMixer", materialSymbol: "volume_up" }, ] diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml index 97fc3b9ab..b7b26b9cf 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml @@ -23,6 +23,6 @@ DelegateChooser { DelegateChoice { roleValue: "fpsLimiter"; FpsLimiter {} } DelegateChoice { roleValue: "recorder"; Recorder {} } DelegateChoice { roleValue: "resources"; Resources {} } - DelegateChoice { roleValue: "stickypad"; Stickypad {} } + DelegateChoice { roleValue: "notes"; Stickypad {} } DelegateChoice { roleValue: "volumeMixer"; VolumeMixer {} } } diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml index b702f9b94..e6a60bd78 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml @@ -1,16 +1,17 @@ import QtQuick import QtQuick.Layouts import Quickshell +import qs.services import qs.modules.common import qs.modules.ii.overlay StyledOverlayWidget { id: root - title: "Stickypad" + title: Translation.tr("Notes") showCenterButton: true contentItem: StickypadContent { - anchors.fill: parent + radius: root.contentRadius isClickthrough: root.clickthrough } } From a5b941360c8826254dc3e0d39950ed86ee067916 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:44:08 +0100 Subject: [PATCH 17/27] stickypad: make placeholder show tip with bulletpoints --- .../ii/overlay/stickypad/StickypadContent.qml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index adc7724d0..a5eac4363 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -55,10 +55,10 @@ OverlayBackground { if (!stickypadInput) return if (immediate) { - copylistDebounce.stop() + copyListDebounce.stop() updateCopylistEntries() } else { - copylistDebounce.restart() + copyListDebounce.restart() } } @@ -156,8 +156,12 @@ OverlayBackground { StyledTextArea { id: stickypadInput + anchors { + left: parent.left + right: parent.right + } wrapMode: TextEdit.Wrap - placeholderText: Translation.tr("Write...") + placeholderText: Translation.tr("Write something here...\nUse '-' to create copyable bullet points, like this:\n\nSheep fricker\n- 4x Slab\n- 1x Boat\n- 4x Redstone Dust\n- 1x Sticky Piston\n- 1x End Rod\n- 4x Redstone Repeater\n- 1x Redstone Torch\n- 1x Sheep") selectByMouse: true persistentSelection: true textFormat: TextEdit.PlainText @@ -292,7 +296,7 @@ OverlayBackground { } Timer { - id: copylistDebounce + id: copyListDebounce interval: 100 repeat: false onTriggered: updateCopylistPositions() From f8ffe5e63f73c2c0e9ea8036974406e3777cc936 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:57:26 +0100 Subject: [PATCH 18/27] format, move text color to styled text area --- .../modules/common/widgets/StyledTextArea.qml | 1 + .../ii/overlay/stickypad/StickypadContent.qml | 249 ++++++++---------- 2 files changed, 118 insertions(+), 132 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml b/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml index b1f4579d2..13702e1f9 100644 --- a/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml +++ b/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml @@ -10,6 +10,7 @@ TextArea { selectedTextColor: Appearance.m3colors.m3onSecondaryContainer selectionColor: Appearance.colors.colSecondaryContainer placeholderTextColor: Appearance.m3colors.m3outline + color: Appearance.colors.colOnLayer0 font { family: Appearance.font.family.main pixelSize: Appearance?.font.pixelSize.small ?? 15 diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index a5eac4363..fe5852c35 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -11,149 +11,146 @@ import qs.modules.ii.overlay OverlayBackground { id: root - - readonly property real panelPadding: 20 + property string stickypadContents: "" property bool pendingReload: false property var copylistEntries: [] property string lastParsedCopylistText: "" property var parsedCopylistLines: [] property bool isClickthrough: false - + Component.onCompleted: { - stickypadFile.reload() - updateCopylistEntries() + stickypadFile.reload(); + updateCopylistEntries(); } - + function saveStickypad() { if (!stickypadInput) - return - stickypadContents = stickypadInput.text - stickypadFile.setText(stickypadContents) + return; + stickypadContents = stickypadInput.text; + stickypadFile.setText(stickypadContents); } - + function focusStickypadAtEnd() { if (!stickypadInput) - return - stickypadInput.forceActiveFocus() - const endPos = stickypadInput.text.length - applySelection(endPos, endPos) + return; + stickypadInput.forceActiveFocus(); + const endPos = stickypadInput.text.length; + applySelection(endPos, endPos); } - + function applySelection(cursorPos, anchorPos) { if (!stickypadInput) - return - const textLength = stickypadInput.text.length - const cursor = Math.max(0, Math.min(cursorPos, textLength)) - const anchor = Math.max(0, Math.min(anchorPos, textLength)) - stickypadInput.select(anchor, cursor) + return; + const textLength = stickypadInput.text.length; + const cursor = Math.max(0, Math.min(cursorPos, textLength)); + const anchor = Math.max(0, Math.min(anchorPos, textLength)); + stickypadInput.select(anchor, cursor); if (cursor === anchor) - stickypadInput.deselect() + stickypadInput.deselect(); } - + function scheduleCopylistUpdate(immediate = false) { if (!stickypadInput) - return + return; if (immediate) { - copyListDebounce.stop() - updateCopylistEntries() + copyListDebounce.stop(); + updateCopylistEntries(); } else { - copyListDebounce.restart() + copyListDebounce.restart(); } } - + function updateCopylistEntries() { if (!stickypadInput) - return - const textValue = stickypadInput.text + return; + const textValue = stickypadInput.text; if (!textValue || textValue.length === 0) { - lastParsedCopylistText = "" - parsedCopylistLines = [] - copylistEntries = [] - return + lastParsedCopylistText = ""; + parsedCopylistLines = []; + copylistEntries = []; + return; } - + if (textValue !== lastParsedCopylistText) { - const lineRegex = /(.*?)(\r?\n|$)/g - let match = null - const parsed = [] + const lineRegex = /(.*?)(\r?\n|$)/g; + let match = null; + const parsed = []; while ((match = lineRegex.exec(textValue)) !== null) { - const lineText = match[1] - const newlineText = match[2] - const lineStart = match.index - const lineEnd = lineStart + lineText.length - const bulletMatch = lineText.match(/^\s*-\s+(.*\S)\s*$/) + const lineText = match[1]; + const newlineText = match[2]; + const lineStart = match.index; + const lineEnd = lineStart + lineText.length; + const bulletMatch = lineText.match(/^\s*-\s+(.*\S)\s*$/); if (bulletMatch) { parsed.push({ content: bulletMatch[1].trim(), start: lineStart, end: lineEnd - }) + }); } if (newlineText === "") - break + break; } - lastParsedCopylistText = textValue - parsedCopylistLines = parsed + lastParsedCopylistText = textValue; + parsedCopylistLines = parsed; if (parsed.length === 0) { - copylistEntries = [] - return + copylistEntries = []; + return; } } - - updateCopylistPositions() + + updateCopylistPositions(); } - + function updateCopylistPositions() { if (!stickypadInput || parsedCopylistLines.length === 0) - return - - const rawSelectionStart = stickypadInput.selectionStart - const rawSelectionEnd = stickypadInput.selectionEnd - const selectionStart = rawSelectionStart === -1 ? stickypadInput.cursorPosition : rawSelectionStart - const selectionEnd = rawSelectionEnd === -1 ? stickypadInput.cursorPosition : rawSelectionEnd - const rangeStart = Math.min(selectionStart, selectionEnd) - const rangeEnd = Math.max(selectionStart, selectionEnd) - + return; + const rawSelectionStart = stickypadInput.selectionStart; + const rawSelectionEnd = stickypadInput.selectionEnd; + const selectionStart = rawSelectionStart === -1 ? stickypadInput.cursorPosition : rawSelectionStart; + const selectionEnd = rawSelectionEnd === -1 ? stickypadInput.cursorPosition : rawSelectionEnd; + const rangeStart = Math.min(selectionStart, selectionEnd); + const rangeEnd = Math.max(selectionStart, selectionEnd); + const entries = parsedCopylistLines.map(line => { - const caretIntersects = rangeEnd > line.start && rangeStart <= line.end + const caretIntersects = rangeEnd > line.start && rangeStart <= line.end; if (caretIntersects) - return null - const startRect = stickypadInput.positionToRectangle(line.start) - let endRect = stickypadInput.positionToRectangle(line.end) + return null; + const startRect = stickypadInput.positionToRectangle(line.start); + let endRect = stickypadInput.positionToRectangle(line.end); if (!isFinite(startRect.y)) - return null + return null; if (!isFinite(endRect.y)) - endRect = startRect - const lineBottom = endRect.y + endRect.height - const rectHeight = Math.max(lineBottom - startRect.y, stickypadInput.font.pixelSize + 8) + endRect = startRect; + const lineBottom = endRect.y + endRect.height; + const rectHeight = Math.max(lineBottom - startRect.y, stickypadInput.font.pixelSize + 8); return { content: line.content, y: startRect.y, height: rectHeight - } - }).filter(entry => entry !== null) - - copylistEntries = entries + }; + }).filter(entry => entry !== null); + + copylistEntries = entries; } - + ColumnLayout { id: stickypadLayout anchors { fill: parent - margins: panelPadding + margins: 16 } - spacing: 14 - + spacing: 10 + ScrollView { id: editorScrollView Layout.fillWidth: true Layout.fillHeight: true - Layout.minimumHeight: 200 clip: true ScrollBar.vertical.policy: ScrollBar.AsNeeded onWidthChanged: root.scheduleCopylistUpdate(true) - + StyledTextArea { id: stickypadInput anchors { @@ -167,19 +164,16 @@ OverlayBackground { textFormat: TextEdit.PlainText background: null rightPadding: 44 - // Adapt text color to theme (light/dark mode) - START - color: Appearance.colors.colOnLayer0 - // Adapt text color to theme (light/dark mode) - END // Disable text area when clickthrough enabled - START enabled: GlobalStates.overlayOpen || !root.isClickthrough activeFocusOnTab: GlobalStates.overlayOpen || !root.isClickthrough // Disable text area when clickthrough enabled - END - + onTextChanged: { if (stickypadInput.activeFocus) { - saveDebounce.restart() + saveDebounce.restart(); } - root.scheduleCopylistUpdate(true) + root.scheduleCopylistUpdate(true); } onCursorPositionChanged: root.scheduleCopylistUpdate() onSelectionStartChanged: root.scheduleCopylistUpdate() @@ -187,25 +181,25 @@ OverlayBackground { onHeightChanged: root.scheduleCopylistUpdate(true) onContentHeightChanged: root.scheduleCopylistUpdate(true) } - + Item { anchors.fill: stickypadInput visible: copylistEntries.length > 0 clip: true - + Repeater { model: copylistEntries delegate: Item { readonly property real lineHeight: Math.max(modelData.height, Appearance.font.pixelSize.normal + 6) readonly property real iconSizeLocal: Appearance.font.pixelSize.normal readonly property real hitPadding: 6 - + width: iconSizeLocal + hitPadding * 2 height: lineHeight y: modelData.y x: Math.max(stickypadInput.width - width - 8, 0) z: 5 - + Rectangle { id: feedbackFlash anchors.centerIn: iconItem @@ -214,9 +208,9 @@ OverlayBackground { radius: width / 2 color: Appearance.colors.colLayer2 opacity: 0 - z: -1 + z: 999 } - + MaterialSymbol { id: iconItem anchors.centerIn: parent @@ -237,7 +231,7 @@ OverlayBackground { } } } - + MouseArea { id: mouseArea anchors.fill: parent @@ -248,12 +242,12 @@ OverlayBackground { onReleased: iconItem.scale = 1 onCanceled: iconItem.scale = 1 onClicked: { - feedbackFlash.opacity = 0.6 - feedbackFade.restart() - Quickshell.clipboardText = modelData.content + feedbackFlash.opacity = 0.6; + feedbackFade.restart(); + Quickshell.clipboardText = modelData.content; } } - + NumberAnimation { id: feedbackFade target: feedbackFlash @@ -266,72 +260,63 @@ OverlayBackground { } } } - - Rectangle { + + StyledText { + id: statusLabel Layout.fillWidth: true - Layout.preferredHeight: 28 - Layout.minimumHeight: 28 - color: "transparent" - - StyledText { - id: statusLabel - anchors { - right: parent.right - verticalCenter: parent.verticalCenter - rightMargin: 8 - } - text: saveDebounce.running ? "Saving..." : "Saved" - color: Appearance.colors.colSubtext - font.pixelSize: Appearance.font.pixelSize.small - font.weight: Font.Medium - } + // Layout.preferredHeight: 28 + horizontalAlignment: Text.AlignRight + text: saveDebounce.running ? Translation.tr("Saving...") : Translation.tr("Saved") + color: Appearance.colors.colSubtext + font.pixelSize: Appearance.font.pixelSize.small + font.weight: Font.Medium } } - + Timer { id: saveDebounce interval: 500 repeat: false onTriggered: saveStickypad() } - + Timer { id: copyListDebounce interval: 100 repeat: false onTriggered: updateCopylistPositions() } - + FileView { id: stickypadFile path: Qt.resolvedUrl(Directories.stickypadPath) onLoaded: { - stickypadContents = stickypadFile.text() + stickypadContents = stickypadFile.text(); if (stickypadInput && stickypadInput.text !== stickypadContents) { - const previousCursor = stickypadInput.cursorPosition - const previousAnchor = stickypadInput.selectionStart - stickypadInput.text = stickypadContents - applySelection(previousCursor, previousAnchor) + const previousCursor = stickypadInput.cursorPosition; + const previousAnchor = stickypadInput.selectionStart; + stickypadInput.text = stickypadContents; + applySelection(previousCursor, previousAnchor); } if (pendingReload) { - pendingReload = false - Qt.callLater(focusStickypadAtEnd) + pendingReload = false; + Qt.callLater(focusStickypadAtEnd); } - Qt.callLater(root.updateCopylistEntries) + Qt.callLater(root.updateCopylistEntries); } - onLoadFailed: (error) => { + onLoadFailed: error => { if (error === FileViewError.FileNotFound) { - stickypadContents = "" - stickypadFile.setText(stickypadContents) + stickypadContents = ""; + stickypadFile.setText(stickypadContents); if (stickypadInput) - stickypadInput.text = stickypadContents + stickypadInput.text = stickypadContents; if (pendingReload) { - pendingReload = false - Qt.callLater(focusStickypadAtEnd) + pendingReload = false; + Qt.callLater(focusStickypadAtEnd); } - Qt.callLater(root.updateCopylistEntries) + Qt.callLater(root.updateCopylistEntries); } else { - console.log("[Stickypad] Error loading file: " + error) + console.log("[Stickypad] Error loading file: " + error); } } } From a3cb292fe9b87e77c1a70a9cd95c649d74d4fd17 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:05:50 +0100 Subject: [PATCH 19/27] reduce manual updates by aliasing stickypadContents to input area's text --- .../ii/overlay/stickypad/StickypadContent.qml | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index fe5852c35..99c3b5173 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -12,7 +12,7 @@ import qs.modules.ii.overlay OverlayBackground { id: root - property string stickypadContents: "" + property alias stickypadContents: stickypadInput.text property bool pendingReload: false property var copylistEntries: [] property string lastParsedCopylistText: "" @@ -27,22 +27,21 @@ OverlayBackground { function saveStickypad() { if (!stickypadInput) return; - stickypadContents = stickypadInput.text; - stickypadFile.setText(stickypadContents); + stickypadFile.setText(root.stickypadContents); } function focusStickypadAtEnd() { if (!stickypadInput) return; stickypadInput.forceActiveFocus(); - const endPos = stickypadInput.text.length; + const endPos = root.stickypadContents.length; applySelection(endPos, endPos); } function applySelection(cursorPos, anchorPos) { if (!stickypadInput) return; - const textLength = stickypadInput.text.length; + const textLength = root.stickypadContents.length; const cursor = Math.max(0, Math.min(cursorPos, textLength)); const anchor = Math.max(0, Math.min(anchorPos, textLength)); stickypadInput.select(anchor, cursor); @@ -64,7 +63,7 @@ OverlayBackground { function updateCopylistEntries() { if (!stickypadInput) return; - const textValue = stickypadInput.text; + const textValue = root.stickypadContents; if (!textValue || textValue.length === 0) { lastParsedCopylistText = ""; parsedCopylistLines = []; @@ -175,9 +174,7 @@ OverlayBackground { } root.scheduleCopylistUpdate(true); } - onCursorPositionChanged: root.scheduleCopylistUpdate() - onSelectionStartChanged: root.scheduleCopylistUpdate() - onSelectionEndChanged: root.scheduleCopylistUpdate() + onHeightChanged: root.scheduleCopylistUpdate(true) onContentHeightChanged: root.scheduleCopylistUpdate(true) } @@ -291,28 +288,26 @@ OverlayBackground { id: stickypadFile path: Qt.resolvedUrl(Directories.stickypadPath) onLoaded: { - stickypadContents = stickypadFile.text(); - if (stickypadInput && stickypadInput.text !== stickypadContents) { + root.stickypadContents = stickypadFile.text(); + if (root.stickypadContents !== root.stickypadContents) { const previousCursor = stickypadInput.cursorPosition; const previousAnchor = stickypadInput.selectionStart; - stickypadInput.text = stickypadContents; + root.stickypadContents = root.stickypadContents; applySelection(previousCursor, previousAnchor); } if (pendingReload) { pendingReload = false; - Qt.callLater(focusStickypadAtEnd); + Qt.callLater(root.focusStickypadAtEnd); } Qt.callLater(root.updateCopylistEntries); } onLoadFailed: error => { if (error === FileViewError.FileNotFound) { - stickypadContents = ""; - stickypadFile.setText(stickypadContents); - if (stickypadInput) - stickypadInput.text = stickypadContents; + root.stickypadContents = ""; + stickypadFile.setText(root.stickypadContents); if (pendingReload) { pendingReload = false; - Qt.callLater(focusStickypadAtEnd); + Qt.callLater(root.focusStickypadAtEnd); } Qt.callLater(root.updateCopylistEntries); } else { From eb8f1379f2ff50e707728629a391fd730c8caf13 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:09:26 +0100 Subject: [PATCH 20/27] fix null warning --- .../ii/modules/ii/overlay/stickypad/StickypadContent.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 99c3b5173..aa4507e0a 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -53,7 +53,7 @@ OverlayBackground { if (!stickypadInput) return; if (immediate) { - copyListDebounce.stop(); + copyListDebounce?.stop(); updateCopylistEntries(); } else { copyListDebounce.restart(); From 8404817e51dc04449d40a21c5eb4622bc13775be Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:13:49 +0100 Subject: [PATCH 21/27] capitalize L in copyList --- .../ii/overlay/stickypad/StickypadContent.qml | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index aa4507e0a..3f4818cb5 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -14,14 +14,14 @@ OverlayBackground { property alias stickypadContents: stickypadInput.text property bool pendingReload: false - property var copylistEntries: [] + property var copyListEntries: [] property string lastParsedCopylistText: "" property var parsedCopylistLines: [] property bool isClickthrough: false Component.onCompleted: { stickypadFile.reload(); - updateCopylistEntries(); + updateCopyListEntries(); } function saveStickypad() { @@ -54,20 +54,20 @@ OverlayBackground { return; if (immediate) { copyListDebounce?.stop(); - updateCopylistEntries(); + updateCopyListEntries(); } else { copyListDebounce.restart(); } } - function updateCopylistEntries() { + function updateCopyListEntries() { if (!stickypadInput) return; const textValue = root.stickypadContents; if (!textValue || textValue.length === 0) { lastParsedCopylistText = ""; parsedCopylistLines = []; - copylistEntries = []; + root.copyListEntries = []; return; } @@ -94,7 +94,7 @@ OverlayBackground { lastParsedCopylistText = textValue; parsedCopylistLines = parsed; if (parsed.length === 0) { - copylistEntries = []; + root.copyListEntries = []; return; } } @@ -131,7 +131,7 @@ OverlayBackground { }; }).filter(entry => entry !== null); - copylistEntries = entries; + root.copyListEntries = entries; } ColumnLayout { @@ -181,11 +181,13 @@ OverlayBackground { Item { anchors.fill: stickypadInput - visible: copylistEntries.length > 0 + visible: root.copyListEntries.length > 0 clip: true Repeater { - model: copylistEntries + model: ScriptModel { + values: root.copyListEntries + } delegate: Item { readonly property real lineHeight: Math.max(modelData.height, Appearance.font.pixelSize.normal + 6) readonly property real iconSizeLocal: Appearance.font.pixelSize.normal @@ -261,12 +263,9 @@ OverlayBackground { StyledText { id: statusLabel Layout.fillWidth: true - // Layout.preferredHeight: 28 horizontalAlignment: Text.AlignRight - text: saveDebounce.running ? Translation.tr("Saving...") : Translation.tr("Saved") + text: saveDebounce.running ? Translation.tr("Saving...") : Translation.tr("Saved ") color: Appearance.colors.colSubtext - font.pixelSize: Appearance.font.pixelSize.small - font.weight: Font.Medium } } @@ -299,7 +298,7 @@ OverlayBackground { pendingReload = false; Qt.callLater(root.focusStickypadAtEnd); } - Qt.callLater(root.updateCopylistEntries); + Qt.callLater(root.updateCopyListEntries); } onLoadFailed: error => { if (error === FileViewError.FileNotFound) { @@ -309,7 +308,7 @@ OverlayBackground { pendingReload = false; Qt.callLater(root.focusStickypadAtEnd); } - Qt.callLater(root.updateCopylistEntries); + Qt.callLater(root.updateCopyListEntries); } else { console.log("[Stickypad] Error loading file: " + error); } From 5bec6594863a8509b18297889d7565c0bd80b465 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:18:31 +0100 Subject: [PATCH 22/27] stickypad: remove redundant stuff, make clickable text area larger --- .../ii/overlay/stickypad/StickypadContent.qml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 3f4818cb5..1dad37cd1 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -136,11 +136,8 @@ OverlayBackground { ColumnLayout { id: stickypadLayout - anchors { - fill: parent - margins: 16 - } - spacing: 10 + anchors.fill: parent + spacing: 0 ScrollView { id: editorScrollView @@ -162,11 +159,8 @@ OverlayBackground { persistentSelection: true textFormat: TextEdit.PlainText background: null - rightPadding: 44 - // Disable text area when clickthrough enabled - START - enabled: GlobalStates.overlayOpen || !root.isClickthrough - activeFocusOnTab: GlobalStates.overlayOpen || !root.isClickthrough - // Disable text area when clickthrough enabled - END + padding: 16 + rightPadding: 44 + padding onTextChanged: { if (stickypadInput.activeFocus) { @@ -263,6 +257,7 @@ OverlayBackground { StyledText { id: statusLabel Layout.fillWidth: true + Layout.margins: 16 horizontalAlignment: Text.AlignRight text: saveDebounce.running ? Translation.tr("Saving...") : Translation.tr("Saved ") color: Appearance.colors.colSubtext From c16cff52b87753b91aa237124fd2e9ad5c59132b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:44:25 +0100 Subject: [PATCH 23/27] simplify copy button --- .../ii/overlay/stickypad/StickypadContent.qml | 76 +++++-------------- 1 file changed, 20 insertions(+), 56 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 1dad37cd1..4055929ae 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -171,6 +171,9 @@ OverlayBackground { onHeightChanged: root.scheduleCopylistUpdate(true) onContentHeightChanged: root.scheduleCopylistUpdate(true) + onCursorPositionChanged: root.scheduleCopylistUpdate() + onSelectionStartChanged: root.scheduleCopylistUpdate() + onSelectionEndChanged: root.scheduleCopylistUpdate() } Item { @@ -182,72 +185,33 @@ OverlayBackground { model: ScriptModel { values: root.copyListEntries } - delegate: Item { - readonly property real lineHeight: Math.max(modelData.height, Appearance.font.pixelSize.normal + 6) + delegate: RippleButton { + id: copyButton + required property var modelData + readonly property real lineHeight: Math.min(Math.max(modelData.height, Appearance.font.pixelSize.normal + 6), 40) readonly property real iconSizeLocal: Appearance.font.pixelSize.normal readonly property real hitPadding: 6 - width: iconSizeLocal + hitPadding * 2 - height: lineHeight + implicitHeight: lineHeight + implicitWidth: lineHeight + buttonRadius: height / 2 y: modelData.y - x: Math.max(stickypadInput.width - width - 8, 0) + x: Math.max(stickypadInput.width - width - 16, 0) z: 5 - Rectangle { - id: feedbackFlash - anchors.centerIn: iconItem - width: iconSizeLocal + hitPadding - height: width - radius: width / 2 - color: Appearance.colors.colLayer2 - opacity: 0 - z: 999 + onClicked: { + Quickshell.clipboardText = copyButton.modelData.content; } - MaterialSymbol { - id: iconItem + contentItem: Item { anchors.centerIn: parent - text: "content_copy" - iconSize: iconSizeLocal - color: Appearance.colors.colOnLayer1 - opacity: mouseArea.containsMouse ? 1 : 0.85 - scale: 1 - Behavior on scale { - NumberAnimation { - duration: 120 - easing.type: Easing.OutQuad - } + MaterialSymbol { + id: iconItem + anchors.centerIn: parent + text: "content_copy" + iconSize: copyButton.iconSizeLocal + color: Appearance.colors.colOnLayer1 } - Behavior on opacity { - NumberAnimation { - duration: 120 - } - } - } - - MouseArea { - id: mouseArea - anchors.fill: parent - anchors.margins: hitPadding - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: iconItem.scale = 0.85 - onReleased: iconItem.scale = 1 - onCanceled: iconItem.scale = 1 - onClicked: { - feedbackFlash.opacity = 0.6; - feedbackFade.restart(); - Quickshell.clipboardText = modelData.content; - } - } - - NumberAnimation { - id: feedbackFade - target: feedbackFlash - property: "opacity" - to: 0 - duration: 200 - easing.type: Easing.OutQuad } } } From 4ea48d60f8f15a1db278f7113296c5ba83204ffa Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:46:21 +0100 Subject: [PATCH 24/27] stickypad: feedback for copy --- .../ii/overlay/stickypad/StickypadContent.qml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 4055929ae..22c467bf8 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -191,6 +191,7 @@ OverlayBackground { readonly property real lineHeight: Math.min(Math.max(modelData.height, Appearance.font.pixelSize.normal + 6), 40) readonly property real iconSizeLocal: Appearance.font.pixelSize.normal readonly property real hitPadding: 6 + property bool justCopied: false implicitHeight: lineHeight implicitWidth: lineHeight @@ -199,8 +200,18 @@ OverlayBackground { x: Math.max(stickypadInput.width - width - 16, 0) z: 5 + Timer { + id: resetState + interval: 700 + onTriggered: { + copyButton.justCopied = false; + } + } + onClicked: { Quickshell.clipboardText = copyButton.modelData.content; + justCopied = true; + resetState.start(); } contentItem: Item { @@ -208,7 +219,7 @@ OverlayBackground { MaterialSymbol { id: iconItem anchors.centerIn: parent - text: "content_copy" + text: copyButton.justCopied ? "check" : "content_copy" iconSize: copyButton.iconSizeLocal color: Appearance.colors.colOnLayer1 } From 02afa37da157579842f61ed7c6b5314c12e3c3f3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 13:34:12 +0100 Subject: [PATCH 25/27] stickypad: adjust spacing --- .../ii/modules/ii/overlay/stickypad/StickypadContent.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 22c467bf8..364df7bc0 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -113,6 +113,7 @@ OverlayBackground { const rangeEnd = Math.max(selectionStart, selectionEnd); const entries = parsedCopylistLines.map(line => { + // Don't show copy button if line is (partially) selected const caretIntersects = rangeEnd > line.start && rangeStart <= line.end; if (caretIntersects) return null; @@ -137,7 +138,7 @@ OverlayBackground { ColumnLayout { id: stickypadLayout anchors.fill: parent - spacing: 0 + spacing: -16 ScrollView { id: editorScrollView @@ -147,7 +148,7 @@ OverlayBackground { ScrollBar.vertical.policy: ScrollBar.AsNeeded onWidthChanged: root.scheduleCopylistUpdate(true) - StyledTextArea { + StyledTextArea { // This has to be a direct child of ScrollView for proper scrolling id: stickypadInput anchors { left: parent.left From 42f29d47b4993959284ec598bace7566eb983afc Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:26:02 +0100 Subject: [PATCH 26/27] stickypad: adjust copy button size --- .../ii/modules/ii/overlay/stickypad/StickypadContent.qml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 364df7bc0..f0e8185d4 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -18,6 +18,7 @@ OverlayBackground { property string lastParsedCopylistText: "" property var parsedCopylistLines: [] property bool isClickthrough: false + property real maxCopyButtonSize: 20 Component.onCompleted: { stickypadFile.reload(); @@ -161,7 +162,7 @@ OverlayBackground { textFormat: TextEdit.PlainText background: null padding: 16 - rightPadding: 44 + padding + rightPadding: root.maxCopyButtonSize + padding onTextChanged: { if (stickypadInput.activeFocus) { @@ -189,7 +190,7 @@ OverlayBackground { delegate: RippleButton { id: copyButton required property var modelData - readonly property real lineHeight: Math.min(Math.max(modelData.height, Appearance.font.pixelSize.normal + 6), 40) + readonly property real lineHeight: Math.min(Math.max(modelData.height, Appearance.font.pixelSize.normal + 6), root.maxCopyButtonSize) readonly property real iconSizeLocal: Appearance.font.pixelSize.normal readonly property real hitPadding: 6 property bool justCopied: false @@ -198,7 +199,8 @@ OverlayBackground { implicitWidth: lineHeight buttonRadius: height / 2 y: modelData.y - x: Math.max(stickypadInput.width - width - 16, 0) + anchors.right: parent.right + anchors.rightMargin: 16 z: 5 Timer { From c19dd725b85bc8357d3617cbf3b61edeb82fa82c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:32:58 +0100 Subject: [PATCH 27/27] really rename all "stickypad" to "notes" --- .../ii/modules/common/Directories.qml | 2 +- .../overlay/OverlayWidgetDelegateChooser.qml | 4 +- .../Stickypad.qml => notes/Notes.qml} | 2 +- .../NotesContent.qml} | 82 +++++++++---------- 4 files changed, 45 insertions(+), 45 deletions(-) rename dots/.config/quickshell/ii/modules/ii/overlay/{stickypad/Stickypad.qml => notes/Notes.qml} (89%) rename dots/.config/quickshell/ii/modules/ii/overlay/{stickypad/StickypadContent.qml => notes/NotesContent.qml} (79%) diff --git a/dots/.config/quickshell/ii/modules/common/Directories.qml b/dots/.config/quickshell/ii/modules/common/Directories.qml index 04b205baf..56f647684 100644 --- a/dots/.config/quickshell/ii/modules/common/Directories.qml +++ b/dots/.config/quickshell/ii/modules/common/Directories.qml @@ -33,7 +33,7 @@ Singleton { property string shellConfigName: "config.json" property string shellConfigPath: `${Directories.shellConfig}/${Directories.shellConfigName}` property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`) - property string stickypadPath: FileUtils.trimFileProtocol(`${Directories.state}/user/stickypad.txt`) + property string notesPath: FileUtils.trimFileProtocol(`${Directories.state}/user/notes.txt`) property string conflictCachePath: FileUtils.trimFileProtocol(`${Directories.cache}/conflict-killer`) property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`) property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml index b7b26b9cf..e004be7dd 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml @@ -12,7 +12,7 @@ import qs.modules.ii.overlay.floatingImage import qs.modules.ii.overlay.fpsLimiter import qs.modules.ii.overlay.recorder import qs.modules.ii.overlay.resources -import qs.modules.ii.overlay.stickypad +import qs.modules.ii.overlay.notes DelegateChooser { id: root @@ -23,6 +23,6 @@ DelegateChooser { DelegateChoice { roleValue: "fpsLimiter"; FpsLimiter {} } DelegateChoice { roleValue: "recorder"; Recorder {} } DelegateChoice { roleValue: "resources"; Resources {} } - DelegateChoice { roleValue: "notes"; Stickypad {} } + DelegateChoice { roleValue: "notes"; Notes {} } DelegateChoice { roleValue: "volumeMixer"; VolumeMixer {} } } diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/ii/overlay/notes/Notes.qml similarity index 89% rename from dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml rename to dots/.config/quickshell/ii/modules/ii/overlay/notes/Notes.qml index e6a60bd78..64aa11d05 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/notes/Notes.qml @@ -10,7 +10,7 @@ StyledOverlayWidget { title: Translation.tr("Notes") showCenterButton: true - contentItem: StickypadContent { + contentItem: NotesContent { radius: root.contentRadius isClickthrough: root.clickthrough } diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml similarity index 79% rename from dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml rename to dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml index f0e8185d4..dfcc4e052 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml @@ -12,7 +12,7 @@ import qs.modules.ii.overlay OverlayBackground { id: root - property alias stickypadContents: stickypadInput.text + property alias content: textInput.text property bool pendingReload: false property var copyListEntries: [] property string lastParsedCopylistText: "" @@ -21,37 +21,37 @@ OverlayBackground { property real maxCopyButtonSize: 20 Component.onCompleted: { - stickypadFile.reload(); + noteFile.reload(); updateCopyListEntries(); } - function saveStickypad() { - if (!stickypadInput) + function saveContent() { + if (!textInput) return; - stickypadFile.setText(root.stickypadContents); + noteFile.setText(root.content); } - function focusStickypadAtEnd() { - if (!stickypadInput) + function focusAtEnd() { + if (!textInput) return; - stickypadInput.forceActiveFocus(); - const endPos = root.stickypadContents.length; + textInput.forceActiveFocus(); + const endPos = root.content.length; applySelection(endPos, endPos); } function applySelection(cursorPos, anchorPos) { - if (!stickypadInput) + if (!textInput) return; - const textLength = root.stickypadContents.length; + const textLength = root.content.length; const cursor = Math.max(0, Math.min(cursorPos, textLength)); const anchor = Math.max(0, Math.min(anchorPos, textLength)); - stickypadInput.select(anchor, cursor); + textInput.select(anchor, cursor); if (cursor === anchor) - stickypadInput.deselect(); + textInput.deselect(); } function scheduleCopylistUpdate(immediate = false) { - if (!stickypadInput) + if (!textInput) return; if (immediate) { copyListDebounce?.stop(); @@ -62,9 +62,9 @@ OverlayBackground { } function updateCopyListEntries() { - if (!stickypadInput) + if (!textInput) return; - const textValue = root.stickypadContents; + const textValue = root.content; if (!textValue || textValue.length === 0) { lastParsedCopylistText = ""; parsedCopylistLines = []; @@ -104,12 +104,12 @@ OverlayBackground { } function updateCopylistPositions() { - if (!stickypadInput || parsedCopylistLines.length === 0) + if (!textInput || parsedCopylistLines.length === 0) return; - const rawSelectionStart = stickypadInput.selectionStart; - const rawSelectionEnd = stickypadInput.selectionEnd; - const selectionStart = rawSelectionStart === -1 ? stickypadInput.cursorPosition : rawSelectionStart; - const selectionEnd = rawSelectionEnd === -1 ? stickypadInput.cursorPosition : rawSelectionEnd; + const rawSelectionStart = textInput.selectionStart; + const rawSelectionEnd = textInput.selectionEnd; + const selectionStart = rawSelectionStart === -1 ? textInput.cursorPosition : rawSelectionStart; + const selectionEnd = rawSelectionEnd === -1 ? textInput.cursorPosition : rawSelectionEnd; const rangeStart = Math.min(selectionStart, selectionEnd); const rangeEnd = Math.max(selectionStart, selectionEnd); @@ -118,14 +118,14 @@ OverlayBackground { const caretIntersects = rangeEnd > line.start && rangeStart <= line.end; if (caretIntersects) return null; - const startRect = stickypadInput.positionToRectangle(line.start); - let endRect = stickypadInput.positionToRectangle(line.end); + const startRect = textInput.positionToRectangle(line.start); + let endRect = textInput.positionToRectangle(line.end); if (!isFinite(startRect.y)) return null; if (!isFinite(endRect.y)) endRect = startRect; const lineBottom = endRect.y + endRect.height; - const rectHeight = Math.max(lineBottom - startRect.y, stickypadInput.font.pixelSize + 8); + const rectHeight = Math.max(lineBottom - startRect.y, textInput.font.pixelSize + 8); return { content: line.content, y: startRect.y, @@ -137,7 +137,7 @@ OverlayBackground { } ColumnLayout { - id: stickypadLayout + id: contentItem anchors.fill: parent spacing: -16 @@ -150,7 +150,7 @@ OverlayBackground { onWidthChanged: root.scheduleCopylistUpdate(true) StyledTextArea { // This has to be a direct child of ScrollView for proper scrolling - id: stickypadInput + id: textInput anchors { left: parent.left right: parent.right @@ -165,7 +165,7 @@ OverlayBackground { rightPadding: root.maxCopyButtonSize + padding onTextChanged: { - if (stickypadInput.activeFocus) { + if (textInput.activeFocus) { saveDebounce.restart(); } root.scheduleCopylistUpdate(true); @@ -179,7 +179,7 @@ OverlayBackground { } Item { - anchors.fill: stickypadInput + anchors.fill: textInput visible: root.copyListEntries.length > 0 clip: true @@ -246,7 +246,7 @@ OverlayBackground { id: saveDebounce interval: 500 repeat: false - onTriggered: saveStickypad() + onTriggered: saveContent() } Timer { @@ -257,33 +257,33 @@ OverlayBackground { } FileView { - id: stickypadFile - path: Qt.resolvedUrl(Directories.stickypadPath) + id: noteFile + path: Qt.resolvedUrl(Directories.notesPath) onLoaded: { - root.stickypadContents = stickypadFile.text(); - if (root.stickypadContents !== root.stickypadContents) { - const previousCursor = stickypadInput.cursorPosition; - const previousAnchor = stickypadInput.selectionStart; - root.stickypadContents = root.stickypadContents; + root.content = noteFile.text(); + if (root.content !== root.content) { + const previousCursor = textInput.cursorPosition; + const previousAnchor = textInput.selectionStart; + root.content = root.content; applySelection(previousCursor, previousAnchor); } if (pendingReload) { pendingReload = false; - Qt.callLater(root.focusStickypadAtEnd); + Qt.callLater(root.focusAtEnd); } Qt.callLater(root.updateCopyListEntries); } onLoadFailed: error => { if (error === FileViewError.FileNotFound) { - root.stickypadContents = ""; - stickypadFile.setText(root.stickypadContents); + root.content = ""; + noteFile.setText(root.content); if (pendingReload) { pendingReload = false; - Qt.callLater(root.focusStickypadAtEnd); + Qt.callLater(root.focusAtEnd); } Qt.callLater(root.updateCopyListEntries); } else { - console.log("[Stickypad] Error loading file: " + error); + console.log("[Overlay Notes] Error loading file: " + error); } } }