Warning, /multimedia/audiotube/src/contents/ui/MaximizedPlayerPage.qml is written in an unsupported language. File is not indexed.
0001 // SPDX-FileCopyrightText: 2020-2022 Devin Lin <devin@kde.org>
0002 //
0003 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004
0005 import QtQuick 2.15
0006 import QtQuick.Effects
0007 import QtQuick.Controls 2.15
0008 import QtQuick.Layouts 1.15
0009
0010 import QtMultimedia
0011
0012 import org.kde.kirigami 2.19 as Kirigami
0013 import org.kde.kirigamiaddons.components 1.0 as Components
0014 import org.kde.ytmusic 1.0
0015
0016 import "dialogs"
0017
0018 Item {
0019 id: root
0020
0021 required property var info // VideoInfoExtractor object
0022 required property var audio // Audio object
0023 required property string thumbnail
0024 readonly property bool isWidescreen: width >= Kirigami.Units.gridUnit * 50
0025
0026 signal requestClose()
0027
0028 onWidthChanged: {sideDrawer.Layout.minimumWidth = -1}
0029
0030 // background image
0031
0032 Item {
0033 id: bg
0034 anchors.fill: parent
0035 clip: true
0036
0037 Rectangle {
0038 anchors.fill: parent
0039 color: Qt.rgba(25, 25, 30, 1)
0040 }
0041
0042 Image {
0043 scale: 1.8
0044 anchors.fill: parent
0045 asynchronous: true
0046
0047 source: root.thumbnail
0048 fillMode: Image.PreserveAspectCrop
0049
0050 sourceSize.width: 512
0051 sourceSize.height: 512
0052 }
0053 }
0054 MultiEffect {
0055 source: bg
0056 anchors.fill: bg
0057
0058 brightness: -0.25
0059 saturation: 0.5
0060
0061 blurEnabled: true
0062 autoPaddingEnabled: false
0063 blur: 1.0
0064 blurMax: 40
0065 blurMultiplier: 3.0
0066 }
0067
0068 Rectangle {
0069 anchors.fill: parent
0070 gradient: Gradient{
0071 GradientStop { position: 0.0; color: "transparent" }
0072 GradientStop { position: 1.1; color: "black" }
0073 }
0074 }
0075
0076 // content
0077 RowLayout {
0078 anchors.fill: parent
0079
0080 ColumnLayout {
0081 id: mainContent
0082 Layout.fillWidth: true
0083 // hide arrow button
0084 ToolButton {
0085 id: closeButton
0086
0087 Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
0088 Layout.maximumHeight: parent.height
0089 Layout.preferredHeight: Kirigami.Units.gridUnit * 3
0090 Layout.maximumWidth: parent.height
0091 Layout.preferredWidth: Kirigami.Units.gridUnit * 3
0092 Layout.topMargin: Kirigami.Units.smallSpacing
0093
0094 icon.name: "arrow-down"
0095 icon.color: "white"
0096 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0097 Kirigami.Theme.inherit: false
0098 onClicked: root.requestClose()
0099 text: i18n("Close Maximized Player")
0100 display: ToolButton.IconOnly
0101
0102 ToolTip.text: text
0103 ToolTip.delay: Kirigami.Units.toolTipDelay
0104 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
0105 }
0106
0107 SwipeView {
0108 interactive: false
0109 Layout.fillHeight: true
0110 Layout.fillWidth: true
0111 clip:true
0112 id: swipeView
0113 property double specWidth: {
0114 let allowedWidth = root.width - Kirigami.Units.largeSpacing * 4;
0115 let allowedHeight = root.height - Kirigami.Units.largeSpacing * 16 - (closeButton.height + bottomPlayerControls.height);
0116 if (allowedWidth > allowedHeight) {
0117 return allowedHeight;
0118 } else {
0119 return allowedWidth;
0120 }
0121 }
0122 Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
0123 Layout.preferredHeight: specWidth
0124
0125 // music art
0126 Flickable {
0127 flickableDirection: Flickable.HorizontalFlick
0128 clip: true
0129 contentWidth: coverArt.width
0130 contentHeight: coverArt.height
0131 height: swipeView.height
0132 width: applicationWindow().width-sideDrawer.width
0133 onFlickEnded:{
0134
0135 if(horizontalVelocity<0){
0136 UserPlaylistModel.next()
0137 }
0138 else{
0139 if(UserPlaylistModel.canSkipBack){
0140 UserPlaylistModel.previous()
0141 }
0142 }
0143 }
0144 Item {
0145 height: swipeView.height
0146 width: applicationWindow().width-sideDrawer.width
0147 Kirigami.ShadowedRectangle {
0148 id: coverArt
0149 x: 4
0150 anchors.centerIn: parent
0151 width: swipeView.specWidth
0152 height: swipeView.specWidth
0153
0154 visible: root.thumbnail.toString() !== ""
0155
0156 color: "transparent"
0157 radius: 10
0158 shadow.size: 15
0159 shadow.xOffset: 5
0160 shadow.yOffset: 5
0161 shadow.color: Qt.rgba(0, 0, 0, 0.2)
0162 RoundedImage {
0163 source: root.thumbnail
0164 height: parent.height
0165 width: height
0166 radius: 10
0167 }
0168 }
0169 }
0170 }
0171
0172 ColumnLayout {
0173 width: swipeView.width
0174 height: swipeView.height
0175 ScrollView {
0176 Layout.maximumWidth: 900
0177 contentWidth: -1
0178 contentHeight: lyrics.implicitHeight
0179 Layout.fillWidth: true
0180 Layout.fillHeight: true
0181 Layout.alignment: Qt.AlignHCenter
0182 clip: true
0183
0184 //contentY: audio.position / audio.duration
0185
0186 Label {
0187 id: lyrics
0188 padding: 20
0189 text: UserPlaylistModel.lyrics
0190 color: "white"
0191 }
0192 }
0193 }
0194 }
0195
0196 ColumnLayout {
0197 id: bottomPlayerControls
0198 Layout.topMargin: Kirigami.Units.largeSpacing
0199 Layout.leftMargin: Kirigami.Units.gridUnit * 2
0200 Layout.rightMargin: Kirigami.Units.gridUnit * 2
0201 Layout.bottomMargin: Kirigami.Units.gridUnit * 0.5
0202
0203 // song name
0204 Label {
0205 id: mainLabel
0206 text: info.title ? info.title : i18n("No media playing")
0207
0208 Layout.fillWidth: true
0209
0210 horizontalAlignment: Text.AlignHCenter
0211 elide: Text.ElideRight
0212 maximumLineCount: 1
0213 // Hardcoded because the footerbar blur always makes a dark-ish
0214 // background, so we don't want to use a color scheme color that
0215 // might also be dark
0216 color: "white"
0217 font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.5
0218 font.weight: Font.Bold
0219 font.bold: true
0220 }
0221
0222 // song artist
0223 Kirigami.Heading {
0224 id: authorLabel
0225 text: info.artist ? info.artist : info.channel
0226 color: Kirigami.Theme.disabledTextColor
0227
0228 Layout.fillWidth: true
0229 Layout.maximumWidth:600
0230 Layout.alignment: Qt.AlignHCenter
0231 horizontalAlignment: Text.AlignHCenter
0232 elide: Text.ElideRight
0233 maximumLineCount: 1
0234 // Hardcoded because the footerbar blur always makes a dark-ish
0235 // background, so we don't want to use a color scheme color that
0236 // might also be dark
0237 opacity: 0.9
0238 font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.3
0239 font.bold: true
0240 Layout.bottomMargin: Kirigami.Units.gridUnit
0241 }
0242 RowLayout {
0243 Layout.topMargin: Kirigami.Units.gridUnit
0244
0245 id: controlButtonBox
0246 Layout.alignment: Qt.AlignHCenter
0247 Layout.fillHeight: true
0248 spacing: 2
0249
0250
0251 Button {
0252 id: skipBackwardButton
0253 focusPolicy: Qt.TabFocus
0254 implicitHeight: 40
0255 implicitWidth: 40
0256
0257 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0258 Kirigami.Theme.inherit: false
0259
0260 enabled: UserPlaylistModel.canSkipBack
0261 onClicked: UserPlaylistModel.previous()
0262 contentItem: Item{
0263 Kirigami.Icon {
0264 anchors.centerIn:parent
0265 source:"media-skip-backward"
0266 color: "white"
0267 width: Kirigami.Units.gridUnit
0268 height: Kirigami.Units.gridUnit
0269
0270 }
0271 }
0272 background: Kirigami.ShadowedRectangle{
0273 border.color: Kirigami.Theme.hoverColor
0274 border.width: skipBackwardButton.activeFocus? 1 :0
0275 corners.topLeftRadius: 7
0276 corners.bottomLeftRadius: 7
0277
0278
0279 color: if (parent.down){
0280 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
0281 }else if(parent.hovered){
0282 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
0283 }else{
0284 Qt.rgba(1, 1, 1, 0.2)
0285 }
0286 }
0287 }
0288
0289 Button {
0290 id: playPauseButton
0291 focusPolicy: Qt.TabFocus
0292 implicitHeight: 40
0293 implicitWidth: 60
0294 enabled: info.title
0295 onClicked: audio.playbackState === MediaPlayer.PlayingState ? audio.pause() : audio.play()
0296 contentItem: Item{
0297 Kirigami.Icon {
0298 anchors.centerIn:parent
0299 source: audio.playbackState === MediaPlayer.PlayingState ? "media-playback-pause" : "media-playback-start"
0300 color: "white"
0301 width: Kirigami.Units.gridUnit
0302 height: Kirigami.Units.gridUnit
0303 }
0304 }
0305 background: Kirigami.ShadowedRectangle{
0306 border.color: Kirigami.Theme.hoverColor
0307 border.width: playPauseButton.activeFocus? 1 :0
0308 color: if (parent.down){
0309 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
0310 }else if(parent.hovered){
0311 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
0312 }else{
0313 Qt.rgba(1, 1, 1, 0.2)
0314 }
0315 }
0316 }
0317
0318 Button {
0319 id: skipForwardButton
0320 focusPolicy: Qt.TabFocus
0321 implicitHeight: 40
0322 implicitWidth: 40
0323 Layout.rightMargin:isWidescreen?0:10
0324
0325 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0326 Kirigami.Theme.inherit: false
0327
0328 enabled: UserPlaylistModel.canSkip
0329 onClicked: UserPlaylistModel.next()
0330 contentItem: Item{
0331 Kirigami.Icon {
0332 anchors.centerIn:parent
0333 source:"media-skip-forward"
0334 color: "white"
0335 width: Kirigami.Units.gridUnit
0336 height: Kirigami.Units.gridUnit
0337
0338 }
0339 }
0340 background: Kirigami.ShadowedRectangle{
0341 border.color: Kirigami.Theme.hoverColor
0342 border.width: skipForwardButton.activeFocus? 1 :0
0343 corners.topRightRadius: 7
0344 corners.bottomRightRadius: 7
0345 color: if (parent.down){
0346 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
0347 }else if(parent.hovered){
0348 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
0349 }else{
0350 Qt.rgba(1, 1, 1, 0.2)
0351 }
0352 }
0353 }
0354 }
0355 // slider row
0356 RowLayout {
0357 Layout.topMargin: Kirigami.Units.gridUnit
0358 spacing: Kirigami.Units.smallSpacing
0359
0360 Label {
0361 Layout.alignment: Qt.AlignVCenter
0362 color: "white"
0363 visible: info.title
0364 text: PlayerUtils.formatTimestamp(audio.position)
0365 }
0366
0367 Slider {
0368 Layout.alignment: Qt.AlignVCenter
0369 Layout.fillWidth: true
0370 from: 0
0371 to: audio.duration
0372 value: audio.position
0373 enabled: audio.seekable
0374 onMoved: {
0375 console.log("Value:", value);
0376 audio.position = Math.floor(value);
0377 }
0378
0379 Behavior on value {
0380 NumberAnimation {
0381 duration: 1000
0382 }
0383 }
0384 }
0385
0386 Label {
0387 Layout.alignment: Qt.AlignVCenter
0388 color: "white"
0389 visible: info.title
0390 text: PlayerUtils.formatTimestamp(audio.duration)
0391 }
0392 }
0393
0394 RowLayout {
0395 Layout.topMargin: Kirigami.Units.largeSpacing
0396 Layout.fillWidth: true
0397 // ensure white icons
0398 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0399 Kirigami.Theme.inherit: false
0400 Item {
0401 width: queueButton.width
0402 visible: wideScreen
0403 }
0404
0405 Item { Layout.fillWidth: true}
0406
0407 ToolButton {
0408 id: favouriteButton
0409 readonly property QtObject favouriteWatcher: Library.favouriteWatcher(info.videoId)
0410 Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
0411 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0412 Layout.maximumWidth: height
0413 Layout.preferredWidth: height
0414 onClicked: {
0415 if (favouriteWatcher) {
0416 if (favouriteWatcher.isFavourite) {
0417 Library.removeFavourite(info.videoId)
0418 // This would insert slightly ugly data into the database, but let's hope the song is already saved
0419 } else {
0420 let index = UserPlaylistModel.index(UserPlaylistModel.currentIndex, 0)
0421 let videoId = UserPlaylistModel.data(index, UserPlaylistModel.VideoId)
0422 let title = UserPlaylistModel.data(index, UserPlaylistModel.Title)
0423 let artist = UserPlaylistModel.data(index, UserPlaylistModel.Artists)
0424 let album = UserPlaylistModel.data(index, UserPlaylistModel.Album)
0425 Library.addFavourite(videoId, title, artist, album)
0426 }
0427 }
0428 }
0429 text: favouriteWatcher ? (favouriteWatcher.isFavourite ? i18n("Remove from Favourites") : i18n("Add to Favourites")) : i18n("Add to Favourites")
0430 icon.name: favouriteWatcher ? (favouriteWatcher.isFavourite ? "starred-symbolic" : "non-starred-symbolic") : "non-starred-symbolic"
0431 enabled: favouriteWatcher
0432 icon.color: "white"
0433 display: AbstractButton.IconOnly
0434
0435 ToolTip.text: text
0436 ToolTip.delay: Kirigami.Units.toolTipDelay
0437 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
0438
0439 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0440 Kirigami.Theme.inherit: false
0441 }
0442
0443 ToolButton {
0444 id: volumeButtonSmallScreen
0445 Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
0446 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0447 Layout.maximumWidth: height
0448 Layout.preferredWidth: height
0449 visible: !isWidescreen
0450 enabled: !isWidescreen
0451
0452 icon.name: muteButton.icon.name
0453
0454 text: i18n("Open Volume Drawer")
0455 display: AbstractButton.IconOnly
0456 ToolTip.text: text
0457 ToolTip.delay: Kirigami.Units.toolTipDelay
0458 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
0459
0460 onClicked:{
0461 if(!volumeDrawer.opened){
0462 volumeDrawer.open()
0463 }
0464 else{
0465 volumeDrawer.close()
0466 }
0467 }
0468 Components.BottomDrawer {
0469 id: volumeDrawer
0470
0471 parent: applicationWindow().overlay
0472
0473 drawerContentItem: RowLayout {
0474 ToolButton {
0475 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0476 Layout.maximumWidth: height
0477 Layout.preferredWidth: height
0478
0479 icon.name: muteButton.icon.name
0480 checkable: true
0481 checked: muteButton.checked
0482 text: muteButton.text
0483 display: muteButton.display
0484
0485 ToolTip.text: text
0486 ToolTip.delay: Kirigami.Units.toolTipDelay
0487 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
0488
0489 onClicked: {
0490 if(audio.muted)
0491 {
0492 muteButton.unmuteAudio()
0493 }
0494 else
0495 {
0496 muteButton.muteAudio()
0497 }
0498 }
0499 }
0500
0501 Slider {
0502 id: slider
0503 value: volumeSlider.value
0504 opacity: volumeSlider.opacity
0505 wheelEnabled: true
0506
0507 Layout.fillWidth: true
0508 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0509
0510 onMoved: {
0511 volumeSlider.value = value
0512 volumeSlider.valueChanged()
0513 }
0514 }
0515
0516 Label {
0517 Layout.preferredHeight: slider.height
0518 Layout.preferredWidth: Kirigami.Units.gridUnit * 2.5
0519
0520 text: volumeLabel.text
0521 }
0522 }
0523 }
0524 }
0525
0526 ToolButton {
0527 id: muteButton
0528
0529 function muteAudio() {
0530 audioOutput.muted = true
0531 volumeSlider.opacity = 0.5
0532 checked = true
0533 }
0534 function unmuteAudio() {
0535 audioOutput.muted = false
0536 volumeSlider.opacity = 1
0537 checked = false
0538 }
0539
0540 Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
0541 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0542 Layout.maximumWidth: height
0543 Layout.preferredWidth: height
0544
0545 onClicked: {
0546 if(audioOutput.muted) {
0547 unmuteAudio()
0548 }
0549 else {
0550 muteAudio()
0551 }
0552 }
0553
0554 icon.name: audioOutput.muted ? "audio-volume-muted" : (volumeSlider.value < .33 ? "audio-volume-low" : (volumeSlider.value < .66 ? "audio-volume-medium" : "audio-volume-high"))
0555 icon.color: "white"
0556
0557 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0558 Kirigami.Theme.inherit: false
0559
0560 checkable: true
0561 visible: isWidescreen
0562 enabled: isWidescreen
0563 text: audioOutput.muted ? i18n("Unmute Audio") : i18n("Mute Audio")
0564 display: AbstractButton.IconOnly
0565
0566 ToolTip.text: text
0567 ToolTip.delay: Kirigami.Units.toolTipDelay
0568 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
0569 }
0570
0571 Slider {
0572 id: volumeSlider
0573 enabled: isWidescreen
0574 visible: isWidescreen
0575
0576 property real volume: PlayerUtils.convertVolume(value)
0577
0578 Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
0579 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0580 Layout.preferredWidth: 2*Layout.preferredHeight
0581
0582 value: 1.0
0583 from: 0.0
0584 to: 1.0
0585 wheelEnabled: true
0586
0587 onMoved: {
0588 audioOutput.volume = volumeSlider.volume
0589 if (volumeSlider.value === 0) {
0590 muteButton.muteAudio()
0591 } else {
0592 muteButton.unmuteAudio()
0593 }
0594 }
0595 }
0596
0597 Label {
0598 id: volumeLabel
0599
0600 enabled: isWidescreen
0601 visible: isWidescreen
0602 text: i18n("%1%", Math.round(volumeSlider.value*100))
0603
0604 Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
0605 Layout.preferredWidth: Kirigami.Units.gridUnit * 2.5
0606 }
0607
0608 ToolButton {
0609 property bool lyricsShown: false
0610 id: lyricsButton
0611 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0612 Layout.maximumWidth: height
0613 Layout.preferredWidth: height
0614 checked: lyricsShown
0615 onClicked: {
0616 if (!lyricsShown)
0617 swipeView.setCurrentIndex(1)
0618 else{
0619 swipeView.setCurrentIndex(0)
0620 }
0621 lyricsShown = !lyricsShown
0622 }
0623 Connections {
0624 target: UserPlaylistModel
0625 function onNoLyrics() {
0626 if(lyricsButton.lyricsShown) {
0627 lyricsButton.clicked()
0628 }
0629 }
0630 }
0631 enabled: UserPlaylistModel.lyrics
0632 text: lyricsShown ? i18n("Hide Lyrics") : i18n("Show Lyrics")
0633 icon.name: "view-media-lyrics"
0634 icon.color: "white"
0635 display: AbstractButton.IconOnly
0636
0637 ToolTip.text: text
0638 ToolTip.delay: Kirigami.Units.toolTipDelay
0639 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
0640
0641 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0642 Kirigami.Theme.inherit: false
0643 }
0644 ToolButton {
0645
0646 id: shareButton
0647 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0648 Layout.maximumWidth: height
0649 Layout.preferredWidth: height
0650 onClicked: openShareMenu(info.title, UserPlaylistModel.webUrl)
0651
0652 text: i18n("Share Song")
0653 icon.name: "emblem-shared-symbolic"
0654 icon.color: "white"
0655 display: AbstractButton.IconOnly
0656
0657 ToolTip.text: text
0658 ToolTip.delay: Kirigami.Units.toolTipDelay
0659 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
0660
0661 enabled: info.title
0662
0663 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0664 Kirigami.Theme.inherit: false
0665 }
0666
0667 PlaylistDialog {
0668 id: playlistsDialog
0669 }
0670 ToolButton {
0671 id: addToPlaylistButton
0672 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0673 Layout.maximumWidth: height
0674 Layout.preferredWidth: height
0675 enabled: info.videoId
0676
0677 onClicked: {
0678 let index = UserPlaylistModel.index(UserPlaylistModel.currentIndex, 0)
0679 let videoId = UserPlaylistModel.data(index, UserPlaylistModel.VideoId)
0680 let title = UserPlaylistModel.data(index, UserPlaylistModel.Title)
0681 let artist = UserPlaylistModel.data(index, UserPlaylistModel.Artists)
0682 let album = UserPlaylistModel.data(index, UserPlaylistModel.Album)
0683 playlistsDialog.videoId = videoId
0684 playlistsDialog.songTitle = title
0685 playlistsDialog.artists = artist
0686 playlistsDialog.album = album
0687
0688 playlistsDialog.open()
0689 }
0690
0691 icon.name: "media-playlist-append"
0692 icon.color: "white"
0693 text: i18n("Add to a local playlist")
0694 display: AbstractButton.IconOnly
0695
0696 ToolTip.text: text
0697 ToolTip.delay: Kirigami.Units.toolTipDelay
0698 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
0699
0700 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0701 Kirigami.Theme.inherit: false
0702 }
0703 Item {
0704 Layout.fillWidth: true
0705 visible: wideScreen
0706 }
0707
0708 ToolButton {
0709 id: queueButton
0710 Layout.alignment: Qt.AlignRight
0711 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0712 Layout.maximumWidth: height
0713 Layout.preferredWidth: height
0714 checked: !sideDrawer.collapsed && wideScreen
0715 enabled: playListView.count != 0 || !sideDrawer.collapsed
0716
0717 onClicked: {
0718 if (wideScreen) {
0719 if (!sideDrawer.collapsed)
0720 collapse.running = true
0721 else{
0722 sideDrawer.visible=true
0723 show.running = true
0724 }
0725 sideDrawer.collapsed = !sideDrawer.collapsed
0726 }else{queueDrawer.open()}
0727 checked = !sideDrawer.collapsed && wideScreen
0728 }
0729
0730 text: checked ? i18n("Hide Queue") : i18n("Show Queue")
0731 display: AbstractButton.IconOnly
0732
0733 ToolTip.text: text
0734 ToolTip.delay: Kirigami.Units.toolTipDelay
0735 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
0736
0737 icon.name: "amarok_playlist"
0738 icon.color: "white"
0739
0740 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0741 Kirigami.Theme.inherit: false
0742 }
0743
0744 Item {
0745 Layout.fillWidth: true
0746 visible: !wideScreen
0747 }
0748
0749 }
0750 }
0751 }
0752
0753 Item {
0754 onWidthChanged: if(!wideScreen) {collapse.running=true; collapsed=true; queueButton.checked=false}
0755 property bool collapsed: true
0756 id: sideDrawer
0757 Layout.fillWidth: true
0758 Layout.maximumWidth: -1
0759 Layout.preferredWidth: Math.max(350, root.width/3)
0760
0761 Layout.fillHeight: true
0762 visible: false
0763 NumberAnimation on Layout.maximumWidth {
0764 id: collapse
0765 easing.type: Easing.OutCubic
0766 running: false
0767 from: Math.min(sideDrawer.Layout.preferredWidth, sideDrawer.Layout.maximumWidth); to: 0
0768 onFinished: { sideDrawer.visible=false}
0769 }
0770 NumberAnimation on Layout.maximumWidth {
0771 id: show
0772 easing.type: Easing.OutCubic
0773 running: false
0774 from: 0; to: Math.min(sideDrawer.Layout.preferredWidth, root.width - mainContent.Layout.minimumWidth)
0775 //onFinished: { sideDrawer.visible=false}
0776 }
0777 Kirigami.Separator{
0778 color: "white"
0779 opacity: 0.3
0780 height: parent.height
0781 anchors.left: parent.left
0782
0783 }
0784 Rectangle{
0785 anchors.fill: parent
0786 color: "white"
0787 opacity: 0.2
0788 }
0789
0790 MouseArea {
0791 id: queueResizer
0792
0793 anchors.horizontalCenter: parent.left
0794 anchors.top: parent.top
0795 anchors.bottom: parent.bottom
0796 width: Kirigami.Units.gridUnit
0797
0798 cursorShape: Qt.SplitHCursor
0799 onPositionChanged: {
0800 if(Math.max(sideDrawer.width - (mouse.x - width/2), queueFooter.Layout.minimumWidth) + mainContent.Layout.minimumWidth < root.width){
0801 sideDrawer.Layout.preferredWidth = sideDrawer.Layout.minimumWidth = sideDrawer.Layout.maximumWidth = Math.max(sideDrawer.width - (mouse.x - width/2), queueFooter.Layout.minimumWidth)
0802 }
0803 }
0804 }
0805
0806 ColumnLayout {
0807 spacing: 0
0808 anchors.fill: parent
0809 ScrollView {
0810 id: playListScrollView
0811
0812 contentWidth: availableWidth
0813
0814 Layout.fillWidth: true
0815 Layout.fillHeight: true
0816 Layout.leftMargin:10
0817 ListView {
0818 id: playListView
0819
0820 reuseItems: true
0821
0822 spacing: 5
0823 rightMargin: 10
0824 topMargin:10
0825 bottomMargin: 10
0826 clip: true
0827 contentWidth: playListScrollView.contentWidth - rightMargin - leftMargin
0828
0829 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0830 Kirigami.Theme.inherit: false
0831
0832 BusyIndicator {
0833 anchors.centerIn: parent
0834 visible: UserPlaylistModel.loading || UserPlaylistModel.loading
0835 }
0836
0837 model: UserPlaylistModel
0838
0839 moveDisplaced: Transition {
0840 YAnimator {
0841 duration: Kirigami.Units.mediumDuration
0842 easing.type: Easing.InOutQuad
0843 }
0844 }
0845
0846 delegate: Item{
0847 //listItemDragHandle requires queueEntry to be a child of the delegate, and not the delegate itself
0848 id: delegateItem
0849
0850 required property string title
0851 required property string videoId
0852 required property string artists
0853 required property bool isCurrent
0854 required property int index
0855 width: queueEntry.implicitWidth
0856 height: queueEntry.implicitHeight
0857
0858 ItemDelegate {
0859 id: queueEntry
0860
0861 width: playListView.contentWidth
0862
0863 background: Rectangle{
0864 radius: 7
0865 color:
0866 if (parent.down){
0867 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
0868 }else if(parent.hovered){
0869 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
0870 }else if(parent.highlighted){
0871 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
0872 }else{
0873 Qt.rgba(0, 0, 0, 0.4)
0874 }
0875
0876 border.color:
0877 if (parent.down){
0878 Kirigami.Theme.hoverColor
0879 }else if(parent.hovered){
0880 Kirigami.Theme.hoverColor
0881 }else{
0882 Qt.rgba(1, 1, 1, 0)
0883 }
0884
0885 border.width: 1
0886 }
0887 highlighted: isCurrent
0888 onClicked: UserPlaylistModel.skipTo(videoId)
0889 contentItem: RowLayout {
0890 id: contentLayout
0891
0892 Item {
0893 width: handle.width
0894 height: handle.height
0895 Kirigami.ListItemDragHandle {
0896 id: handle
0897 Layout.fillHeight: true
0898 listItem: queueEntry
0899 listView: playListView
0900 onMoveRequested: UserPlaylistModel.moveRow(oldIndex, newIndex)
0901 }
0902 Rectangle {
0903 anchors.fill: handle
0904 layer.enabled: true
0905 layer.effect: MultiEffect {
0906 maskSource: handle
0907 maskEnabled: true
0908 }
0909 }
0910 }
0911 ThumbnailSource {
0912 id: delegateThumbnailSource
0913 videoId: delegateItem.videoId
0914 }
0915 RoundedImage {
0916 source: delegateThumbnailSource.cachedPath
0917 Layout.margins: 2.5
0918 height: column.implicitHeight
0919 width: column.implicitHeight
0920 radius: 5
0921 }
0922
0923 ColumnLayout {
0924 id: column
0925 Layout.margins: 5
0926
0927 Layout.fillWidth: true
0928 Layout.fillHeight: true
0929
0930 Kirigami.Heading {
0931 elide: Text.ElideRight
0932 Layout.fillWidth: true
0933 level: 2
0934 text: title
0935
0936 MouseArea {
0937 anchors.fill: parent
0938 hoverEnabled: true
0939 ToolTip.text: parent.text
0940 ToolTip.delay: Kirigami.Units.toolTipDelay
0941 ToolTip.visible: parent.truncated ? (Kirigami.Settings.isMobile ? containsPress : containsMouse) : false
0942 }
0943 }
0944
0945 Label {
0946 elide: Text.ElideRight
0947 Layout.fillWidth: true
0948 color: Kirigami.Theme.disabledTextColor
0949 text: artists
0950 }
0951
0952 }
0953 ToolButton {
0954 text: i18n("Remove Track")
0955 icon.name: "list-remove"
0956 icon.color: "white"
0957 display: AbstractButton.IconOnly
0958 onClicked: UserPlaylistModel.remove(delegateItem.videoId)
0959 }
0960 }
0961 }
0962 }
0963 }
0964 }
0965
0966
0967 Kirigami.Separator {
0968 color: "white"
0969 opacity: 0.3
0970 Layout.fillWidth: true
0971 }
0972
0973 RowLayout {
0974 id: queueFooter
0975
0976 Layout.margins: Kirigami.Units.gridUnit * 0.5
0977 enabled: playListView.count != 0
0978 Item {
0979 Layout.fillWidth: true
0980 }
0981
0982 ToolButton {
0983 id: clearPlaylistButton
0984
0985 Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
0986 Layout.maximumWidth: height
0987 Layout.preferredWidth: height
0988
0989 text: i18n("Clear Queue")
0990 icon {
0991 name: "edit-clear-all"
0992 color: "white"
0993 }
0994 display: AbstractButton.IconOnly
0995
0996 ToolTip.text: text
0997 ToolTip.delay: Kirigami.Units.toolTipDelay
0998 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
0999
1000 onClicked: UserPlaylistModel.clearExceptCurrent()
1001
1002 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
1003 Kirigami.Theme.inherit: false
1004 }
1005
1006 ToolButton {
1007 id: shuffleButton
1008 Layout.preferredHeight: Math.round(Kirigami.Units.gridUnit * 2.5)
1009 Layout.maximumWidth: height
1010 Layout.preferredWidth: height
1011
1012 onClicked: UserPlaylistModel.shufflePlaylist()
1013
1014 text: i18n("Shuffle Queue")
1015
1016 ToolTip.text: text
1017 ToolTip.delay: Kirigami.Units.toolTipDelay
1018 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
1019
1020 icon {
1021 name: "media-playlist-shuffle"
1022 color: "white"
1023 }
1024 display: AbstractButton.IconOnly
1025 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
1026 Kirigami.Theme.inherit: false
1027 }
1028
1029 Item {
1030 Layout.fillWidth: true
1031 }
1032 }
1033 }
1034 }
1035
1036 Components.BottomDrawer {
1037 id: queueDrawer
1038
1039 parent: applicationWindow().overlay
1040
1041 onClosed:{sideDrawer.collapsed=true}
1042 height: applicationWindow().height-50
1043 interactive: true
1044
1045 headerContentItem: RowLayout {
1046 Kirigami.Heading {
1047 text: i18n("Upcoming Songs")
1048 elide: Qt.ElideRight
1049 Layout.margins: 0
1050 Layout.fillWidth: true
1051 }
1052 Item {
1053 Layout.fillWidth: true
1054 }
1055 ToolButton {
1056 Layout.topMargin: 0
1057 Layout.bottomMargin: 0
1058 Layout.maximumWidth: height
1059 Layout.preferredWidth: height
1060 text: clearPlaylistButton.text
1061
1062 ToolTip.text: text
1063 ToolTip.delay: Kirigami.Units.toolTipDelay
1064 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
1065
1066 icon.name: "edit-clear-all"
1067 display: clearPlaylistButton.display
1068 onClicked: {
1069 UserPlaylistModel.clearExceptCurrent()
1070 }
1071 enabled: playListView.count != 0
1072 }
1073
1074 ToolButton {
1075 Layout.topMargin: 0
1076 Layout.bottomMargin: 0
1077 Layout.maximumWidth: height
1078 Layout.preferredWidth: height
1079 icon.name: "media-playlist-shuffle"
1080 text: shuffleButton.text
1081 display: shuffleButton.display
1082
1083 ToolTip.text: text
1084 ToolTip.delay: Kirigami.Units.toolTipDelay
1085 ToolTip.visible: Kirigami.Settings.isMobile ? pressed : hovered
1086
1087 onClicked: {
1088 UserPlaylistModel.shufflePlaylist()
1089 }
1090 enabled: playListView.count != 0
1091 }
1092 }
1093
1094 drawerContentItem: ScrollView {
1095 ListView {
1096 id: drawerListView
1097 topMargin: 10
1098 clip: true
1099
1100 reuseItems: true
1101
1102 BusyIndicator {
1103 anchors.centerIn: parent
1104 visible: UserPlaylistModel.loading || UserPlaylistModel.loading
1105 }
1106
1107 model: UserPlaylistModel
1108
1109 moveDisplaced: Transition {
1110 YAnimator {
1111 duration: Kirigami.Units.mediumDuration
1112 easing.type: Easing.InOutQuad
1113 }
1114 }
1115
1116 delegate: Item {
1117 id: drawerDelegateItem
1118 required property string title
1119 required property string videoId
1120 required property string artists
1121 required property bool isCurrent
1122 required property int index
1123
1124 width: drawerListView.width
1125 height: drawerQueueEntry.height
1126
1127 ItemDelegate {
1128 id: drawerQueueEntry
1129
1130 width: parent.width
1131
1132 highlighted: drawerDelegateItem.isCurrent
1133 onClicked: {
1134 queueDrawer.close()
1135 UserPlaylistModel.skipTo(drawerDelegateItem.videoId)
1136 }
1137 contentItem: RowLayout {
1138 Layout.fillWidth: true
1139 Item {
1140 width: drawerHandle.width
1141 height: drawerHandle.height
1142 Kirigami.ListItemDragHandle {
1143 id: drawerHandle
1144 Layout.fillHeight: true
1145 listItem: drawerQueueEntry
1146 listView: drawerListView
1147 onMoveRequested: UserPlaylistModel.moveRow(oldIndex, newIndex)
1148 }
1149
1150 Rectangle {
1151 anchors.fill: drawerHandle
1152 layer.enabled: true
1153 layer.effect: MultiEffect {
1154 maskSource: drawerHandle
1155 maskEnabled: true
1156 }
1157 }
1158 }
1159 ThumbnailSource {
1160 id: drawerDelegateThumbnailSource
1161 videoId: drawerDelegateItem.videoId
1162 }
1163 RoundedImage {
1164 source: drawerDelegateThumbnailSource.cachedPath
1165
1166 height: 50
1167 width: height
1168 radius: 5
1169 }
1170
1171 ColumnLayout {
1172 Layout.margins: 5
1173 Layout.fillWidth: true
1174 Kirigami.Heading {
1175 elide: Text.ElideRight
1176 Layout.fillWidth: true
1177 level: 2
1178 text: drawerDelegateItem.title
1179
1180 MouseArea {
1181 anchors.fill: parent
1182 hoverEnabled: true
1183 ToolTip.text: parent.text
1184 ToolTip.delay: Kirigami.Units.toolTipDelay
1185 ToolTip.visible: parent.truncated ? (Kirigami.Settings.isMobile ? containsPress : containsMouse) : false
1186 }
1187 }
1188
1189 Label {
1190 elide: Text.ElideRight
1191 Layout.fillWidth: true
1192 color: Kirigami.Theme.disabledTextColor
1193 text: drawerDelegateItem.artists
1194 }
1195 }
1196
1197 ToolButton {
1198 text: i18n("Remove Track")
1199 icon.name: "list-remove"
1200 display: AbstractButton.IconOnly
1201 onClicked: UserPlaylistModel.remove(drawerDelegateItem.videoId)
1202 }
1203 }
1204 }
1205 }
1206 }
1207 }
1208 }
1209 }
1210 }