mirror of
https://github.com/HenkKalkwater/harbour-sailfin.git
synced 2024-11-24 18:15:16 +00:00
ui: improve empty state, add remote playback indicator
This commit is contained in:
parent
3783de9ce7
commit
7c6d8486de
|
@ -69,7 +69,11 @@ function randomBackdrop(baseUrl, item) {
|
||||||
|
|
||||||
function itemBackdropUrl(baseUrl, item, idx, options) {
|
function itemBackdropUrl(baseUrl, item, idx, options) {
|
||||||
var extraQuery = propsToQuery(options)
|
var extraQuery = propsToQuery(options)
|
||||||
return baseUrl + "/Items/" + item.jellyfinId + "/Images/Backdrop/" + idx + "?tag=" + item.backdropImageTags[idx] + extraQuery;
|
if (item.backdropImageTags[idx]) {
|
||||||
|
return baseUrl + "/Items/" + item.jellyfinId + "/Images/Backdrop/" + idx + "?tag=" + item.backdropImageTags[idx] + extraQuery;
|
||||||
|
} else {
|
||||||
|
return baseUrl + "/Items/" + item.parentBackdropItemId + "/Images/Backdrop/" + idx + "?tag=" + item.parentBackdropImageTags[idx] + extraQuery;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@ PanelBackground {
|
||||||
property bool showQueue: false
|
property bool showQueue: false
|
||||||
|
|
||||||
property bool _pageWasShowingNavigationIndicator
|
property bool _pageWasShowingNavigationIndicator
|
||||||
|
readonly property bool _isItemSet: manager.item !== null && manager.item !== undefined && manager.item.jellyfinId.length > 0
|
||||||
|
readonly property bool controllingRemote: !manager.controllingSessionLocal
|
||||||
readonly property bool mediaLoading: [J.MediaStatus.Loading, J.MediaStatus.Buffering].indexOf(manager.mediaStatus) >= 0
|
readonly property bool mediaLoading: [J.MediaStatus.Loading, J.MediaStatus.Buffering].indexOf(manager.mediaStatus) >= 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,9 +69,12 @@ PanelBackground {
|
||||||
top: parent.top
|
top: parent.top
|
||||||
}
|
}
|
||||||
width: height
|
width: height
|
||||||
Binding on blurhash {
|
blurhash: {
|
||||||
when: manager.item !== null && "Primary" in manager.item.imageBlurHashes && "Primary" in manager.item.imageTags
|
if (_isItemSet && "Primary" in manager.item.imageBlurHashes && "Primary" in manager.item.imageTags) {
|
||||||
value: manager.item.imageBlurHashes["Primary"][manager.item.imageTags["Primary"]]
|
return manager.item.imageBlurHashes["Primary"][manager.item.imageTags["Primary"]]
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
source: largeAlbumArt.source
|
source: largeAlbumArt.source
|
||||||
fillMode: Image.PreserveAspectCrop
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
@ -125,7 +130,10 @@ PanelBackground {
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: name
|
id: name
|
||||||
text: manager.item === null ? qsTr("No media selected") : manager.item.name
|
text: manager.item.jellyfinId
|
||||||
|
? manager.item.name
|
||||||
|
//: Shown in a bright font when no media is playing in the bottom bar and now playing screen
|
||||||
|
: qsTr("Nothing is playing")
|
||||||
width: Math.min(contentWidth, parent.width)
|
width: Math.min(contentWidth, parent.width)
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
|
@ -133,8 +141,23 @@ PanelBackground {
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
id: artists
|
id: artists
|
||||||
|
leftPadding: controllingRemote ? remoteIcon.width + Theme.paddingSmall : 0
|
||||||
text: {
|
text: {
|
||||||
if (manager.item === null) return qsTr("Play some media!")
|
if (!_isItemSet) {
|
||||||
|
if (controllingRemote) {
|
||||||
|
//: Shown when no media is being played, but the app is controlling another Jellyfin client
|
||||||
|
//: %1 is the name of said client
|
||||||
|
return qsTr("Connected to %1").arg(manager.controllingSessionName)
|
||||||
|
} else {
|
||||||
|
return qsTr("Start playing some media!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var remoteText = "";
|
||||||
|
|
||||||
|
if (controllingRemote) {
|
||||||
|
remoteText = manager.controllingSessionName + " - "
|
||||||
|
}
|
||||||
|
|
||||||
switch(manager.item.mediaType) {
|
switch(manager.item.mediaType) {
|
||||||
case "Audio":
|
case "Audio":
|
||||||
var links = [];
|
var links = [];
|
||||||
|
@ -147,7 +170,7 @@ PanelBackground {
|
||||||
.arg(Theme.secondaryColor)
|
.arg(Theme.secondaryColor)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return links.join(", ")
|
return remoteText + links.join(", ")
|
||||||
}
|
}
|
||||||
return qsTr("No audio")
|
return qsTr("No audio")
|
||||||
}
|
}
|
||||||
|
@ -162,6 +185,16 @@ PanelBackground {
|
||||||
appWindow.navigateToItem(link, "Audio", "MusicArtist", true)
|
appWindow.navigateToItem(link, "Audio", "MusicArtist", true)
|
||||||
}
|
}
|
||||||
textFormat: Text.StyledText
|
textFormat: Text.StyledText
|
||||||
|
Icon {
|
||||||
|
id: remoteIcon
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
height: parent
|
||||||
|
source: "image://theme/icon-s-device-upload"
|
||||||
|
visible: controllingRemote
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +428,9 @@ PanelBackground {
|
||||||
},
|
},
|
||||||
State {
|
State {
|
||||||
name: "hidden"
|
name: "hidden"
|
||||||
when: ((manager.playbackState === J.PlayerState.Stopped && !mediaLoading) || "__hidePlaybackBar" in pageStack.currentPage) && !isFullPage
|
when: ((manager.playbackState === J.PlayerState.Stopped && !mediaLoading)
|
||||||
|
|| ("__hidePlaybackBar" in pageStack.currentPage && pageStack.currentPage.__hidePlaybackBar))
|
||||||
|
&& !isFullPage
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: playbackBarTranslate
|
target: playbackBarTranslate
|
||||||
// + small padding since the ProgressBar otherwise would stick out
|
// + small padding since the ProgressBar otherwise would stick out
|
||||||
|
|
|
@ -50,6 +50,16 @@ SilicaItem {
|
||||||
color: Theme.overlayBackgroundColor
|
color: Theme.overlayBackgroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RemoteImage {
|
||||||
|
id: backdrop
|
||||||
|
anchors.fill: parent
|
||||||
|
visible: !manager.controllingSessionLocal
|
||||||
|
|| [J.MediaStatus.NoMedia, J.MediaStatus.Loading].indexOf(manager.mediaStatus) >= 0
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: Utils.itemBackdropUrl(apiClient.baseUrl, item, 0, {"maxWidth": parent.width})
|
||||||
|
blurhash: item.imageBlurHashes["Backdrop"][item.backdropImageTags[0]]
|
||||||
|
}
|
||||||
|
|
||||||
VideoOutput {
|
VideoOutput {
|
||||||
id: videoOutput
|
id: videoOutput
|
||||||
source: manager
|
source: manager
|
||||||
|
@ -64,7 +74,7 @@ SilicaItem {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
manager: playerRoot.manager
|
manager: playerRoot.manager
|
||||||
title: videoPlayer.title
|
title: videoPlayer.title
|
||||||
|
alwaysVisible: !manager.controllingSessionLocal
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoError {
|
VideoError {
|
||||||
|
|
|
@ -34,6 +34,8 @@ Item {
|
||||||
property var manager
|
property var manager
|
||||||
property string title
|
property string title
|
||||||
property bool _manuallyActivated: false
|
property bool _manuallyActivated: false
|
||||||
|
/// Don't allow the HUD to hide
|
||||||
|
property bool alwaysVisible: false
|
||||||
readonly property bool hidden: opacity == 0.0
|
readonly property bool hidden: opacity == 0.0
|
||||||
|
|
||||||
Behavior on opacity { FadeAnimator {} }
|
Behavior on opacity { FadeAnimator {} }
|
||||||
|
@ -174,6 +176,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide(manual) {
|
function hide(manual) {
|
||||||
|
if (alwaysVisible) return
|
||||||
// Don't hide if the user decided on their own to show the hud
|
// Don't hide if the user decided on their own to show the hud
|
||||||
//if (!manual && _manuallyActivated) return;
|
//if (!manual && _manuallyActivated) return;
|
||||||
// Don't give in to the user if they want to hide the hud while it was forced upon them
|
// Don't give in to the user if they want to hide the hud while it was forced upon them
|
||||||
|
|
|
@ -75,7 +75,7 @@ ApplicationWindow {
|
||||||
//cover: CoverBackground {CoverPlaceholder { icon.source: "icon.png"; text: "Sailfin"}}
|
//cover: CoverBackground {CoverPlaceholder { icon.source: "icon.png"; text: "Sailfin"}}
|
||||||
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 ([MediaStatus.NoMedia, MediaStatus.InvalidMedia].indexOf(_playbackManager.mediaStatus) >= 0
|
||||||
|| _playbackManager.playbackState === MediaPlayer.StoppedState) {
|
|| _playbackManager.playbackState === MediaPlayer.StoppedState) {
|
||||||
return Qt.resolvedUrl("cover/CollectionPage.qml")
|
return Qt.resolvedUrl("cover/CollectionPage.qml")
|
||||||
} else {
|
} else {
|
||||||
|
@ -134,7 +134,9 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayBlanking {
|
DisplayBlanking {
|
||||||
preventBlanking: playbackManager.playbackState === MediaPlayer.PlayingState && playbackManager.hasVideo
|
preventBlanking: playbackManager.playbackState === MediaPlayer.PlayingState
|
||||||
|
&& playbackManager.hasVideo
|
||||||
|
&& playbackManager.controllingSessionLocal // Must be controlling a local session
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaybackBar {
|
PlaybackBar {
|
||||||
|
|
|
@ -25,7 +25,7 @@ Page {
|
||||||
property bool isConnected: model.jellyfinId === appWindow.playbackManager.controllingSessionId
|
property bool isConnected: model.jellyfinId === appWindow.playbackManager.controllingSessionId
|
||||||
onClicked: deviceList.activateSession(appWindow.playbackManager, model.index)
|
onClicked: deviceList.activateSession(appWindow.playbackManager, model.index)
|
||||||
contentHeight: Theme.itemSizeMedium
|
contentHeight: Theme.itemSizeMedium
|
||||||
HighlightImage {
|
Icon {
|
||||||
id: deviceIcon
|
id: deviceIcon
|
||||||
anchors {
|
anchors {
|
||||||
left: parent.left
|
left: parent.left
|
||||||
|
|
|
@ -38,7 +38,16 @@ Page {
|
||||||
property int subtitleTrack
|
property int subtitleTrack
|
||||||
property bool resume: true
|
property bool resume: true
|
||||||
|
|
||||||
allowedOrientations: Orientation.All
|
allowedOrientations: {
|
||||||
|
if (itemData.width !== null && itemData.height !== null) {
|
||||||
|
return itemData.width / itemData.height > Screen.width / Screen.height
|
||||||
|
? Orientation.LandscapeMask
|
||||||
|
: Orientation.PortraitMask
|
||||||
|
} else {
|
||||||
|
return Orientation.All
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
showNavigationIndicator: videoPlayer.hudVisible
|
showNavigationIndicator: videoPlayer.hudVisible
|
||||||
|
|
||||||
VideoPlayer {
|
VideoPlayer {
|
||||||
|
|
Loading…
Reference in a new issue