From af99b39722807cb610d7f037d78ea042c20ad993 Mon Sep 17 00:00:00 2001 From: Henk Kalkwater Date: Fri, 10 Sep 2021 05:17:28 +0200 Subject: [PATCH] Update UserData based when notified over websocket --- core/include/JellyfinQt/viewmodel/item.h | 3 + core/include/JellyfinQt/viewmodel/itemmodel.h | 3 + core/src/model/item.cpp | 1 + core/src/viewmodel/itemmodel.cpp | 24 +++++++- core/src/websocket.cpp | 57 ++++++------------- 5 files changed, 48 insertions(+), 40 deletions(-) diff --git a/core/include/JellyfinQt/viewmodel/item.h b/core/include/JellyfinQt/viewmodel/item.h index c8cc4fb..d545a1a 100644 --- a/core/include/JellyfinQt/viewmodel/item.h +++ b/core/include/JellyfinQt/viewmodel/item.h @@ -114,6 +114,7 @@ public: Q_PROPERTY(QList audioStreams READ audioStreams NOTIFY audioStreamsChanged) Q_PROPERTY(QList videoStreams READ videoStreams NOTIFY videoStreamsChanged) Q_PROPERTY(QList subtitleStreams READ subtitleStreams NOTIFY subtitleStreamsChanged) + Q_PROPERTY(double primaryImageAspectRatio READ primaryImageAspectRatio NOTIFY primaryImageAspectRatioChanged) Q_PROPERTY(QStringList artists READ artists NOTIFY artistsChanged) // Why is this a QJsonObject? Well, because I couldn't be bothered to implement the deserialisations of // a QHash at the moment. @@ -159,6 +160,7 @@ public: QObjectList audioStreams() const { return m_audioStreams; } QObjectList videoStreams() const { return m_videoStreams; } QObjectList subtitleStreams() const { return m_subtitleStreams; } + double primaryImageAspectRatio() const { return m_data->primaryImageAspectRatio().value_or(1.0); } QStringList artists() const { return m_data->artists(); } QJsonObject imageTags() const { return m_data->imageTags(); } QStringList backdropImageTags() const { return m_data->backdropImageTags(); } @@ -219,6 +221,7 @@ signals: void audioStreamsChanged(QVariantList &newAudioStreams); void videoStreamsChanged(QVariantList &newVideoStreams); void subtitleStreamsChanged(QVariantList &newSubtitleStreams); + void primaryImageAspectRatioChanged(double newPrimaryImageAspectRatio); void artistsChanged(const QStringList &newArtists); void imageTagsChanged(); void backdropImageTagsChanged(); diff --git a/core/include/JellyfinQt/viewmodel/itemmodel.h b/core/include/JellyfinQt/viewmodel/itemmodel.h index c584fd1..b3385bf 100644 --- a/core/include/JellyfinQt/viewmodel/itemmodel.h +++ b/core/include/JellyfinQt/viewmodel/itemmodel.h @@ -376,6 +376,9 @@ public: } QVariant data(const QModelIndex &index, int role) const override; QSharedPointer itemAt(int index); +private slots: + void onInsertItems(const QModelIndex &parent, int start, int end); + void onUserDataUpdated(const DTO::UserItemDataDto &newUserData); }; #undef JFRN diff --git a/core/src/model/item.cpp b/core/src/model/item.cpp index 1a4362b..22c0510 100644 --- a/core/src/model/item.cpp +++ b/core/src/model/item.cpp @@ -51,6 +51,7 @@ void Item::setApiClient(ApiClient *apiClient) { void Item::updateUserData(const QString &itemId, const DTO::UserItemDataDto &userData) { if (itemId == this->jellyfinId()) { + this->m_userData = QSharedPointer::create(userData); emit userDataChanged(userData); } } diff --git a/core/src/viewmodel/itemmodel.cpp b/core/src/viewmodel/itemmodel.cpp index cd7cbb0..f94f074 100644 --- a/core/src/viewmodel/itemmodel.cpp +++ b/core/src/viewmodel/itemmodel.cpp @@ -58,7 +58,9 @@ NextUpLoader::NextUpLoader(QObject *parent) : NextUpLoaderBase(new Jellyfin::Loader::HTTP::GetNextUpLoader(), parent) {} ItemModel::ItemModel(QObject *parent) - : ApiModel(parent) { } + : ApiModel(parent) { + connect(this, &QAbstractItemModel::rowsInserted, this, &ItemModel::onInsertItems); +} QVariant ItemModel::data(const QModelIndex &index, int role) const { if (role <= Qt::UserRole || !index.isValid()) return QVariant(); @@ -123,6 +125,26 @@ QSharedPointer ItemModel::itemAt(int index) { return m_array[index]; } + +void ItemModel::onInsertItems(const QModelIndex &parent, int start, int end) { + if (parent.isValid()) return; + qDebug() << "Connecting " << (end - start + 1) << "items!"; + for (int i = start; i <= end; i++) { + connect(itemAt(i).data(), &Model::Item::userDataChanged, this, &ItemModel::onUserDataUpdated); + } +} + +void ItemModel::onUserDataUpdated(const DTO::UserItemDataDto &newUserData) { + const QString &itemId = newUserData.itemId(); + qDebug() << "ApiModel: item updated: " << itemId; + for (int i = 0; i < rowCount(QModelIndex()); i++) { + if (itemAt(i)->jellyfinId() == itemId) { + QModelIndex index = this->index(i); + emit this->dataChanged(index, index); + } + } +} + } // NS ViewModel } // NS Jellyfin diff --git a/core/src/websocket.cpp b/core/src/websocket.cpp index 8745e99..a4e7638 100644 --- a/core/src/websocket.cpp +++ b/core/src/websocket.cpp @@ -95,7 +95,7 @@ void WebSocket::textMessageReceived(const QString &message) { setupKeepAlive(data.toInt()); } else if (messageType == QStringLiteral("GeneralCommand")) { try { - DTO::GeneralCommand command = DTO::GeneralCommand::fromJson(messageRoot["Data"].toObject()); + DTO::GeneralCommand command = DTO::GeneralCommand::fromJson(data.toObject()); // TODO: move command handling out of here switch(command.name()) { @@ -108,7 +108,7 @@ void WebSocket::textMessageReceived(const QString &message) { } break; default: - qCDebug(jellyfinWebSocket) << "Unhandled command: " << messageRoot["Data"]; + qCDebug(jellyfinWebSocket) << "Unhandled command: " << data; break; } @@ -117,49 +117,28 @@ void WebSocket::textMessageReceived(const QString &message) { } } else if (messageType == QStringLiteral("Playstate")) { try { - DTO::PlaystateRequest request = PlaystateRequest::fromJson(messageRoot["Data"].toObject()); + DTO::PlaystateRequest request = PlaystateRequest::fromJson(data.toObject()); emit m_apiClient->eventbus()->playstateCommandReceived(request); } catch (QException &e) { - qCWarning(jellyfinWebSocket()) << "Error while deserialzing PlaystateRequest " << e.what(); + qCWarning(jellyfinWebSocket) << "Error while deserialzing PlaystateRequest " << e.what(); + } + } else if(messageType == QStringLiteral("UserDataChanged")) { + QString userId = data.toObject()["UserId"].toString(); + if (userId != m_apiClient->userId()) { + qCDebug(jellyfinWebSocket) << "Received UserDataCHanged for other user"; + } else { + try { + QList userDataList = Support::fromJsonValue>(data.toObject()["UserDataList"]); + for (auto it = userDataList.cbegin(); it != userDataList.cend(); it++) { + emit m_apiClient->eventbus()->itemUserDataUpdated(it->itemId(), *it); + } + } catch (QException *e) { + qCWarning(jellyfinWebSocket) << "Unparseable UserData list received: " << e->what(); + } } } else { qCDebug(jellyfinWebSocket) << messageType; } - bool ok; - /*MessageType messageType = static_cast(QMetaEnum::fromType().keyToValue(messageTypeStr.toLatin1(), &ok)); - if (!ok) { - qWarning() << "Unknown message arrived: " << messageTypeStr; - if (messageRoot.contains("Data")) { - qDebug() << "with data: " << QJsonDocument(messageRoot["Data"].toObject()).toJson(); - } - return; - } - - qDebug() << "Received message: " << messageTypeStr; - - switch (messageType) { - case ForceKeepAlive: - setupKeepAlive(data.toInt(-1)); - break; - case KeepAlive: - //TODO: do something? - break; - case UserDataChanged: { - QJsonObject data2 = data.toObject(); - if (data2["UserId"] != m_apiClient->userId()) { - qDebug() << "Received UserDataCHanged for other user"; - break; - } - QJsonArray userDataList = data2["UserDataList"].toArray(); - for (QJsonValue val: userDataList) { - UserItemDataDto userData = UserItemDataDto::fromJson(val.toObject()); - //m_apiClient->onUserDataChanged(userData->itemId(), userData); - } - - } - break; - }*/ - } void WebSocket::sendKeepAlive() {