From 17bbc60f6f89d4da9234fda5c86b756c749fbc13 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Sat, 14 Aug 2021 20:27:11 +0000 Subject: [PATCH] Spellchecking with new Sonnet declarative API This replaces all the custom code with a shared implementation in QQC2-desktop style --- imports/NeoChat/Component/ChatBox/ChatBar.qml | 91 +----- .../Component/ChatBox/CursorDelegate.qml | 65 ----- .../Component/ChatBox/CursorHandle.qml | 98 ------- .../ChatBox/MobileTextActionsToolBar.qml | 77 ------ .../ChatBox/TextFieldContextMenu.qml | 259 ------------------ imports/NeoChat/Component/ChatBox/qmldir | 4 - imports/NeoChat/Page/SettingsPage.qml | 13 + res.qrc | 4 - 8 files changed, 16 insertions(+), 595 deletions(-) delete mode 100644 imports/NeoChat/Component/ChatBox/CursorDelegate.qml delete mode 100644 imports/NeoChat/Component/ChatBox/CursorHandle.qml delete mode 100644 imports/NeoChat/Component/ChatBox/MobileTextActionsToolBar.qml delete mode 100644 imports/NeoChat/Component/ChatBox/TextFieldContextMenu.qml diff --git a/imports/NeoChat/Component/ChatBox/ChatBar.qml b/imports/NeoChat/Component/ChatBox/ChatBar.qml index add0dc6e5..1392d46ba 100644 --- a/imports/NeoChat/Component/ChatBox/ChatBar.qml +++ b/imports/NeoChat/Component/ChatBox/ChatBar.qml @@ -9,8 +9,7 @@ import QtQuick.Templates 2.15 as T import Qt.labs.platform 1.1 as Platform import QtQuick.Window 2.15 -import org.kde.kirigami 2.15 as Kirigami - +import org.kde.kirigami 2.18 as Kirigami import org.kde.neochat 1.0 ToolBar { @@ -69,7 +68,7 @@ ToolBar { font: inputField.font } - T.TextArea { + TextArea { id: inputField focus: true /* Some QQC2 styles will have their own predefined backgrounds for TextAreas. @@ -101,16 +100,9 @@ ToolBar { wrapMode: Text.Wrap readOnly: currentRoom.usesEncryption - palette: Kirigami.Theme.palette Kirigami.Theme.colorSet: Kirigami.Theme.View Kirigami.Theme.inherit: false - - implicitWidth: Math.max(contentWidth + leftPadding + rightPadding, - implicitBackgroundWidth + leftInset + rightInset, - placeholder.implicitWidth + leftPadding + rightPadding) - implicitHeight: Math.max(contentHeight + topPadding + bottomPadding, - implicitBackgroundHeight + topInset + bottomInset, - placeholder.implicitHeight + topPadding + bottomPadding) + Kirigami.SpellChecking.enabled: true color: Kirigami.Theme.textColor selectionColor: Kirigami.Theme.highlightColor @@ -123,65 +115,6 @@ ToolBar { selectByMouse: !Kirigami.Settings.tabletMode - cursorDelegate: Loader { - visible: inputField.activeFocus && !inputField.readOnly && inputField.selectionStart === inputField.selectionEnd - active: visible - sourceComponent: CursorDelegate { target: inputField } - } - - CursorHandle { - id: selectionStartHandle - target: inputField - } - - CursorHandle { - id: selectionEndHandle - target: inputField - isSelectionEnd: true - } - - TapHandler { - acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus - acceptedButtons: Qt.LeftButton | Qt.RightButton - - // unfortunately, taphandler's pressed event only triggers when the press is lifted - // we need to use the longpress signal since it triggers when the button is first pressed - longPressThreshold: 0 - onLongPressed: TextFieldContextMenu.targetClick(point, inputField, spellcheckhighlighter, inputField.positionAt(point.position.x, point.position.y)); - } - - onPressAndHold: { - if (!Kirigami.Settings.tabletMode) { - return; - } - forceActiveFocus(); - cursorPosition = positionAt(event.x, event.y); - selectWord(); - } - - onFocusChanged: { - if (focus) { - MobileTextActionsToolBar.controlRoot = inputField; - } - } - - Label { - id: placeholder - x: inputField.leftPadding - y: inputField.topPadding - width: inputField.width - (inputField.leftPadding + inputField.rightPadding) - height: inputField.height - (inputField.topPadding + inputField.bottomPadding) - - text: inputField.placeholderText - font: inputField.font - color: Kirigami.Theme.disabledTextColor - horizontalAlignment: inputField.horizontalAlignment - verticalAlignment: inputField.verticalAlignment - visible: !inputField.length && !inputField.preeditText && (!inputField.activeFocus || inputField.horizontalAlignment !== Qt.AlignHCenter) - elide: Text.ElideRight - } - - ChatDocumentHandler { id: documentHandler document: inputField.textDocument @@ -191,18 +124,6 @@ ToolBar { room: currentRoom ?? null } - SpellcheckHighlighter { - id: spellcheckhighlighter - document: inputField.textDocument - cursorPosition: inputField.cursorPosition - selectionStart: inputField.selectionStart - selectionEnd: inputField.selectionEnd - onChangeCursorPosition: { - inputField.cursorPosition = start; - inputField.moveCursorSelection(end, TextEdit.SelectCharacters); - } - } - Timer { id: timeoutTimer repeat: false @@ -243,9 +164,6 @@ ToolBar { } Keys.onPressed: { - // trigger if context menu button is pressed - TextFieldContextMenu.targetKeyPressed(event, inputField) - if (event.key === Qt.Key_PageDown) { switchRoomDown(); } else if (event.key === Qt.Key_PageUp) { @@ -329,10 +247,7 @@ ToolBar { chatBar.complete(); } - onPressed: MobileTextActionsToolBar.shouldBeVisible = true; - onTextChanged: { - MobileTextActionsToolBar.shouldBeVisible = false; timeoutTimer.restart() repeatTimer.start() currentRoom.cachedInput = text diff --git a/imports/NeoChat/Component/ChatBox/CursorDelegate.qml b/imports/NeoChat/Component/ChatBox/CursorDelegate.qml deleted file mode 100644 index 851daa052..000000000 --- a/imports/NeoChat/Component/ChatBox/CursorDelegate.qml +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-FileCopyrightText: 2018 Marco Martin - * SPDX-FileCopyrightText: 2021 Noah Davis - * SPDX-License-Identifier: LGPL-2.0-or-later - */ - -import QtQuick 2.15 -import QtQuick.Window 2.15 -import QtQuick.Templates 2.15 -import org.kde.kirigami 2.14 as Kirigami - -Item { - id: root - property alias target: root.parent - - Rectangle { - id: cursorLine - property real previousX: 0 - property real previousY: 0 - parent: target - implicitWidth: target.cursorRectangle.width - implicitHeight: target.cursorRectangle.height - x: Math.floor(target.cursorRectangle.x) - y: Math.floor(target.cursorRectangle.y) - - color: target.color - SequentialAnimation { - id: blinkAnimation - running: root.visible && Qt.styleHints.cursorFlashTime != 0 && target.selectionStart === target.selectionEnd - PropertyAction { - target: cursorLine - property: "opacity" - value: 1 - } - PauseAnimation { - duration: Qt.styleHints.cursorFlashTime/2 - } - SequentialAnimation { - loops: Animation.Infinite - OpacityAnimator { - target: cursorLine - from: 1 - to: 0 - duration: Qt.styleHints.cursorFlashTime/2 - easing.type: Easing.OutCubic - } - OpacityAnimator { - target: cursorLine - from: 0 - to: 1 - duration: Qt.styleHints.cursorFlashTime/2 - easing.type: Easing.OutCubic - } - } - } - } - - Connections { - target: root.target - function onCursorPositionChanged() { - blinkAnimation.restart() - } - } -} - - diff --git a/imports/NeoChat/Component/ChatBox/CursorHandle.qml b/imports/NeoChat/Component/ChatBox/CursorHandle.qml deleted file mode 100644 index a401f79af..000000000 --- a/imports/NeoChat/Component/ChatBox/CursorHandle.qml +++ /dev/null @@ -1,98 +0,0 @@ -/* SPDX-FileCopyrightText: 2018 Marco Martin - * SPDX-FileCopyrightText: 2021 Noah Davis - * SPDX-License-Identifier: LGPL-2.0-or-later - */ - -import QtQuick 2.15 -import QtQuick.Window 2.15 -import QtQuick.Templates 2.15 -import org.kde.kirigami 2.14 as Kirigami - -Loader { - id: root - property Item target - property bool isSelectionEnd: false - visible: Kirigami.Settings.tabletMode && target.activeFocus && (isSelectionEnd ? target.selectionStart !== target.selectionEnd : true) - active: visible - sourceComponent: Kirigami.ShadowedRectangle { - id: handle - property real selectionStartX: Math.floor(Qt.inputMethod.anchorRectangle.x + (Qt.inputMethod.cursorRectangle.width - width)/2) - property real selectionStartY: Math.floor(Qt.inputMethod.anchorRectangle.y + Qt.inputMethod.cursorRectangle.height + pointyBitVerticalOffset) - property real selectionEndX: Math.floor(Qt.inputMethod.cursorRectangle.x + (Qt.inputMethod.cursorRectangle.width - width)/2) - property real selectionEndY: Math.floor(Qt.inputMethod.cursorRectangle.y + Qt.inputMethod.cursorRectangle.height + pointyBitVerticalOffset) - property real pointyBitVerticalOffset: Math.abs(pointyBit.y*2) - parent: Overlay.overlay - x: isSelectionEnd ? selectionEndX : selectionStartX - y: isSelectionEnd ? selectionEndY : selectionStartY - - // HACK: make it appear above most popups that show up in the - // overlay in case any of them use TextField or TextArea - z: 999 - - //opacity: target.activeFocus ? 1 : 0 - implicitHeight: { - let h = Kirigami.Units.gridUnit - return h - (h % 2 == 0 ? 1 : 0) - } - implicitWidth: implicitHeight - radius: width/2 - - color: target.selectionColor - - shadow { - color: Qt.rgba(0,0,0,0.2) - size: 3 - yOffset: 1 - } - - Rectangle { - id: pointyBit - x: (parent.width - width)/2 - y: -height/4 + 0.2 // magic number to get it to line up with the edge of the circle - implicitHeight: parent.implicitHeight/2 - implicitWidth: implicitHeight - antialiasing: true - rotation: 45 - color: parent.color - } - - Kirigami.ShadowedRectangle { - id: inner - visible: target.selectionStart !== target.selectionEnd && (handle.y < selectionStartY || handle.y < selectionEndY) - anchors.fill: parent - anchors.margins: Kirigami.Units.smallBorder - color: target.selectedTextColor - radius: height/2 - Rectangle { - id: innerPointyBit - x: (parent.width - width)/2 - y: -height/4 + 0.8 // magic number to get it to line up with the edge of the circle - implicitHeight: pointyBit.implicitHeight - implicitWidth: implicitHeight - antialiasing: true - rotation: 45 - color: parent.color - } - } - - MouseArea { - enabled: handle.visible - anchors.fill: parent - // preventStealing: true - onPositionChanged: { - let pos = mapToItem(root.target, mouse.x, mouse.y); - pos = root.target.positionAt(pos.x, pos.y - handle.height - handle.pointyBitVerticalOffset); - - if (target.selectionStart !== target.selectionEnd) { - if (!isSelectionEnd) { - root.target.select(Math.min(pos, root.target.selectionEnd - 1), root.target.selectionEnd); - } else { - root.target.select(root.target.selectionStart, Math.max(pos, root.target.selectionStart + 1)); - } - } else { - root.target.cursorPosition = pos; - } - } - } - } -} diff --git a/imports/NeoChat/Component/ChatBox/MobileTextActionsToolBar.qml b/imports/NeoChat/Component/ChatBox/MobileTextActionsToolBar.qml deleted file mode 100644 index a159ca8eb..000000000 --- a/imports/NeoChat/Component/ChatBox/MobileTextActionsToolBar.qml +++ /dev/null @@ -1,77 +0,0 @@ -/* - SPDX-FileCopyrightText: 2018 Marco Martin - - SPDX-License-Identifier: LGPL-2.0-or-later -*/ - -pragma Singleton - -import QtQuick 2.1 -import QtQuick.Layouts 1.2 -import QtQuick.Window 2.2 -import QtQuick.Controls 2.15 -import org.kde.kirigami 2.5 as Kirigami - -Popup { - id: root - - property Item controlRoot - parent: controlRoot ? controlRoot.Window.contentItem : undefined - modal: false - focus: false - closePolicy: Popup.NoAutoClose - property bool shouldBeVisible: false - - x: { - if (!controlRoot || !controlRoot.Window.contentItem) { - return 0; - } - return Math.min(Math.max(0, controlRoot.mapToItem(root.parent, controlRoot.positionToRectangle(controlRoot.selectionStart).x, 0).x - root.width/2), controlRoot.Window.contentItem.width - root.width); - } - - y: { - if (!controlRoot || !controlRoot.Window.contentItem) { - return 0; - } - var desiredY = controlRoot.mapToItem(root.parent, 0, controlRoot.positionToRectangle(controlRoot.selectionStart).y).y - root.height; - - if (desiredY >= 0) { - return Math.min(desiredY, controlRoot.Window.contentItem.height - root.height); - } else { - return Math.min(Math.max(0, controlRoot.mapToItem(root.parent, 0, controlRoot.positionToRectangle(controlRoot.selectionEnd).y + Math.round(Kirigami.Units.gridUnit*1.5)).y), controlRoot.Window.contentItem.height - root.height); - } - } - - - visible: controlRoot ? shouldBeVisible && Qt.platform.os !== "android" && Kirigami.Settings.tabletMode && (controlRoot.selectedText.length > 0 || controlRoot.canPaste) : false - - width: contentItem.implicitWidth + leftPadding + rightPadding - - contentItem: RowLayout { - ToolButton { - focusPolicy: Qt.NoFocus - icon.name: "edit-cut" - visible: controlRoot && controlRoot.selectedText.length > 0 && (!controlRoot.hasOwnProperty("echoMode") || controlRoot.echoMode === TextInput.Normal) - onClicked: { - controlRoot.cut(); - } - } - ToolButton { - focusPolicy: Qt.NoFocus - icon.name: "edit-copy" - visible: controlRoot && controlRoot.selectedText.length > 0 && (!controlRoot.hasOwnProperty("echoMode") || controlRoot.echoMode === TextInput.Normal) - onClicked: { - controlRoot.copy(); - } - } - ToolButton { - focusPolicy: Qt.NoFocus - icon.name: "edit-paste" - visible: controlRoot && controlRoot.canPaste - onClicked: { - controlRoot.paste(); - } - } - } -} - diff --git a/imports/NeoChat/Component/ChatBox/TextFieldContextMenu.qml b/imports/NeoChat/Component/ChatBox/TextFieldContextMenu.qml deleted file mode 100644 index 2c70f1e4f..000000000 --- a/imports/NeoChat/Component/ChatBox/TextFieldContextMenu.qml +++ /dev/null @@ -1,259 +0,0 @@ -/* - SPDX-FileCopyrightText: 2020 Devin Lin - SPDX-FileCopyrightText: 2021 Carl Schwan - - SPDX-License-Identifier: LGPL-2.0-or-later -*/ - -pragma Singleton - -import QtQuick 2.6 -import QtQml 2.2 -import QtQuick.Controls 2.15 -import org.kde.kirigami 2.5 as Kirigami - -Menu { - id: contextMenu - - property Item target - property bool deselectWhenMenuClosed: true - property int restoredCursorPosition: 0 - property int restoredSelectionStart - property int restoredSelectionEnd - property bool persistentSelectionSetting - property var spellcheckhighlighter: null - property var suggestions: ([]) - Component.onCompleted: persistentSelectionSetting = persistentSelectionSetting // break binding - - property var runOnMenuClose - - parent: Overlay.overlay - - function storeCursorAndSelection() { - contextMenu.restoredCursorPosition = target.cursorPosition; - contextMenu.restoredSelectionStart = target.selectionStart; - contextMenu.restoredSelectionEnd = target.selectionEnd; - } - - // target is pressed with mouse - function targetClick(handlerPoint, newTarget, spellcheckhighlighter, mousePosition) { - if (handlerPoint.pressedButtons === Qt.RightButton) { // only accept just right click - if (contextMenu.visible) { - deselectWhenMenuClosed = false; // don't deselect text if menu closed by right click on textfield - dismiss(); - } else { - contextMenu.target = newTarget; - contextMenu.target.persistentSelection = true; // persist selection when menu is opened - contextMenu.spellcheckhighlighter = spellcheckhighlighter - contextMenu.suggestions = spellcheckhighlighter.suggestions(mousePosition); - storeCursorAndSelection(); - popup(contextMenu.target); - // slightly locate context menu away from mouse so no item is selected when menu is opened - x += 1 - y += 1 - } - } else { - dismiss(); - } - } - - // context menu keyboard key - function targetKeyPressed(event, newTarget) { - if (event.modifiers === Qt.NoModifier && event.key === Qt.Key_Menu) { - contextMenu.target = newTarget; - target.persistentSelection = true; // persist selection when menu is opened - storeCursorAndSelection(); - popup(contextMenu.target); - } - } - - readonly property bool targetIsPassword: target !== null && (target.echoMode === TextInput.PasswordEchoOnEdit || target.echoMode === TextInput.Password) - - onAboutToShow: { - if (Overlay.overlay) { - let tempZ = 0 - for (let i in Overlay.overlay.visibleChildren) { - tempZ = Math.max(tempZ, Overlay.overlay.visibleChildren[i].z) - } - z = tempZ + 1 - } - } - - // deal with whether or not text should be deselected - onClosed: { - // restore text field's original persistent selection setting - target.persistentSelection = persistentSelectionSetting - // deselect text field text if menu is closed not because of a right click on the text field - if (deselectWhenMenuClosed) { - target.deselect(); - } - deselectWhenMenuClosed = true; - - // restore cursor position - target.forceActiveFocus(); - target.cursorPosition = restoredCursorPosition; - target.select(restoredSelectionStart, restoredSelectionEnd); - - // run action - runOnMenuClose(); - } - - onOpened: { - runOnMenuClose = function() {}; - } - - Instantiator { - active: target !== null && !target.readOnly && spellcheckhighlighter !== null && spellcheckhighlighter.wordIsMisspelled - model: suggestions - delegate: MenuItem { - text: modelData - onClicked: { - deselectWhenMenuClosed = false; - runOnMenuClose = function() { - spellcheckhighlighter.replaceWord(modelData); - }; - } - } - onObjectAdded: contextMenu.insertItem(0, object) - onObjectRemoved: contextMenu.removeItem(0) - } - - MenuItem { - visible: target !== null && !target.readOnly && spellcheckhighlighter !== null && spellcheckhighlighter.wordIsMisspelled && suggestions.length === 0 - action: Action { - text: spellcheckhighlighter ? i18nc("@action:inmenu", "No suggestions for %1", spellcheckhighlighter.wordUnderMouse) : "" - enabled: false - } - } - - MenuSeparator { - visible: target !== null && !target.readOnly && spellcheckhighlighter !== null && spellcheckhighlighter.wordIsMisspelled - } - - MenuItem { - visible: target !== null && !target.readOnly && spellcheckhighlighter !== null && spellcheckhighlighter.wordIsMisspelled - action: Action { - text: i18n("Add to dictionary") - onTriggered: { - deselectWhenMenuClosed = false; - runOnMenuClose = function() { - spellcheckhighlighter.addWordToDictionary(spellcheckhighlighter.wordUnderMouse) - }; - } - } - } - - MenuItem { - visible: target !== null && !target.readOnly && spellcheckhighlighter !== null && spellcheckhighlighter.wordIsMisspelled - action: Action { - text: i18n("Ignore") - onTriggered: { - deselectWhenMenuClosed = false; - runOnMenuClose = function() { - spellcheckhighlighter.ignoreWord(spellcheckhighlighter.wordUnderMouse) - }; - } - } - } - - MenuSeparator { - visible: target !== null && !target.readOnly && spellcheckhighlighter !== null && spellcheckhighlighter.wordIsMisspelled - } - - MenuItem { - visible: target !== null && !target.readOnly - action: Action { - icon.name: "edit-undo-symbolic" - text: i18nc("@action:inmenu", "Undo") - shortcut: StandardKey.Undo - } - enabled: target !== null && target.canUndo - onTriggered: { - deselectWhenMenuClosed = false; - runOnMenuClose = function() {target.undo()}; - } - } - MenuItem { - visible: target !== null && !target.readOnly - action: Action { - icon.name: "edit-redo-symbolic" - text: i18nc("@action:inmenu", "Redo") - shortcut: StandardKey.Redo - } - enabled: target !== null && target.canRedo - onTriggered: { - deselectWhenMenuClosed = false; - runOnMenuClose = function() {target.redo()}; - } - } - MenuSeparator { - visible: target !== null && !target.readOnly - } - MenuItem { - visible: target !== null && !target.readOnly && !targetIsPassword - action: Action { - icon.name: "edit-cut-symbolic" - text: i18nc("@action:inmenu", "Cut") - shortcut: StandardKey.Cut - } - enabled: target !== null && target.selectedText - onTriggered: { - deselectWhenMenuClosed = false; - runOnMenuClose = function() {target.cut()} - } - } - MenuItem { - action: Action { - icon.name: "edit-copy-symbolic" - text: i18nc("@action:inmenu", "Copy") - shortcut: StandardKey.Copy - } - enabled: target !== null && target.selectedText - visible: !targetIsPassword - onTriggered: { - deselectWhenMenuClosed = false; - runOnMenuClose = function() {target.copy()} - } - } - MenuItem { - visible: target !== null && !target.readOnly - action: Action { - icon.name: "edit-paste-symbolic" - text: i18nc("@action:inmenu", "Paste") - shortcut: StandardKey.Paste - } - enabled: target !== null && target.canPaste - onTriggered: { - deselectWhenMenuClosed = false; - runOnMenuClose = function() {target.paste()}; - } - } - MenuItem { - visible: target !== null && !target.readOnly - action: Action { - icon.name: "edit-delete-symbolic" - text: i18nc("@action:inmenu", "Delete") - shortcut: StandardKey.Delete - } - enabled: target !== null && target.selectedText - onTriggered: { - deselectWhenMenuClosed = false; - runOnMenuClose = function() {target.remove(target.selectionStart, target.selectionEnd)}; - } - } - MenuSeparator { - visible: !targetIsPassword - } - MenuItem { - action: Action { - icon.name: "edit-select-all-symbolic" - text: i18nc("@action:inmenu", "Select All") - shortcut: StandardKey.SelectAll - } - visible: !targetIsPassword - onTriggered: { - deselectWhenMenuClosed = false; - runOnMenuClose = function() {target.selectAll()}; - } - } -} diff --git a/imports/NeoChat/Component/ChatBox/qmldir b/imports/NeoChat/Component/ChatBox/qmldir index 8f9b11f86..28b7a8a94 100644 --- a/imports/NeoChat/Component/ChatBox/qmldir +++ b/imports/NeoChat/Component/ChatBox/qmldir @@ -5,7 +5,3 @@ ReplyPane 1.0 ReplyPane.qml AttachmentPane 1.0 AttachmentPane.qml CompletionMenu 1.0 CompletionMenu.qml EmojiPickerPane 1.0 EmojiPickerPane.qml -singleton TextFieldContextMenu 1.0 TextFieldContextMenu.qml -CursorDelegate 1.0 CursorDelegate.qml -CursorHandle 1.0 CursorHandle.qml -singleton MobileTextActionsToolBar 1.0 MobileTextActionsToolBar.qml diff --git a/imports/NeoChat/Page/SettingsPage.qml b/imports/NeoChat/Page/SettingsPage.qml index be097e101..48fa1fdf7 100644 --- a/imports/NeoChat/Page/SettingsPage.qml +++ b/imports/NeoChat/Page/SettingsPage.qml @@ -7,6 +7,7 @@ import QtQuick.Controls 2.15 as QQC2 import QtQuick.Layouts 1.15 import org.kde.kirigami 2.15 as Kirigami +import org.kde.sonnet 1.0 as Sonnet import org.kde.neochat 1.0 import NeoChat.Settings 1.0 @@ -65,6 +66,11 @@ Kirigami.ScrollablePage { iconName: "network-connect" onTriggered: pageSettingStack.push("qrc:/imports/NeoChat/Page/DevicesPage.qml") }, + Kirigami.Action { + text: i18n("Spell Checking") + iconName: "tools-check-spelling" + onTriggered: pageSettingStack.push(spellCheckingPage) + }, Kirigami.Action { text: i18n("About NeoChat") icon.name: "help-about" @@ -85,4 +91,11 @@ Kirigami.ScrollablePage { aboutData: Controller.aboutData } } + + Component { + id: spellCheckingPage + Sonnet.ConfigPage { + wideMode: pageSettingStack.wideMode + } + } } diff --git a/res.qrc b/res.qrc index 71787cb28..e415847ba 100644 --- a/res.qrc +++ b/res.qrc @@ -26,10 +26,6 @@ imports/NeoChat/Component/ChatBox/AttachmentPane.qml imports/NeoChat/Component/ChatBox/ReplyPane.qml imports/NeoChat/Component/ChatBox/CompletionMenu.qml - imports/NeoChat/Component/ChatBox/CursorHandle.qml - imports/NeoChat/Component/ChatBox/CursorDelegate.qml - imports/NeoChat/Component/ChatBox/MobileTextActionsToolBar.qml - imports/NeoChat/Component/ChatBox/TextFieldContextMenu.qml imports/NeoChat/Component/ChatBox/qmldir imports/NeoChat/Component/Emoji/EmojiPicker.qml imports/NeoChat/Component/Emoji/qmldir