summary refs log tree commit diff
path: root/src/ReadReceiptsModel.cpp
blob: dfaab567b7a208ea44f25a8225f06e92727bf9cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// SPDX-FileCopyrightText: Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "ReadReceiptsModel.h"

#include <QLocale>

#include "Cache.h"
#include "Cache_p.h"
#include "Logging.h"
#include "Utils.h"

ReadReceiptsModel::ReadReceiptsModel(QString event_id, QString room_id, QObject *parent)
  : QAbstractListModel{parent}
  , event_id_{event_id}
  , room_id_{room_id}
{
    try {
        addUsers(cache::readReceipts(event_id_, room_id_));
    } catch (const lmdb::error &) {
        nhlog::db()->warn("failed to retrieve read receipts for {} {}",
                          event_id_.toStdString(),
                          room_id_.toStdString());

        return;
    }

    connect(cache::client(), &Cache::newReadReceipts, this, &ReadReceiptsModel::update);
}

void
ReadReceiptsModel::update()
{
    try {
        addUsers(cache::readReceipts(event_id_, room_id_));
    } catch (const lmdb::error &) {
        nhlog::db()->warn("failed to retrieve read receipts for {} {}",
                          event_id_.toStdString(),
                          room_id_.toStdString());

        return;
    }
}

QHash<int, QByteArray>
ReadReceiptsModel::roleNames() const
{
    // Note: RawTimestamp is purposely not included here
    return {
      {Mxid, "mxid"},
      {DisplayName, "displayName"},
      {AvatarUrl, "avatarUrl"},
      {Timestamp, "timestamp"},
    };
}

QVariant
ReadReceiptsModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() >= (int)readReceipts_.size() || index.row() < 0)
        return {};

    switch (role) {
    case Mxid:
        return readReceipts_[index.row()].first;
    case DisplayName:
        return cache::displayName(room_id_, readReceipts_[index.row()].first);
    case AvatarUrl:
        return cache::avatarUrl(room_id_, readReceipts_[index.row()].first);
    case Timestamp:
        return dateFormat(readReceipts_[index.row()].second);
    case RawTimestamp:
        return readReceipts_[index.row()].second;
    default:
        return {};
    }
}

void
ReadReceiptsModel::addUsers(
  const std::multimap<uint64_t, std::string, std::greater<uint64_t>> &users)
{
    auto newReceipts = users.size() - readReceipts_.size();

    if (newReceipts > 0) {
        beginInsertRows(QModelIndex{},
                        static_cast<int>(readReceipts_.size()),
                        static_cast<int>(readReceipts_.size() + newReceipts - 1));

        for (const auto &user : users) {
            QPair<QString, QDateTime> item = {QString::fromStdString(user.second),
                                              QDateTime::fromMSecsSinceEpoch(user.first)};
            if (!readReceipts_.contains(item))
                readReceipts_.push_back(item);
        }

        endInsertRows();
    }
}

QString
ReadReceiptsModel::dateFormat(const QDateTime &then) const
{
    auto now  = QDateTime::currentDateTime();
    auto days = then.daysTo(now);

    if (days == 0)
        return QLocale::system().toString(then.time(), QLocale::ShortFormat);
    else if (days < 2)
        return tr("Yesterday, %1")
          .arg(QLocale::system().toString(then.time(), QLocale::ShortFormat));
    else if (days < 7)
        //: %1 is the name of the current day, %2 is the time the read receipt was read. The
        //: result may look like this: Monday, 7:15
        return QStringLiteral("%1, %2").arg(
          then.toString(QStringLiteral("dddd")),
          QLocale::system().toString(then.time(), QLocale::ShortFormat));

    return QLocale::system().toString(then.time(), QLocale::ShortFormat);
}

ReadReceiptsProxy::ReadReceiptsProxy(QString event_id, QString room_id, QObject *parent)
  : QSortFilterProxyModel{parent}
  , model_{event_id, room_id, this}
{
    setSourceModel(&model_);
    setSortRole(ReadReceiptsModel::RawTimestamp);
    sort(0, Qt::DescendingOrder);
    setDynamicSortFilter(true);
}