mirror of https://github.com/KDE/kasts.git
Finished player and beginning of queue
This commit is contained in:
parent
5abbd56c88
commit
61d443f0e3
|
@ -54,7 +54,7 @@ Kirigami.SwipeListItem {
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
model.entry.read = true
|
model.entry.read = true
|
||||||
pageStack.push(model.entry.enclosure ? "qrc:/PodcastPlayerPage.qml" : "qrc:/EntryPage.qml", {"entry": model.entry})
|
pageStack.push("qrc:/EntryPage.qml", {"entry": model.entry})
|
||||||
}
|
}
|
||||||
|
|
||||||
actions: [
|
actions: [
|
||||||
|
|
|
@ -14,19 +14,19 @@ import org.kde.kirigami 2.12 as Kirigami
|
||||||
|
|
||||||
import org.kde.alligator 1.0
|
import org.kde.alligator 1.0
|
||||||
|
|
||||||
Kirigami.Page {
|
Kirigami.ScrollablePage {
|
||||||
id: page
|
id: page
|
||||||
|
|
||||||
property QtObject entry
|
property QtObject entry
|
||||||
|
|
||||||
title: entry.title
|
title: entry.title
|
||||||
|
|
||||||
Flickable {
|
/*Flickable {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
contentHeight: text.height
|
contentHeight: text.height
|
||||||
|
*/
|
||||||
Controls.Label {
|
Controls.Label {
|
||||||
width: page.width - 30
|
width: page.width - 30
|
||||||
id: text
|
id: text
|
||||||
|
@ -35,8 +35,25 @@ Kirigami.Page {
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
onLinkActivated: Qt.openUrlExternally(link)
|
onLinkActivated: Qt.openUrlExternally(link)
|
||||||
onWidthChanged: entry.adjustedContent(width, font.pixelSize)
|
onWidthChanged: entry.adjustedContent(width, font.pixelSize)
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
|
actions.main: Kirigami.Action {
|
||||||
|
text: !entry.enclosure ? i18n("Open in Browser") :
|
||||||
|
entry.enclosure.status === Enclosure.Downloadable ? i18n("Download") :
|
||||||
|
entry.enclosure.status === Enclosure.Downloading ? i18n("Cancel download") :
|
||||||
|
i18n("Delete downloaded file")
|
||||||
|
icon.name: !entry.enclosure ? "globe" :
|
||||||
|
entry.enclosure.status === Enclosure.Downloadable ? "download" :
|
||||||
|
entry.enclosure.status === Enclosure.Downloading ? "edit-delete-remove" :
|
||||||
|
"delete"
|
||||||
|
onTriggered: {
|
||||||
|
if(!entry.enclosure) Qt.openUrlExternally(entry.link)
|
||||||
|
else if(entry.enclosure.status === Enclosure.Downloadable) entry.enclosure.download()
|
||||||
|
else if(entry.enclosure.status === Enclosure.Downloading) entry.enclosure.cancelDownload()
|
||||||
|
else entry.enclosure.deleteFile()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import org.kde.kirigami 2.12 as Kirigami
|
||||||
import org.kde.alligator 1.0
|
import org.kde.alligator 1.0
|
||||||
|
|
||||||
Kirigami.ScrollablePage {
|
Kirigami.ScrollablePage {
|
||||||
title: "Alligator"
|
title: "Alligator Feed List"
|
||||||
|
|
||||||
property var lastFeed: ""
|
property var lastFeed: ""
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ Flickable {
|
||||||
// a cover for content underneath the panel
|
// a cover for content underneath the panel
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: coverUnderneath
|
id: coverUnderneath
|
||||||
color: "#424242" // since background blurs have a dark hue, it doesn't make sense to theme
|
color: Kirigami.Theme.backgroundColor
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ Flickable {
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
height: mainWindow.height + elisaTheme.mediaPlayerControlHeight
|
height: root.height + footerLoader.minimizedSize
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
MinimizedPlayerControls {
|
MinimizedPlayerControls {
|
||||||
|
|
|
@ -16,9 +16,9 @@ import org.kde.alligator 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: (audio.entry == undefined) ? 0 : (footerrowlayout.height + 3.0 * miniprogressbar.height)
|
height: (audio.entry == undefined || audio.playerOpen) ? 0 : (footerrowlayout.height + 3.0 * miniprogressbar.height)
|
||||||
//margins.bottom: miniprogressbar.height
|
//margins.bottom: miniprogressbar.height
|
||||||
visible: audio.entry !== undefined
|
visible: (audio.entry !== undefined) && !audio.playerOpen
|
||||||
|
|
||||||
// progress bar for limited width (phones)
|
// progress bar for limited width (phones)
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -89,7 +89,7 @@ Item {
|
||||||
id: trackClick
|
id: trackClick
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onClicked: playeroverlay.open()
|
onClicked: pageStack.layers.push("qrc:/PlayerControls.qml") // playeroverlay.open()
|
||||||
//showPassiveNotification("Ping")
|
//showPassiveNotification("Ping")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,9 @@ Kirigami.Page {
|
||||||
clip: true
|
clip: true
|
||||||
Layout.margins: 0
|
Layout.margins: 0
|
||||||
|
|
||||||
|
Component.onCompleted: audio.playerOpen = true
|
||||||
|
Component.onDestruction: audio.playerOpen = false
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Kirigami.Icon {
|
Kirigami.Icon {
|
||||||
|
|
|
@ -21,122 +21,14 @@ Kirigami.Page {
|
||||||
clip: true
|
clip: true
|
||||||
Layout.margins: 0
|
Layout.margins: 0
|
||||||
|
|
||||||
Kirigami.SwipeNavigator {
|
|
||||||
anchors.fill: parent
|
|
||||||
initialIndex: 1
|
|
||||||
Layout.margins: 0
|
|
||||||
|
|
||||||
Kirigami.Page {
|
|
||||||
id: playpage
|
|
||||||
property var entry: podcastPlayerPage.entry
|
|
||||||
Component.onCompleted: audio.entry = entry
|
|
||||||
|
|
||||||
icon.name: "media-playback-start"
|
icon.name: "media-playback-start"
|
||||||
title: "Play"
|
title: "Play"
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
Kirigami.Icon {
|
|
||||||
source: Fetcher.image(entry.feed.image)
|
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
|
||||||
Layout.preferredWidth: Math.min(parent.width, Kirigami.Units.iconSizes.enormous * 3)
|
|
||||||
Layout.preferredHeight: Math.min(parent.height - 2*controls.height, Kirigami.Units.iconSizes.enormous * 3)
|
|
||||||
}
|
|
||||||
Item {
|
|
||||||
id: media
|
|
||||||
|
|
||||||
implicitHeight: mediaControls.height
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.margins: 0
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: mediaControls
|
|
||||||
|
|
||||||
implicitHeight: controls.height
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
id: controls
|
|
||||||
Controls.Label {
|
|
||||||
text: (Math.floor(audio.position/3600000) < 10 ? "0" : "") + Math.floor(audio.position/3600000) + ":" + (Math.floor(audio.position/60000) % 60 < 10 ? "0" : "") + Math.floor(audio.position/60000) % 60 + ":" + (Math.floor(audio.position/1000) % 60 < 10 ? "0" : "") + Math.floor(audio.position/1000) % 60
|
|
||||||
padding: Kirigami.Units.gridUnit
|
|
||||||
}
|
|
||||||
Controls.Slider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
from: 0
|
|
||||||
to: audio.duration
|
|
||||||
value: audio.position
|
|
||||||
onMoved: audio.seek(value)
|
|
||||||
}
|
|
||||||
Controls.Label {
|
|
||||||
text: (Math.floor(audio.duration/3600000) < 10 ? "0" : "") + Math.floor(audio.duration/3600000) + ":" + (Math.floor(audio.duration/60000) % 60 < 10 ? "0" : "") + Math.floor(audio.duration/60000) % 60 + ":" + (Math.floor(audio.duration/1000) % 60 < 10 ? "0" : "") + Math.floor(audio.duration/1000) % 60
|
|
||||||
padding: Kirigami.Units.gridUnit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RowLayout {
|
|
||||||
Layout.maximumWidth: Number.POSITIVE_INFINITY //TODO ?
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
Controls.Button {
|
|
||||||
text: audio.playbackRate + "x"
|
|
||||||
onClicked: {
|
|
||||||
if(audio.playbackRate === 2.5)
|
|
||||||
audio.playbackRate = 1
|
|
||||||
else
|
|
||||||
audio.playbackRate = audio.playbackRate + 0.25
|
|
||||||
}
|
|
||||||
flat: true
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
implicitWidth: playButton.width
|
|
||||||
implicitHeight: playButton.height
|
|
||||||
}
|
|
||||||
Controls.Button {
|
|
||||||
icon.name: "media-seek-backward"
|
|
||||||
icon.height: Kirigami.Units.gridUnit * 2
|
|
||||||
icon.width: Kirigami.Units.gridUnit * 2
|
|
||||||
flat: true
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
onClicked: audio.seek(audio.position - 10000)
|
|
||||||
}
|
|
||||||
Controls.Button {
|
|
||||||
id: playButton
|
|
||||||
icon.name: audio.playbackState === Audio.PlayingState ? "media-playback-pause" : "media-playback-start"
|
|
||||||
icon.height: Kirigami.Units.gridUnit * 2
|
|
||||||
icon.width: Kirigami.Units.gridUnit * 2
|
|
||||||
flat: true
|
|
||||||
onClicked: audio.playbackState === Audio.PlayingState ? audio.pause() : audio.play()
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
}
|
|
||||||
Controls.Button {
|
|
||||||
icon.name: "media-seek-forward"
|
|
||||||
icon.height: Kirigami.Units.gridUnit * 2
|
|
||||||
icon.width: Kirigami.Units.gridUnit * 2
|
|
||||||
flat: true
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
onClicked: audio.seek(audio.position + 10000)
|
|
||||||
}
|
|
||||||
Controls.Button {
|
|
||||||
icon.name: "media-skip-forward"
|
|
||||||
icon.height: Kirigami.Units.gridUnit * 2
|
|
||||||
icon.width: Kirigami.Units.gridUnit * 2
|
|
||||||
flat: true
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
onClicked: console.log("TODO")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EntryPage {
|
EntryPage {
|
||||||
entry: podcastPlayerPage.entry
|
entry: podcastPlayerPage.entry
|
||||||
|
anchors.fill: parent
|
||||||
icon.name: "help-about"
|
icon.name: "help-about"
|
||||||
title: "Info"
|
title: "Info"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
actions.main: Kirigami.Action {
|
actions.main: Kirigami.Action {
|
||||||
text: !entry.enclosure ? i18n("Open in Browser") :
|
text: !entry.enclosure ? i18n("Open in Browser") :
|
||||||
entry.enclosure.status === Enclosure.Downloadable ? i18n("Download") :
|
entry.enclosure.status === Enclosure.Downloadable ? i18n("Download") :
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 (c) Bart De Vries <bart@mogwai.be>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Includes relevant modules used by the QML
|
||||||
|
import QtQuick 2.6
|
||||||
|
import QtQuick.Controls 2.0 as Controls
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import org.kde.kirigami 2.13 as Kirigami
|
||||||
|
import QtMultimedia 5.15
|
||||||
|
import org.kde.alligator 1.0
|
||||||
|
|
||||||
|
Kirigami.ScrollablePage {
|
||||||
|
id: queuepage
|
||||||
|
title: "Alligator Play Queue"
|
||||||
|
Component {
|
||||||
|
id: delegateComponent
|
||||||
|
Kirigami.SwipeListItem {
|
||||||
|
id: listItem
|
||||||
|
contentItem: RowLayout {
|
||||||
|
Kirigami.ListItemDragHandle {
|
||||||
|
listItem: listItem
|
||||||
|
listView: mainList
|
||||||
|
onMoveRequested: listModel.move(oldIndex, newIndex, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
Controls.Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: Math.max(implicitHeight, Kirigami.Units.iconSizes.smallMedium)
|
||||||
|
text: model.title
|
||||||
|
color: listItem.checked || (listItem.pressed && !listItem.checked && !listItem.sectionDelegate) ? listItem.activeTextColor : listItem.textColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actions: [
|
||||||
|
Kirigami.Action {
|
||||||
|
iconName: "media-playback-start"
|
||||||
|
text: "Play"
|
||||||
|
onTriggered: showPassiveNotification(model.title + " Action 1 clicked")
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: mainList
|
||||||
|
Timer {
|
||||||
|
id: refreshRequestTimer
|
||||||
|
interval: 3000
|
||||||
|
onTriggered: page.refreshing = false
|
||||||
|
}
|
||||||
|
|
||||||
|
model: ListModel {
|
||||||
|
id: listModel
|
||||||
|
Component.onCompleted: {
|
||||||
|
for (var i = 0; i < 200; ++i) {
|
||||||
|
listModel.append({"title": "Item " + i,
|
||||||
|
"actions": [{text: "Action 1", icon: "document-decrypt"},
|
||||||
|
{text: "Action 2", icon: "mail-reply-sender"}]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
moveDisplaced: Transition {
|
||||||
|
YAnimator {
|
||||||
|
duration: Kirigami.Units.longDuration
|
||||||
|
easing.type: Easing.InOutQuad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate: Kirigami.DelegateRecycler {
|
||||||
|
width: parent ? parent.width : implicitWidth
|
||||||
|
sourceComponent: delegateComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,11 +19,25 @@ Kirigami.ApplicationWindow {
|
||||||
|
|
||||||
title: "Alligator"
|
title: "Alligator"
|
||||||
|
|
||||||
|
property bool playerOpen: false
|
||||||
|
|
||||||
pageStack.initialPage: feedList
|
pageStack.initialPage: feedList
|
||||||
|
|
||||||
globalDrawer: Kirigami.GlobalDrawer {
|
globalDrawer: Kirigami.GlobalDrawer {
|
||||||
isMenu: true
|
isMenu: true
|
||||||
actions: [
|
actions: [
|
||||||
|
Kirigami.Action {
|
||||||
|
text: i18n("Feed List")
|
||||||
|
iconName: "rss"
|
||||||
|
onTriggered: root.pageStack.clear(), root.pageStack.push(feedList)
|
||||||
|
enabled: pageStack.layers.currentItem.title !== i18n("Feed List")
|
||||||
|
},
|
||||||
|
Kirigami.Action {
|
||||||
|
text: i18n("Podcast Queue")
|
||||||
|
iconName: "source-playlist"
|
||||||
|
onTriggered: root.pageStack.clear(), root.pageStack.push(queuelist)
|
||||||
|
enabled: pageStack.layers.currentItem.title !== i18n("Podcast Queue")
|
||||||
|
},
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: i18n("Settings")
|
text: i18n("Settings")
|
||||||
iconName: "settings-configure"
|
iconName: "settings-configure"
|
||||||
|
@ -54,28 +68,43 @@ Kirigami.ApplicationWindow {
|
||||||
id: feedList
|
id: feedList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueuePage {
|
||||||
|
id: queuelist
|
||||||
|
}
|
||||||
|
|
||||||
Audio {
|
Audio {
|
||||||
id: audio
|
id: audio
|
||||||
|
|
||||||
property var entry
|
property var entry
|
||||||
|
property bool playerOpen: false
|
||||||
|
|
||||||
source: "gst-pipeline: playbin uri=file://" + entry.enclosure.path + " audio_sink=\"scaletempo ! audioconvert ! audioresample ! autoaudiosink\" video_sink=\"fakevideosink\""
|
source: "gst-pipeline: playbin uri=file://" + entry.enclosure.path + " audio_sink=\"scaletempo ! audioconvert ! audioresample ! autoaudiosink\" video_sink=\"fakevideosink\""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Loader {
|
Loader {
|
||||||
|
id: footerLoader
|
||||||
|
|
||||||
|
property var minimizedSize: Kirigami.Units.gridUnit * 3.0
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
active: true
|
active: (audio.entry == undefined) ? false : true
|
||||||
visible: true
|
visible: active
|
||||||
//z: (!item || item.contentY == 0) ? 0 : 999
|
z: (!item || item.contentY == 0) ? -1 : 999
|
||||||
z: (audio.entry == undefined) ? -1 : 0
|
|
||||||
sourceComponent: FooterBar {
|
sourceComponent: FooterBar {
|
||||||
contentHeight: root.height * 2
|
contentHeight: root.height * 2
|
||||||
focus: true
|
focus: true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//footer: MinimizedPlayerControls { }
|
footer: MinimizedPlayerControls {}
|
||||||
|
/*Item {
|
||||||
|
visible: (audio.entry !== undefined)
|
||||||
|
height: footerLoader.minimizedSize
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*Kirigami.OverlaySheet {
|
/*Kirigami.OverlaySheet {
|
||||||
id: playeroverlay
|
id: playeroverlay
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
<file alias="MinimizedPlayerControls.qml">qml/MinimizedPlayerControls.qml</file>
|
<file alias="MinimizedPlayerControls.qml">qml/MinimizedPlayerControls.qml</file>
|
||||||
<file alias="PlayerControls.qml">qml/PlayerControls.qml</file>
|
<file alias="PlayerControls.qml">qml/PlayerControls.qml</file>
|
||||||
<file alias="FooterBar.qml">qml/FooterBar.qml</file>
|
<file alias="FooterBar.qml">qml/FooterBar.qml</file>
|
||||||
|
<file alias="QueuePage.qml">qml/QueuePage.qml</file>
|
||||||
<file>qtquickcontrols2.conf</file>
|
<file>qtquickcontrols2.conf</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
Loading…
Reference in New Issue