Highlight navigated to message

This commit is contained in:
Nicolas Werner 2021-04-29 19:09:16 +02:00
parent 620b6e8838
commit 82fa8ab292
No known key found for this signature in database
GPG Key ID: C8D75E610773F2D9
10 changed files with 131 additions and 8 deletions

View File

@ -25,10 +25,6 @@ Popup {
height: implicitHeight + completerPopup.height + padding * 2
leftPadding: 10
rightPadding: 10
background: Rectangle {
color: colors.window
}
onOpened: {
completerPopup.open();
roomTextInput.forceActiveFocus();
@ -110,6 +106,10 @@ Popup {
target: completerPopup
}
background: Rectangle {
color: colors.window
}
Overlay.modal: Rectangle {
color: Qt.rgba(colors.window.r, colors.window.g, colors.window.b, 0.7)
}

View File

@ -14,7 +14,7 @@ TextEdit {
selectByMouse: !Settings.mobileMode
enabled: selectByMouse
color: colors.text
onLinkActivated: TimelineManager.openLink(link);
onLinkActivated: TimelineManager.openLink(link)
ToolTip.visible: hoveredLink
ToolTip.text: hoveredLink

View File

@ -258,6 +258,7 @@ ScrollView {
onRoomAvatarUrlChanged: {
messageUserAvatar.url = modelData ? chat.model.avatarUrl(modelData.userId).replace("mxc://", "image://MxcImage/") : "";
}
onScrollToIndex: chat.positionViewAtIndex(index, ListView.Visible)
}
Label {
@ -302,10 +303,58 @@ ScrollView {
delegate: Item {
id: wrapper
property bool scrolledToThis: model.id === chat.model.scrollTarget && (y + height > chat.y + chat.contentY && y < chat.y + chat.height + chat.contentY)
anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
width: chat.delegateMaxWidth
height: section ? section.height + timelinerow.height : timelinerow.height
Rectangle {
id: scrollHighlight
opacity: 0
visible: true
anchors.fill: timelinerow
color: colors.highlight
states: State {
name: "revealed"
when: wrapper.scrolledToThis
}
transitions: Transition {
from: ""
to: "revealed"
SequentialAnimation {
PropertyAnimation {
target: scrollHighlight
properties: "opacity"
easing.type: Easing.InOutQuad
from: 0
to: 1
duration: 500
}
PropertyAnimation {
target: scrollHighlight
properties: "opacity"
easing.type: Easing.InOutQuad
from: 1
to: 0
duration: 500
}
ScriptAction {
script: chat.model.eventShown()
}
}
}
}
Loader {
id: section

View File

@ -8,7 +8,7 @@ import im.nheko 1.0
Item {
property double tempWidth: Math.min(parent ? parent.width : undefined, model.data.width < 1 ? parent.width : model.data.width)
property double tempHeight: tempWidth * model.data.proportionalHeight
property double divisor: model.isReply ? 4 : 2
property double divisor: model.isReply ? 5 : 3
property bool tooHigh: tempHeight > timelineRoot.height / divisor
height: Math.round(tooHigh ? timelineRoot.height / divisor : tempHeight)

View File

@ -18,7 +18,7 @@ Item {
height: replyContainer.height
TapHandler {
onSingleTapped: chat.positionViewAtIndex(chat.model.idToIndex(modelData.id), ListView.Contain)
onSingleTapped: chat.model.showEvent(modelData.id)
gesturePolicy: TapHandler.ReleaseWithinBounds
}

View File

@ -1376,7 +1376,7 @@ ChatPage::handleMatrixUri(const QByteArray &uri)
return;
QString mxid2;
if (segments.size() == 4 && segments[2] == "event") {
if (segments.size() == 4 && segments[2] == "e") {
if (segments[3].isEmpty())
return;
else
@ -1410,6 +1410,8 @@ ChatPage::handleMatrixUri(const QByteArray &uri)
for (auto roomid : joined_rooms) {
if (roomid == targetRoomId) {
room_list_->highlightSelectedRoom(mxid1);
if (!mxid2.isEmpty())
view_manager_->showEvent(mxid1, mxid2);
return;
}
}
@ -1427,6 +1429,9 @@ ChatPage::handleMatrixUri(const QByteArray &uri)
if (aliases->alias == targetRoomAlias) {
room_list_->highlightSelectedRoom(
QString::fromStdString(roomid));
if (!mxid2.isEmpty())
view_manager_->showEvent(
QString::fromStdString(roomid), mxid2);
return;
}
}

View File

@ -265,6 +265,8 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
connect(&events, &EventStore::updateFlowEventId, this, [this](std::string event_id) {
this->updateFlowEventId(event_id);
});
showEventTimer.callOnTimeout(this, &TimelineModel::scrollTimerEvent);
}
QHash<int, QByteArray>
@ -1298,6 +1300,42 @@ TimelineModel::cacheMedia(QString eventId)
cacheMedia(eventId, NULL);
}
void
TimelineModel::showEvent(QString eventId)
{
using namespace std::chrono_literals;
if (idToIndex(eventId) != -1) {
eventIdToShow = eventId;
emit scrollTargetChanged();
showEventTimer.start(50ms);
}
}
void
TimelineModel::eventShown()
{
eventIdToShow.clear();
emit scrollTargetChanged();
}
QString
TimelineModel::scrollTarget() const
{
return eventIdToShow;
}
void
TimelineModel::scrollTimerEvent()
{
if (eventIdToShow.isEmpty() || showEventTimerCounter > 3) {
showEventTimer.stop();
showEventTimerCounter = 0;
} else {
emit scrollToIndex(idToIndex(eventIdToShow));
showEventTimerCounter++;
}
}
QString
TimelineModel::formatTypingUsers(const std::vector<QString> &users, QColor bg)
{

View File

@ -9,6 +9,7 @@
#include <QDate>
#include <QHash>
#include <QSet>
#include <QTimer>
#include <mtxclient/http/errors.hpp>
@ -149,6 +150,7 @@ class TimelineModel : public QAbstractListModel
int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
Q_PROPERTY(std::vector<QString> typingUsers READ typingUsers WRITE updateTypingUsers NOTIFY
typingUsersChanged)
Q_PROPERTY(QString scrollTarget READ scrollTarget NOTIFY scrollTargetChanged)
Q_PROPERTY(QString reply READ reply WRITE setReply NOTIFY replyChanged RESET resetReply)
Q_PROPERTY(QString edit READ edit WRITE setEdit NOTIFY editChanged RESET resetEdit)
Q_PROPERTY(
@ -232,6 +234,7 @@ public:
Q_INVOKABLE void openMedia(QString eventId);
Q_INVOKABLE void cacheMedia(QString eventId);
Q_INVOKABLE bool saveMedia(QString eventId) const;
Q_INVOKABLE void showEvent(QString eventId);
void cacheMedia(QString eventId, std::function<void(const QString filename)> callback);
std::vector<::Reaction> reactions(const std::string &event_id)
@ -253,6 +256,7 @@ public:
public slots:
void setCurrentIndex(int index);
int currentIndex() const { return idToIndex(currentId); }
void eventShown();
void markEventsAsRead(const std::vector<QString> &event_ids);
QVariantMap getDump(QString eventId, QString relatedTo) const;
void updateTypingUsers(const std::vector<QString> &users)
@ -298,8 +302,11 @@ public slots:
QString roomAvatarUrl() const;
QString roomId() const { return room_id_; }
QString scrollTarget() const;
private slots:
void addPendingMessage(mtx::events::collections::TimelineEvents event);
void scrollTimerEvent();
signals:
void currentIndexChanged(int index);
@ -312,6 +319,7 @@ signals:
void editChanged(QString reply);
void paginationInProgressChanged(const bool);
void newCallEvent(const mtx::events::collections::TimelineEvents &event);
void scrollToIndex(int index);
void openProfile(UserProfile *profile);
void openRoomSettingsDialog(RoomSettings *settings);
@ -325,6 +333,8 @@ signals:
void roomAvatarUrlChanged();
void forwardToRoom(mtx::events::collections::TimelineEvents *e, QString roomId);
void scrollTargetChanged();
private:
template<typename T>
void sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::EventType eventType);
@ -350,6 +360,10 @@ private:
InputBar input_{this};
QTimer showEventTimer{this};
QString eventIdToShow;
int showEventTimerCounter = 0;
friend struct SendMessageVisitor;
};

View File

@ -404,6 +404,22 @@ TimelineViewManager::highlightRoom(const QString &room_id)
ChatPage::instance()->highlightRoom(room_id);
}
void
TimelineViewManager::showEvent(const QString &room_id, const QString &event_id)
{
auto room = models.find(room_id);
if (room != models.end()) {
if (timeline_ != room.value().data()) {
timeline_ = room.value().data();
emit activeTimelineChanged(timeline_);
container->setFocus();
nhlog::ui()->info("Activated room {}", room_id.toStdString());
}
timeline_->showEvent(event_id);
}
}
QString
TimelineViewManager::escapeEmoji(QString str) const
{

View File

@ -106,6 +106,7 @@ public slots:
void setHistoryView(const QString &room_id);
void highlightRoom(const QString &room_id);
void showEvent(const QString &room_id, const QString &event_id);
void focusTimeline();
TimelineModel *getHistoryView(const QString &room_id)
{