diff options
| author | Nippy <nippy@rp1.hu> | 2026-05-08 19:50:49 +0200 |
|---|---|---|
| committer | Nippy <nippy@rp1.hu> | 2026-05-08 19:50:49 +0200 |
| commit | 3462bcc46ecf74f576ea4397f16492c16bd75b10 (patch) | |
| tree | c5ab7aef4498647e057bda8d49c11e5f9dda74c9 /raveos-hyprland-theme/theme-data/dms/Modules/Notepad/NotepadTextEditor.qml | |
| parent | 56616f693b4f263cbf0d47da43b67424efa6022d (diff) | |
| download | RaveOS-PKGBUILD-3462bcc46ecf74f576ea4397f16492c16bd75b10.tar.gz RaveOS-PKGBUILD-3462bcc46ecf74f576ea4397f16492c16bd75b10.zip | |
raveos update
Diffstat (limited to 'raveos-hyprland-theme/theme-data/dms/Modules/Notepad/NotepadTextEditor.qml')
| -rw-r--r-- | raveos-hyprland-theme/theme-data/dms/Modules/Notepad/NotepadTextEditor.qml | 924 |
1 files changed, 924 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/dms/Modules/Notepad/NotepadTextEditor.qml b/raveos-hyprland-theme/theme-data/dms/Modules/Notepad/NotepadTextEditor.qml new file mode 100644 index 0000000..7ea0b27 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Modules/Notepad/NotepadTextEditor.qml @@ -0,0 +1,924 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell.Io +import qs.Common +import qs.Services +import qs.Widgets + +pragma ComponentBehavior: Bound + +Column { + id: root + + Component.onCompleted: { + if (PluginService.isPluginLoaded("dankNotepadModule")) { + pluginHighlightedHtml = SettingsData.getBuiltInPluginSetting("dankNotepadModule", "highlightedHtml", "") + } + } + + property alias text: textArea.text + property alias textArea: textArea + property bool contentLoaded: false + property string lastSavedContent: "" + property var currentTab: NotepadStorageService.tabs.length > NotepadStorageService.currentTabIndex ? NotepadStorageService.tabs[NotepadStorageService.currentTabIndex] : null + property bool searchVisible: false + property string searchQuery: "" + property var searchMatches: [] + property int currentMatchIndex: -1 + property int matchCount: 0 + property bool inlinePreviewVisible: false + property string previewMode: "split" // split | full + property string pluginHighlightedHtml: "" + property string lastPluginContent: "" + property int loadRequestId: 0 + + signal saveRequested() + signal openRequested() + signal newRequested() + signal previewRequested() + signal escapePressed() + signal contentChanged() + signal settingsRequested() + + function hasUnsavedChanges() { + if (!currentTab || !contentLoaded) { + return false + } + + if (currentTab.isTemporary) { + return textArea.text.length > 0 + } + return textArea.text !== lastSavedContent + } + + function loadCurrentTabContent() { + if (!currentTab) return + + const requestedTabId = currentTab.id + const requestId = ++loadRequestId + contentLoaded = false + NotepadStorageService.loadTabContent( + NotepadStorageService.currentTabIndex, + (content) => { + const activeTab = NotepadStorageService.tabs.length > NotepadStorageService.currentTabIndex + ? NotepadStorageService.tabs[NotepadStorageService.currentTabIndex] + : null + if (requestId !== loadRequestId || !activeTab || activeTab.id !== requestedTabId) + return + + lastSavedContent = content + textArea.text = content + contentLoaded = true + syncContentToPlugin() + } + ) + } + + function saveCurrentTabContent() { + if (!currentTab || !contentLoaded) return + + NotepadStorageService.saveTabContent( + NotepadStorageService.currentTabIndex, + textArea.text + ) + lastSavedContent = textArea.text + } + + function autoSaveToSession() { + if (!currentTab || !contentLoaded) return + saveCurrentTabContent() + } + + function setTextDocumentLineHeight() { + return + } + + property string lastTextForLineModel: "" + property var lineModel: [] + + function updateLineModel() { + if (!SettingsData.notepadShowLineNumbers) { + lineModel = [] + lastTextForLineModel = "" + return + } + + if (textArea.text !== lastTextForLineModel || lineModel.length === 0) { + lastTextForLineModel = textArea.text + lineModel = textArea.text.split('\n') + } + } + + function performSearch() { + let matches = [] + currentMatchIndex = -1 + + if (!searchQuery || searchQuery.length === 0) { + searchMatches = [] + matchCount = 0 + textArea.select(0, 0) + return + } + + const text = textArea.text + const query = searchQuery.toLowerCase() + let index = 0 + + while (index < text.length) { + const foundIndex = text.toLowerCase().indexOf(query, index) + if (foundIndex === -1) break + + matches.push({ + start: foundIndex, + end: foundIndex + searchQuery.length + }) + index = foundIndex + 1 + } + + searchMatches = matches + matchCount = matches.length + + if (matchCount > 0) { + currentMatchIndex = 0 + highlightCurrentMatch() + } else { + textArea.select(0, 0) + } + } + + function highlightCurrentMatch() { + if (currentMatchIndex >= 0 && currentMatchIndex < searchMatches.length) { + const match = searchMatches[currentMatchIndex] + + textArea.cursorPosition = match.start + textArea.moveCursorSelection(match.end, TextEdit.SelectCharacters) + + const flickable = textArea.parent + if (flickable && flickable.contentY !== undefined) { + const lineHeight = textArea.font.pixelSize * 1.5 + const approxLine = textArea.text.substring(0, match.start).split('\n').length + const targetY = approxLine * lineHeight - flickable.height / 2 + flickable.contentY = Math.max(0, Math.min(targetY, flickable.contentHeight - flickable.height)) + } + } + } + + function findNext() { + if (matchCount === 0 || searchMatches.length === 0) return + + currentMatchIndex = (currentMatchIndex + 1) % matchCount + highlightCurrentMatch() + } + + function findPrevious() { + if (matchCount === 0 || searchMatches.length === 0) return + + currentMatchIndex = currentMatchIndex <= 0 ? matchCount - 1 : currentMatchIndex - 1 + highlightCurrentMatch() + } + + function showSearch() { + searchVisible = true + Qt.callLater(() => { + searchField.forceActiveFocus() + }) + } + + function togglePreview() { + if (!inlinePreviewVisible) { + inlinePreviewVisible = true + previewMode = "split" + } else if (previewMode === "split") { + previewMode = "full" + } else { + inlinePreviewVisible = false + previewMode = "split" + } + syncContentToPlugin() + } + + function renderPreviewHtml() { + if (!inlinePreviewVisible) return "" + return pluginHighlightedHtml.length > 0 ? pluginHighlightedHtml : "<p><i>Rendering preview…</i></p>" + } + + function syncContentToPlugin() { + if (!PluginService.isPluginLoaded("dankNotepadModule")) + return + + if (!currentTab) + return + + const filePath = currentTab?.filePath || "" + const ext = filePath.split('.').pop().toLowerCase() + const content = textArea.text + + if (content === lastPluginContent && SettingsData.getBuiltInPluginSetting("dankNotepadModule", "previewActive", false) === inlinePreviewVisible) { + return + } + + lastPluginContent = content + SettingsData.setBuiltInPluginSetting("dankNotepadModule", "previewActive", inlinePreviewVisible) + SettingsData.setBuiltInPluginSetting("dankNotepadModule", "currentFilePath", filePath) + SettingsData.setBuiltInPluginSetting("dankNotepadModule", "currentFileExtension", ext) + SettingsData.setBuiltInPluginSetting("dankNotepadModule", "sourceContent", content) + SettingsData.setBuiltInPluginSetting("dankNotepadModule", "updatedAt", Date.now()) + } + + function hideSearch() { + searchVisible = false + searchQuery = "" + searchMatches = [] + matchCount = 0 + currentMatchIndex = -1 + textArea.select(0, 0) + textArea.forceActiveFocus() + } + + function copyPlainTextToClipboard() { + if (!inlinePreviewVisible || !textArea.text) return + + const content = textArea.text + if (content.length > 0) { + const proc = Qt.createQmlObject(` + import QtQuick + import Quickshell.Io + Process { + property string content: "" + command: ["sh", "-c", "printf '%s' \\"$CONTENT\\" | dms clipboard copy"] + environment: { "CONTENT": content } + running: false + }`, + root, + "copyProc" + ) + proc.content = content + proc.running = true + proc.exited.connect(() => { + ToastService.showInfo(I18n.tr("Copied to clipboard")) + proc.destroy() + }) + } + } + + function copyHtmlToClipboard() { + if (!inlinePreviewVisible || !pluginHighlightedHtml) return + + if (pluginHighlightedHtml.length > 0) { + const proc = Qt.createQmlObject(` + import QtQuick + import Quickshell.Io + Process { + property string content: "" + command: ["sh", "-c", "printf '%s' \\"$CONTENT\\" | dms clipboard copy"] + environment: { "CONTENT": content } + running: false + }`, + root, + "copyProcHtml" + ) + proc.content = pluginHighlightedHtml + proc.running = true + proc.exited.connect(() => { + ToastService.showInfo(I18n.tr("HTML copied to clipboard")) + proc.destroy() + }) + } + } + + spacing: Theme.spacingM + + StyledRect { + id: searchBar + width: parent.width + height: 48 + visible: searchVisible + opacity: searchVisible ? 1 : 0 + color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + border.color: searchField.activeFocus ? Theme.primary : Theme.outlineMedium + border.width: searchField.activeFocus ? 2 : 1 + radius: Theme.cornerRadius + + Behavior on opacity { + NumberAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + + RowLayout { + anchors.fill: parent + anchors.leftMargin: Theme.spacingM + anchors.rightMargin: Theme.spacingM + spacing: Theme.spacingS + + // Search icon + DankIcon { + Layout.alignment: Qt.AlignVCenter + name: "search" + size: Theme.iconSize - 2 + color: searchField.activeFocus ? Theme.primary : Theme.surfaceVariantText + } + + // Search input field + TextInput { + id: searchField + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + height: 32 + font.pixelSize: Theme.fontSizeMedium + color: Theme.surfaceText + verticalAlignment: TextInput.AlignVCenter + selectByMouse: true + clip: true + + Component.onCompleted: { + text = root.searchQuery + } + + Connections { + target: root + function onSearchQueryChanged() { + if (searchField.text !== root.searchQuery) { + searchField.text = root.searchQuery + } + } + } + + onTextChanged: { + if (root.searchQuery !== text) { + root.searchQuery = text + root.performSearch() + } + } + Keys.onEscapePressed: event => { + root.hideSearch() + event.accepted = true + } + Keys.onReturnPressed: event => { + if (event.modifiers & Qt.ShiftModifier) { + root.findPrevious() + } else { + root.findNext() + } + event.accepted = true + } + Keys.onEnterPressed: event => { + if (event.modifiers & Qt.ShiftModifier) { + root.findPrevious() + } else { + root.findNext() + } + event.accepted = true + } + } + + // Placeholder text + StyledText { + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + text: I18n.tr("Find in note...") + font: searchField.font + color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) + visible: searchField.text.length === 0 && !searchField.activeFocus + Layout.leftMargin: -(searchField.width - 20) // Position over the input field + } + + // Match count display + StyledText { + Layout.alignment: Qt.AlignVCenter + text: matchCount > 0 ? "%1/%2".arg(currentMatchIndex + 1).arg(matchCount) : searchQuery.length > 0 ? I18n.tr("No matches") : "" + font.pixelSize: Theme.fontSizeSmall + color: matchCount > 0 ? Theme.primary : Theme.surfaceTextMedium + visible: searchQuery.length > 0 + Layout.rightMargin: Theme.spacingS + } + + // Navigation buttons + DankActionButton { + id: prevButton + Layout.alignment: Qt.AlignVCenter + iconName: "keyboard_arrow_up" + iconSize: Theme.iconSize + iconColor: matchCount > 0 ? Theme.surfaceText : Theme.surfaceTextAlpha + enabled: matchCount > 0 + onClicked: root.findPrevious() + } + + DankActionButton { + id: nextButton + Layout.alignment: Qt.AlignVCenter + iconName: "keyboard_arrow_down" + iconSize: Theme.iconSize + iconColor: matchCount > 0 ? Theme.surfaceText : Theme.surfaceTextAlpha + enabled: matchCount > 0 + onClicked: root.findNext() + } + + DankActionButton { + id: closeSearchButton + Layout.alignment: Qt.AlignVCenter + iconName: "close" + iconSize: Theme.iconSize - 2 + iconColor: Theme.surfaceText + onClicked: root.hideSearch() + } + } + } + + StyledRect { + width: parent.width + height: parent.height - bottomControls.height - Theme.spacingM - (searchVisible ? searchBar.height + Theme.spacingM : 0) + color: Qt.rgba(Theme.surface.r, Theme.surface.g, Theme.surface.b, Theme.notepadTransparency) + border.color: Theme.outlineMedium + border.width: 1 + radius: Theme.cornerRadius + + RowLayout { + id: editorPreviewRow + anchors.fill: parent + anchors.margins: 1 + spacing: Theme.spacingM + + Item { + id: editorPane + visible: !inlinePreviewVisible || previewMode === "split" + Layout.fillHeight: true + Layout.fillWidth: !inlinePreviewVisible || previewMode === "split" + Layout.preferredWidth: inlinePreviewVisible ? parent.width * 0.55 : parent.width + clip: true + + DankFlickable { + id: flickable + anchors.fill: parent + clip: true + contentWidth: width - 11 + + Rectangle { + id: lineNumberArea + anchors.left: parent.left + anchors.top: parent.top + width: SettingsData.notepadShowLineNumbers ? Math.max(30, 32 + Theme.spacingXS) : 0 + height: textArea.contentHeight + textArea.topPadding + textArea.bottomPadding + color: "transparent" + visible: SettingsData.notepadShowLineNumbers + + ListView { + id: lineNumberList + anchors.top: parent.top + anchors.topMargin: textArea.topPadding + anchors.right: parent.right + anchors.rightMargin: 2 + width: 32 + height: textArea.contentHeight + model: SettingsData.notepadShowLineNumbers ? root.lineModel : [] + interactive: false + spacing: 0 + + delegate: Item { + id: lineDelegate + required property int index + required property string modelData + width: 32 + height: measuringText.contentHeight + + Text { + id: measuringText + width: textArea.width - textArea.leftPadding - textArea.rightPadding + text: modelData || " " + font: textArea.font + wrapMode: Text.Wrap + visible: false + } + + StyledText { + anchors.right: parent.right + anchors.rightMargin: 4 + anchors.top: parent.top + text: index + 1 + font.family: textArea.font.family + font.pixelSize: textArea.font.pixelSize + color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.4) + horizontalAlignment: Text.AlignRight + } + } + } + } + + TextArea.flickable: TextArea { + id: textArea + placeholderText: "" + placeholderTextColor: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) + font.family: SettingsData.notepadUseMonospace ? SettingsData.monoFontFamily : (SettingsData.notepadFontFamily || SettingsData.fontFamily) + font.pixelSize: SettingsData.notepadFontSize * SettingsData.fontScale + font.letterSpacing: 0 + color: Theme.surfaceText + selectedTextColor: Theme.background + selectionColor: Theme.primary + selectByMouse: true + selectByKeyboard: true + wrapMode: TextArea.Wrap + focus: true + activeFocusOnTab: true + textFormat: TextEdit.PlainText + inputMethodHints: Qt.ImhNoPredictiveText | Qt.ImhNoAutoUppercase + persistentSelection: true + tabStopDistance: 40 + leftPadding: (SettingsData.notepadShowLineNumbers ? lineNumberArea.width + Theme.spacingXS : Theme.spacingM) + topPadding: Theme.spacingM + rightPadding: Theme.spacingM + bottomPadding: Theme.spacingM + cursorDelegate: Rectangle { + width: 1.5 + radius: 1 + color: Theme.surfaceText + x: textArea.cursorRectangle.x + y: textArea.cursorRectangle.y + height: textArea.cursorRectangle.height + opacity: 1.0 + + SequentialAnimation on opacity { + running: textArea.activeFocus + loops: Animation.Infinite + PropertyAnimation { from: 1.0; to: 0.0; duration: 650; easing.type: Easing.InOutQuad } + PropertyAnimation { from: 0.0; to: 1.0; duration: 650; easing.type: Easing.InOutQuad } + } + } + + Component.onCompleted: { + loadCurrentTabContent() + setTextDocumentLineHeight() + root.updateLineModel() + Qt.callLater(() => { + textArea.forceActiveFocus() + }) + } + + Connections { + target: NotepadStorageService + function onCurrentTabIndexChanged() { + loadCurrentTabContent() + Qt.callLater(() => { + textArea.forceActiveFocus() + }) + } + function onTabsChanged() { + if (NotepadStorageService.tabs.length > 0 && !contentLoaded) { + loadCurrentTabContent() + } + } + } + + Connections { + target: SettingsData + function onNotepadShowLineNumbersChanged() { + root.updateLineModel() + } + } + + onTextChanged: { + if (contentLoaded && text !== lastSavedContent) { + autoSaveTimer.restart() + } + root.contentChanged() + root.updateLineModel() + pluginSyncTimer.restart() + } + + Keys.onEscapePressed: (event) => { + root.escapePressed() + event.accepted = true + } + + Keys.onPressed: (event) => { + if (event.modifiers & Qt.ControlModifier) { + switch (event.key) { + case Qt.Key_S: + event.accepted = true + root.saveRequested() + break + case Qt.Key_O: + event.accepted = true + root.openRequested() + break + case Qt.Key_N: + event.accepted = true + root.newRequested() + break + case Qt.Key_A: + event.accepted = true + textArea.selectAll() + break + case Qt.Key_F: + event.accepted = true + root.showSearch() + break + case Qt.Key_P: + if (PluginService.isPluginLoaded("dankNotepadModule")) { + event.accepted = true + root.previewRequested() + } + break + } + } + } + + background: Rectangle { + color: "transparent" + } + } + + StyledText { + id: placeholderOverlay + text: I18n.tr("Start typing your notes here...") + color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) + font.family: textArea.font.family + font.pixelSize: textArea.font.pixelSize + visible: textArea.text.length === 0 + anchors.left: textArea.left + anchors.top: textArea.top + anchors.leftMargin: textArea.leftPadding + anchors.topMargin: textArea.topPadding + z: textArea.z + 1 + } + } + } + + Rectangle { + id: previewDivider + visible: inlinePreviewVisible && previewMode === "split" + Layout.fillHeight: true + Layout.preferredWidth: 1 + color: Theme.outlineMedium + } + + Item { + id: previewPane + visible: inlinePreviewVisible + Layout.fillHeight: true + Layout.fillWidth: previewMode === "full" + Layout.preferredWidth: previewMode === "full" ? parent.width : parent.width * 0.45 + clip: true + + // Preview header with copy buttons + Rectangle { + id: previewHeader + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + height: 36 + color: Qt.rgba(Theme.surface.r, Theme.surface.g, Theme.surface.b, Theme.notepadTransparency) + z: 2 + + Row { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.rightMargin: Theme.spacingM + spacing: Theme.spacingS + + // Copy plain text button + DankActionButton { + iconName: "content_copy" + iconSize: Theme.iconSize - 4 + iconColor: Theme.surfaceTextMedium + onClicked: copyPlainTextToClipboard() + } + + StyledText { + anchors.verticalCenter: parent.verticalCenter + text: I18n.tr("Copy Text") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + } + + Rectangle { + width: 1 + height: 20 + color: Theme.outlineVariant + anchors.verticalCenter: parent.verticalCenter + } + + // Copy HTML button + DankActionButton { + iconName: "code" + iconSize: Theme.iconSize - 4 + iconColor: Theme.surfaceTextMedium + onClicked: copyHtmlToClipboard() + } + + StyledText { + anchors.verticalCenter: parent.verticalCenter + text: I18n.tr("Copy HTML") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + } + } + } + + DankFlickable { + id: previewFlickable + anchors.top: previewHeader.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.topMargin: Theme.spacingS + clip: true + contentWidth: width - 11 + contentHeight: previewText.paintedHeight + Theme.spacingM * 2 + + Text { + id: previewText + width: parent.width - Theme.spacingM + padding: Theme.spacingM + wrapMode: Text.WordWrap + textFormat: Text.RichText + text: inlinePreviewVisible ? renderPreviewHtml() : "" + color: Theme.surfaceText + font.family: SettingsData.notepadFontFamily || SettingsData.fontFamily + font.pixelSize: Theme.fontSizeMedium + linkColor: Theme.primary + + onLinkActivated: url => Qt.openUrlExternally(url) + } + } + } + } + } + + Column { + id: bottomControls + width: parent.width + spacing: Theme.spacingS + + Item { + width: parent.width + height: 32 + + Row { + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.spacingL + + Row { + spacing: Theme.spacingS + DankActionButton { + iconName: "save" + iconSize: Theme.iconSize - 2 + iconColor: Theme.primary + enabled: currentTab && (hasUnsavedChanges() || textArea.text.length > 0) + onClicked: root.saveRequested() + } + StyledText { + anchors.verticalCenter: parent.verticalCenter + text: I18n.tr("Save") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + } + } + + Row { + spacing: Theme.spacingS + DankActionButton { + iconName: "folder_open" + iconSize: Theme.iconSize - 2 + iconColor: Theme.secondary + onClicked: root.openRequested() + } + StyledText { + anchors.verticalCenter: parent.verticalCenter + text: I18n.tr("Open") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + } + } + + Row { + spacing: Theme.spacingS + DankActionButton { + iconName: "note_add" + iconSize: Theme.iconSize - 2 + iconColor: Theme.surfaceText + onClicked: root.newRequested() + } + StyledText { + anchors.verticalCenter: parent.verticalCenter + text: I18n.tr("New") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + } + } + + Row { + spacing: Theme.spacingS + visible: PluginService.isPluginLoaded("dankNotepadModule") + DankActionButton { + iconName: inlinePreviewVisible ? "visibility" : "visibility_off" + iconSize: Theme.iconSize - 2 + iconColor: Theme.surfaceText + enabled: textArea.text.length > 0 + onClicked: root.previewRequested() + } + StyledText { + anchors.verticalCenter: parent.verticalCenter + text: I18n.tr("Preview") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + } + } + } + + DankActionButton { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + iconName: "more_horiz" + iconSize: Theme.iconSize - 2 + iconColor: Theme.surfaceText + onClicked: root.settingsRequested() + } + } + + Row { + width: parent.width + spacing: Theme.spacingL + + StyledText { + text: { + const len = textArea.text.length; + if (len === 0) return I18n.tr("Empty"); + return len === 1 + ? I18n.tr("%1 character").arg(len) + : I18n.tr("%1 characters").arg(len); + } + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + } + + StyledText { + text: textArea.lineCount === 1 + ? I18n.tr("Line: %1").arg(textArea.lineCount) + : I18n.tr("Lines: %1").arg(textArea.lineCount) + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + visible: textArea.text.length > 0 + opacity: 1.0 + } + + StyledText { + text: { + if (autoSaveTimer.running) { + return I18n.tr("Auto-saving...") + } + + if (hasUnsavedChanges()) { + if (currentTab && currentTab.isTemporary) { + return I18n.tr("Unsaved note...") + } else { + return I18n.tr("Unsaved changes") + } + } else { + return I18n.tr("Saved") + } + } + font.pixelSize: Theme.fontSizeSmall + color: { + if (autoSaveTimer.running) { + return Theme.primary + } + + if (hasUnsavedChanges()) { + return Theme.warning + } else { + return Theme.success + } + } + opacity: textArea.text.length > 0 ? 1.0 : 0.0 + } + } + } + + Timer { + id: autoSaveTimer + interval: 2000 + repeat: false + onTriggered: { + autoSaveToSession() + } + } + + Timer { + id: pluginSyncTimer + interval: 350 + repeat: false + onTriggered: syncContentToPlugin() + } + + Connections { + target: SettingsData + function onBuiltInPluginSettingsChanged() { + if (PluginService.isPluginLoaded("dankNotepadModule")) { + pluginHighlightedHtml = SettingsData.getBuiltInPluginSetting("dankNotepadModule", "highlightedHtml", "") + } + } + } +} |