Add podcast detail page
This commit is contained in:
parent
3ec5d94c30
commit
172dabc6be
7 changed files with 187 additions and 11 deletions
15
main.py
15
main.py
|
@ -368,6 +368,20 @@ class gPotherSide:
|
|||
if episode.total_time > 0:
|
||||
yield '%02d:%02d:%02d' % (episode.total_time / (60 * 60), (episode.total_time / 60) % 60, episode.total_time % 60)
|
||||
|
||||
def show_podcast(self, podcast_id):
|
||||
podcast = self._get_podcast_by_id(podcast_id)
|
||||
if podcast is None:
|
||||
return {}
|
||||
|
||||
return {
|
||||
'title': podcast.title,
|
||||
'description': util.remove_html_tags(podcast.description),
|
||||
'link': podcast.link,
|
||||
'url': podcast.url,
|
||||
'section': podcast.section,
|
||||
'coverart': self._get_cover(podcast),
|
||||
}
|
||||
|
||||
def set_config_value(self, option, value):
|
||||
self.core.config.update_field(option, value)
|
||||
|
||||
|
@ -430,3 +444,4 @@ set_config_value = gpotherside.set_config_value
|
|||
get_config_value = gpotherside.get_config_value
|
||||
get_directory_providers = gpotherside.get_directory_providers
|
||||
get_directory_entries = gpotherside.get_directory_entries
|
||||
show_podcast = gpotherside.show_podcast
|
||||
|
|
|
@ -45,6 +45,7 @@ SlidePage {
|
|||
|
||||
Component.onCompleted: {
|
||||
py.call('main.show_episode', [episode_id], function (episode) {
|
||||
detailPage.title = episode.title;
|
||||
descriptionLabel.text = episode.description;
|
||||
metadataLabel.text = episode.metadata;
|
||||
detailPage.link = episode.link;
|
||||
|
|
|
@ -47,6 +47,12 @@ SlidePage {
|
|||
py.call('main.mark_episodes_as_old', [episodesPage.podcast_id]);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Podcast details',
|
||||
callback: function () {
|
||||
pgst.loadPage('PodcastDetail.qml', {podcast_id: podcast_id, title: title});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Unsubscribe',
|
||||
callback: function () {
|
||||
|
|
|
@ -27,7 +27,7 @@ import 'common/util.js' as Util
|
|||
Item {
|
||||
id: expander
|
||||
|
||||
property bool expanded: false
|
||||
property bool expanded: !canExpand
|
||||
property bool canExpand: expandedHeight > contractedHeight
|
||||
|
||||
property real contractedHeight: 100 * pgst.scalef
|
||||
|
|
161
touch/PodcastDetail.qml
Normal file
161
touch/PodcastDetail.qml
Normal file
|
@ -0,0 +1,161 @@
|
|||
|
||||
/**
|
||||
*
|
||||
* gPodder QML UI Reference Implementation
|
||||
* Copyright (c) 2014, Thomas Perl <m@thp.io>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
|
||||
import 'common/constants.js' as Constants
|
||||
import 'common/util.js' as Util
|
||||
import 'icons/icons.js' as Icons
|
||||
|
||||
SlidePage {
|
||||
id: podcastDetail
|
||||
|
||||
property int podcast_id
|
||||
property string title
|
||||
property string description
|
||||
property string link
|
||||
property string section
|
||||
property string coverart
|
||||
property string url
|
||||
|
||||
property bool ready: false
|
||||
|
||||
hasMenuButton: true
|
||||
onMenuButtonClicked: {
|
||||
pgst.showSelection([
|
||||
{
|
||||
label: 'Visit website',
|
||||
callback: function () {
|
||||
Qt.openUrlExternally(podcastDetail.link);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Copy feed URL',
|
||||
callback: function () {
|
||||
pgst.loadPage('TextInputDialog.qml', {
|
||||
placeholderText: 'Feed URL',
|
||||
text: podcastDetail.url,
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Change section',
|
||||
callback: function () {
|
||||
var ctx = { py: py, id: podcastDetail.podcast_id };
|
||||
pgst.loadPage('TextInputDialog.qml', {
|
||||
buttonText: 'Change section',
|
||||
placeholderText: 'New section',
|
||||
text: section,
|
||||
callback: function (new_section) {
|
||||
ctx.py.call('main.change_section', [ctx.id, new_section]);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
PBusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
visible: !podcastDetail.ready
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
py.call('main.show_podcast', [podcast_id], function (podcast) {
|
||||
podcastDetail.title = podcast.title;
|
||||
podcastDetail.description = podcast.description;
|
||||
podcastDetail.link = podcast.link;
|
||||
podcastDetail.section = podcast.section;
|
||||
podcastDetail.coverart = podcast.coverart;
|
||||
podcastDetail.url = podcast.url;
|
||||
podcastDetail.ready = true;
|
||||
});
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: flickable
|
||||
anchors.fill: parent
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
contentWidth: detailColumn.width
|
||||
contentHeight: detailColumn.height + detailColumn.spacing
|
||||
|
||||
Column {
|
||||
id: detailColumn
|
||||
|
||||
width: podcastDetail.width
|
||||
spacing: Constants.layout.padding * pgst.scalef
|
||||
|
||||
Item { height: Constants.layout.padding * pgst.scalef; width: parent.width }
|
||||
|
||||
Column {
|
||||
width: parent.width - 2 * Constants.layout.padding * pgst.scalef
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Constants.layout.padding * pgst.scalef
|
||||
|
||||
PExpander {
|
||||
width: parent.width
|
||||
expandedHeight: coverImage.height
|
||||
|
||||
Image {
|
||||
id: coverImage
|
||||
source: podcastDetail.coverart
|
||||
fillMode: Image.PreserveAspectFit
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
PLabel {
|
||||
text: podcastDetail.title
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 35 * pgst.scalef
|
||||
color: Constants.colors.highlight
|
||||
}
|
||||
|
||||
PLabel {
|
||||
visible: text !== ''
|
||||
text: podcastDetail.link
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 20 * pgst.scalef
|
||||
color: Constants.colors.placeholder
|
||||
}
|
||||
|
||||
PLabel {
|
||||
text: 'Section: ' + podcastDetail.section
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 20 * pgst.scalef
|
||||
color: Constants.colors.placeholder
|
||||
}
|
||||
|
||||
PLabel {
|
||||
text: podcastDetail.description
|
||||
width: parent.width
|
||||
font.pixelSize: 30 * pgst.scalef
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PScrollDecorator { flickable: flickable }
|
||||
}
|
|
@ -137,17 +137,9 @@ SlidePage {
|
|||
},
|
||||
},
|
||||
{
|
||||
label: 'Change section',
|
||||
label: 'Podcast details',
|
||||
callback: function () {
|
||||
var ctx = { py: py, id: id };
|
||||
pgst.loadPage('TextInputDialog.qml', {
|
||||
buttonText: 'Change section',
|
||||
placeholderText: 'New section',
|
||||
text: section,
|
||||
callback: function (new_section) {
|
||||
ctx.py.call('main.change_section', [ctx.id, new_section]);
|
||||
}
|
||||
});
|
||||
pgst.loadPage('PodcastDetail.qml', {podcast_id: id, title: title});
|
||||
}
|
||||
},
|
||||
], title);
|
||||
|
|
|
@ -62,6 +62,7 @@ Dialog {
|
|||
id: button
|
||||
width: input.width
|
||||
height: input.height
|
||||
visible: textInputDialog.buttonText !== ''
|
||||
|
||||
PLabel {
|
||||
anchors.centerIn: parent
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue