Really reenable editing messages, don't just do half a job.

This commit is contained in:
James Graham
2026-02-02 15:11:03 +00:00
parent a3cd0c0e8d
commit 234d823366
17 changed files with 132 additions and 421 deletions

View File

@@ -8,6 +8,7 @@ ecm_add_qml_module(Chatbar GENERATE_PLUGIN_SOURCE
QML_FILES
AttachDialog.qml
ChatBar.qml
ChatBarCore.qml
RichEditBar.qml
SendBar.qml
CompletionMenu.qml

View File

@@ -42,9 +42,9 @@ Item {
}
}
property int chatBarType: LibNeoChat.ChatBarType.Room
onActiveFocusChanged: chatContentView.itemAt(contentModel.index(contentModel.focusRow, 0)).forceActiveFocus()
onActiveFocusChanged: if (activeFocus) {
core.forceActiveFocus();
}
Connections {
target: ShareHandler
@@ -67,97 +67,16 @@ Item {
}
}
Message.room: root.currentRoom
Message.contentModel: contentModel
implicitHeight: chatBar.implicitHeight + Kirigami.Units.largeSpacing
QQC2.Control {
id: chatBar
implicitHeight: core.implicitHeight + Kirigami.Units.largeSpacing
ChatBarCore {
id: core
anchors.top: root.top
anchors.horizontalCenter: root.horizontalCenter
spacing: 0
width: chatBarSizeHelper.availableWidth - Kirigami.Units.largeSpacing * 2
topPadding: Kirigami.Units.smallSpacing
bottomPadding: Kirigami.Units.smallSpacing
contentItem: ColumnLayout {
RichEditBar {
id: richEditBar
visible: NeoChatConfig.sendMessageWith === 1
maxAvailableWidth: chatBarSizeHelper.availableWidth - Kirigami.Units.largeSpacing * 2
room: root.currentRoom
contentModel: chatContentView.model
onClicked: contentModel.refocusCurrentComponent()
}
Kirigami.Separator {
Layout.fillWidth: true
visible: NeoChatConfig.sendMessageWith === 1
}
RowLayout {
spacing: 0
QQC2.ScrollView {
id: chatScrollView
Layout.fillWidth: true
Layout.maximumHeight: Kirigami.Units.gridUnit * 8
clip: true
ColumnLayout {
readonly property real visibleTop: chatScrollView.QQC2.ScrollBar.vertical.position * chatScrollView.contentHeight
readonly property real visibleBottom: chatScrollView.QQC2.ScrollBar.vertical.position * chatScrollView.contentHeight + chatScrollView.QQC2.ScrollBar.vertical.size * chatScrollView.contentHeight
readonly property rect cursorRectInColumn: mapFromItem(contentModel.focusedTextItem.textItem, contentModel.focusedTextItem.cursorRectangle);
onCursorRectInColumnChanged: {
if (chatScrollView.QQC2.ScrollBar.vertical.visible) {
if (cursorRectInColumn.y < visibleTop) {
chatScrollView.QQC2.ScrollBar.vertical.position = cursorRectInColumn.y / chatScrollView.contentHeight
} else if (cursorRectInColumn.y + cursorRectInColumn.height > visibleBottom) {
chatScrollView.QQC2.ScrollBar.vertical.position = (cursorRectInColumn.y + cursorRectInColumn.height - (chatScrollView.QQC2.ScrollBar.vertical.size * chatScrollView.contentHeight)) / chatScrollView.contentHeight
}
}
}
width: chatScrollView.width
spacing: Kirigami.Units.smallSpacing
Repeater {
id: chatContentView
model: ChatBarMessageContentModel {
id: contentModel
type: root.chatBarType
room: root.currentRoom
sendMessageWithEnter: NeoChatConfig.sendMessageWith === 0
}
delegate: MessageComponentChooser {
rightAnchorMargin: chatScrollView.QQC2.ScrollBar.vertical.visible ? chatScrollView.QQC2.ScrollBar.vertical.width : 0
}
}
}
}
SendBar {
room: root.currentRoom
contentModel: chatContentView.model
}
}
}
background: Kirigami.ShadowedRectangle {
Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false
radius: Kirigami.Units.cornerRadius
color: Kirigami.Theme.backgroundColor
border {
color: Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, Kirigami.Theme.frameContrast)
width: 1
}
}
Message.room: root.currentRoom
room: root.currentRoom
maxAvailableWidth: chatBarSizeHelper.availableWidth
}
MouseArea {
id: hoverArea
@@ -165,7 +84,7 @@ Item {
top: chatModeButton.top
left: root.left
right: root.right
bottom: chatBar.top
bottom: core.top
}
propagateComposedEvents: true
hoverEnabled: true
@@ -174,12 +93,12 @@ Item {
QQC2.Button {
id: chatModeButton
anchors {
bottom: chatBar.top
bottom: core.top
bottomMargin: Kirigami.Units.smallSpacing
horizontalCenter: root.horizontalCenter
}
visible: hoverArea.containsMouse || hovered || chatBar.hovered
visible: hoverArea.containsMouse || hovered || core.hovered
width: Kirigami.Units.iconSizes.enormous
height: Kirigami.Units.iconSizes.smallMedium
@@ -197,27 +116,4 @@ Item {
endPercentWidth: NeoChatConfig.compactLayout ? 100 : 85
maxWidth: NeoChatConfig.compactLayout ? root.width - Kirigami.Units.largeSpacing * 2 : Kirigami.Units.gridUnit * 60
}
QtObject {
id: _private
property LibNeoChat.CompletionModel completionModel: LibNeoChat.CompletionModel {
room: root.currentRoom
type: root.chatBarType
textItem: contentModel.focusedTextItem
roomListModel: RoomManager.roomListModel
userListModel: RoomManager.userListModel
onIsCompletingChanged: {
if (!isCompleting) {
return;
}
let dialog = Qt.createComponent('org.kde.neochat.chatbar', 'CompletionMenu').createObject(contentModel.focusedTextItem.textItem, {
model: _private.completionModel,
keyHelper: contentModel.keyHelper
}).open();
}
}
}
}

View File

@@ -8,14 +8,26 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.neochat
import org.kde.neochat.libneochat as LibNeoChat
QQC2.Control {
id: root
required property real availableWidth
/**
* @brief The current room that user is viewing.
*/
required property LibNeoChat.NeoChatRoom room
width: root.availableWidth - Kirigami.Units.largeSpacing * 2
property int chatBarType: LibNeoChat.ChatBarType.Room
required property real maxAvailableWidth
Message.contentModel: contentModel
onActiveFocusChanged: contentModel.refocusCurrentComponent()
implicitWidth: root.maxAvailableWidth - (root.maxAvailableWidth >= (parent?.width ?? 0) ? Kirigami.Units.largeSpacing * 2 : 0)
topPadding: Kirigami.Units.smallSpacing
bottomPadding: Kirigami.Units.smallSpacing
@@ -23,9 +35,9 @@ QQC2.Control {
RichEditBar {
id: richEditBar
visible: NeoChatConfig.sendMessageWith === 1
maxAvailableWidth: root.availableWidth - Kirigami.Units.largeSpacing * 2
maxAvailableWidth: root.maxAvailableWidth - Kirigami.Units.largeSpacing * 2
room: root.currentRoom
room: root.room
contentModel: chatContentView.model
onClicked: contentModel.refocusCurrentComponent()
@@ -65,18 +77,18 @@ QQC2.Control {
model: ChatBarMessageContentModel {
id: contentModel
type: root.chatBarType
room: root.currentRoom
room: root.room
sendMessageWithEnter: NeoChatConfig.sendMessageWith === 0
}
delegate: MessageComponentChooser {
delegate: BaseMessageComponentChooser {
rightAnchorMargin: chatScrollView.QQC2.ScrollBar.vertical.visible ? chatScrollView.QQC2.ScrollBar.vertical.width : 0
}
}
}
}
SendBar {
room: root.currentRoom
room: root.room
contentModel: chatContentView.model
}
}
@@ -93,4 +105,27 @@ QQC2.Control {
width: 1
}
}
QtObject {
id: _private
property LibNeoChat.CompletionModel completionModel: LibNeoChat.CompletionModel {
room: root.room
type: root.chatBarType
textItem: contentModel.focusedTextItem
roomListModel: RoomManager.roomListModel
userListModel: RoomManager.userListModel
onIsCompletingChanged: {
if (!isCompleting) {
return;
}
let dialog = Qt.createComponent('org.kde.neochat.chatbar', 'CompletionMenu').createObject(contentModel.focusedTextItem.textItem, {
model: _private.completionModel,
keyHelper: contentModel.keyHelper
}).open();
}
}
}
}

View File

@@ -31,7 +31,7 @@ RowLayout {
property bool isBusy: root.room && root.room.hasFileUploading
visible: root.chatBarCache.attachmentPath.length === 0
visible: !root.contentModel.hasAttachment && (root.contentModel?.type ?? true) === LibNeoChat.ChatBarType.Room
icon.name: "mail-attachment"
text: i18n("Attach an image or file")
display: QQC2.AbstractButton.IconOnly
@@ -84,6 +84,7 @@ RowLayout {
}
QQC2.ToolButton {
id: mapButton
visible: (root.contentModel?.type ?? true) === LibNeoChat.ChatBarType.Room
icon.name: "globe"
property bool isBusy: false
text: i18n("Send a Location")
@@ -100,6 +101,7 @@ RowLayout {
}
QQC2.ToolButton {
id: pollButton
visible: (root.contentModel?.type ?? true) === LibNeoChat.ChatBarType.Room
icon.name: "amarok_playcount"
property bool isBusy: false
text: i18nc("@action:button", "Create a Poll")
@@ -128,4 +130,21 @@ RowLayout {
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
QQC2.ToolTip.text: text
}
QQC2.ToolButton {
id: cancelButton
visible: (root.contentModel?.type ?? true) === LibNeoChat.ChatBarType.Edit
display: QQC2.AbstractButton.IconOnly
text: i18nc("@action:button", "Cancel")
icon.name: "dialog-close"
onClicked: root.room.cacheForType(contentModel.type).clearRelations()
Kirigami.Action {
shortcut: "Escape"
onTriggered: cancelButton.clicked()
}
QQC2.ToolTip.text: text
QQC2.ToolTip.visible: hovered
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
}
}