Files
amnezia-client/client/ui/models/newsModel.cpp
T

177 lines
4.5 KiB
C++
Raw Normal View History

2025-10-06 08:06:36 +04:00
#include "ui/models/newsModel.h"
#include "core/repositories/secureAppSettingsRepository.h"
2025-10-06 08:06:36 +04:00
#include <QDir>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QQmlEngine>
#include <QStandardPaths>
#include <algorithm>
NewsModel::NewsModel(SecureAppSettingsRepository* appSettingsRepository, QObject *parent)
: QAbstractListModel(parent), m_appSettingsRepository(appSettingsRepository)
2025-10-06 08:06:36 +04:00
{
loadReadIds();
}
int NewsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return m_items.size();
}
QVariant NewsModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size())
return QVariant();
const NewsItem &item = m_items.at(index.row());
switch (role) {
case IdRole: return item.id;
case TitleRole: return item.title;
case ContentRole: return item.content;
case TimestampRole: return item.timestamp.toLocalTime().toString(Qt::ISODate);
2026-05-04 07:37:19 +03:00
case IsReadRole: return m_readIds.contains(item.id);
2025-10-06 08:06:36 +04:00
case IsProcessedRole: return index.row() == m_processedIndex;
2026-05-04 07:37:19 +03:00
case IsUpdateRole: return item.isUpdate;
2025-10-06 08:06:36 +04:00
default: return QVariant();
}
}
QHash<int, QByteArray> NewsModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[IdRole] = "id";
roles[TitleRole] = "title";
roles[ContentRole] = "content";
roles[TimestampRole] = "timestamp";
roles[IsReadRole] = "read";
roles[IsProcessedRole] = "isProcessed";
2026-05-04 07:37:19 +03:00
roles[IsUpdateRole] = "isUpdate";
2025-10-06 08:06:36 +04:00
return roles;
}
void NewsModel::markAsRead(int index)
{
if (index < 0 || index >= m_items.size())
return;
2026-05-04 07:37:19 +03:00
const QString &itemId = m_items.at(index).id;
if (itemId.isEmpty() || m_readIds.contains(itemId))
return;
m_readIds.insert(itemId);
saveReadIds();
QModelIndex idx = createIndex(index, 0);
emit dataChanged(idx, idx, { IsReadRole });
emit hasUnreadChanged();
}
void NewsModel::markUpdateAsSkipped()
{
if (!m_updateItem.has_value())
return;
const QString updateId = m_updateItem->id;
if (updateId.isEmpty())
return;
for (int i = 0; i < m_items.size(); ++i) {
if (m_items.at(i).id == updateId) {
markAsRead(i);
break;
}
2025-10-06 08:06:36 +04:00
}
}
int NewsModel::processedIndex() const
{
return m_processedIndex;
}
void NewsModel::setProcessedIndex(int index)
{
if (index < 0 || index >= m_items.size() || m_processedIndex == index)
return;
m_processedIndex = index;
emit processedIndexChanged(index);
}
2026-05-04 07:37:19 +03:00
void NewsModel::setNewsList(const QJsonArray &serverItems)
2025-10-06 08:06:36 +04:00
{
2026-05-04 07:37:19 +03:00
QVector<NewsItem> updatedItems;
updatedItems.reserve(serverItems.size());
2025-10-06 08:06:36 +04:00
for (const QJsonValue &value : serverItems) {
if (!value.isObject())
continue;
2026-05-04 07:37:19 +03:00
const QJsonObject object = value.toObject();
NewsItem item;
item.id = object.value("id").toString();
2026-05-04 07:37:19 +03:00
if (item.id.isEmpty())
continue;
item.title = object.value("title").toString();
item.content = object.value("content").toString();
item.timestamp = QDateTime::fromString(object.value("timestamp").toString(), Qt::ISODate);
2026-05-04 07:37:19 +03:00
item.isUpdate = false;
updatedItems.append(item);
2025-10-06 08:06:36 +04:00
}
2026-05-04 07:37:19 +03:00
m_apiItems = updatedItems;
updateModel();
}
void NewsModel::setUpdateNotification(const QString &id, const QString &title, const QString &content)
{
if (id.isEmpty())
return;
NewsItem updateItem;
updateItem.id = id;
updateItem.title = title;
updateItem.content = content;
updateItem.timestamp = QDateTime::currentDateTimeUtc();
updateItem.isUpdate = true;
m_updateItem = updateItem;
updateModel();
}
void NewsModel::updateModel()
{
2025-10-06 08:06:36 +04:00
beginResetModel();
2026-05-04 07:37:19 +03:00
m_items = m_apiItems;
2025-10-06 08:06:36 +04:00
std::sort(m_items.begin(), m_items.end(), [](const NewsItem &a, const NewsItem &b) { return a.timestamp > b.timestamp; });
2026-05-04 07:37:19 +03:00
if (m_updateItem.has_value()) {
m_items.prepend(*m_updateItem);
}
2025-10-06 08:06:36 +04:00
endResetModel();
emit hasUnreadChanged();
}
bool NewsModel::hasUnread() const
{
for (const NewsItem &item : m_items) {
2026-05-04 07:37:19 +03:00
if (!m_readIds.contains(item.id))
2025-10-06 08:06:36 +04:00
return true;
}
return false;
}
void NewsModel::loadReadIds()
{
QStringList ids = m_appSettingsRepository->getReadNewsIds();
2025-10-06 08:06:36 +04:00
m_readIds = QSet<QString>(ids.begin(), ids.end());
}
void NewsModel::saveReadIds() const
{
m_appSettingsRepository->setReadNewsIds(QStringList(m_readIds.begin(), m_readIds.end()));
2025-10-06 08:06:36 +04:00
}