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] 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); } } }