This is the start of a significant refactoring of everything related to sending messages, which is roughly:
- the chatbox
- action handling
- message sending on the c++ side
- autocompletion of users/rooms/emojis/commands/things i forgot
Notable changes so far include:
- ChatBox is now a ColumnLayout. As part of this, i removed the height animations for now. <del>as far as i can tell, they were broken anyway.</del> I'll readd them later
- Actions were refactored to live outside of the message sending function and are now each an object; it's mostly a wrapper around a function that is executed when the action is invoked
- Everything that used to live in ChatBoxHelper is now in NeoChatRoom; that means that the exact input status (text, message being replied to, message being edited, attachment) is now saved between room switching).
- To edit/reply an event, set `NeoChatRoom::chatBox{edit,reply}Id` to the desired event id, `NeoChatRoom::chatBox{reply,edit}{User,Message}` will then be updated automatically
- Attachments behave equivalently with `NeoChatRoom::chatBoxAttachmentPath`
- Error message reporting from ActionsHandler has been fixed (same fix as in !517) and moved to NeoChatRoom
Broken at the moment:
- [x] Any kind of autocompletion
- [x] Mentions
- [x] Fancy effects
- [x] sed-style edits
- [x] last-user-message edits and replies
- [x] Some of the actions, probably
- [x] Replies from notifications
- [x] Lots of keyboard shortcuts
- [x] Custom emojis
- [x] ChatBox height animations
TODO:
- [x] User / room mentions based on QTextCursors instead of the hack we currently use
- [x] Refactor autocompletion stuff
- [x] ???
- [x] Profit
120 lines
3.4 KiB
QML
120 lines
3.4 KiB
QML
// SPDX-FileCopyrightText: 2021 Carson Black <uhhadd@gmail.com>
|
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
|
|
|
import QtQuick 2.15
|
|
import QtQuick.Controls 2.15 as QQC2
|
|
import QtQuick.Layouts 1.15
|
|
|
|
import Qt.labs.platform 1.1
|
|
|
|
import org.kde.kirigami 2.15 as Kirigami
|
|
|
|
import org.kde.neochat 1.0
|
|
import NeoChat.Settings 1.0
|
|
|
|
import NeoChat.Component 1.0 as Components
|
|
import NeoChat.Dialog 1.0
|
|
|
|
Kirigami.ScrollablePage {
|
|
title: i18nc("@title:window", "Custom Emojis")
|
|
|
|
ListView {
|
|
anchors.fill: parent
|
|
|
|
model: CustomEmojiModel
|
|
|
|
Kirigami.PlaceholderMessage {
|
|
anchors.centerIn: parent
|
|
text: i18n("No custom inline stickers found")
|
|
visible: parent.model.count === 0
|
|
}
|
|
|
|
delegate: Kirigami.BasicListItem {
|
|
id: del
|
|
|
|
required property string name
|
|
required property url imageURL
|
|
|
|
text: name
|
|
reserveSpaceForSubtitle: true
|
|
|
|
leading: Image {
|
|
width: height
|
|
sourceSize.width: width
|
|
sourceSize.height: height
|
|
source: imageURL
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
visible: parent.status === Image.Loading
|
|
radius: height/2
|
|
gradient: Components.ShimmerGradient { }
|
|
}
|
|
}
|
|
|
|
trailing: QQC2.ToolButton {
|
|
width: height
|
|
icon.name: "delete"
|
|
onClicked: emojiModel.removeEmoji(del.name)
|
|
}
|
|
}
|
|
}
|
|
|
|
footer: QQC2.ToolBar {
|
|
Kirigami.Theme.colorSet: Kirigami.Theme.Window
|
|
Kirigami.ActionToolBar {
|
|
id: emojiCreator
|
|
alignment: Qt.AlignRight
|
|
rightPadding: Kirigami.Units.smallSpacing
|
|
width: parent.width
|
|
flat: false
|
|
property string name
|
|
actions: [
|
|
Kirigami.Action {
|
|
displayComponent: QQC2.TextField {
|
|
id: emojiField
|
|
placeholderText: i18n("new_emoji_name_here")
|
|
|
|
validator: RegularExpressionValidator {
|
|
regularExpression: /[a-zA-Z_0-9]*/
|
|
}
|
|
onTextChanged: emojiCreator.name = text
|
|
}
|
|
},
|
|
Kirigami.Action {
|
|
text: i18n("Add Emoji...")
|
|
|
|
enabled: emojiCreator.name.length > 0
|
|
property var fileDialog: null
|
|
icon.name: 'list-add'
|
|
|
|
onTriggered: {
|
|
if (this.fileDialog !== null) {
|
|
return;
|
|
}
|
|
|
|
this.fileDialog = openFileDialog.createObject(QQC2.Overlay.overlay)
|
|
|
|
this.fileDialog.chosen.connect((url) => {
|
|
CustomEmojiModel.addEmoji(emojiCreator.name, url)
|
|
this.fileDialog = null
|
|
})
|
|
this.fileDialog.onRejected.connect(() => {
|
|
this.fileDialog = null
|
|
})
|
|
this.fileDialog.open()
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: openFileDialog
|
|
|
|
OpenFileDialog {
|
|
folder: StandardPaths.writableLocation(StandardPaths.PicturesLocation)
|
|
}
|
|
}
|
|
}
|