126 lines
5.2 KiB
C++
126 lines
5.2 KiB
C++
/* История и composer выбранного канала/PM: модель сообщений, позиция чтения, загрузки и воспроизведение.
|
|
* Применяет события bridge в GUI-потоке; сетевые операции передаёт ядру. */
|
|
#pragma once
|
|
|
|
#include <QWidget>
|
|
#include <QStandardItemModel>
|
|
#include <QHash>
|
|
#include <QTimer>
|
|
#include <QSet>
|
|
#include <QThreadPool>
|
|
#include <QJsonObject>
|
|
#include <QPointer>
|
|
|
|
class ChatView;
|
|
class InputBar;
|
|
class EmojiPanel;
|
|
class DbManager;
|
|
class ChannelList;
|
|
class AudioRecorder;
|
|
class QLabel;
|
|
class QPushButton;
|
|
class RadioPanel;
|
|
class QDialog;
|
|
class QMenu;
|
|
struct MessageRow;
|
|
|
|
class MessageList : public QWidget {
|
|
Q_OBJECT
|
|
public:
|
|
explicit MessageList(DbManager* db = nullptr, AudioRecorder* recorder = nullptr,
|
|
QWidget *parent = nullptr);
|
|
|
|
void loadChannel(const QString& channelId);
|
|
void refresh();
|
|
void reloadLocalNicks();
|
|
void saveChannelState();
|
|
static void cleanupAnimations();
|
|
void updateMessageProgress(const QString& chId, int64_t msgId, int blocksDone, int numBlocks);
|
|
void onAttachmentDownloaded(const QString& chId, int64_t msgId);
|
|
void onDmMessages(const uint8_t* data, int len);
|
|
void refreshDmCallRoute();
|
|
void onDmCallRoute(const uint8_t* data, int len);
|
|
void clearDmCallRoute();
|
|
void onAttachmentPreparation(const uint8_t* data, int len);
|
|
void onFeedbackChanged(const uint8_t* data, int len);
|
|
void onFeedbackResult(const uint8_t* data, int len);
|
|
void onMessageSubmitted(const uint8_t* data, int len);
|
|
void onRadioTalk(quint64 groupId, quint64 srcNodeId, bool on); /* индикация говорящего */
|
|
void onStreamSources(const uint8_t* data, int len);
|
|
void clearStreams();
|
|
void watchStreams();
|
|
|
|
signals:
|
|
void readPositionChanged(const QString& channelId, qint64 lastReadMsgId);
|
|
void callRequested(const QString& target, quint64 peer, const QString& name);
|
|
void openVideoRequested(const QString& filePath);
|
|
void streamRequested(quint64 group, quint64 source, quint64 epoch, const QString& name);
|
|
void streamPublishRequested(quint64 group);
|
|
void openImageRequested(const QString& filePath);
|
|
void inviteRequested(const QString& sourceChannel, quint64 peer, const QString& name);
|
|
void ownFilesRequested(const QString& channelId);
|
|
void filesRequested(const QString& channelId);
|
|
void shareInviteRequested(const QString& channelId);
|
|
void inviteByLinkRequested(const QString& channelId);
|
|
void channelSettingsRequested(const QString& channelId);
|
|
void linkActivated(const QString& link);
|
|
|
|
private:
|
|
ChatView *m_view;
|
|
QStandardItemModel *m_model;
|
|
InputBar *m_inputBar;
|
|
EmojiPanel *m_emojiPanel;
|
|
DbManager *m_db;
|
|
QString m_currentChannelId;
|
|
QHash<quint64, QColor> m_avatarCache;
|
|
qint64 m_lastReadMsgId = 0;
|
|
QTimer* m_readDebounce;
|
|
qint64 m_savedTopMsgId = 0;
|
|
bool m_wasAtBottom = false;
|
|
QMap<quint64, QString> m_localNicks;
|
|
AudioRecorder* m_recorder = nullptr;
|
|
QLabel* m_peerStatus = nullptr;
|
|
QLabel* m_channelTitle = nullptr; /* шапка: название канала */
|
|
QLabel* m_talkingLabel = nullptr; /* шапка: кто говорит в рации */
|
|
QPushButton* m_callBtn = nullptr;
|
|
QPushButton* m_inviteBtn = nullptr;
|
|
QPushButton* m_groupMenuButton = nullptr;
|
|
quint64 m_callPeer = 0;
|
|
quint64 m_callGroup = 0;
|
|
QPushButton* m_radioBtn = nullptr; /* шапка: переключатель рации */
|
|
QPushButton* m_streamBtn = nullptr;
|
|
struct LiveSource { quint64 id, epoch; QString name; bool self = false; };
|
|
QList<LiveSource> m_streamSources;
|
|
RadioPanel* m_radioPanel = nullptr; /* верхняя панель устройств, VAD и PTT */
|
|
bool m_radioOn = false;
|
|
QThreadPool m_thumbnailPool;
|
|
QSet<QString> m_thumbnailJobs;
|
|
QHash<QString, QJsonObject> m_feedback;
|
|
QPointer<QDialog> m_pollDialog;
|
|
QString m_pollDialogMessage, m_pendingPoll;
|
|
quint64 m_feedbackSequence = 0;
|
|
QByteArray m_historyAnchor;
|
|
void updateReply(QStandardItem* item, const QByteArray& original);
|
|
void refreshReplies();
|
|
void jumpToMessage(const QString& messageId);
|
|
|
|
void sendFeedback(QJsonObject command, bool userAction = true);
|
|
void setupFeedback(QStandardItem* item, const MessageRow& message, const QString& channel);
|
|
void createPoll();
|
|
void showPoll(const QString& messageId);
|
|
void applyFeedback(const QJsonObject& state);
|
|
void requestReaction(const QModelIndex& index, int emoji);
|
|
void addReactionActions(QMenu* menu, const QString& channel, const QString& messageId);
|
|
|
|
QString authorName(quint64 nodeId) const;
|
|
void restoreScrollPosition(const QString& channelId);
|
|
void updateReadPosition();
|
|
void onMessageContextMenu(const QPoint& pos);
|
|
void requestDmMessages(const QString& channelId);
|
|
void prepareVideoThumbnail(const QString& path);
|
|
void onRadioToggled(bool on);
|
|
void updateRadioUi();
|
|
static bool isDmChannel(const QString& channelId);
|
|
static QString dmConvId(const QString& channelId);
|
|
};
|