import QtQuick import QtQuick.Controls import Quickshell import qs.Common import qs.Services import qs.Widgets Item { id: widget readonly property var currentTab: { const tabs = NotepadStorageService.tabs || []; const index = NotepadStorageService.currentTabIndex; return (index >= 0 && index < tabs.length) ? tabs[index] : null; } // DMS only writes back temporary (scratch) tabs automatically; a tab backed // by a real file is shown read-only so edits here cannot clobber it. readonly property bool editable: currentTab !== null && currentTab.isTemporary === true property bool contentLoaded: false property int loadedTabId: -1 property bool applyingRemote: false property bool dirty: false function loadContent() { if (!widget.currentTab) return; const tabId = widget.currentTab.id; widget.contentLoaded = false; NotepadStorageService.loadTabContent(NotepadStorageService.currentTabIndex, content => { const buffer = NotepadStorageService.getSessionBuffer(tabId); widget.applyingRemote = true; editor.text = (buffer !== undefined) ? buffer.content : content; widget.applyingRemote = false; widget.loadedTabId = tabId; widget.contentLoaded = true; widget.dirty = false; }); } function save() { if (!widget.contentLoaded || !widget.editable || widget.loadedTabId < 0) return; NotepadStorageService.setSessionBuffer(widget.loadedTabId, editor.text, editor.text); NotepadStorageService.saveTabContent(NotepadStorageService.currentTabIndex, editor.text); widget.dirty = false; } Ref { service: NotepadStorageService } Component.onCompleted: widget.loadContent() Component.onDestruction: { if (widget.dirty) widget.save(); } Connections { target: NotepadStorageService function onCurrentTabIndexChanged() { widget.loadContent(); } } Timer { id: saveTimer interval: 900 repeat: false onTriggered: widget.save() } Rectangle { id: editorFrame anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right anchors.bottom: footer.top anchors.bottomMargin: Theme.spacingXS radius: Theme.cornerRadius color: Theme.withAlpha(Theme.surfaceLight, Theme.popupTransparency) border.color: editor.activeFocus ? Theme.primary : Theme.outlineLight border.width: editor.activeFocus ? 1 : Theme.layerOutlineWidth clip: true DankFlickable { id: editorFlick anchors.fill: parent anchors.margins: Theme.spacingS contentWidth: width contentHeight: editor.implicitHeight clip: true TextArea { id: editor width: editorFlick.width readOnly: !widget.editable wrapMode: TextArea.Wrap selectByMouse: true placeholderText: widget.editable ? "Notes, seeds, codes…" : "Open the DMS notepad to edit this tab" color: Theme.surfaceText placeholderTextColor: Theme.surfaceVariantText font.pixelSize: Theme.fontSizeMedium font.family: Theme.monoFontFamily background: null onTextChanged: { if (widget.applyingRemote || !widget.contentLoaded || !widget.editable) return; widget.dirty = true; saveTimer.restart(); } } } } Item { id: footer anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom height: 26 StyledText { anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter anchors.right: openButton.left anchors.rightMargin: Theme.spacingS text: { if (!widget.currentTab) return "No notepad tab"; if (!widget.editable) return widget.currentTab.title + " · read-only here"; return widget.currentTab.title + (widget.dirty ? " · saving…" : " · saved"); } font.pixelSize: Theme.fontSizeSmall color: Theme.surfaceVariantText elide: Text.ElideRight } Rectangle { id: openButton anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter width: openRow.width + Theme.spacingM * 2 height: 24 radius: Theme.cornerRadius color: openArea.containsMouse ? Theme.surfaceHover : "transparent" Row { id: openRow anchors.centerIn: parent spacing: Theme.spacingXS DankIcon { anchors.verticalCenter: parent.verticalCenter name: "open_in_new" size: Theme.fontSizeMedium color: Theme.surfaceVariantText } StyledText { anchors.verticalCenter: parent.verticalCenter text: "Full notepad" font.pixelSize: Theme.fontSizeSmall color: Theme.surfaceVariantText } } MouseArea { id: openArea anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { widget.save(); Quickshell.execDetached(["dms", "ipc", "call", "notepad", "toggle"]); } } } } }