diff --git a/harbour-sailfin.pro b/harbour-sailfin.pro
index 0187e82..a665637 100644
--- a/harbour-sailfin.pro
+++ b/harbour-sailfin.pro
@@ -41,31 +41,32 @@ DISTFILES += \
qml/components/LibraryItemDelegate.qml \
qml/components/MoreSection.qml \
qml/components/PlainLabel.qml \
+ qml/components/PlayToolbar.qml \
qml/components/RemoteImage.qml \
qml/components/Shim.qml \
qml/components/UserGridDelegate.qml \
qml/components/VideoPlayer.qml \
- qml/components/itemdetails/CollectionFolder.qml \
- qml/components/itemdetails/EpisodeDetails.qml \
- qml/components/itemdetails/FilmDetails.qml \
- qml/components/itemdetails/PlayToolbar.qml \
+ qml/components/VideoTrackSelector.qml \
qml/components/itemdetails/SeasonDetails.qml \
- qml/components/itemdetails/SeriesDetails.qml \
- qml/components/itemdetails/UnsupportedDetails.qml \
- qml/components/itemdetails/VideoTrackSelector.qml \
qml/components/videoplayer/VideoError.qml \
qml/components/videoplayer/VideoHud.qml \
qml/cover/CoverPage.qml \
qml/cover/PosterCover.qml \
qml/cover/VideoCover.qml \
- qml/pages/CollectionPage.qml \
- qml/pages/DetailPage.qml \
qml/pages/LegalPage.qml \
qml/pages/MainPage.qml \
qml/pages/AboutPage.qml \
qml/harbour-sailfin.qml \
qml/pages/SettingsPage.qml \
qml/pages/VideoPage.qml \
+ qml/pages/itemdetails/BaseDetailPage.qml \
+ qml/pages/itemdetails/CollectionPage.qml \
+ qml/pages/itemdetails/EpisodePage.qml \
+ qml/pages/itemdetails/FilmPage.qml \
+ qml/pages/itemdetails/MusicAlbumPage.qml \
+ qml/pages/itemdetails/SeasonPage.qml \
+ qml/pages/itemdetails/SeriesPage.qml \
+ qml/pages/itemdetails/UnsupportedPage.qml \
qml/pages/setup/AddServerConnectingPage.qml \
qml/pages/setup/LoginDialog.qml \
qml/qmldir
diff --git a/qml/Utils.js b/qml/Utils.js
index 4f67621..efbe310 100644
--- a/qml/Utils.js
+++ b/qml/Utils.js
@@ -40,7 +40,7 @@ function ticksToText(ticks) {
function itemImageUrl(baseUrl, item, type, options) {
if (!item.ImageTags[type]) { return "" }
return itemModelImageUrl(baseUrl, item.Id, item.ImageTags[type], type, options)
- }
+}
function itemModelImageUrl(baseUrl, itemId, tag, type, options) {
if (tag == undefined) return ""
@@ -56,3 +56,23 @@ function itemModelImageUrl(baseUrl, itemId, tag, type, options) {
function usePortraitCover(itemType) {
return ["Series", "Movie", "tvshows", "movies"].indexOf(itemType) >= 0
}
+
+/**
+ * Returns the page url for a certain item type.
+ */
+function getPageUrl(itemType) {
+ switch (itemType.toLowerCase()) {
+ case "series":
+ return Qt.resolvedUrl("pages/itemdetails/SeriesPage.qml")
+ case "movie":
+ return Qt.resolvedUrl("pages/itemdetails/FilmPage.qml")
+ case "collection":
+ return Qt.resolvedUrl("pages/itemdetails/ColectionPage.qml")
+ case "season":
+ return Qt.resolvedUrl("pages/itemdetails/SeasonPage.qml")
+ case "episode":
+ return Qt.resolvedUrl("pages/itemdetails/EpisodePage.qml")
+ default:
+ return Qt.resolvedUrl("pages/itemdetails/UnsupportedPage.qml")
+ }
+}
diff --git a/qml/components/PlayToolbar.qml b/qml/components/PlayToolbar.qml
new file mode 100644
index 0000000..d1b6e1f
--- /dev/null
+++ b/qml/components/PlayToolbar.qml
@@ -0,0 +1,61 @@
+/*
+Sailfin: a Jellyfin client written using Qt
+Copyright (C) 2020 Chris Josten
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+import QtQuick 2.6
+import Sailfish.Silica 1.0
+
+Column {
+ property alias imageSource : playImage.source
+ property real imageAspectRatio: 1.0
+ signal playPressed()
+ spacing: Theme.paddingLarge
+
+ BackgroundItem {
+ width: parent.width
+ height: width / imageAspectRatio
+ HighlightImage {
+ id: playImage
+ anchors.fill: parent
+ fillMode: Image.PreserveAspectCrop
+ color: Theme.overlayBackgroundColor
+ clip: true
+ }
+ Icon {
+ id: playButton
+ source: "image://theme/icon-l-play"
+ anchors.centerIn: parent
+ highlighted: parent.highlighted
+ }
+ onClicked: playPressed()
+ }
+ Row {
+ anchors {
+ //left: parent.left
+ right: parent.right
+ leftMargin: Theme.horizontalPageMargin
+ rightMargin: Theme.horizontalPageMargin
+ }
+ spacing: Theme.paddingMedium
+ IconButton {
+ id: favouriteButton
+ icon.source: "image://theme/icon-m-favorite"
+ }
+
+ }
+}
diff --git a/qml/components/itemdetails/VideoTrackSelector.qml b/qml/components/VideoTrackSelector.qml
similarity index 100%
rename from qml/components/itemdetails/VideoTrackSelector.qml
rename to qml/components/VideoTrackSelector.qml
diff --git a/qml/components/itemdetails/CollectionFolder.qml b/qml/components/itemdetails/CollectionFolder.qml
deleted file mode 100644
index 4f0aa37..0000000
--- a/qml/components/itemdetails/CollectionFolder.qml
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-Sailfin: a Jellyfin client written using Qt
-Copyright (C) 2020 Chris Josten
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-import QtQuick 2.6
-
-Item {
-
-}
diff --git a/qml/components/itemdetails/EpisodeDetails.qml b/qml/components/itemdetails/EpisodeDetails.qml
deleted file mode 100644
index 8331545..0000000
--- a/qml/components/itemdetails/EpisodeDetails.qml
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-Sailfin: a Jellyfin client written using Qt
-Copyright (C) 2020 Chris Josten
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-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 ".."
-import "../../Utils.js" as Utils
-
-Column {
- property var itemData
- spacing: Theme.paddingMedium
-
- PlayToolbar {
- onPlayPressed: pageStack.push(Qt.resolvedUrl("../../pages/VideoPage.qml"),
- {"itemId": itemId, "itemData": itemData, "audioTrack": trackSelector.audioTrack,
- "subtitleTrack": trackSelector.subtitleTrack })
- }
-
- VideoTrackSelector {
- id: trackSelector
- width: parent.width
- tracks: itemData.MediaStreams
- }
-
- PlainLabel {
- id: tinyDetails
- text: {
- if (typeof itemData.IndexNumberEnd !== "undefined") {
- qsTr("Episode %1–%2 Season %3").arg(itemData.IndexNumber)
- .arg(itemData.IndexNumberEnd)
- .arg(itemData.ParentIndexNumber)
- } else {
- qsTr("Episode %1 Season %2").arg(itemData.IndexNumber).arg(itemData.ParentIndexNumber)
- }
- }
- }
-
- PlainLabel {
- id: overviewText
- text: itemData.Overview
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.secondaryHighlightColor
- }
-}
diff --git a/qml/components/itemdetails/FilmDetails.qml b/qml/components/itemdetails/FilmDetails.qml
deleted file mode 100644
index bc4850a..0000000
--- a/qml/components/itemdetails/FilmDetails.qml
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-Sailfin: a Jellyfin client written using Qt
-Copyright (C) 2020 Chris Josten
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-import QtQuick 2.6
-import Sailfish.Silica 1.0
-
-import "../"
-import "../../Utils.js" as Utils
-
-Column {
- property var itemData
- spacing: Theme.paddingMedium
-
- PlayToolbar {
- onPlayPressed: pageStack.push(Qt.resolvedUrl("../../pages/VideoPage.qml"),
- {"itemId": itemId, "itemData": itemData, "audioTrack": trackSelector.audioTrack,
- "subtitleTrack": trackSelector.subtitleTrack })
- }
-
- VideoTrackSelector {
- id: trackSelector
- width: parent.width
- tracks: itemData.MediaStreams
- }
-
- PlainLabel {
- id: tinyDetails
- text: qsTr("Released: %1 — Run time: %2").arg(itemData.ProductionYear).arg(Utils.ticksToText(itemData.RunTimeTicks))
- }
-
- PlainLabel {
- id: overviewText
- text: itemData.Overview
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.secondaryHighlightColor
- }
-}
diff --git a/qml/components/itemdetails/PlayToolbar.qml b/qml/components/itemdetails/PlayToolbar.qml
deleted file mode 100644
index 7262294..0000000
--- a/qml/components/itemdetails/PlayToolbar.qml
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Sailfin: a Jellyfin client written using Qt
-Copyright (C) 2020 Chris Josten
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-import QtQuick 2.6
-import Sailfish.Silica 1.0
-
-Row {
- signal playPressed()
-
- anchors {
- //left: parent.left
- right: parent.right
- leftMargin: Theme.horizontalPageMargin
- rightMargin: Theme.horizontalPageMargin
- }
- spacing: Theme.paddingMedium
- IconButton {
- id: favouriteButton
- icon.source: "image://theme/icon-m-favorite"
- }
- IconButton {
- id: playButton
- icon.source: "image://theme/icon-l-play"
- onPressed: playPressed()
- }
-
-}
diff --git a/qml/components/itemdetails/SeasonDetails.qml b/qml/components/itemdetails/SeasonDetails.qml
index 7353b34..8b13789 100644
--- a/qml/components/itemdetails/SeasonDetails.qml
+++ b/qml/components/itemdetails/SeasonDetails.qml
@@ -1,123 +1 @@
-/*
-Sailfin: a Jellyfin client written using Qt
-Copyright (C) 2020 Chris Josten
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-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 "../../Utils.js" as Utils
-import "../.."
-import ".."
-
-Column {
- property var itemData
-
- ShowEpisodesModel {
- id: episodeModel
- apiClient: ApiClient
- show: itemData.SeriesId
- seasonId: itemData.Id
- fields: ["Overview"]
- }
-
- ColumnView {
- model: episodeModel
- itemHeight: Constants.libraryDelegateHeight
- delegate: BackgroundItem {
- height: Constants.libraryDelegateHeight
- RemoteImage {
- id: episodeImage
- anchors {
- top: parent.top
- left: parent.left
- bottom: parent.bottom
- }
- width: Constants.libraryDelegateWidth
- height: Constants.libraryDelegateHeight
- source: Utils.itemModelImageUrl(ApiClient.baseUrl, model.id, model.imageTags["Primary"], "Primary", {"maxHeight": height})
- fillMode: Image.PreserveAspectCrop
- clip: true
-
- // Makes the progress bar stand out more
- Shim {
- anchors {
- left: parent.left
- bottom: parent.bottom
- right: parent.right
- }
- height: parent.height / 3
- shimColor: Theme.overlayBackgroundColor
- shimOpacity: Theme.opacityOverlay
- //width: model.userData.PlayedPercentage * parent.width / 100
- visible: episodeProgress.width > 0 // It doesn't look nice when it's visible on every image
- }
-
- Rectangle {
- id: episodeProgress
- anchors {
- left: parent.left
- bottom: parent.bottom
- }
- height: Theme.paddingMedium
- width: model.userData.PlayedPercentage * parent.width / 100
- color: Theme.highlightColor
- }
- }
-
- Label {
- id: episodeTitle
- anchors {
- left: episodeImage.right
- leftMargin: Theme.paddingLarge
- top: parent.top
- right: parent.right
- rightMargin: Theme.horizontalPageMargin
- }
- text: model.name
- truncationMode: TruncationMode.Fade
- horizontalAlignment: Text.AlignLeft
- }
-
- Label {
- id: episodeOverview
- anchors {
- left: episodeImage.right
- leftMargin: Theme.paddingLarge
- right: parent.right
- rightMargin: Theme.horizontalPageMargin
- top: episodeTitle.bottom
- bottom: parent.bottom
- }
- color: highlighted ? Theme.secondaryHighlightColor: Theme.secondaryColor
- font.pixelSize: Theme.fontSizeExtraSmall
- //: No overview/summary text of an episode available
- text: model.overview || qsTr("No overview available")
- wrapMode: Text.WordWrap
- elide: Text.ElideRight
- }
- onClicked: pageStack.push(Qt.resolvedUrl("../../pages/DetailPage.qml"), {"itemId": model.id})
- }
- }
- onItemDataChanged: {
- console.log(JSON.stringify(itemData))
- episodeModel.show = itemData.SeriesId
- episodeModel.seasonId = itemData.Id
- episodeModel.reload()
- }
-}
diff --git a/qml/components/itemdetails/SeriesDetails.qml b/qml/components/itemdetails/SeriesDetails.qml
deleted file mode 100644
index f5e24fa..0000000
--- a/qml/components/itemdetails/SeriesDetails.qml
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-Sailfin: a Jellyfin client written using Qt
-Copyright (C) 2020 Chris Josten
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-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 "../"
-import "../../Utils.js" as Utils
-
-Column {
- property var itemData
-
- PlainLabel {
- id: overviewText
- text: itemData.Overview
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.secondaryHighlightColor
- }
-
- SectionHeader {
- //: Seasons of a (TV) show
- text: qsTr("Seasons")
- }
-
- ShowSeasonsModel {
- id: showSeasonsModel
- apiClient: ApiClient
- show: itemData.Id
- }
-
- SilicaListView {
- model: showSeasonsModel
- clip: true
- width: parent.width
- height: Screen.width / 2
- orientation: ListView.Horizontal
- spacing: Theme.paddingLarge
- leftMargin: Theme.horizontalPageMargin
- rightMargin: Theme.horizontalPageMargin
- delegate: LibraryItemDelegate {
- poster: Utils.itemModelImageUrl(ApiClient.baseUrl, model.id, model.imageTags["Primary"], "Primary", {"maxHeight": height})
- title: model.name
- onClicked: pageStack.push(Qt.resolvedUrl("../../pages/DetailPage.qml"), {"itemId": model.id})
- }
- }
-
- onItemDataChanged: {
- showSeasonsModel.show = itemData.Id
- showSeasonsModel.reload()
- }
-}
diff --git a/qml/pages/MainPage.qml b/qml/pages/MainPage.qml
index 8645b84..afd82ab 100644
--- a/qml/pages/MainPage.qml
+++ b/qml/pages/MainPage.qml
@@ -94,7 +94,7 @@ Page {
text: model.name
busy: userItemModel.status != ApiModel.Ready
- onHeaderClicked: pageStack.push(Qt.resolvedUrl("CollectionPage.qml"), {"itemId": model.id})
+ onHeaderClicked: pageStack.push(Qt.resolvedUrl("itemdetails/CollectionPage.qml"), {"itemId": model.id})
Loader {
width: parent.width
sourceComponent: carrouselView
@@ -202,7 +202,7 @@ Page {
progress: model.userData.PlayedPercentage / 100
onClicked: {
- pageStack.push(Qt.resolvedUrl("DetailPage.qml"), {"itemId": model.id})
+ pageStack.push(Utils.getPageUrl(model.type), {"itemId": model.id})
}
}
}
diff --git a/qml/pages/DetailPage.qml b/qml/pages/itemdetails/BaseDetailPage.qml
similarity index 57%
rename from qml/pages/DetailPage.qml
rename to qml/pages/itemdetails/BaseDetailPage.qml
index c85070b..7ce36df 100644
--- a/qml/pages/DetailPage.qml
+++ b/qml/pages/itemdetails/BaseDetailPage.qml
@@ -21,8 +21,7 @@ import Sailfish.Silica 1.0
import nl.netsoj.chris.Jellyfin 1.0
-import "../components"
-import "../components/itemdetails"
+import "../../components"
/**
* This page displays details about a film, show, season, episode, and so on.
@@ -35,11 +34,11 @@ Page {
property string itemId: ""
property var itemData: ({})
property bool _loading: true
- readonly property bool _hasLogo: itemData.ImageTags.Logo !== undefined
- readonly property string _logo: itemData.ImageTags.Logo
+ readonly property bool hasLogo: (typeof itemData.ImageTags !== "undefined") && (typeof itemData.ImageTags["Logo"] !== "undefined")
readonly property var _backdropImages: itemData.BackdropImageTags
readonly property var _parentBackdropImages: itemData.ParentBackdropImageTags
readonly property string parentId: itemData.ParentId || ""
+ property alias backdrop: backdrop
on_BackdropImagesChanged: updateBackdrop()
on_ParentBackdropImagesChanged: updateBackdrop()
@@ -62,72 +61,6 @@ Page {
anchors.fill: parent
}
- SilicaFlickable {
- anchors.fill: parent
- contentHeight: content.height
-
- Column {
- id: content
- width: parent.width
-
- PageHeader {
- title: itemData.Name || qsTr("Loading")
- visible: !_hasLogo
- }
-
- Column {
- width: parent.width
- Item {
- width: 1
- height: Theme.paddingLarge
- }
- RemoteImage {
- anchors {
- horizontalCenter: parent.horizontalCenter
- }
- source: _hasLogo ? ApiClient.baseUrl + "/Items/" + itemId + "/Images/Logo?tag=" + _logo : ""
- }
- Item {
- width: 1
- height: Theme.paddingLarge
- }
- visible: _hasLogo
- }
-
- Item {
- width: 1
- height: Theme.paddingLarge
- }
-
- Loader {
- active: itemData != undefined
- asynchronous: true
- width: parent.width
- source: {
- switch (itemData.Type){
- case "Movie":
- return Qt.resolvedUrl("../components/itemdetails/FilmDetails.qml")
- case "Series":
- return Qt.resolvedUrl("../components/itemdetails/SeriesDetails.qml")
- case "Season":
- return Qt.resolvedUrl("../components/itemdetails/SeasonDetails.qml")
- case "Episode":
- return Qt.resolvedUrl("../components/itemdetails/EpisodeDetails.qml")
- case undefined:
- return ""
- default:
- return Qt.resolvedUrl("../components/itemdetails/UnsupportedDetails.qml")
- }
- }
- onLoaded: {
- item.itemData = Qt.binding(function() { return pageRoot.itemData; })
- }
- }
-
-
- }
- }
-
PageBusyIndicator {
running: pageRoot._loading
}
@@ -160,8 +93,13 @@ Page {
//console.log(JSON.stringify(result))
pageRoot.itemData = result
pageRoot._loading = false
- if (status == PageStatus.Active)
- appWindow.itemData = result
+ if (status == PageStatus.Active) {
+ if (itemData.Type === "CollectionFolder") {
+ appWindow.collectionId = itemData.Id
+ } else {
+ appWindow.itemData = result
+ }
+ }
}
}
}
diff --git a/qml/pages/CollectionPage.qml b/qml/pages/itemdetails/CollectionPage.qml
similarity index 79%
rename from qml/pages/CollectionPage.qml
rename to qml/pages/itemdetails/CollectionPage.qml
index 2585608..50d82e1 100644
--- a/qml/pages/CollectionPage.qml
+++ b/qml/pages/itemdetails/CollectionPage.qml
@@ -21,21 +21,18 @@ import Sailfish.Silica 1.0
import nl.netsoj.chris.Jellyfin 1.0
-import ".."
-import "../components"
-import "../Utils.js" as Utils
+import "../.."
+import "../../components"
-Page {
+BaseDetailPage {
id: pageRoot
- property var itemId
- property var itemData
- property bool _loading: true
UserItemModel {
id: collectionModel
apiClient: ApiClient
parentId: itemData.Id || ""
sortBy: ["SortName"]
+ onParentIdChanged: reload()
}
SilicaGridView {
@@ -99,7 +96,7 @@ Page {
pageStack.push(Qt.resolvedUrl("CollectionPage.qml"), {"itemId": model.id})
break;
default:
- pageStack.push(Qt.resolvedUrl("DetailPage.qml"), {"itemId": model.id})
+ pageStack.push(Utils.getPageUrl(model.type), {"itemId": model.id})
}
}
}
@@ -113,48 +110,6 @@ Page {
VerticalScrollDecorator {}
}
- PageBusyIndicator {
- running: pageRoot._loading
- }
-
- onItemIdChanged: {
- itemData = {}
- if (itemId.length && PageStatus.Active) {
- pageRoot._loading = true
- ApiClient.fetchItem(itemId)
- }
- }
-
- onStatusChanged: {
- if (status == PageStatus.Deactivating) {
- backdrop.clear()
- }
- if (status == PageStatus.Active) {
- if (itemId && !itemData) {
- ApiClient.fetchItem(itemId)
- appWindow.collectionId = itemId
- }
-
- }
- }
-
- Connections {
- target: ApiClient
- onItemFetched: {
- if (itemId === pageRoot.itemId) {
- pageRoot.itemData = result
- pageRoot._loading = false
- console.log(JSON.stringify(result))
- collectionModel.parentId = result.Id
- collectionModel.reload()
- if (status == PageStatus.Active) {
- appWindow.itemData = null
- appWindow.collectionId = itemId
- }
- }
- }
- }
-
Component {
id: sortPageComponent
Page {
diff --git a/qml/pages/itemdetails/EpisodePage.qml b/qml/pages/itemdetails/EpisodePage.qml
new file mode 100644
index 0000000..ade3cb0
--- /dev/null
+++ b/qml/pages/itemdetails/EpisodePage.qml
@@ -0,0 +1,75 @@
+/*
+Sailfin: a Jellyfin client written using Qt
+Copyright (C) 2020 Chris Josten
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+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 "../../components"
+import "../../"
+
+BaseDetailPage {
+ SilicaFlickable {
+ anchors.fill: parent
+ contentHeight: content.height
+ Column {
+ id: content
+ width: parent.width
+
+ PageHeader {
+ title: itemData.Name
+ description: {
+ if (typeof itemData.IndexNumberEnd !== "undefined") {
+ qsTr("Episode %1–%2 | %3").arg(itemData.IndexNumber)
+ .arg(itemData.IndexNumberEnd)
+ .arg(itemData.SeasonName)
+ } else {
+ qsTr("Episode %1 | %2").arg(itemData.IndexNumber).arg(itemData.SeasonName)
+ }
+ }
+ }
+
+ PlayToolbar {
+ imageSource: Utils.itemImageUrl(ApiClient.baseUrl, itemData, "Primary", {"maxWidth": parent.width})
+ imageAspectRatio: itemData.PrimaryImageAspectRatio
+ onPlayPressed: pageStack.push(Qt.resolvedUrl("../VideoPage.qml"),
+ {"itemId": itemId, "itemData": itemData, "audioTrack": trackSelector.audioTrack,
+ "subtitleTrack": trackSelector.subtitleTrack })
+ width: parent.width
+ }
+
+ VideoTrackSelector {
+ id: trackSelector
+ width: parent.width
+ tracks: itemData.MediaStreams
+ }
+
+ SectionHeader {
+ text: qsTr("Overview")
+ }
+
+ PlainLabel {
+ id: overviewText
+ text: itemData.Overview
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.secondaryHighlightColor
+ }
+ }
+ }
+}
diff --git a/qml/pages/itemdetails/FilmPage.qml b/qml/pages/itemdetails/FilmPage.qml
new file mode 100644
index 0000000..e02160a
--- /dev/null
+++ b/qml/pages/itemdetails/FilmPage.qml
@@ -0,0 +1,70 @@
+/*
+Sailfin: a Jellyfin client written using Qt
+Copyright (C) 2020 Chris Josten
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+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 "../../components"
+import "../.."
+
+BaseDetailPage {
+ SilicaFlickable {
+ anchors.fill: parent
+ contentHeight: content.height
+
+ Column {
+ id: content
+ width: parent.width
+ spacing: Theme.paddingMedium
+
+ PageHeader {
+ title: itemData.Name
+ description: qsTr("Released: %1 — Run time: %2").arg(itemData.ProductionYear).arg(Utils.ticksToText(itemData.RunTimeTicks))
+ }
+
+ PlayToolbar {
+ width: parent.width
+ imageSource: Utils.itemImageUrl(ApiClient.baseUrl, itemData, "Primary", {"maxWidth": parent.width})
+ imageAspectRatio: 1.66666 //itemData.PrimaryImageAspectRatio
+ onPlayPressed: pageStack.push(Qt.resolvedUrl("../../pages/VideoPage.qml"),
+ {"itemId": itemId, "itemData": itemData, "audioTrack": trackSelector.audioTrack,
+ "subtitleTrack": trackSelector.subtitleTrack })
+ }
+
+ VideoTrackSelector {
+ id: trackSelector
+ width: parent.width
+ tracks: itemData.MediaStreams
+ }
+
+ SectionHeader {
+ text: qsTr("Overview")
+ }
+
+ PlainLabel {
+ id: overviewText
+ text: itemData.Overview
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.secondaryHighlightColor
+ }
+ }
+ }
+}
diff --git a/qml/pages/itemdetails/MusicAlbumPage.qml b/qml/pages/itemdetails/MusicAlbumPage.qml
new file mode 100644
index 0000000..9c36e13
--- /dev/null
+++ b/qml/pages/itemdetails/MusicAlbumPage.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Item {
+
+}
diff --git a/qml/pages/itemdetails/SeasonPage.qml b/qml/pages/itemdetails/SeasonPage.qml
new file mode 100644
index 0000000..e983c2d
--- /dev/null
+++ b/qml/pages/itemdetails/SeasonPage.qml
@@ -0,0 +1,137 @@
+/*
+Sailfin: a Jellyfin client written using Qt
+Copyright (C) 2020 Chris Josten
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+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 "../.."
+import "../../components"
+import ".."
+
+BaseDetailPage {
+ SilicaFlickable {
+ anchors.fill: parent
+ contentHeight: content.height
+
+ Column {
+ id: content
+ width: parent.width
+
+ PageHeader {
+ title: itemData.Name
+ description: itemData.SeriesName
+ }
+
+ ShowEpisodesModel {
+ id: episodeModel
+ apiClient: ApiClient
+ show: itemData.SeriesId
+ seasonId: itemData.Id
+ fields: ["Overview"]
+ }
+
+ ColumnView {
+ model: episodeModel
+ itemHeight: Constants.libraryDelegateHeight
+ delegate: BackgroundItem {
+ height: Constants.libraryDelegateHeight
+ RemoteImage {
+ id: episodeImage
+ anchors {
+ top: parent.top
+ left: parent.left
+ bottom: parent.bottom
+ }
+ width: Constants.libraryDelegateWidth
+ height: Constants.libraryDelegateHeight
+ source: Utils.itemModelImageUrl(ApiClient.baseUrl, model.id, model.imageTags["Primary"], "Primary", {"maxHeight": height})
+ fillMode: Image.PreserveAspectCrop
+ clip: true
+
+ // Makes the progress bar stand out more
+ Shim {
+ anchors {
+ left: parent.left
+ bottom: parent.bottom
+ right: parent.right
+ }
+ height: parent.height / 3
+ shimColor: Theme.overlayBackgroundColor
+ shimOpacity: Theme.opacityOverlay
+ //width: model.userData.PlayedPercentage * parent.width / 100
+ visible: episodeProgress.width > 0 // It doesn't look nice when it's visible on every image
+ }
+
+ Rectangle {
+ id: episodeProgress
+ anchors {
+ left: parent.left
+ bottom: parent.bottom
+ }
+ height: Theme.paddingMedium
+ width: model.userData.PlayedPercentage * parent.width / 100
+ color: Theme.highlightColor
+ }
+ }
+
+ Label {
+ id: episodeTitle
+ anchors {
+ left: episodeImage.right
+ leftMargin: Theme.paddingLarge
+ top: parent.top
+ right: parent.right
+ rightMargin: Theme.horizontalPageMargin
+ }
+ text: model.name
+ truncationMode: TruncationMode.Fade
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ Label {
+ id: episodeOverview
+ anchors {
+ left: episodeImage.right
+ leftMargin: Theme.paddingLarge
+ right: parent.right
+ rightMargin: Theme.horizontalPageMargin
+ top: episodeTitle.bottom
+ bottom: parent.bottom
+ }
+ color: highlighted ? Theme.secondaryHighlightColor: Theme.secondaryColor
+ font.pixelSize: Theme.fontSizeExtraSmall
+ //: No overview/summary text of an episode available
+ text: model.overview || qsTr("No overview available")
+ wrapMode: Text.WordWrap
+ elide: Text.ElideRight
+ }
+ onClicked: pageStack.push(Utils.getPageUrl(model.type), {"itemId": model.id})
+ }
+ }
+
+ }
+ }
+ onItemDataChanged: {
+ console.log(JSON.stringify(itemData))
+ episodeModel.show = itemData.SeriesId
+ episodeModel.seasonId = itemData.Id
+ episodeModel.reload()
+ }
+}
diff --git a/qml/pages/itemdetails/SeriesPage.qml b/qml/pages/itemdetails/SeriesPage.qml
new file mode 100644
index 0000000..be5c45d
--- /dev/null
+++ b/qml/pages/itemdetails/SeriesPage.qml
@@ -0,0 +1,93 @@
+/*
+Sailfin: a Jellyfin client written using Qt
+Copyright (C) 2020 Chris Josten
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+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 "../../components"
+import "../.."
+
+BaseDetailPage {
+ SilicaFlickable {
+ anchors.fill: parent
+ contentHeight: content.height
+
+ Column {
+ id: content
+ width: parent.width
+
+ PageHeader {
+ id: header
+ title: itemData.Name
+ visible: !hasLogo
+ }
+
+ Item {
+ visible: hasLogo
+ width: parent.width
+ height: Math.max(logoImage.height, header.height) + 2 * Theme.paddingLarge
+ RemoteImage {
+ id: logoImage
+ anchors.centerIn: parent
+ source: Utils.itemImageUrl(ApiClient.baseUrl, itemData, "Logo")
+ }
+ }
+
+ PlainLabel {
+ id: overviewText
+ text: itemData.Overview
+ font.pixelSize: Theme.fontSizeSmall
+ color: Theme.secondaryHighlightColor
+ }
+
+ SectionHeader {
+ //: Seasons of a (TV) show
+ text: qsTr("Seasons")
+ }
+
+ ShowSeasonsModel {
+ id: showSeasonsModel
+ apiClient: ApiClient
+ show: itemData.Id
+ }
+
+ SilicaListView {
+ model: showSeasonsModel
+ clip: true
+ width: parent.width
+ height: Screen.width / 2
+ orientation: ListView.Horizontal
+ spacing: Theme.paddingLarge
+ leftMargin: Theme.horizontalPageMargin
+ rightMargin: Theme.horizontalPageMargin
+ delegate: LibraryItemDelegate {
+ poster: Utils.itemModelImageUrl(ApiClient.baseUrl, model.id, model.imageTags["Primary"], "Primary", {"maxHeight": height})
+ title: model.name
+ onClicked: pageStack.push(Utils.getPageUrl(model.type), {"itemId": model.id})
+ }
+ }
+
+ }
+ }
+ onItemDataChanged: {
+ showSeasonsModel.show = itemData.Id
+ showSeasonsModel.reload()
+ }
+}
diff --git a/qml/components/itemdetails/UnsupportedDetails.qml b/qml/pages/itemdetails/UnsupportedPage.qml
similarity index 71%
rename from qml/components/itemdetails/UnsupportedDetails.qml
rename to qml/pages/itemdetails/UnsupportedPage.qml
index 32881c2..f0d70d7 100644
--- a/qml/components/itemdetails/UnsupportedDetails.qml
+++ b/qml/pages/itemdetails/UnsupportedPage.qml
@@ -20,10 +20,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import QtQuick 2.6
import Sailfish.Silica 1.0
-ViewPlaceholder {
- property var itemData
+BaseDetailPage {
+ SilicaFlickable {
+ anchors.fill: parent
+ PageHeader {
+ title: itemData.Name
+ }
+ ViewPlaceholder {
- enabled: true
- text: qsTr("Item type (%1) unsupported").arg(itemData.Type)
- hintText: qsTr("This is still an alpha version :)")
+ enabled: true
+ text: qsTr("Item type (%1) unsupported").arg(itemData.Type)
+ hintText: qsTr("This is still an alpha version :)")
+ }
+ }
}
diff --git a/qml/qmldir b/qml/qmldir
index c6de29c..0b84cf2 100644
--- a/qml/qmldir
+++ b/qml/qmldir
@@ -16,3 +16,4 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
singleton Constants 1.0 Constants.qml
+Utils 1.0 Utils.js
diff --git a/translations/harbour-sailfin.ts b/translations/harbour-sailfin.ts
index 51d1f19..56ee869 100644
--- a/translations/harbour-sailfin.ts
+++ b/translations/harbour-sailfin.ts
@@ -102,14 +102,7 @@
- DetailPage
-
-
-
-
-
-
- EpisodeDetails
+ EpisodePage
@@ -120,7 +113,7 @@
- FilmDetails
+ FilmPage
@@ -205,7 +198,7 @@
- SeasonDetails
+ SeasonPage
No overview/summary text of an episode available
@@ -213,7 +206,7 @@
- SeriesDetails
+ SeriesPage
Seasons of a (TV) show
@@ -258,13 +251,13 @@
- UnsupportedDetails
+ UnsupportedPage
-
+
-
+