mirror of
https://github.com/HenkKalkwater/harbour-sailfin.git
synced 2025-09-04 01:42:44 +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
19 changed files with 179 additions and 81 deletions
|
@ -38,9 +38,9 @@ set(sailfin_QML_SOURCES
|
|||
qml/components/UserGridDelegate.qml
|
||||
qml/components/VideoPlayer.qml
|
||||
qml/components/VideoTrackSelector.qml
|
||||
qml/cover/CoverPage.qml
|
||||
qml/cover/CollectionPage.qml
|
||||
qml/cover/PosterCover.qml
|
||||
qml/cover/VideoCover.qml
|
||||
qml/cover/NowPlayingCover.qml
|
||||
qml/pages/LegalPage.qml
|
||||
qml/pages/MainPage.qml
|
||||
qml/pages/AboutPage.qml
|
||||
|
|
|
@ -87,7 +87,7 @@ PanelBackground {
|
|||
Rectangle {
|
||||
id: playQueueShim
|
||||
anchors.fill: albumArt
|
||||
color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityLow)
|
||||
color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityOverlay)
|
||||
opacity: 0
|
||||
}
|
||||
Loader {
|
||||
|
@ -159,6 +159,7 @@ PanelBackground {
|
|||
}
|
||||
icon.source: "image://theme/icon-m-shuffle"
|
||||
opacity: 0
|
||||
enabled: false
|
||||
onClicked: Notices.show(qsTr("Shuffle not yet implemented"))
|
||||
}
|
||||
|
||||
|
@ -330,7 +331,7 @@ PanelBackground {
|
|||
target: nextButton; opacity: 1; enabled: true;
|
||||
}
|
||||
PropertyChanges {
|
||||
target: playModeButton; opacity: 1; //enabled: true;
|
||||
target: playModeButton; opacity: 1; enabled: true;
|
||||
}
|
||||
PropertyChanges {
|
||||
target: queueButton; opacity: 1; enabled: true;
|
||||
|
|
|
@ -31,7 +31,7 @@ CoverBackground {
|
|||
readonly property real rowHeight: height / 2
|
||||
readonly property real bottomOffset: width - rowHeight
|
||||
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
|
||||
|
||||
J.ItemModel {
|
||||
|
@ -39,14 +39,14 @@ CoverBackground {
|
|||
loader: J.UserItemsLoader {
|
||||
id: randomItemsLoader
|
||||
apiClient: appWindow.apiClient
|
||||
limit: cover.rowCount * 2
|
||||
limit: cover.rowCount * 2 - 2
|
||||
imageTypes: [J.ImageType.Primary]
|
||||
sortBy: "IsFavoriteOrLiked,Random"
|
||||
recursive: false
|
||||
parentId: hasParent ? itemId : ""
|
||||
parentId: itemId
|
||||
autoReload: false
|
||||
onParentIdChanged: {
|
||||
if (parentId.length > 0) reload()
|
||||
reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,12 +82,15 @@ CoverBackground {
|
|||
x: -rowHeight * rowOffset
|
||||
y: rowHeight * 0.5
|
||||
}
|
||||
PathPercent {
|
||||
value: 1
|
||||
}
|
||||
}
|
||||
delegate: RemoteImage {
|
||||
height: rowHeight
|
||||
width: height
|
||||
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
|
||||
? model.imageBlurHashes["Primary"][model.imageTags["Primary"]]
|
||||
|
@ -96,14 +99,18 @@ CoverBackground {
|
|||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
/*Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityHigh)
|
||||
}
|
||||
}*/
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
opacity: randomItemsLoader.status === J.ModelStatus.Ready ? 0.0 : 1.0
|
||||
Behavior on opacity {
|
||||
NumberAnimation {}
|
||||
}
|
||||
Image {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
source: Qt.resolvedUrl("../icon.png")
|
||||
|
@ -122,13 +129,12 @@ CoverBackground {
|
|||
target: appWindow.pageStack
|
||||
onCurrentPageChanged: {
|
||||
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 {
|
||||
running: true
|
||||
interval: 5000
|
|
@ -28,19 +28,6 @@ import "../components"
|
|||
PosterCover {
|
||||
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 {
|
||||
anchors {
|
||||
left: parent.left
|
||||
|
@ -51,8 +38,27 @@ PosterCover {
|
|||
}
|
||||
|
||||
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 {
|
||||
id: playPause
|
||||
iconSource: player.playbackState === MediaPlayer.PlayingState ? "image://theme/icon-cover-pause"
|
||||
: "image://theme/icon-cover-play"
|
||||
onTriggered: {
|
|
@ -27,7 +27,7 @@ import ".."
|
|||
|
||||
CoverBackground {
|
||||
// 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 {
|
||||
anchors.fill: parent
|
||||
source: mData === null ? "" : Utils.itemImageUrl(appWindow.apiClient.baseUrl, mData, "Primary", {"maxWidth": parent.width})
|
||||
|
@ -78,7 +78,7 @@ CoverBackground {
|
|||
Label {
|
||||
visible: typeof mData.runTimeTicks !== "undefined"
|
||||
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: {
|
||||
// Disabled due to buggy Loader behaviour
|
||||
if ([MediaPlayer.NoMedia, MediaPlayer.InvalidMedia, MediaPlayer.UnknownStatus].indexOf(_playbackManager.mediaStatus) >= 0) {
|
||||
return Qt.resolvedUrl("cover/CoverPage.qml")
|
||||
} else if (playbackManager.hasVideo){
|
||||
return Qt.resolvedUrl("cover/VideoCover.qml")
|
||||
return Qt.resolvedUrl("cover/CollectionPage.qml")
|
||||
} else {
|
||||
return Qt.resolvedUrl("cover/CoverPage.qml")
|
||||
return Qt.resolvedUrl("cover/NowPlayingCover.qml")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ import "../"
|
|||
Page {
|
||||
/// True if the models on this page already have been loaded and don't necessarily need a refresh
|
||||
property bool _modelsLoaded: false
|
||||
// Only for cover page
|
||||
readonly property string itemId: ""
|
||||
|
||||
id: mainPage
|
||||
allowedOrientations: Orientation.All
|
||||
|
@ -48,7 +50,7 @@ Page {
|
|||
text: qsTr("Reload")
|
||||
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.
|
||||
text: qsTr("Resume watching")
|
||||
clickable: false
|
||||
busy: userResumeLoader.status === J.UsersViewsLoader.Loading
|
||||
busy: userResumeLoader.status === J.ModelStatus.Loading
|
||||
Loader {
|
||||
width: parent.width
|
||||
sourceComponent: carrouselView
|
||||
|
@ -102,7 +104,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 === .Loading
|
||||
busy: showNextUpLoader.status === J.ModelStatus.Loading
|
||||
|
||||
Loader {
|
||||
width: parent.width
|
||||
|
@ -112,8 +114,11 @@ Page {
|
|||
|
||||
J.ItemModel {
|
||||
id: showNextUpModel
|
||||
/*apiClient: appWindow.apiClient
|
||||
limit: 12*/
|
||||
loader: J.NextUpLoader {
|
||||
id: showNextUpLoader
|
||||
apiClient: appWindow.apiClient
|
||||
enableUserData: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ Page {
|
|||
if (status === PageStatus.Active) {
|
||||
console.log("Page ready, ItemID: ", itemId, ", UserID: ", apiClient.userId)
|
||||
jItemLoader.autoReload = true
|
||||
//appWindow.itemData = jItemLoader.data
|
||||
appWindow.itemData = Qt.binding(function() { return jItemLoader.data; })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue