mirror of
https://github.com/HenkKalkwater/harbour-sailfin.git
synced 2025-09-05 10:12:46 +00:00
WIP: Add playlists/queues and add support for Sailfish back
This commit is contained in:
parent
fbc154fb56
commit
86672be051
89 changed files with 1637 additions and 849 deletions
|
@ -19,9 +19,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../components"
|
||||
import ".."
|
||||
|
||||
Page {
|
||||
id: page
|
||||
|
|
|
@ -19,7 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import QtQuick 2.0
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../components"
|
||||
import "../"
|
||||
|
@ -32,7 +32,7 @@ Page {
|
|||
/// True if the models on this page already have been loaded and don't necessarily need a refresh
|
||||
property bool _modelsLoaded: false
|
||||
|
||||
id: page
|
||||
id: mainPage
|
||||
allowedOrientations: Orientation.All
|
||||
|
||||
// This component is reused both in the normal state and error state
|
||||
|
@ -49,7 +49,7 @@ Page {
|
|||
text: qsTr("Reload")
|
||||
onClicked: loadModels(true)
|
||||
}
|
||||
busy: mediaLibraryModel.status == ApiModel.Loading
|
||||
busy: userViewsLoader.status === J.UsersViewsLoader.Loading
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,29 +67,33 @@ Page {
|
|||
// of the page, followed by our content.
|
||||
Column {
|
||||
id: column
|
||||
width: page.width
|
||||
width: mainPage.width
|
||||
|
||||
UserViewModel {
|
||||
id: mediaLibraryModel2
|
||||
apiClient: ApiClient
|
||||
J.ItemModel {
|
||||
id: mediaLibraryModel
|
||||
loader: J.UsersViewsLoader {
|
||||
id: mediaLibraryLoader
|
||||
apiClient: ApiClient
|
||||
}
|
||||
}
|
||||
|
||||
MoreSection {
|
||||
//- Section header for films and TV shows that an user hasn't completed yet.
|
||||
text: qsTr("Resume watching")
|
||||
clickable: false
|
||||
busy: userResumeModel.status === ApiModel.Loading
|
||||
//busy: userResumeModel.status === J.ApiModel.Loading
|
||||
Loader {
|
||||
width: parent.width
|
||||
sourceComponent: carrouselView
|
||||
property alias itemModel: userResumeModel
|
||||
property string collectionType: "series"
|
||||
|
||||
UserItemResumeModel {
|
||||
J.ItemModel {
|
||||
id: userResumeModel
|
||||
apiClient: ApiClient
|
||||
// Resume model
|
||||
/*apiClient: ApiClient
|
||||
limit: 12
|
||||
recursive: true
|
||||
recursive: true*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +101,7 @@ Page {
|
|||
//- Section header for next episodes in a TV show that an user was watching.
|
||||
text: qsTr("Next up")
|
||||
clickable: false
|
||||
busy: showNextUpModel.status === ApiModel.Loading
|
||||
//busy: showNextUpModel.status === .Loading
|
||||
|
||||
Loader {
|
||||
width: parent.width
|
||||
|
@ -105,23 +109,18 @@ Page {
|
|||
property alias itemModel: showNextUpModel
|
||||
property string collectionType: "series"
|
||||
|
||||
ShowNextUpModel {
|
||||
J.ItemModel {
|
||||
id: showNextUpModel
|
||||
apiClient: ApiClient
|
||||
limit: 12
|
||||
/*apiClient: ApiClient
|
||||
limit: 12*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UserViewModel {
|
||||
id: mediaLibraryModel
|
||||
apiClient: ApiClient
|
||||
}
|
||||
Repeater {
|
||||
model: mediaLibraryModel
|
||||
MoreSection {
|
||||
text: model.name
|
||||
busy: userItemModel.status !== ApiModel.Ready
|
||||
busy: userItemModel.status !== J.UsersViewsLoader.Ready
|
||||
|
||||
onHeaderClicked: pageStack.push(Qt.resolvedUrl("itemdetails/CollectionPage.qml"), {"itemId": model.jellyfinId})
|
||||
Loader {
|
||||
|
@ -130,11 +129,12 @@ Page {
|
|||
property alias itemModel: userItemModel
|
||||
property string collectionType: model.collectionType || ""
|
||||
|
||||
UserItemLatestModel {
|
||||
J.ItemModel {
|
||||
id: userItemModel
|
||||
apiClient: ApiClient
|
||||
parentId: jellyfinId
|
||||
limit: 16
|
||||
loader: J.LatestMediaLoader {
|
||||
apiClient: ApiClient
|
||||
parentId: jellyfinId
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: mediaLibraryModel
|
||||
|
@ -184,8 +184,8 @@ Page {
|
|||
if (force || (ApiClient.authenticated && !_modelsLoaded)) {
|
||||
_modelsLoaded = true;
|
||||
mediaLibraryModel.reload()
|
||||
userResumeModel.reload()
|
||||
showNextUpModel.reload()
|
||||
//userResumeModel.reload()
|
||||
//showNextUpModel.reload()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,11 +236,11 @@ Page {
|
|||
states: [
|
||||
State {
|
||||
name: "default"
|
||||
when: mediaLibraryModel2.status !== ApiModel.Error
|
||||
when: mediaLibraryLoader.status !== J.UsersViewsLoader.Error
|
||||
},
|
||||
State {
|
||||
name: "error"
|
||||
when: mediaLibraryModel2.status === ApiModel.Error
|
||||
when: mediaLibraryLoader.status === J.UsersViewsLoader.Error
|
||||
|
||||
PropertyChanges {
|
||||
target: errorFlickable
|
||||
|
|
|
@ -19,7 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../components"
|
||||
|
||||
|
@ -57,9 +57,9 @@ Page {
|
|||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
height: user.implicitHeight + server.implicitHeight + Theme.paddingMedium
|
||||
User {
|
||||
QtObject {
|
||||
id: loggedInUser
|
||||
apiClient: ApiClient
|
||||
//apiClient: ApiClient
|
||||
}
|
||||
RemoteImage {
|
||||
id: userIcon
|
||||
|
|
|
@ -19,7 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../../components"
|
||||
import "../.."
|
||||
|
@ -32,14 +32,14 @@ import "../.."
|
|||
*/
|
||||
Page {
|
||||
id: pageRoot
|
||||
property alias itemId: jItem.jellyfinId
|
||||
property alias itemData: jItem
|
||||
property string itemId: ""
|
||||
property alias itemData: jItemLoader.data
|
||||
//property string itemId: ""
|
||||
//property var itemData: ({})
|
||||
property bool _loading: jItem.status === "Loading"
|
||||
readonly property bool hasLogo: (typeof itemData.ImageTags !== "undefined") && (typeof itemData.ImageTags["Logo"] !== "undefined")
|
||||
property bool _loading: jItemLoader.status === J.ItemLoader.Loading
|
||||
readonly property bool hasLogo: (typeof itemData.imageTags !== "undefined") && (typeof itemData.imageTags["Logo"] !== "undefined")
|
||||
property string _chosenBackdropImage: ""
|
||||
readonly property string parentId: itemData.ParentId || ""
|
||||
readonly property string parentId: itemData.parentId || ""
|
||||
|
||||
function updateBackdrop() {
|
||||
var rand = 0;
|
||||
|
@ -62,13 +62,13 @@ Page {
|
|||
SilicaFlickable {
|
||||
anchors.fill: parent
|
||||
contentHeight: errorContent.height
|
||||
visible: jItem.status == JellyfinItem.Error
|
||||
visible: jItemLoader.status === J.ItemLoader.Error
|
||||
|
||||
PullDownMenu {
|
||||
busy: jItem.status == JellyfinItem.Loading
|
||||
busy: jItemLoader.status === J.ItemLoader.Loading
|
||||
MenuItem {
|
||||
text: qsTr("Retry")
|
||||
onClicked: jItem.reload()
|
||||
onClicked: jItemLoader.reload()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,28 +79,33 @@ Page {
|
|||
ViewPlaceholder {
|
||||
enabled: true
|
||||
text: qsTr("An error has occured")
|
||||
hintText: jItem.errorString
|
||||
hintText: jItemLoader.errorString
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JellyfinItem {
|
||||
id: jItem
|
||||
J.ItemLoader {
|
||||
id: jItemLoader
|
||||
apiClient: ApiClient
|
||||
itemId: pageRoot.itemId
|
||||
onStatusChanged: {
|
||||
//console.log("Status changed: " + newStatus, JSON.stringify(jItem))
|
||||
if (status == JellyfinItem.Ready) {
|
||||
console.log("Status changed: " + newStatus, JSON.stringify(jItemLoader.data))
|
||||
if (status === J.ItemLoader.Ready) {
|
||||
updateBackdrop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: "ItemLoader status=%1, \nitemId=%2\nitemData=%3".arg(jItemLoader.status).arg(jItemLoader.itemId).arg(jItemLoader.data)
|
||||
}
|
||||
|
||||
onStatusChanged: {
|
||||
if (status == PageStatus.Deactivating) {
|
||||
//appWindow.itemData = ({})
|
||||
}
|
||||
if (status == PageStatus.Active) {
|
||||
appWindow.itemData = jItem
|
||||
//appWindow.itemData = jItemLoader.data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../.."
|
||||
import "../../components"
|
||||
|
@ -27,12 +27,13 @@ import "../../components"
|
|||
BaseDetailPage {
|
||||
id: pageRoot
|
||||
|
||||
UserItemModel {
|
||||
J.ItemModel {
|
||||
id: collectionModel
|
||||
apiClient: ApiClient
|
||||
parentId: itemData.jellyfinId
|
||||
sortBy: ["SortName"]
|
||||
onParentIdChanged: reload()
|
||||
//sortBy: ["SortName"]
|
||||
loader: J.UserItemsLoader {
|
||||
apiClient: ApiClient
|
||||
parentId: itemData.jellyfinId
|
||||
}
|
||||
}
|
||||
|
||||
SilicaGridView {
|
||||
|
@ -42,7 +43,7 @@ BaseDetailPage {
|
|||
cellWidth: Constants.libraryDelegateWidth
|
||||
cellHeight: Utils.usePortraitCover(itemData.collectionType) ? Constants.libraryDelegatePosterHeight
|
||||
: Constants.libraryDelegateHeight
|
||||
visible: itemData.status !== JellyfinItem.Error
|
||||
visible: itemData.status !== J.ItemLoader.Error
|
||||
|
||||
header: PageHeader {
|
||||
title: itemData.name || qsTr("Loading")
|
||||
|
@ -54,7 +55,7 @@ BaseDetailPage {
|
|||
text: qsTr("Sort by")
|
||||
onClicked: pageStack.push(sortPageComponent)
|
||||
}
|
||||
busy: collectionModel.status === ApiModel.Loading
|
||||
busy: collectionModel.status === J.UserItemsLoader.Loading
|
||||
}
|
||||
delegate: GridItem {
|
||||
RemoteImage {
|
||||
|
|
|
@ -20,7 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../../components"
|
||||
import "../.."
|
||||
|
|
|
@ -20,7 +20,7 @@ import QtQuick 2.6
|
|||
import Sailfish.Silica 1.0
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../../components"
|
||||
import "../../components/music"
|
||||
|
@ -33,13 +33,15 @@ BaseDetailPage {
|
|||
|
||||
readonly property bool _twoColumns: albumPageRoot.width / Theme.pixelRatio >= 800
|
||||
|
||||
UserItemModel {
|
||||
J.ItemModel {
|
||||
id: collectionModel
|
||||
apiClient: ApiClient
|
||||
sortBy: ["SortName"]
|
||||
fields: ["ItemCounts","PrimaryImageAspectRatio","BasicSyncInfo","CanDelete","MediaSourceCount"]
|
||||
parentId: itemData.jellyfinId
|
||||
onParentIdChanged: reload()
|
||||
loader: J.UserItemsLoader {
|
||||
apiClient: ApiClient
|
||||
//sortBy: ["SortName"]
|
||||
//fields: ["ItemCounts","PrimaryImageAspectRatio","BasicSyncInfo","CanDelete","MediaSourceCount"]
|
||||
parentId: itemData.jellyfinId
|
||||
onParentIdChanged: reload()
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
@ -50,9 +52,9 @@ BaseDetailPage {
|
|||
visible: _twoColumns
|
||||
Layout.minimumWidth: 1000 / Theme.pixelRatio
|
||||
Layout.fillHeight: true
|
||||
source: visible
|
||||
/*source: visible
|
||||
? "../../components/music/WideAlbumCover.qml" : ""
|
||||
onLoaded: bindAlbum(item)
|
||||
onLoaded: bindAlbum(item)*/
|
||||
}
|
||||
Item {height: 1; width: Theme.horizontalPageMargin; visible: wideAlbumCover.visible; }
|
||||
SilicaListView {
|
||||
|
@ -62,8 +64,8 @@ BaseDetailPage {
|
|||
model: collectionModel
|
||||
header: Loader {
|
||||
width: parent.width
|
||||
source: "../../components/music/NarrowAlbumCover.qml"
|
||||
onLoaded: bindAlbum(item)
|
||||
/*source: "../../components/music/NarrowAlbumCover.qml"
|
||||
onLoaded: bindAlbum(item)*/
|
||||
}
|
||||
section {
|
||||
property: "parentIndexNumber"
|
||||
|
@ -84,14 +86,8 @@ BaseDetailPage {
|
|||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: itemData
|
||||
onAlbumArtistsChanged: {
|
||||
}
|
||||
}
|
||||
|
||||
function bindAlbum(item) {
|
||||
item.albumArt = Qt.binding(function(){ return Utils.itemImageUrl(ApiClient.baseUrl, itemData, "Primary", {"maxWidth": parent.width})})
|
||||
//item.albumArt = Qt.binding(function(){ return Utils.itemImageUrl(ApiClient.baseUrl, itemData, "Primary", {"maxWidth": parent.width})})
|
||||
item.name = Qt.binding(function(){ return itemData.name})
|
||||
item.releaseYear = Qt.binding(function() { return itemData.productionYear})
|
||||
item.albumArtist = Qt.binding(function() { return itemData.albumArtist})
|
||||
|
|
|
@ -20,7 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../../components"
|
||||
import "../.."
|
||||
|
@ -33,11 +33,11 @@ BaseDetailPage {
|
|||
property alias subtitle: pageHeader.description
|
||||
default property alias _data: content.data
|
||||
property real _playbackProsition: itemData.userData.playbackPositionTicks
|
||||
readonly property bool _userdataReady: itemData.status == JellyfinItem.Ready && itemData.userData != null
|
||||
readonly property bool _userdataReady: itemData.status === J.ItemLoader.Ready && itemData.userData !== null
|
||||
SilicaFlickable {
|
||||
anchors.fill: parent
|
||||
contentHeight: content.height + Theme.paddingLarge
|
||||
visible: itemData.status !== JellyfinItem.Error
|
||||
visible: itemData.status !== J.ItemLoader.Error
|
||||
|
||||
VerticalScrollDecorator {}
|
||||
|
||||
|
@ -84,7 +84,7 @@ BaseDetailPage {
|
|||
Connections {
|
||||
target: itemData
|
||||
onStatusChanged: {
|
||||
if (status == JellyfinItem.Ready) {
|
||||
if (status === J.ItemLoader.Ready) {
|
||||
console.log(itemData.mediaStreams)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../../components"
|
||||
import "../.."
|
||||
|
||||
Page {
|
||||
id: page
|
||||
|
@ -53,7 +54,7 @@ Page {
|
|||
label: qsTr("Connection state")
|
||||
value: {
|
||||
var stateText
|
||||
switch( ApiClient.websocket.state) {
|
||||
switch(ApiClient.websocket.state) {
|
||||
case 0:
|
||||
//- Socket state
|
||||
stateText = qsTr("Unconnected");
|
||||
|
|
|
@ -18,7 +18,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../.."
|
||||
|
||||
/**
|
||||
* Page to indicate that the application is connecting to a server.
|
||||
|
|
|
@ -18,7 +18,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../../"
|
||||
|
||||
/**
|
||||
* Dialog showed when the user has to connect to a Jellyfin server.
|
||||
|
@ -49,7 +51,7 @@ Dialog {
|
|||
title: qsTr("Connect to Jellyfin")
|
||||
}
|
||||
|
||||
ServerDiscoveryModel {
|
||||
J.ServerDiscoveryModel {
|
||||
id: serverModel
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0
|
||||
import nl.netsoj.chris.Jellyfin 1.0 as J
|
||||
|
||||
import "../../components"
|
||||
import "../../"
|
||||
|
||||
/**
|
||||
* Page where the user can login on their server. Is displayed after the AddServerPage successfully connected
|
||||
|
@ -31,7 +32,7 @@ Dialog {
|
|||
id: loginDialog
|
||||
property string loginMessage
|
||||
property Page firstPage
|
||||
property User selectedUser: null
|
||||
property QtObject /*User*/ selectedUser: null
|
||||
|
||||
property string error
|
||||
|
||||
|
@ -65,11 +66,13 @@ Dialog {
|
|||
}
|
||||
}
|
||||
|
||||
PublicUserModel {
|
||||
QtObject { id: userModel; }
|
||||
|
||||
/*PublicUserModel {
|
||||
id: userModel
|
||||
apiClient: ApiClient
|
||||
Component.onCompleted: reload();
|
||||
}
|
||||
}*/
|
||||
|
||||
DialogHeader {
|
||||
id: dialogHeader
|
||||
|
@ -97,7 +100,7 @@ Dialog {
|
|||
width: parent.width
|
||||
Repeater {
|
||||
id: userRepeater
|
||||
model: userModel
|
||||
model: 0 //userModel
|
||||
delegate: UserGridDelegate {
|
||||
name: model.name
|
||||
image: model.primaryImageTag ? "%1/Users/%2/Images/Primary?tag=%3".arg(ApiClient.baseUrl).arg(model.jellyfinId).arg(model.primaryImageTag) : ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue