mirror of
https://github.com/HenkKalkwater/harbour-sailfin.git
synced 2024-11-22 01:05:17 +00:00
Fix a few bugs and unimplemented features
* Show the now playing cover when playing an item, otherwise show the collection cover. * ItemModelLoaders now correctly expose list properties of non-built-in Qt objects * toString is now implemented for lists, fixing some query construction code. * PlaybackManager now clears the playlist when playing a single item to prevent weird behaviour. * The covers are slightly updated.
This commit is contained in:
parent
60bc90c5fa
commit
caf72af999
|
@ -47,6 +47,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#include "support/loader.h"
|
#include "support/loader.h"
|
||||||
#include "viewmodel/modelstatus.h"
|
#include "viewmodel/modelstatus.h"
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(jellyfinApiModel)
|
||||||
|
|
||||||
namespace Jellyfin {
|
namespace Jellyfin {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -121,6 +123,7 @@ protected:
|
||||||
int m_limit = -1;
|
int m_limit = -1;
|
||||||
int m_startIndex = 0;
|
int m_startIndex = 0;
|
||||||
int m_totalRecordCount = 0;
|
int m_totalRecordCount = 0;
|
||||||
|
bool m_explicitLimitSet = false;
|
||||||
const int DEFAULT_LIMIT = 100;
|
const int DEFAULT_LIMIT = 100;
|
||||||
void emitModelShouldClear() { emit modelShouldClear(); }
|
void emitModelShouldClear() { emit modelShouldClear(); }
|
||||||
void emitItemsLoaded() { emit itemsLoaded(); }
|
void emitItemsLoaded() { emit itemsLoaded(); }
|
||||||
|
@ -165,14 +168,14 @@ public:
|
||||||
m_startIndex = 0;
|
m_startIndex = 0;
|
||||||
m_totalRecordCount = -1;
|
m_totalRecordCount = -1;
|
||||||
emitModelShouldClear();
|
emitModelShouldClear();
|
||||||
loadMore(0, m_limit, ViewModel::ModelStatus::Loading);
|
loadMore(ViewModel::ModelStatus::Loading);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadMore() {
|
void loadMore() {
|
||||||
if (!canReload()) {
|
if (!canReload()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loadMore(m_startIndex, m_limit, ViewModel::ModelStatus::LoadingMore);
|
loadMore(ViewModel::ModelStatus::LoadingMore);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool canLoadMore() const {
|
virtual bool canLoadMore() const {
|
||||||
|
@ -192,12 +195,10 @@ protected:
|
||||||
* The itemsLoaded() signal is emitted when new data is ready. Call
|
* The itemsLoaded() signal is emitted when new data is ready. Call
|
||||||
* getLoadedItems to retrieve the loaded items.
|
* getLoadedItems to retrieve the loaded items.
|
||||||
*
|
*
|
||||||
* @param offset The offset to start loading items from
|
|
||||||
* @param limit The maximum amount of items to load.
|
|
||||||
* @param suggestedStatus The suggested status this model should take on if it is able to load (more).
|
* @param suggestedStatus The suggested status this model should take on if it is able to load (more).
|
||||||
* Either LOADING or LOAD_MORE.
|
* Either LOADING or LOAD_MORE.
|
||||||
*/
|
*/
|
||||||
virtual void loadMore(int offset, int limit, ViewModel::ModelStatus suggestedStatus) = 0;
|
virtual void loadMore(ViewModel::ModelStatus suggestedStatus) = 0;
|
||||||
std::pair<QList<T*>, int> m_result;
|
std::pair<QList<T*>, int> m_result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -270,7 +271,7 @@ public:
|
||||||
this->connect(m_loader.data(), &Support::Loader<R, P>::error, this, &LoaderModelLoader<T, D, R, P>::loaderError);
|
this->connect(m_loader.data(), &Support::Loader<R, P>::error, this, &LoaderModelLoader<T, D, R, P>::loaderError);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
void loadMore(int offset, int limit, ViewModel::ModelStatus suggestedModelStatus) override {
|
void loadMore(ViewModel::ModelStatus suggestedModelStatus) override {
|
||||||
// This method should only be callable on one thread.
|
// This method should only be callable on one thread.
|
||||||
// If futureWatcher's future is running, this method should not be called again.
|
// If futureWatcher's future is running, this method should not be called again.
|
||||||
if (m_loader->isRunning()) {
|
if (m_loader->isRunning()) {
|
||||||
|
@ -279,20 +280,22 @@ protected:
|
||||||
// Set an invalid result.
|
// Set an invalid result.
|
||||||
this->m_result = { QList<T*>(), -1 };
|
this->m_result = { QList<T*>(), -1 };
|
||||||
|
|
||||||
if (!setRequestStartIndex<P>(this->m_parameters, offset)
|
if (!setRequestStartIndex<P>(this->m_parameters, this->m_startIndex)
|
||||||
&& suggestedModelStatus == ViewModel::ModelStatus::LoadingMore) {
|
&& suggestedModelStatus == ViewModel::ModelStatus::LoadingMore) {
|
||||||
// This loader's parameters does not setting a starting index,
|
// This loader's parameters does not setting a starting index,
|
||||||
// meaning loadMore is not supported.
|
// meaning loadMore is not supported.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
setRequestStartIndex<P>(this->m_parameters, this->m_startIndex);
|
||||||
|
|
||||||
if (limit > 0) {
|
if (suggestedModelStatus == ViewModel::ModelStatus::LoadingMore && this->m_explicitLimitSet) {
|
||||||
if (suggestedModelStatus == ViewModel::ModelStatus::Loading) {
|
// If an explicit limit is set, we should load no more
|
||||||
setRequestLimit<P>(this->m_parameters, limit);
|
return;
|
||||||
} else {
|
}
|
||||||
// If an explicit limit is set, we should load no more
|
|
||||||
return;
|
qCDebug(jellyfinApiModel) << "Explicit limit set: " << this->m_explicitLimitSet << ", " << this->m_limit;
|
||||||
}
|
if (this->m_explicitLimitSet) {
|
||||||
|
setRequestLimit<P>(this->m_parameters, this->m_limit);
|
||||||
} else {
|
} else {
|
||||||
setRequestLimit<P>(this->m_parameters, this->DEFAULT_LIMIT);
|
setRequestLimit<P>(this->m_parameters, this->DEFAULT_LIMIT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void appendToList(ViewModel::ItemModel &model);
|
void appendToList(ViewModel::ItemModel &model);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief appendToList Appends a single item to the current list
|
||||||
|
* @param item The item to append
|
||||||
|
*/
|
||||||
|
void appendToList(QSharedPointer<Model::Item> item);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start playing this playlist
|
* @brief Start playing this playlist
|
||||||
* @param index The index to start from.
|
* @param index The index to start from.
|
||||||
|
|
|
@ -139,6 +139,12 @@ QJsonValue toJsonValue(const QSharedPointer<T> &source, convertType<QSharedPoint
|
||||||
* Templates for string conversion.
|
* Templates for string conversion.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
QString toString(const T &source) {
|
||||||
|
return toString(source, convertType<T>{});
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
QString toString(const T &source, convertType<T>) {
|
QString toString(const T &source, convertType<T>) {
|
||||||
return toJsonValue(source).toString();
|
return toJsonValue(source).toString();
|
||||||
|
@ -154,11 +160,15 @@ QString toString(const std::optional<T> &source, convertType<std::optional<T>>)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
QString toString(const T &source) {
|
QString toString(const QList<T> &source, convertType<QList<T>>) {
|
||||||
return toString(source, convertType<T>{});
|
QStringList tmp;
|
||||||
|
tmp.reserve(source.size());
|
||||||
|
for (auto it = source.cbegin(); it != source.cend(); it++) {
|
||||||
|
tmp.append(toString<T>(*it, convertType<T>{}));
|
||||||
|
}
|
||||||
|
return tmp.join(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // NS Support
|
} // NS Support
|
||||||
} // NS Jellyfin
|
} // NS Jellyfin
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
#include <QVariantList>
|
||||||
|
|
||||||
#include "../dto/baseitemdto.h"
|
#include "../dto/baseitemdto.h"
|
||||||
#include "../dto/baseitemdtoqueryresult.h"
|
#include "../dto/baseitemdtoqueryresult.h"
|
||||||
|
@ -45,6 +46,31 @@
|
||||||
Q_SIGNALS: \
|
Q_SIGNALS: \
|
||||||
void propName##Changed();
|
void propName##Changed();
|
||||||
|
|
||||||
|
#define FWDLISTPROP(type, propName, propSetName) \
|
||||||
|
public: \
|
||||||
|
Q_PROPERTY(QVariantList propName READ propName WRITE set##propSetName NOTIFY propName##Changed) \
|
||||||
|
QVariantList propName() const { \
|
||||||
|
QVariantList result; \
|
||||||
|
QList<type> list; \
|
||||||
|
result.reserve(list.size()); \
|
||||||
|
for (auto it = list.cbegin(); it != list.cend(); it++) { \
|
||||||
|
result.append(QVariant::fromValue<type>(*it)); \
|
||||||
|
} \
|
||||||
|
return result; \
|
||||||
|
} \
|
||||||
|
void set##propSetName(const QVariantList &newValue) { \
|
||||||
|
QList<type> list;\
|
||||||
|
list.reserve(newValue.size()); \
|
||||||
|
for(auto it = newValue.cbegin(); it != newValue.cend(); it++) { \
|
||||||
|
list.append(it->value<type>()); \
|
||||||
|
} \
|
||||||
|
this->m_parameters.set##propSetName(list); \
|
||||||
|
emit propName##Changed(); \
|
||||||
|
autoReloadIfNeeded(); \
|
||||||
|
} \
|
||||||
|
Q_SIGNALS: \
|
||||||
|
void propName##Changed();
|
||||||
|
|
||||||
namespace Jellyfin {
|
namespace Jellyfin {
|
||||||
|
|
||||||
namespace ViewModel {
|
namespace ViewModel {
|
||||||
|
@ -112,7 +138,7 @@ public:
|
||||||
FWDPROP(QList<Jellyfin::DTO::ImageTypeClass::Value>, enableImageTypes, EnableImageTypes)
|
FWDPROP(QList<Jellyfin::DTO::ImageTypeClass::Value>, enableImageTypes, EnableImageTypes)
|
||||||
FWDPROP(bool, enableImages, EnableImages)
|
FWDPROP(bool, enableImages, EnableImages)
|
||||||
FWDPROP(bool, enableUserData, EnableUserData)
|
FWDPROP(bool, enableUserData, EnableUserData)
|
||||||
FWDPROP(QList<Jellyfin::DTO::ItemFieldsClass::Value>, fields, Fields)
|
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
|
||||||
FWDPROP(bool, groupItems, GroupItems)
|
FWDPROP(bool, groupItems, GroupItems)
|
||||||
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
||||||
FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
|
FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
|
||||||
|
@ -134,7 +160,7 @@ public:
|
||||||
FWDPROP(QStringList, artists, Artists)
|
FWDPROP(QStringList, artists, Artists)
|
||||||
FWDPROP(bool, collapseBoxSetItems, CollapseBoxSetItems)
|
FWDPROP(bool, collapseBoxSetItems, CollapseBoxSetItems)
|
||||||
FWDPROP(QStringList, contributingArtistIds, ContributingArtistIds)
|
FWDPROP(QStringList, contributingArtistIds, ContributingArtistIds)
|
||||||
FWDPROP(QList<Jellyfin::DTO::ImageTypeClass::Value>, enableImageTypes, EnableImageTypes);
|
FWDLISTPROP(Jellyfin::DTO::ImageTypeClass::Value, enableImageTypes, EnableImageTypes);
|
||||||
FWDPROP(bool, enableImages, EnableImages)
|
FWDPROP(bool, enableImages, EnableImages)
|
||||||
FWDPROP(bool, enableTotalRecordCount, EnableTotalRecordCount)
|
FWDPROP(bool, enableTotalRecordCount, EnableTotalRecordCount)
|
||||||
FWDPROP(bool, enableUserData, EnableUserData)
|
FWDPROP(bool, enableUserData, EnableUserData)
|
||||||
|
@ -142,8 +168,8 @@ public:
|
||||||
FWDPROP(QStringList, excludeItemIds, ExcludeItemIds)
|
FWDPROP(QStringList, excludeItemIds, ExcludeItemIds)
|
||||||
FWDPROP(QStringList, excludeItemTypes, ExcludeItemTypes)
|
FWDPROP(QStringList, excludeItemTypes, ExcludeItemTypes)
|
||||||
FWDPROP(QList<Jellyfin::DTO::LocationTypeClass::Value>, excludeLocationTypes, ExcludeLocationTypes)
|
FWDPROP(QList<Jellyfin::DTO::LocationTypeClass::Value>, excludeLocationTypes, ExcludeLocationTypes)
|
||||||
FWDPROP(QList<Jellyfin::DTO::ItemFieldsClass::Value>, fields, Fields)
|
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
|
||||||
FWDPROP(QList<Jellyfin::DTO::ItemFilterClass::Value>, filters, Filters)
|
FWDLISTPROP(Jellyfin::DTO::ItemFilterClass::Value, filters, Filters)
|
||||||
FWDPROP(QStringList, genreIds, GenreIds)
|
FWDPROP(QStringList, genreIds, GenreIds)
|
||||||
FWDPROP(QStringList, genres, Genres)
|
FWDPROP(QStringList, genres, Genres)
|
||||||
FWDPROP(bool, hasImdbId, HasImdbId)
|
FWDPROP(bool, hasImdbId, HasImdbId)
|
||||||
|
@ -159,7 +185,7 @@ public:
|
||||||
FWDPROP(bool, hasTvdbId, HasTvdbId)
|
FWDPROP(bool, hasTvdbId, HasTvdbId)
|
||||||
FWDPROP(QStringList, ids, Ids)
|
FWDPROP(QStringList, ids, Ids)
|
||||||
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
||||||
FWDPROP(QList<Jellyfin::DTO::ImageTypeClass::Value>, imageTypes, ImageTypes)
|
FWDLISTPROP(Jellyfin::DTO::ImageTypeClass::Value, imageTypes, ImageTypes)
|
||||||
FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
|
FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
|
||||||
FWDPROP(bool, is3D, Is3D)
|
FWDPROP(bool, is3D, Is3D)
|
||||||
FWDPROP(bool, is4K, Is4K)
|
FWDPROP(bool, is4K, Is4K)
|
||||||
|
@ -170,8 +196,7 @@ public:
|
||||||
FWDPROP(bool, isPlaceHolder, IsPlaceHolder)
|
FWDPROP(bool, isPlaceHolder, IsPlaceHolder)
|
||||||
FWDPROP(bool, isPlayed, IsPlayed)
|
FWDPROP(bool, isPlayed, IsPlayed)
|
||||||
FWDPROP(bool, isUnaired, IsUnaired)
|
FWDPROP(bool, isUnaired, IsUnaired)
|
||||||
FWDPROP(int, limit, Limit)
|
FWDLISTPROP(Jellyfin::DTO::LocationTypeClass::Value, locationTypes, LocationTypes)
|
||||||
FWDPROP(QList<Jellyfin::DTO::LocationTypeClass::Value>, locationTypes, LocationTypes)
|
|
||||||
FWDPROP(qint32, maxHeight, MaxHeight)
|
FWDPROP(qint32, maxHeight, MaxHeight)
|
||||||
FWDPROP(QString, maxOfficialRating, MaxOfficialRating)
|
FWDPROP(QString, maxOfficialRating, MaxOfficialRating)
|
||||||
FWDPROP(QDateTime, maxPremiereDate, MaxPremiereDate)
|
FWDPROP(QDateTime, maxPremiereDate, MaxPremiereDate)
|
||||||
|
@ -198,12 +223,12 @@ class ResumeItemsLoader : public ResumeItemsLoaderBase {
|
||||||
public:
|
public:
|
||||||
explicit ResumeItemsLoader(QObject *parent = nullptr);
|
explicit ResumeItemsLoader(QObject *parent = nullptr);
|
||||||
|
|
||||||
FWDPROP(QList<Jellyfin::DTO::ImageTypeClass::Value>, enableImageTypes, EnableImageTypes);
|
FWDLISTPROP(Jellyfin::DTO::ImageTypeClass::Value, enableImageTypes, EnableImageTypes);
|
||||||
FWDPROP(bool, enableImages, EnableImages)
|
FWDPROP(bool, enableImages, EnableImages)
|
||||||
FWDPROP(bool, enableTotalRecordCount, EnableTotalRecordCount)
|
FWDPROP(bool, enableTotalRecordCount, EnableTotalRecordCount)
|
||||||
FWDPROP(bool, enableUserData, EnableUserData)
|
FWDPROP(bool, enableUserData, EnableUserData)
|
||||||
FWDPROP(QStringList, excludeItemTypes, ExcludeItemTypes)
|
FWDPROP(QStringList, excludeItemTypes, ExcludeItemTypes)
|
||||||
FWDPROP(QList<Jellyfin::DTO::ItemFieldsClass::Value>, fields, Fields)
|
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
|
||||||
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
||||||
FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
|
FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
|
||||||
FWDPROP(QStringList, mediaTypes, MediaTypes)
|
FWDPROP(QStringList, mediaTypes, MediaTypes)
|
||||||
|
@ -219,10 +244,10 @@ public:
|
||||||
|
|
||||||
FWDPROP(QString, seriesId, SeriesId)
|
FWDPROP(QString, seriesId, SeriesId)
|
||||||
FWDPROP(QString, adjacentTo, AdjacentTo)
|
FWDPROP(QString, adjacentTo, AdjacentTo)
|
||||||
FWDPROP(QList<Jellyfin::DTO::ImageTypeClass::Value>, enableImageTypes, EnableImageTypes)
|
FWDLISTPROP(Jellyfin::DTO::ImageTypeClass::Value, enableImageTypes, EnableImageTypes)
|
||||||
FWDPROP(bool, enableImages, EnableImages)
|
FWDPROP(bool, enableImages, EnableImages)
|
||||||
FWDPROP(bool, enableUserData, EnableUserData)
|
FWDPROP(bool, enableUserData, EnableUserData)
|
||||||
FWDPROP(QList<Jellyfin::DTO::ItemFieldsClass::Value>, fields, Fields)
|
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
|
||||||
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
||||||
FWDPROP(bool, isMissing, IsMissing)
|
FWDPROP(bool, isMissing, IsMissing)
|
||||||
FWDPROP(bool, isSpecialSeason, IsSpecialSeason)
|
FWDPROP(bool, isSpecialSeason, IsSpecialSeason)
|
||||||
|
@ -239,7 +264,7 @@ public:
|
||||||
FWDPROP(QString, adjacentTo, AdjacentTo)
|
FWDPROP(QString, adjacentTo, AdjacentTo)
|
||||||
FWDPROP(bool, enableImages, EnableImages)
|
FWDPROP(bool, enableImages, EnableImages)
|
||||||
FWDPROP(bool, enableUserData, EnableUserData)
|
FWDPROP(bool, enableUserData, EnableUserData)
|
||||||
FWDPROP(QList<Jellyfin::DTO::ItemFieldsClass::Value>, fields, Fields)
|
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
|
||||||
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
||||||
FWDPROP(bool, isMissing, IsMissing)
|
FWDPROP(bool, isMissing, IsMissing)
|
||||||
FWDPROP(qint32, season, Season)
|
FWDPROP(qint32, season, Season)
|
||||||
|
@ -248,6 +273,23 @@ public:
|
||||||
FWDPROP(QString, startItemId, StartItemId)
|
FWDPROP(QString, startItemId, StartItemId)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using NextUpLoaderBase = AbstractUserParameterLoader<Model::Item, DTO::BaseItemDto, DTO::BaseItemDtoQueryResult, Jellyfin::Loader::GetNextUpParams>;
|
||||||
|
class NextUpLoader : public NextUpLoaderBase {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit NextUpLoader(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
FWDPROP(bool, disableFirstEpisode, DisableFirstEpisode)
|
||||||
|
FWDLISTPROP(Jellyfin::DTO::ImageTypeClass::Value, enableImageTypes, EnableImageTypes);
|
||||||
|
FWDPROP(bool, enableImges, EnableImges)
|
||||||
|
FWDPROP(bool, enableTotalRecordCount, EnableTotalRecordCount)
|
||||||
|
FWDPROP(bool, enableUserData, EnableUserData)
|
||||||
|
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
|
||||||
|
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
|
||||||
|
FWDPROP(QString, parentId, ParentId)
|
||||||
|
FWDPROP(QString, seriesId, SeriesId)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Base class for each model that works with items.
|
* @brief Base class for each model that works with items.
|
||||||
|
@ -278,6 +320,7 @@ public:
|
||||||
runTimeTicks,
|
runTimeTicks,
|
||||||
artists,
|
artists,
|
||||||
isFolder,
|
isFolder,
|
||||||
|
overview,
|
||||||
parentIndexNumber,
|
parentIndexNumber,
|
||||||
userDataRating,
|
userDataRating,
|
||||||
userDataPlayedPercentage,
|
userDataPlayedPercentage,
|
||||||
|
@ -317,6 +360,7 @@ public:
|
||||||
JFRN(runTimeTicks),
|
JFRN(runTimeTicks),
|
||||||
JFRN(artists),
|
JFRN(artists),
|
||||||
JFRN(isFolder),
|
JFRN(isFolder),
|
||||||
|
JFRN(overview),
|
||||||
JFRN(parentIndexNumber),
|
JFRN(parentIndexNumber),
|
||||||
JFRN(userDataRating),
|
JFRN(userDataRating),
|
||||||
JFRN(userDataPlayedPercentage),
|
JFRN(userDataPlayedPercentage),
|
||||||
|
|
|
@ -60,7 +60,7 @@ public:
|
||||||
: QObject(parent), m_apiClient(apiClient) {}
|
: QObject(parent), m_apiClient(apiClient) {}
|
||||||
|
|
||||||
Q_PROPERTY(ApiClient *apiClient MEMBER m_apiClient WRITE setApiClient NOTIFY apiClientChanged STORED false)
|
Q_PROPERTY(ApiClient *apiClient MEMBER m_apiClient WRITE setApiClient NOTIFY apiClientChanged STORED false)
|
||||||
Q_PROPERTY(Status status READ status NOTIFY statusChanged STORED false)
|
Q_PROPERTY(Jellyfin::ViewModel::LoaderBase::Status status READ status NOTIFY statusChanged STORED false)
|
||||||
Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged STORED false)
|
Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged STORED false)
|
||||||
Q_PROPERTY(bool autoReload MEMBER m_autoReload NOTIFY autoReloadChanged)
|
Q_PROPERTY(bool autoReload MEMBER m_autoReload NOTIFY autoReloadChanged)
|
||||||
Q_PROPERTY(QObject *data READ data NOTIFY dataChanged STORED false)
|
Q_PROPERTY(QObject *data READ data NOTIFY dataChanged STORED false)
|
||||||
|
@ -73,7 +73,7 @@ public:
|
||||||
void setApiClient(ApiClient *newApiClient);
|
void setApiClient(ApiClient *newApiClient);
|
||||||
void setExtraFields(const QStringList &extraFields);
|
void setExtraFields(const QStringList &extraFields);
|
||||||
signals:
|
signals:
|
||||||
void statusChanged(Status newStatus);
|
void statusChanged(Jellyfin::ViewModel::LoaderBase::Status newStatus);
|
||||||
void apiClientChanged(ApiClient *newApiClient);
|
void apiClientChanged(ApiClient *newApiClient);
|
||||||
void errorStringChanged(QString newErrorString);
|
void errorStringChanged(QString newErrorString);
|
||||||
void autoReloadChanged(bool newAutoReload);
|
void autoReloadChanged(bool newAutoReload);
|
||||||
|
|
|
@ -438,7 +438,7 @@ void ApiClient::generateDeviceProfile() {
|
||||||
clientCapabilities->setIconUrl("https://chris.netsoj.nl/static/img/logo.png");
|
clientCapabilities->setIconUrl("https://chris.netsoj.nl/static/img/logo.png");
|
||||||
clientCapabilities->setSupportsPersistentIdentifier(true);
|
clientCapabilities->setSupportsPersistentIdentifier(true);
|
||||||
clientCapabilities->setSupportsSync(false);
|
clientCapabilities->setSupportsSync(false);
|
||||||
clientCapabilities->setSupportsMediaControl(false);
|
clientCapabilities->setSupportsMediaControl(true);
|
||||||
clientCapabilities->setSupportsContentUploading(false);
|
clientCapabilities->setSupportsContentUploading(false);
|
||||||
|
|
||||||
d->clientCapabilities = clientCapabilities;
|
d->clientCapabilities = clientCapabilities;
|
||||||
|
|
|
@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#include "JellyfinQt/dto/useritemdatadto.h"
|
#include "JellyfinQt/dto/useritemdatadto.h"
|
||||||
#include "JellyfinQt/dto/userdto.h"
|
#include "JellyfinQt/dto/userdto.h"
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(jellyfinApiModel, "jellyfin.apimodel")
|
||||||
|
|
||||||
namespace Jellyfin {
|
namespace Jellyfin {
|
||||||
|
|
||||||
// BaseApiModel
|
// BaseApiModel
|
||||||
|
@ -46,7 +48,7 @@ void BaseModelLoader::componentComplete() {
|
||||||
|
|
||||||
void BaseModelLoader::autoReloadIfNeeded() {
|
void BaseModelLoader::autoReloadIfNeeded() {
|
||||||
if (m_autoReload && canReload()) {
|
if (m_autoReload && canReload()) {
|
||||||
qDebug() << "reloading due to 'autoReloadIfNeeded()'";
|
qCDebug(jellyfinApiModel) << "reloading due to 'autoReloadIfNeeded()'";
|
||||||
emit reloadWanted();
|
emit reloadWanted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,14 +59,14 @@ void BaseModelLoader::setApiClient(ApiClient *newApiClient) {
|
||||||
if (changed) {
|
if (changed) {
|
||||||
emit apiClientChanged(newApiClient);
|
emit apiClientChanged(newApiClient);
|
||||||
}
|
}
|
||||||
|
autoReloadIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseModelLoader::setLimit(int newLimit) {
|
void BaseModelLoader::setLimit(int newLimit) {
|
||||||
int oldLimit = this->m_limit;
|
m_explicitLimitSet = newLimit >= 0;
|
||||||
m_limit = newLimit;
|
qCDebug(jellyfinApiModel) << "Limit explicitly set to " << newLimit;
|
||||||
if (oldLimit != newLimit) {
|
this->m_limit = newLimit;
|
||||||
emit limitChanged(this->m_limit);
|
emit limitChanged(newLimit);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseModelLoader::setAutoReload(bool newAutoReload) {
|
void BaseModelLoader::setAutoReload(bool newAutoReload) {
|
||||||
|
@ -90,7 +92,7 @@ bool BaseModelLoader::canReload() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseApiModel::reload() {
|
void BaseApiModel::reload() {
|
||||||
qWarning() << " BaseApiModel slot called instead of overloaded method";
|
qCWarning(jellyfinApiModel) << " BaseApiModel slot called instead of overloaded method";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parameters injectors and result extractors
|
// Parameters injectors and result extractors
|
||||||
|
|
|
@ -75,6 +75,7 @@ void JellyfinPlugin::registerTypes(const char *uri) {
|
||||||
qmlRegisterType<ViewModel::ResumeItemsLoader>(uri, 1, 0, "ResumeItemsLoader");
|
qmlRegisterType<ViewModel::ResumeItemsLoader>(uri, 1, 0, "ResumeItemsLoader");
|
||||||
qmlRegisterType<ViewModel::ShowSeasonsLoader>(uri, 1, 0, "ShowSeasonsLoader");
|
qmlRegisterType<ViewModel::ShowSeasonsLoader>(uri, 1, 0, "ShowSeasonsLoader");
|
||||||
qmlRegisterType<ViewModel::ShowEpisodesLoader>(uri, 1, 0, "ShowEpisodesLoader");
|
qmlRegisterType<ViewModel::ShowEpisodesLoader>(uri, 1, 0, "ShowEpisodesLoader");
|
||||||
|
qmlRegisterType<ViewModel::NextUpLoader>(uri, 1, 0, "NextUpLoader");
|
||||||
qmlRegisterType<ViewModel::PublicUsersLoader>(uri, 1, 0, "PublicUsersLoader");
|
qmlRegisterType<ViewModel::PublicUsersLoader>(uri, 1, 0, "PublicUsersLoader");
|
||||||
|
|
||||||
// Enumerations
|
// Enumerations
|
||||||
|
|
|
@ -144,6 +144,14 @@ void Playlist::appendToList(ViewModel::ItemModel &model) {
|
||||||
reshuffle();
|
reshuffle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Playlist::appendToList(QSharedPointer<Model::Item> item) {
|
||||||
|
int start = m_list.size();
|
||||||
|
emit beforeItemsAddedToList(start, 1);
|
||||||
|
m_list.append(item);
|
||||||
|
emit itemsAddedToList();
|
||||||
|
reshuffle();
|
||||||
|
}
|
||||||
|
|
||||||
void Playlist::reshuffle() {
|
void Playlist::reshuffle() {
|
||||||
if (m_shuffler->canShuffleInAdvance()) {
|
if (m_shuffler->canShuffleInAdvance()) {
|
||||||
m_shuffler->shuffleInAdvance();
|
m_shuffler->shuffleInAdvance();
|
||||||
|
|
|
@ -54,6 +54,9 @@ ShowSeasonsLoader::ShowSeasonsLoader(QObject *parent)
|
||||||
ShowEpisodesLoader::ShowEpisodesLoader(QObject *parent)
|
ShowEpisodesLoader::ShowEpisodesLoader(QObject *parent)
|
||||||
: ShowEpisodesLoaderBase(new Jellyfin::Loader::HTTP::GetEpisodesLoader(), parent) {}
|
: ShowEpisodesLoaderBase(new Jellyfin::Loader::HTTP::GetEpisodesLoader(), parent) {}
|
||||||
|
|
||||||
|
NextUpLoader::NextUpLoader(QObject *parent)
|
||||||
|
: NextUpLoaderBase(new Jellyfin::Loader::HTTP::GetNextUpLoader(), parent) {}
|
||||||
|
|
||||||
ItemModel::ItemModel(QObject *parent)
|
ItemModel::ItemModel(QObject *parent)
|
||||||
: ApiModel<Model::Item>(parent) { }
|
: ApiModel<Model::Item>(parent) { }
|
||||||
|
|
||||||
|
@ -86,6 +89,7 @@ QVariant ItemModel::data(const QModelIndex &index, int role) const {
|
||||||
JF_CASE(artists)
|
JF_CASE(artists)
|
||||||
case RoleNames::isFolder:
|
case RoleNames::isFolder:
|
||||||
return QVariant(item->isFolder().value_or(false));
|
return QVariant(item->isFolder().value_or(false));
|
||||||
|
JF_CASE(overview)
|
||||||
case RoleNames::parentIndexNumber:
|
case RoleNames::parentIndexNumber:
|
||||||
return QVariant(item->parentIndexNumber().value_or(1));
|
return QVariant(item->parentIndexNumber().value_or(1));
|
||||||
// UserData
|
// UserData
|
||||||
|
|
|
@ -156,7 +156,9 @@ void PlaybackManager::mediaPlayerMediaStatusChanged(QMediaPlayer::MediaStatus ne
|
||||||
m_mediaPlayer->setPosition(m_resumePosition / MS_TICK_FACTOR);
|
m_mediaPlayer->setPosition(m_resumePosition / MS_TICK_FACTOR);
|
||||||
}
|
}
|
||||||
} else if (newStatus == QMediaPlayer::EndOfMedia) {
|
} else if (newStatus == QMediaPlayer::EndOfMedia) {
|
||||||
next();
|
if (m_queue->hasNext() && m_queue->totalSize() > 1) {
|
||||||
|
next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +180,8 @@ void PlaybackManager::updatePlaybackInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaybackManager::playItem(Item *item) {
|
void PlaybackManager::playItem(Item *item) {
|
||||||
|
m_queue->clearList();
|
||||||
|
m_queue->appendToList(item->data());
|
||||||
setItem(item->data());
|
setItem(item->data());
|
||||||
emit hasNextChanged(m_queue->hasNext());
|
emit hasNextChanged(m_queue->hasNext());
|
||||||
emit hasPreviousChanged(m_queue->hasPrevious());
|
emit hasPreviousChanged(m_queue->hasPrevious());
|
||||||
|
|
|
@ -38,9 +38,9 @@ set(sailfin_QML_SOURCES
|
||||||
qml/components/UserGridDelegate.qml
|
qml/components/UserGridDelegate.qml
|
||||||
qml/components/VideoPlayer.qml
|
qml/components/VideoPlayer.qml
|
||||||
qml/components/VideoTrackSelector.qml
|
qml/components/VideoTrackSelector.qml
|
||||||
qml/cover/CoverPage.qml
|
qml/cover/CollectionPage.qml
|
||||||
qml/cover/PosterCover.qml
|
qml/cover/PosterCover.qml
|
||||||
qml/cover/VideoCover.qml
|
qml/cover/NowPlayingCover.qml
|
||||||
qml/pages/LegalPage.qml
|
qml/pages/LegalPage.qml
|
||||||
qml/pages/MainPage.qml
|
qml/pages/MainPage.qml
|
||||||
qml/pages/AboutPage.qml
|
qml/pages/AboutPage.qml
|
||||||
|
|
|
@ -87,7 +87,7 @@ PanelBackground {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: playQueueShim
|
id: playQueueShim
|
||||||
anchors.fill: albumArt
|
anchors.fill: albumArt
|
||||||
color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityLow)
|
color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityOverlay)
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}
|
}
|
||||||
Loader {
|
Loader {
|
||||||
|
@ -159,6 +159,7 @@ PanelBackground {
|
||||||
}
|
}
|
||||||
icon.source: "image://theme/icon-m-shuffle"
|
icon.source: "image://theme/icon-m-shuffle"
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
enabled: false
|
||||||
onClicked: Notices.show(qsTr("Shuffle not yet implemented"))
|
onClicked: Notices.show(qsTr("Shuffle not yet implemented"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +331,7 @@ PanelBackground {
|
||||||
target: nextButton; opacity: 1; enabled: true;
|
target: nextButton; opacity: 1; enabled: true;
|
||||||
}
|
}
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: playModeButton; opacity: 1; //enabled: true;
|
target: playModeButton; opacity: 1; enabled: true;
|
||||||
}
|
}
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: queueButton; opacity: 1; enabled: true;
|
target: queueButton; opacity: 1; enabled: true;
|
||||||
|
|
|
@ -31,7 +31,7 @@ CoverBackground {
|
||||||
readonly property real rowHeight: height / 2
|
readonly property real rowHeight: height / 2
|
||||||
readonly property real bottomOffset: width - rowHeight
|
readonly property real bottomOffset: width - rowHeight
|
||||||
readonly property bool onMainScreen: appWindow.itemData === null
|
readonly property bool onMainScreen: appWindow.itemData === null
|
||||||
readonly property bool itemId: appWindow.itemData.jellyfinId || appWindow.pageStack.currentPage.itemId
|
readonly property string itemId: appWindow.pageStack.currentPage.itemId
|
||||||
readonly property bool hasParent: !appWindow.itemData !== null && appWindow.itemData.jellyfinId.length !== 0
|
readonly property bool hasParent: !appWindow.itemData !== null && appWindow.itemData.jellyfinId.length !== 0
|
||||||
|
|
||||||
J.ItemModel {
|
J.ItemModel {
|
||||||
|
@ -39,14 +39,14 @@ CoverBackground {
|
||||||
loader: J.UserItemsLoader {
|
loader: J.UserItemsLoader {
|
||||||
id: randomItemsLoader
|
id: randomItemsLoader
|
||||||
apiClient: appWindow.apiClient
|
apiClient: appWindow.apiClient
|
||||||
limit: cover.rowCount * 2
|
limit: cover.rowCount * 2 - 2
|
||||||
imageTypes: [J.ImageType.Primary]
|
imageTypes: [J.ImageType.Primary]
|
||||||
sortBy: "IsFavoriteOrLiked,Random"
|
sortBy: "IsFavoriteOrLiked,Random"
|
||||||
recursive: false
|
recursive: false
|
||||||
parentId: hasParent ? itemId : ""
|
parentId: itemId
|
||||||
autoReload: false
|
autoReload: false
|
||||||
onParentIdChanged: {
|
onParentIdChanged: {
|
||||||
if (parentId.length > 0) reload()
|
reload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,12 +82,15 @@ CoverBackground {
|
||||||
x: -rowHeight * rowOffset
|
x: -rowHeight * rowOffset
|
||||||
y: rowHeight * 0.5
|
y: rowHeight * 0.5
|
||||||
}
|
}
|
||||||
|
PathPercent {
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delegate: RemoteImage {
|
delegate: RemoteImage {
|
||||||
height: rowHeight
|
height: rowHeight
|
||||||
width: height
|
width: height
|
||||||
source: model.jellyfinId
|
source: model.jellyfinId
|
||||||
? Utils.itemModelImageUrl(appWindow.apiClient.baseUrl, model.jellyfinId, model.imageTags["Primary"], "Primary", {"maxHeight": row1.height})
|
? Utils.itemModelImageUrl(appWindow.apiClient.baseUrl, model.jellyfinId, model.imageTags["Primary"], "Primary", {"maxHeight": rowHeight})
|
||||||
: ""
|
: ""
|
||||||
blurhash: model.jellyfinId
|
blurhash: model.jellyfinId
|
||||||
? model.imageBlurHashes["Primary"][model.imageTags["Primary"]]
|
? model.imageBlurHashes["Primary"][model.imageTags["Primary"]]
|
||||||
|
@ -96,14 +99,18 @@ CoverBackground {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
/*Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityHigh)
|
color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityHigh)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
opacity: randomItemsLoader.status === J.ModelStatus.Ready ? 0.0 : 1.0
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation {}
|
||||||
|
}
|
||||||
Image {
|
Image {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
source: Qt.resolvedUrl("../icon.png")
|
source: Qt.resolvedUrl("../icon.png")
|
||||||
|
@ -122,13 +129,12 @@ CoverBackground {
|
||||||
target: appWindow.pageStack
|
target: appWindow.pageStack
|
||||||
onCurrentPageChanged: {
|
onCurrentPageChanged: {
|
||||||
console.log("Reloading cover collection")
|
console.log("Reloading cover collection")
|
||||||
/*randomItems1Loader.parentId = Qt.binding(function() { return onMainScreen ? "" : appWindow.itemData.jellyfinId; })
|
|
||||||
randomItems2Loader.parentId = Qt.binding(function() { return onMainScreen ? "" : appWindow.itemData.jellyfinId; })*/
|
|
||||||
//randomItems1.reload()
|
|
||||||
//randomItems2.reload()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Component.onCompleted: randomItems.reload()
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
running: true
|
running: true
|
||||||
interval: 5000
|
interval: 5000
|
|
@ -28,19 +28,6 @@ import "../components"
|
||||||
PosterCover {
|
PosterCover {
|
||||||
readonly property var player: appWindow.playbackManager
|
readonly property var player: appWindow.playbackManager
|
||||||
|
|
||||||
// Wanted to display the currently running move on here, but it's hard :/
|
|
||||||
/*Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "black"
|
|
||||||
|
|
||||||
VideoOutput {
|
|
||||||
id: coverOutput
|
|
||||||
anchors.fill: parent
|
|
||||||
source: player
|
|
||||||
}
|
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
Shim {
|
Shim {
|
||||||
anchors {
|
anchors {
|
||||||
left: parent.left
|
left: parent.left
|
||||||
|
@ -51,8 +38,27 @@ PosterCover {
|
||||||
}
|
}
|
||||||
|
|
||||||
CoverActionList {
|
CoverActionList {
|
||||||
|
enabled: player.hasNext
|
||||||
|
CoverAction {
|
||||||
|
iconSource: player.playbackState === MediaPlayer.PlayingState ? "image://theme/icon-cover-pause"
|
||||||
|
: "image://theme/icon-cover-play"
|
||||||
|
onTriggered: {
|
||||||
|
if (player.playbackState === MediaPlayer.PlayingState) {
|
||||||
|
player.pause()
|
||||||
|
} else {
|
||||||
|
player.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CoverAction {
|
||||||
|
iconSource: "image://theme/icon-cover-next-song"
|
||||||
|
onTriggered: player.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CoverActionList {
|
||||||
|
enabled: !player.hasNext
|
||||||
CoverAction {
|
CoverAction {
|
||||||
id: playPause
|
|
||||||
iconSource: player.playbackState === MediaPlayer.PlayingState ? "image://theme/icon-cover-pause"
|
iconSource: player.playbackState === MediaPlayer.PlayingState ? "image://theme/icon-cover-pause"
|
||||||
: "image://theme/icon-cover-play"
|
: "image://theme/icon-cover-play"
|
||||||
onTriggered: {
|
onTriggered: {
|
|
@ -27,7 +27,7 @@ import ".."
|
||||||
|
|
||||||
CoverBackground {
|
CoverBackground {
|
||||||
// Due QTBUG-10822, declarartions such as `property J.Item foo` are not possible.
|
// Due QTBUG-10822, declarartions such as `property J.Item foo` are not possible.
|
||||||
property var mData: appWindow.itemData
|
property var mData: appWindow.playbackManager.item
|
||||||
RemoteImage {
|
RemoteImage {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: mData === null ? "" : Utils.itemImageUrl(appWindow.apiClient.baseUrl, mData, "Primary", {"maxWidth": parent.width})
|
source: mData === null ? "" : Utils.itemImageUrl(appWindow.apiClient.baseUrl, mData, "Primary", {"maxWidth": parent.width})
|
||||||
|
@ -78,7 +78,7 @@ CoverBackground {
|
||||||
Label {
|
Label {
|
||||||
visible: typeof mData.runTimeTicks !== "undefined"
|
visible: typeof mData.runTimeTicks !== "undefined"
|
||||||
color: Theme.secondaryColor
|
color: Theme.secondaryColor
|
||||||
text: Utils.ticksToText(mData.runTimeTicks)
|
text: qsTr("%1/%2").arg(Utils.timeToText(appWindow.playbackManager.position)).arg(Utils.ticksToText(mData.runTimeTicks))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,11 +81,9 @@ ApplicationWindow {
|
||||||
cover: {
|
cover: {
|
||||||
// Disabled due to buggy Loader behaviour
|
// Disabled due to buggy Loader behaviour
|
||||||
if ([MediaPlayer.NoMedia, MediaPlayer.InvalidMedia, MediaPlayer.UnknownStatus].indexOf(_playbackManager.mediaStatus) >= 0) {
|
if ([MediaPlayer.NoMedia, MediaPlayer.InvalidMedia, MediaPlayer.UnknownStatus].indexOf(_playbackManager.mediaStatus) >= 0) {
|
||||||
return Qt.resolvedUrl("cover/CoverPage.qml")
|
return Qt.resolvedUrl("cover/CollectionPage.qml")
|
||||||
} else if (playbackManager.hasVideo){
|
|
||||||
return Qt.resolvedUrl("cover/VideoCover.qml")
|
|
||||||
} else {
|
} else {
|
||||||
return Qt.resolvedUrl("cover/CoverPage.qml")
|
return Qt.resolvedUrl("cover/NowPlayingCover.qml")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ import "../"
|
||||||
Page {
|
Page {
|
||||||
/// True if the models on this page already have been loaded and don't necessarily need a refresh
|
/// True if the models on this page already have been loaded and don't necessarily need a refresh
|
||||||
property bool _modelsLoaded: false
|
property bool _modelsLoaded: false
|
||||||
|
// Only for cover page
|
||||||
|
readonly property string itemId: ""
|
||||||
|
|
||||||
id: mainPage
|
id: mainPage
|
||||||
allowedOrientations: Orientation.All
|
allowedOrientations: Orientation.All
|
||||||
|
@ -48,7 +50,7 @@ Page {
|
||||||
text: qsTr("Reload")
|
text: qsTr("Reload")
|
||||||
onClicked: loadModels(true)
|
onClicked: loadModels(true)
|
||||||
}
|
}
|
||||||
busy: mediaLibraryLoader.status === J.UsersViewsLoader.Loading
|
busy: mediaLibraryLoader.status === J.ModelStatus.Loading
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +82,7 @@ Page {
|
||||||
//- Section header for films and TV shows that an user hasn't completed yet.
|
//- Section header for films and TV shows that an user hasn't completed yet.
|
||||||
text: qsTr("Resume watching")
|
text: qsTr("Resume watching")
|
||||||
clickable: false
|
clickable: false
|
||||||
busy: userResumeLoader.status === J.UsersViewsLoader.Loading
|
busy: userResumeLoader.status === J.ModelStatus.Loading
|
||||||
Loader {
|
Loader {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
sourceComponent: carrouselView
|
sourceComponent: carrouselView
|
||||||
|
@ -102,7 +104,7 @@ Page {
|
||||||
//- Section header for next episodes in a TV show that an user was watching.
|
//- Section header for next episodes in a TV show that an user was watching.
|
||||||
text: qsTr("Next up")
|
text: qsTr("Next up")
|
||||||
clickable: false
|
clickable: false
|
||||||
//busy: showNextUpModel.status === .Loading
|
busy: showNextUpLoader.status === J.ModelStatus.Loading
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
@ -112,8 +114,11 @@ Page {
|
||||||
|
|
||||||
J.ItemModel {
|
J.ItemModel {
|
||||||
id: showNextUpModel
|
id: showNextUpModel
|
||||||
/*apiClient: appWindow.apiClient
|
loader: J.NextUpLoader {
|
||||||
limit: 12*/
|
id: showNextUpLoader
|
||||||
|
apiClient: appWindow.apiClient
|
||||||
|
enableUserData: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ Page {
|
||||||
if (status === PageStatus.Active) {
|
if (status === PageStatus.Active) {
|
||||||
console.log("Page ready, ItemID: ", itemId, ", UserID: ", apiClient.userId)
|
console.log("Page ready, ItemID: ", itemId, ", UserID: ", apiClient.userId)
|
||||||
jItemLoader.autoReload = true
|
jItemLoader.autoReload = true
|
||||||
//appWindow.itemData = jItemLoader.data
|
appWindow.itemData = Qt.binding(function() { return jItemLoader.data; })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue