Refactor input stuff

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
This commit is contained in:
Tobias Fella
2022-10-10 23:10:00 +00:00
parent b2fa269515
commit 4bfd857093
38 changed files with 1579 additions and 1300 deletions

View File

@@ -6,9 +6,12 @@
#include <room.h>
#include <QObject>
#include <events/roomevent.h>
#include <QTextCursor>
#include <qcoro/task.h>
class NeoChatUser;
class PushNotificationState : public QObject
{
Q_OBJECT
@@ -24,11 +27,20 @@ public:
Q_ENUM(State);
};
struct Mention {
QTextCursor cursor;
QString text;
int start = 0;
int position = 0;
QString id;
};
class NeoChatRoom : public Quotient::Room
{
Q_OBJECT
Q_PROPERTY(QVariantList usersTyping READ getUsersTyping NOTIFY typingChanged)
Q_PROPERTY(QString cachedInput MEMBER m_cachedInput NOTIFY cachedInputChanged)
Q_PROPERTY(bool hasFileUploading READ hasFileUploading WRITE setHasFileUploading NOTIFY hasFileUploadingChanged)
Q_PROPERTY(int fileUploadingProgress READ fileUploadingProgress NOTIFY fileUploadingProgressChanged)
Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged STORED false)
@@ -40,7 +52,24 @@ class NeoChatRoom : public Quotient::Room
Q_PROPERTY(PushNotificationState::State pushNotificationState MEMBER m_currentPushNotificationState WRITE setPushNotificationState NOTIFY
pushNotificationStateChanged)
// Due to problems with QTextDocument, unlike the other properties here, chatBoxText is *not* used to store the text when switching rooms
Q_PROPERTY(QString chatBoxText READ chatBoxText WRITE setChatBoxText NOTIFY chatBoxTextChanged)
Q_PROPERTY(QString chatBoxReplyId READ chatBoxReplyId WRITE setChatBoxReplyId NOTIFY chatBoxReplyIdChanged)
Q_PROPERTY(QString chatBoxEditId READ chatBoxEditId WRITE setChatBoxEditId NOTIFY chatBoxEditIdChanged)
Q_PROPERTY(NeoChatUser *chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged)
Q_PROPERTY(QString chatBoxReplyMessage READ chatBoxReplyMessage NOTIFY chatBoxReplyIdChanged)
Q_PROPERTY(NeoChatUser *chatBoxEditUser READ chatBoxEditUser NOTIFY chatBoxEditIdChanged)
Q_PROPERTY(QString chatBoxEditMessage READ chatBoxEditMessage NOTIFY chatBoxEditIdChanged)
Q_PROPERTY(QString chatBoxAttachmentPath READ chatBoxAttachmentPath WRITE setChatBoxAttachmentPath NOTIFY chatBoxAttachmentPathChanged)
public:
enum MessageType {
Positive,
Info,
Error,
};
Q_ENUM(MessageType);
explicit NeoChatRoom(Quotient::Connection *connection, QString roomId, Quotient::JoinState joinState = {});
[[nodiscard]] QVariantList getUsersTyping() const;
@@ -137,6 +166,29 @@ public:
Q_INVOKABLE void setPushNotificationState(PushNotificationState::State state);
QString chatBoxText() const;
void setChatBoxText(const QString &text);
QString chatBoxReplyId() const;
void setChatBoxReplyId(const QString &replyId);
NeoChatUser *chatBoxReplyUser() const;
QString chatBoxReplyMessage() const;
QString chatBoxEditId() const;
void setChatBoxEditId(const QString &editId);
NeoChatUser *chatBoxEditUser() const;
QString chatBoxEditMessage() const;
QString chatBoxAttachmentPath() const;
void setChatBoxAttachmentPath(const QString &attachmentPath);
QVector<Mention> *mentions();
QString savedText() const;
void setSavedText(const QString &savedText);
#ifndef QUOTIENT_07
Q_INVOKABLE QString htmlSafeMemberName(const QString &userId) const
{
@@ -145,7 +197,6 @@ public:
#endif
private:
QString m_cachedInput;
QSet<const Quotient::RoomEvent *> highlights;
bool m_hasFileUploading = false;
@@ -160,10 +211,16 @@ private:
void onAddHistoricalTimelineEvents(rev_iter_t from) override;
void onRedaction(const Quotient::RoomEvent &prevEvent, const Quotient::RoomEvent &after) override;
static QString markdownToHTML(const QString &markdown);
QCoro::Task<void> doDeleteMessagesByUser(const QString &user);
QCoro::Task<void> doUploadFile(QUrl url, QString body = QString());
QString m_chatBoxText;
QString m_chatBoxReplyId;
QString m_chatBoxEditId;
QString m_chatBoxAttachmentPath;
QVector<Mention> m_mentions;
QString m_savedText;
private Q_SLOTS:
void countChanged();
void updatePushNotificationState(QString type);
@@ -179,14 +236,17 @@ Q_SIGNALS:
void isInviteChanged();
void displayNameChanged();
void pushNotificationStateChanged(PushNotificationState::State state);
void positiveMessage(const QString &message);
void showMessage(MessageType messageType, const QString &message);
void chatBoxTextChanged();
void chatBoxReplyIdChanged();
void chatBoxEditIdChanged();
void chatBoxAttachmentPathChanged();
public Q_SLOTS:
void uploadFile(const QUrl &url, const QString &body = QString());
void acceptInvitation();
void forget();
void sendTypingNotification(bool isTyping);
QString preprocessText(const QString &text);
/// @param rawText The text as it was typed.
/// @param cleanedText The text with link to the users.