git.iko.soy/maciek134/podphoenix
on main help sign in
Add new 'Episodes' tab in place of 'What's New'. Add ability to favourite episodes. Remove zebra colouring. Rename 'What's New' to 'Recent' and implement as tab on 'Episodes' page.
commit5ca91381a8b4052c9dedf181af2feae2ea5528ff authorNekhelesh Ramananthan <krnekhelesh@gmail.com> dateMon 28 Mar 2016, 23:49 (11 years ago) parentb43b6419b823de
13 files changed+527−376
app/components/HeaderListItem.qml+2 app/components/SingleValueListItem.qml+3 app/components/TabsList.qml+2−10 app/podbird.qml+4−17 app/podcasts.js+37−19 app/themes/Dark.qml+3−3 app/themes/Light.qml+3−3 app/ui/EpisodesPage.qml+91−92 app/ui/WhatsNewTab.qml → app/ui/EpisodesTab.qml+229−92 app/ui/PodcastsTab.qml+6−15 app/ui/SearchPage.qml+4−14 app/ui/SettingsPage.qml+14 po/com.mikeasoft.podbird.pot+129−111
app/components/HeaderListItem.qml+2
@@ -25,6 +25,8 @@ ListItem {
2525 property alias title: headerText.title
2626
2727 height: headerText.height + divider.height
28+ divider.anchors.leftMargin: units.gu(2)
29+ divider.anchors.rightMargin: units.gu(2)
2830
2931 ListItemLayout {
3032 id: headerText
app/components/SingleValueListItem.qml+3
@@ -25,6 +25,9 @@ ListItem {
2525 property alias title: customItemLayout.title
2626 property alias value: _value.text
2727
28+ divider.anchors.leftMargin: units.gu(2)
29+ divider.anchors.rightMargin: units.gu(2)
30+
2831 ListItemLayout {
2932 id: customItemLayout
3033
app/components/TabsList.qml+2−10
@@ -26,7 +26,7 @@ ActionList {
2626
2727 children: [
2828 Action {
29− text: i18n.tr("What's New")
29+ text: i18n.tr("Episodes")
3030 visible: currentTab !== 0
3131 onTriggered: {
3232 tabs.selectedTabIndex = 0
@@ -42,19 +42,11 @@ ActionList {
4242 },
4343
4444 Action {
45− text: i18n.tr("Add New Podcasts")
45+ text: i18n.tr("Settings")
4646 visible: currentTab !== 2
4747 onTriggered: {
4848 tabs.selectedTabIndex = 2
4949 }
50− },
51−
52− Action {
53− text: i18n.tr("Settings")
54− visible: currentTab !== 3
55− onTriggered: {
56− tabs.selectedTabIndex = 3
57− }
5850 }
5951 ]
6052}
app/podbird.qml+4−17
@@ -56,7 +56,7 @@ MainView {
5656 // visible on application start.
5757 function refreshModels() {
5858 if (tabs.selectedTabIndex === 0) {
59− whatsNewTab.refreshModel()
59+ episodesTab.refreshModel()
6060 } else if (tabs.selectedTabIndex === 1) {
6161 podcastPage.item.refreshModel()
6262 }
@@ -246,9 +246,9 @@ MainView {
246246 }
247247 }
248248
249− WhatsNewTab {
250− id: whatsNewTab
251− objectName: "whatsNewTab"
249+ EpisodesTab {
250+ id: episodesTab
251+ objectName: "episodesTab"
252252 }
253253
254254 Tab {
@@ -263,19 +263,6 @@ MainView {
263263 }
264264 }
265265
266− Tab {
267− id: searchTab
268−
269− // Dynamically load/unload the search tab as required
270− page: Loader {
271− parent: searchTab
272− anchors.left: parent.left
273− anchors.right: parent.right
274− anchors.bottom: parent.bottom
275− source: (tabs.selectedTab === searchTab) ? Qt.resolvedUrl("ui/SearchPage.qml") : ""
276− }
277− }
278−
279266 Tab {
280267 id: settingsTab
281268
app/podcasts.js+37−19
@@ -21,18 +21,35 @@ function init() {
2121
2222 db.transaction(function(tx) {
2323 tx.executeSql('CREATE TABLE IF NOT EXISTS Podcast(artist TEXT, name TEXT, description TEXT, feed TEXT, image TEXT, lastupdate TIMESTAMP)');
24− tx.executeSql('CREATE TABLE IF NOT EXISTS Episode(guid TEXT, podcast INTEGER, name TEXT, subtitle TEXT, description TEXT, duration INTEGER, audiourl TEXT, downloadedfile TEXT, published TIMESTAMP, queued BOOLEAN, listened BOOLEAN, position INTEGER, FOREIGN KEY(podcast) REFERENCES Podcast(rowid))');
24+ tx.executeSql('CREATE TABLE IF NOT EXISTS Episode(guid TEXT, podcast INTEGER, name TEXT, subtitle TEXT, description TEXT, duration INTEGER, audiourl TEXT, downloadedfile TEXT, published TIMESTAMP, queued BOOLEAN, listened BOOLEAN, favourited BOOLEAN, position INTEGER, FOREIGN KEY(podcast) REFERENCES Podcast(rowid))');
2525 });
2626
27− /*
28− Schema Upgrade to v1.1 which adds a new queued boolean variable which is needed to track the queued status
29− of a episode properly.
30− */
31− if (db.version == "1.0") {
32− db.changeVersion("1.0", "1.1", function(tx) {
33− tx.executeSql('ALTER TABLE Episode ADD queued BOOLEAN');
34− tx.executeSql('UPDATE Episode SET queued=0');
35− });
27+ try {
28+ /*
29+ Schema Upgrade to v1.1 which adds a new queued boolean variable which is needed to track the queued status
30+ of a episode properly.
31+ */
32+ if (db.version === "1.0" || db.version === "") {
33+ console.log("Upgrading database from %1 -> v1.1".arg(db.version))
34+ db.changeVersion(db.version, "1.1", function(tx) {
35+ tx.executeSql('ALTER TABLE Episode ADD queued BOOLEAN');
36+ tx.executeSql('UPDATE Episode SET queued=0');
37+ });
38+ }
39+
40+ /*
41+ Schema Upgrade to v1.2 which adds a new favourited boolean variable which is needed to track the favourite status
42+ of an episode.
43+ */
44+ if (db.version === "1.1") {
45+ console.log("Upgrading database from %1 -> v1.2".arg(db.version))
46+ db.changeVersion("1.1", "1.2", function(tx) {
47+ tx.executeSql('ALTER TABLE Episode ADD favourited BOOLEAN');
48+ tx.executeSql('UPDATE Episode SET favourited=?', [false]);
49+ });
50+ }
51+ } catch(ex) {
52+ console.log(ex)
3653 }
3754
3855 return db;
@@ -110,15 +127,16 @@ function updateEpisodes(refreshModel) {
110127 db.transaction(function(tx2) {
111128 var ers = tx2.executeSql("SELECT rowid FROM Episode WHERE guid=?", [track.guid]);
112129 if (ers.rows.length === 0) {
113− tx2.executeSql("INSERT INTO Episode(podcast, name, description, audiourl, guid, listened, queued, duration, published) VALUES(?, ?, ? , ?, ?, ?, ?, ?, ?)", [pid,
114− track.name,
115− track.description,
116− track.audiourl,
117− track.guid,
118− false,
119− false,
120− track.duration,
121− track.published]);
130+ tx2.executeSql("INSERT INTO Episode(podcast, name, description, audiourl, guid, listened, queued, favourited, duration, published) VALUES(?, ?, ? , ?, ?, ?, ?, ?, ?, ?)", [pid,
131+ track.name,
132+ track.description,
133+ track.audiourl,
134+ track.guid,
135+ false,
136+ false,
137+ false,
138+ track.duration,
139+ track.published]);
122140 }
123141 });
124142 }
app/themes/Dark.qml+3−3
@@ -33,9 +33,9 @@ QtObject {
3333 property color baseIcon: "White"
3434
3535 // Button Colors
36− property color positiveActionButton: UbuntuColors.green
37− property color negativeActionButton: UbuntuColors.red
38− property color neutralActionButton: UbuntuColors.coolGrey
36+ property color positiveActionButton: "#3EB34F" // UbuntuColors.green
37+ property color negativeActionButton: "#ED3146" // UbuntuColors.red
38+ property color neutralActionButton: "#5D5D5D" // UbuntuColors.coolGrey
3939
4040 // Bottom Player Bar Colors
4141 property color bottomBarBackground: "#15141A"
app/themes/Light.qml+3−3
@@ -33,9 +33,9 @@ QtObject {
3333 property color baseIcon: UbuntuColors.darkGrey
3434
3535 // Button Colors
36− property color positiveActionButton: UbuntuColors.green
37− property color negativeActionButton: UbuntuColors.red
38− property color neutralActionButton: UbuntuColors.coolGrey
36+ property color positiveActionButton: "#3EB34F" // UbuntuColors.green
37+ property color negativeActionButton: "#ED3146" // UbuntuColors.red
38+ property color neutralActionButton: "#5D5D5D" // UbuntuColors.coolGrey
3939
4040 // Bottom Player Bar Colors
4141 property color bottomBarBackground: "#323435"
app/ui/EpisodesPage.qml+91−92
@@ -19,7 +19,6 @@
1919import QtQuick 2.4
2020import QtMultimedia 5.4
2121import Ubuntu.Components 1.3
22−import QtQuick.Layouts 1.1
2322import QtQuick.LocalStorage 2.0
2423import Ubuntu.DownloadManager 0.1
2524import Ubuntu.Components.Popups 1.3
@@ -105,17 +104,14 @@ Page {
105104 name: "search"
106105 head: episodesPage.head
107106
108− actions: [
109− Action {
110− iconName: "edit-clear"
111− text: i18n.tr("Cancel")
112− onTriggered: {
113− episodeList.forceActiveFocus()
114− episodesPage.state = "default"
115− episodeList.positionViewAtBeginning()
116− }
107+ backAction: Action {
108+ iconName: "back"
109+ onTriggered: {
110+ episodeList.forceActiveFocus()
111+ episodesPage.state = "default"
112+ episodeList.positionViewAtBeginning()
117113 }
118− ]
114+ }
119115
120116 contents: Loader {
121117 id: searchField
@@ -229,7 +225,6 @@ Page {
229225 Label {
230226 width: parent.width
231227 wrapMode: Text.WordWrap
232− color: UbuntuColors.darkGrey
233228 linkColor: "Blue"
234229 text: dialogInternal.description
235230 onLinkActivated: Qt.openUrlExternally(link)
@@ -281,7 +276,7 @@ Page {
281276 : RegExp("", "gi")
282277 }
283278
284− UbuntuListView {
279+ ListView {
285280 id: episodeList
286281
287282 Component.onCompleted: {
@@ -294,76 +289,97 @@ Page {
294289
295290 anchors.fill: parent
296291 model: sortedEpisodeModel
297− currentIndex: -1
298292 clip: true
299293
300294 header: Column {
301− height: blurredBackground.height + modeTabs.height + units.gu(2)
302− spacing: units.gu(2)
303− BlurredBackground {
304− id: blurredBackground
295+ height: coverArtContainer.height + modeTabs.height + units.gu(2)
296+ Item {
297+ id: coverArtContainer
305298
306− art: episodeImage
307− width: parent.width
299+ width: episodesPage.width
308300 visible: episodesPage.state !== "search" && sortedEpisodeModel.count !== 0
309− height: episodesPage.state !== "search" && sortedEpisodeModel.count !== 0 ? cover.height + units.gu(4) : 0
310− backgroundStrength: podbird.settings.themeName === "Light.qml" ? 0.3 : 0.6
301+ height: episodesPage.state !== "search" && sortedEpisodeModel.count !== 0 ? cover.height + units.gu(6) : 0
311302
312303 Image {
313304 id:cover
314− width: units.gu(12)
305+ width: units.gu(18)
315306 height: width
316307 sourceSize.height: width
317308 sourceSize.width: width
318309 source: episodeImage
319310 asynchronous: true
320311 anchors {
321− left: parent.left
312+ horizontalCenter: parent.horizontalCenter
322313 top: parent.top
323314 margins: units.gu(2)
324315 }
325316 }
326317
327− Column {
328− id: podcastTitle
329−
330− anchors {
331− left: cover.right
332− right: parent.right
333− bottom: parent.bottom
334− margins: units.gu(2)
335− }
336−
337− Label {
338− text: episodeName
339− width: parent.width
340− wrapMode: Text.WordWrap
341− maximumLineCount: 2
342− elide: Text.ElideRight
343− color: podbird.appTheme.baseText
344− }
345−
346− Label {
347− text: i18n.tr("%1 episode", "%1 episodes", episodeList.count).arg(episodeList.count)
348− width: parent.width
349− elide: Text.ElideRight
350− textSize: Label.XSmall
351− color: podbird.appTheme.baseText
352− }
318+ Label {
319+ text: episodeName
320+ width: parent.width
321+ wrapMode: Text.WordWrap
322+ horizontalAlignment: Text.AlignHCenter
323+ maximumLineCount: 2
324+ elide: Text.ElideRight
325+ color: podbird.appTheme.baseText
326+ anchors.top: cover.bottom
327+ anchors.topMargin: units.gu(2)
353328 }
354329 }
355330
331+ Item {
332+ width: parent.width
333+ height: units.gu(2)
334+ }
335+
356336 Item {
357337 id: modeTabs
358− height: unheardTab.implicitHeight + units.gu(2)
338+ height: unheardTab.implicitHeight + units.gu(2.25)
359339 width: episodesPage.width
360340
341+ Rectangle {
342+ id: sliderContainer
343+ anchors.top: unheardTab.bottom
344+ anchors.topMargin: units.gu(1)
345+ anchors.left: parent.left
346+ anchors.right: parent.right
347+ anchors.margins: units.gu(2)
348+ height: units.gu(0.25)
349+ radius: width/3
350+ color: UbuntuColors.lightGrey
351+ }
352+
353+ Rectangle {
354+ id: slider
355+ anchors.top: unheardTab.bottom
356+ anchors.topMargin: units.gu(1)
357+ height: units.gu(0.25)
358+ radius: width/3
359+ width: sliderContainer.width/3
360+ color: podbird.appTheme.focusText
361+ x: {
362+ if (episodesPage.mode === "unheard")
363+ return units.gu(2)
364+ else if (episodesPage.mode === "listened")
365+ return width + units.gu(2)
366+ else
367+ return 2 * width + units.gu(2)
368+ }
369+
370+ Behavior on x {
371+ UbuntuNumberAnimation {}
372+ }
373+ }
374+
361375 Label {
362376 id: unheardTab
363− textSize: Label.Large
364377 text: i18n.tr("Unheard")
365378 anchors.left: parent.left
366379 anchors.leftMargin: units.gu(2)
380+ width: sliderContainer.width/3
381+ horizontalAlignment: Text.AlignHCenter
382+ font.weight: Font.DemiBold
367383 color: episodesPage.mode == "unheard" ? podbird.appTheme.focusText : podbird.appTheme.baseText
368384
369385 AbstractButton {
@@ -372,23 +388,13 @@ Page {
372388 }
373389 }
374390
375− Rectangle {
376− anchors.top: unheardTab.bottom
377− anchors.topMargin: units.gu(1)
378− anchors.horizontalCenter: unheardTab.horizontalCenter
379− height: units.gu(0.25)
380− width: unheardTab.width
381− radius: width/3
382− color: podbird.appTheme.focusText
383− visible: episodesPage.mode == "unheard"
384− }
385−
386391 Label {
387392 id: listenedTab
388393 anchors.left: unheardTab.right
389− anchors.leftMargin: (parent.width - unheardTab.width - listenedTab.width - downloadedTab.width - unheardTab.anchors.leftMargin - downloadedTab.anchors.rightMargin) / 2.0
390− textSize: Label.Large
391394 text: i18n.tr("Listened")
395+ width: sliderContainer.width/3
396+ font.weight: Font.DemiBold
397+ horizontalAlignment: Text.AlignHCenter
392398 color: episodesPage.mode == "listened" ? podbird.appTheme.focusText : podbird.appTheme.baseText
393399
394400 AbstractButton {
@@ -397,22 +403,13 @@ Page {
397403 }
398404 }
399405
400− Rectangle {
401− anchors.top: listenedTab.bottom
402− anchors.topMargin: units.gu(1)
403− anchors.horizontalCenter: listenedTab.horizontalCenter
404− height: units.gu(0.25)
405− width: listenedTab.width
406− radius: width/3
407− color: podbird.appTheme.focusText
408− visible: episodesPage.mode == "listened"
409− }
410−
411406 Label {
412407 id: downloadedTab
413408 anchors.right: parent.right
414409 anchors.rightMargin: units.gu(2)
415− textSize: Label.Large
410+ width: sliderContainer.width/3
411+ font.weight: Font.DemiBold
412+ horizontalAlignment: Text.AlignHCenter
416413 text: i18n.tr("Downloaded")
417414 color: episodesPage.mode == "downloaded" ? podbird.appTheme.focusText : podbird.appTheme.baseText
418415
@@ -421,17 +418,6 @@ Page {
421418 onClicked: episodesPage.mode = "downloaded"
422419 }
423420 }
424−
425− Rectangle {
426− anchors.top: downloadedTab.bottom
427− anchors.topMargin: units.gu(1)
428− anchors.horizontalCenter: downloadedTab.horizontalCenter
429− height: units.gu(0.25)
430− width: downloadedTab.width
431− radius: width/3
432− color: podbird.appTheme.focusText
433− visible: episodesPage.mode == "downloaded"
434− }
435421 }
436422
437423 }
@@ -445,9 +431,8 @@ Page {
445431 id: listItem
446432
447433 divider.visible: false
448− highlightColor: "Transparent"
434+ highlightColor: podbird.appTheme.hightlightListView
449435 height: visible ? listItemLayout.height + progressBarLoader.height + units.gu(1) : 0
450− color: index % 2 === 0 ? podbird.appTheme.hightlightListView : "Transparent"
451436
452437 visible: episodesPage.mode == "listened" ? model.listened
453438 : (episodesPage.mode == "unheard" ? !model.listened
@@ -525,6 +510,20 @@ Page {
525510 }
526511 },
527512
513+ Action {
514+ iconName: model.favourited ? "unlike" : "like"
515+ onTriggered: {
516+ var db = Podcasts.init();
517+ db.transaction(function (tx) {
518+ if (model.favourited)
519+ tx.executeSql("UPDATE Episode SET favourited=0 WHERE guid=?", [model.guid])
520+ else
521+ tx.executeSql("UPDATE Episode SET favourited=1 WHERE guid=?", [model.guid])
522+ refreshModel();
523+ });
524+ }
525+ },
526+
528527 Action {
529528 iconName: "info"
530529 onTriggered: {
@@ -584,10 +583,10 @@ Page {
584583 for(i = 0; i < rs.rows.length; i++) {
585584 episode = rs.rows.item(i);
586585 if (!episode.listened) {
587− episodeModel.insert(newCount, {"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : img, "artist" : artist, "audiourl" : episode.audiourl, "queued": episode.queued});
586+ episodeModel.insert(newCount, {"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : img, "artist" : artist, "audiourl" : episode.audiourl, "queued": episode.queued, "favourited": episode.favourited});
588587 newCount++;
589588 } else {
590− episodeModel.insert(i,{"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : img, "artist" : artist, "audiourl" : episode.audiourl, "queued": episode.queued});
589+ episodeModel.insert(i,{"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : img, "artist" : artist, "audiourl" : episode.audiourl, "queued": episode.queued, "favourited": episode.favourited});
591590 }
592591 }
593592 });
app/ui/WhatsNewTab.qml → app/ui/EpisodesTab.qmlrenamed+229−92
@@ -26,7 +26,7 @@ import "../podcasts.js" as Podcasts
2626import "../components"
2727
2828Tab {
29− id: whatsNewTab
29+ id: episodesTab
3030
3131 property var today: new Date()
3232 property int dayToMs: 86400000
@@ -38,14 +38,14 @@ Tab {
3838 }
3939
4040 page: Page {
41− id: whatsNewPage
41+ id: episodesPage
4242
4343 header: standardHeader
4444
4545 PageHeader {
4646 id: standardHeader
47− visible: whatsNewPage.header === standardHeader
48− title: i18n.tr("What's New")
47+ visible: episodesPage.header === standardHeader
48+ title: i18n.tr("Episodes")
4949
5050 StyleHints {
5151 backgroundColor: podbird.appTheme.background
@@ -61,47 +61,87 @@ Tab {
6161 iconName: "search"
6262 text: i18n.tr("Search Episode")
6363 onTriggered: {
64− whatsNewPage.header = searchHeader
64+ episodesPage.header = searchHeader
6565 searchField.item.forceActiveFocus()
6666 }
6767 },
6868
6969 Action {
7070 iconName: "select"
71+ visible: episodesPageHeaderSections.selectedIndex === 0
7172 text: i18n.tr("Mark all listened")
7273 onTriggered: {
7374 var db = Podcasts.init();
7475 db.transaction(function (tx) {
75− for (var i=0; i<whatsNewModel.count; i++) {
76− tx.executeSql("UPDATE Episode SET listened=1 WHERE guid=?", [whatsNewModel.get(i).guid]);
76+ for (var i=0; i<episodesModel.count; i++) {
77+ tx.executeSql("UPDATE Episode SET listened=1 WHERE guid=?", [episodesModel.get(i).guid]);
7778 }
78− whatsNewModel.clear()
79+ episodesModel.clear()
7980 });
8081 }
8182 },
8283
8384 Action {
8485 iconName: "save"
86+ visible: episodesPageHeaderSections.selectedIndex === 0
8587 text: i18n.tr("Download all")
8688 onTriggered: {
8789 var db = Podcasts.init();
8890 db.transaction(function (tx) {
89− for (var i=0; i<whatsNewModel.count; i++) {
90− if (!whatsNewModel.get(i).downloadedfile) {
91− whatsNewModel.setProperty(i, "queued", 1)
92− tx.executeSql("UPDATE Episode SET queued=1 WHERE guid = ?", [whatsNewModel.get(i).guid]);
93− downloader.addDownload(whatsNewModel.get(i).guid, whatsNewModel.get(i).audiourl);
91+ for (var i=0; i<episodesModel.count; i++) {
92+ if (!episodesModel.get(i).downloadedfile) {
93+ episodesModel.setProperty(i, "queued", 1)
94+ tx.executeSql("UPDATE Episode SET queued=1 WHERE guid = ?", [episodesModel.get(i).guid]);
95+ downloader.addDownload(episodesModel.get(i).guid, episodesModel.get(i).audiourl);
9496 }
9597 }
9698 });
9799 }
100+ },
101+
102+ Action {
103+ iconName: "delete"
104+ text: i18n.tr("Delete all")
105+ visible: episodesPageHeaderSections.selectedIndex === 1
106+ onTriggered: {
107+ var db = Podcasts.init();
108+ db.transaction(function (tx) {
109+ for (var i=0; i<episodesModel.count; i++) {
110+ if (episodesModel.get(i).downloadedfile) {
111+ fileManager.deleteFile(episodesModel.get(i).downloadedfile);
112+ tx.executeSql("UPDATE Episode SET downloadedfile = NULL WHERE guid = ?", [episodesModel.get(i).guid]);
113+ episodesModel.setProperty(i, "downloadedfile", "")
114+ }
115+ }
116+ });
117+ refreshModel();
118+ }
98119 }
99120 ]
121+
122+ extension: Sections {
123+ id: episodesPageHeaderSections
124+
125+ anchors {
126+ left: parent.left
127+ leftMargin: units.gu(2)
128+ bottom: parent.bottom
129+ }
130+
131+ StyleHints {
132+ selectedSectionColor: podbird.appTheme.focusText
133+ }
134+
135+ model: [i18n.tr("Recent"), i18n.tr("Downloaded"), i18n.tr("Favourites")]
136+ onSelectedIndexChanged: {
137+ refreshModel();
138+ }
139+ }
100140 }
101141
102142 PageHeader {
103143 id: searchHeader
104− visible: whatsNewPage.header === searchHeader
144+ visible: episodesPage.header === searchHeader
105145
106146 StyleHints {
107147 backgroundColor: podbird.appTheme.background
@@ -109,19 +149,18 @@ Tab {
109149
110150 contents: Loader {
111151 id: searchField
112− sourceComponent: whatsNewPage.header === searchHeader ? searchFieldComponent : undefined
152+ sourceComponent: episodesPage.header === searchHeader ? searchFieldComponent : undefined
113153 anchors.left: parent ? parent.left : undefined
114154 anchors.right: parent ? parent.right : undefined
115155 anchors.verticalCenter: parent ? parent.verticalCenter : undefined
116156 }
117157
118− trailingActionBar.actions: [
158+ leadingActionBar.actions: [
119159 Action {
120− iconName: "edit-clear"
121− text: i18n.tr("Cancel")
160+ iconName: "back"
122161 onTriggered: {
123162 episodeList.forceActiveFocus()
124− whatsNewPage.header = standardHeader
163+ episodesPage.header = standardHeader
125164 }
126165 }
127166 ]
@@ -146,28 +185,50 @@ Tab {
146185 verticalCenterOffset: Qt.inputMethod.visible ? units.gu(4) : 0
147186 }
148187
149− sourceComponent: whatsNewModel.count === 0 || sortedEpisodeModel.count === 0 ? emptyStateComponent : undefined
188+ sourceComponent: episodesModel.count === 0 || sortedEpisodeModel.count === 0 ? emptyStateComponent : undefined
150189 }
151190
152191 Component {
153192 id: emptyStateComponent
154193 EmptyState {
155− icon.source: whatsNewModel.count === 0 ? Qt.resolvedUrl("../graphics/owlSearch.svg") : Qt.resolvedUrl("../graphics/notFound.svg")
156− title: whatsNewModel.count === 0 ? i18n.tr("No New Episodes") : i18n.tr("No Episodes Found")
157− subTitle: whatsNewModel.count === 0 ? i18n.tr("No more episodes to listen to!") : i18n.tr("No Episodes found matching the search term.")
194+ icon.source: episodesModel.count === 0 ? Qt.resolvedUrl("../graphics/owlSearch.svg") : Qt.resolvedUrl("../graphics/notFound.svg")
195+ title: {
196+ if (episodesModel.count === 0 && episodesPage.header === standardHeader) {
197+ if (episodesPageHeaderSections.selectedIndex === 0)
198+ return i18n.tr("No New Episodes")
199+ else if (episodesPageHeaderSections.selectedIndex === 1)
200+ return i18n.tr("No Downloaded Episodes")
201+ else if (episodesPageHeaderSections.selectedIndex === 2)
202+ return i18n.tr("No Favourited Episodes")
203+ } else {
204+ return i18n.tr("No Episodes Found")
205+ }
206+ }
207+ subTitle: {
208+ if (episodesModel.count === 0 && episodesPage.header === standardHeader) {
209+ if (episodesPageHeaderSections.selectedIndex === 0)
210+ return i18n.tr("No more episodes to listen to!")
211+ else if (episodesPageHeaderSections.selectedIndex === 1)
212+ return i18n.tr("No episodes have been downloaded for offline listening")
213+ else if (episodesPageHeaderSections.selectedIndex === 2)
214+ return i18n.tr("No episodes have been favourited.")
215+ } else {
216+ return i18n.tr("No Episodes found matching the search term.")
217+ }
218+ }
158219 }
159220 }
160221
161222 ListModel {
162− id: whatsNewModel
223+ id: episodesModel
163224 }
164225
165226 SortFilterModel {
166227 id: sortedEpisodeModel
167− model: whatsNewModel
228+ model: episodesModel
168229 filter.property: "name"
169− filter.pattern: whatsNewPage.state === "search" && searchField.status == Loader.Ready ? RegExp(searchField.item.text, "gi")
170− : RegExp("", "gi")
230+ filter.pattern: episodesPage.header === searchHeader && searchField.status == Loader.Ready ? RegExp(searchField.item.text, "gi")
231+ : RegExp("", "gi")
171232 }
172233
173234 onVisibleChanged: {
@@ -176,7 +237,7 @@ Tab {
176237 if (downloader.downloadingGuid != "")
177238 tempGuid = downloader.downloadingGuid
178239 } else {
179− whatsNewPage.header = standardHeader
240+ episodesPage.header = standardHeader
180241 }
181242 }
182243
@@ -187,16 +248,16 @@ Tab {
187248 db.transaction(function (tx) {
188249 /*
189250 If tempGuid is NULL, then the episode currently being downloaded is not found within
190− this podcast. On the other hand, if it is within this podcast, then update the whatsNewModel
251+ this podcast. On the other hand, if it is within this podcast, then update the episodesModel
191252 with the downloadedfile location we just received from the downloader.
192253 */
193254 if (tempGuid != "NULL") {
194255 var rs2 = tx.executeSql("SELECT downloadedfile FROM Episode WHERE guid=?", [tempGuid]);
195− for (var i=0; i<whatsNewModel.count; i++) {
196− if (whatsNewModel.get(i).guid == tempGuid) {
256+ for (var i=0; i<episodesModel.count; i++) {
257+ if (episodesModel.get(i).guid == tempGuid) {
197258 console.log("[LOG]: Setting episode download URL to " + rs2.rows.item(0).downloadedfile)
198− whatsNewModel.setProperty(i, "downloadedfile", rs2.rows.item(0).downloadedfile)
199− whatsNewModel.setProperty(i, "queued", 0)
259+ episodesModel.setProperty(i, "downloadedfile", rs2.rows.item(0).downloadedfile)
260+ episodesModel.setProperty(i, "queued", 0)
200261 break
201262 }
202263 }
@@ -236,7 +297,6 @@ Tab {
236297 Label {
237298 width: parent.width
238299 wrapMode: Text.WordWrap
239− color: UbuntuColors.darkGrey
240300 linkColor: "Blue"
241301 text: dialogInternal.description
242302 onLinkActivated: Qt.openUrlExternally(link)
@@ -252,7 +312,7 @@ Tab {
252312 }
253313 }
254314
255− UbuntuListView {
315+ ListView {
256316 id: episodeList
257317
258318 Component.onCompleted: {
@@ -264,33 +324,25 @@ Tab {
264324 }
265325
266326 anchors {
267− top: whatsNewPage.header.bottom
327+ top: episodesPage.header.bottom
268328 left: parent.left
269329 right: parent.right
270330 bottom: parent.bottom
271331 }
272332
273333 clip: true
274−
275334 model: sortedEpisodeModel
276− currentIndex: -1
277335 section.property: "diff"
278336 section.labelPositioning: ViewSection.InlineLabels
279337
280− section.delegate: Rectangle {
281− width: parent.width
282− color: "Transparent"
283− height: header.implicitHeight + units.gu(2)
284− Label {
285− id: header
286− anchors {
287− left: parent.left
288− right: parent.right
289− margins: units.gu(2)
290− verticalCenter: parent.verticalCenter
291− }
292− textSize: Label.XLarge
293− text: {
338+ section.delegate: ListItem {
339+ height: headerText.title.text !== "" ? headerText.height + divider.height : units.gu(0)
340+ divider.anchors.leftMargin: units.gu(2)
341+ divider.anchors.rightMargin: units.gu(2)
342+
343+ ListItemLayout {
344+ id: headerText
345+ title.text: {
294346 if (section === "Today") {
295347 return i18n.tr("Today")
296348 }
@@ -299,9 +351,16 @@ Tab {
299351 return i18n.tr("Yesterday")
300352 }
301353
302− else if (section === "Older")
354+ else if (section === "Older") {
303355 return i18n.tr("Older")
356+ }
357+
358+ else {
359+ return ""
360+ }
304361 }
362+ title.color: podbird.appTheme.baseText
363+ title.font.weight: Font.DemiBold
305364 }
306365 }
307366
@@ -314,9 +373,8 @@ Tab {
314373 id: listItem
315374
316375 divider.visible: false
317− highlightColor: "Transparent"
376+ highlightColor: podbird.appTheme.hightlightListView
318377 height: downloader.downloadingGuid === model.guid ? listItemLayout.height + progressBarLoader.height + units.gu(1) : listItemLayout.height + units.gu(0.5)
319− color: index % 2 === 0 ? podbird.appTheme.hightlightListView : "Transparent"
320378
321379 ListItemLayout {
322380 id: listItemLayout
@@ -372,24 +430,56 @@ Tab {
372430 db.transaction(function (tx) {
373431 tx.executeSql("UPDATE Episode SET downloadedfile = NULL WHERE guid = ?", [model.guid]);
374432 });
375− whatsNewModel.setProperty(model.index, "downloadedfile", "")
433+ episodesModel.setProperty(model.index, "downloadedfile", "")
434+ if (episodesPageHeaderSections.selectedIndex === 1) {
435+ episodesModel.remove(model.index, 1)
436+ }
376437 } else {
377438 db.transaction(function (tx) {
378439 tx.executeSql("UPDATE Episode SET queued=1 WHERE guid = ?", [model.guid]);
379440 });
380− whatsNewModel.setProperty(model.index, "queued", 1)
441+ episodesModel.setProperty(model.index, "queued", 1)
381442 downloader.addDownload(model.guid, model.audiourl);
382443 }
383444 }
384445 },
385446
386447 Action {
387− iconName: "select"
448+ iconName: model.listened ? "view-collapse" : "select"
388449 onTriggered: {
389450 var db = Podcasts.init();
390451 db.transaction(function (tx) {
391− tx.executeSql("UPDATE Episode SET listened=1 WHERE guid=?", [model.guid])
392− whatsNewModel.remove(model.index, 1)
452+ if (model.listened) {
453+ tx.executeSql("UPDATE Episode SET listened=0 WHERE guid=?", [model.guid])
454+ episodesModel.setProperty(model.index, "listened", 0)
455+ }
456+ else {
457+ tx.executeSql("UPDATE Episode SET listened=1 WHERE guid=?", [model.guid])
458+ episodesModel.setProperty(model.index, "listened", 1)
459+ if (episodesPageHeaderSections.selectedIndex === 0) {
460+ episodesModel.remove(model.index, 1)
461+ }
462+ }
463+ });
464+ }
465+ },
466+
467+ Action {
468+ iconName: model.favourited ? "unlike" : "like"
469+ onTriggered: {
470+ var db = Podcasts.init();
471+ db.transaction(function (tx) {
472+ if (model.favourited) {
473+ tx.executeSql("UPDATE Episode SET favourited=0 WHERE guid=?", [model.guid])
474+ episodesModel.setProperty(model.index, "favourited", 0)
475+ if (episodesPageHeaderSections.selectedIndex === 2) {
476+ episodesModel.remove(model.index, 1)
477+ }
478+ }
479+ else {
480+ tx.executeSql("UPDATE Episode SET favourited=1 WHERE guid=?", [model.guid])
481+ episodesModel.setProperty(model.index, "favourited", 1)
482+ }
393483 });
394484 }
395485 },
@@ -397,7 +487,7 @@ Tab {
397487 Action {
398488 iconName: "info"
399489 onTriggered: {
400− var popup = PopupUtils.open(episodeDescriptionDialog, whatsNewTab);
490+ var popup = PopupUtils.open(episodeDescriptionDialog, episodesTab);
401491 popup.description = model.description
402492 }
403493 }
@@ -437,44 +527,91 @@ Tab {
437527 }
438528
439529 function refreshModel() {
440− var today = new Date()
441− var dayToMs = 86400000; //1 * 24 * 60 * 60 * 1000
442− var i, j, episode, diff
443− var todayCount, yesterdayCount
530+ var i, j, episode
531+ var db = Podcasts.init()
444532
445− whatsNewModel.clear()
446− todayCount = 0
447− yesterdayCount = 0
533+ episodesModel.clear()
534+
535+ // Episode Model for the what's new view
536+ if (episodesPageHeaderSections.selectedIndex === 0) {
537+ var today = new Date()
538+ var dayToMs = 86400000; //1 * 24 * 60 * 60 * 1000
539+ var todayCount, yesterdayCount, diff
540+
541+ todayCount = 0
542+ yesterdayCount = 0
543+
544+ db.transaction(function (tx) {
545+ var rs = tx.executeSql("SELECT rowid, * FROM Podcast ORDER BY name ASC");
546+ for (i=0; i < rs.rows.length; i++) {
547+ var podcast = rs.rows.item(i);
548+ var rs2 = tx.executeSql("SELECT rowid, * FROM Episode WHERE podcast=? ORDER BY published DESC", [rs.rows.item(i).rowid]);
549+ for (j=0; j < rs2.rows.length; j++) {
550+ episode = rs2.rows.item(j)
551+ diff = Math.floor((today - episode.published)/dayToMs)
552+ if (diff < 7 && !episode.listened) {
553+ if (diff < 1) {
554+ episodesModel.insert(todayCount, {"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : podcast.image, "artist" : podcast.artist, "audiourl" : episode.audiourl, "queued": episode.queued, "favourited": episode.favourited, "diff": "Today"})
555+ todayCount++;
556+ } else if (diff < 2) {
557+ episodesModel.insert(todayCount + yesterdayCount, {"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : podcast.image, "artist" : podcast.artist, "audiourl" : episode.audiourl, "queued": episode.queued, "favourited": episode.favourited, "diff": "Yesterday"})
558+ yesterdayCount++;
559+ } else {
560+ episodesModel.append({"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : podcast.image, "artist" : podcast.artist, "audiourl" : episode.audiourl, "queued": episode.queued, "favourited": episode.favourited, "diff": "Older"})
561+ }
562+ } else if (diff >= 7){
563+ break
564+ }
565+ }
448566
449− var db = Podcasts.init()
450− db.transaction(function (tx) {
451− var rs = tx.executeSql("SELECT rowid, * FROM Podcast ORDER BY name ASC");
452− for (i=0; i < rs.rows.length; i++) {
453− var podcast = rs.rows.item(i);
454− var rs2 = tx.executeSql("SELECT rowid, * FROM Episode WHERE podcast=? ORDER BY published DESC", [rs.rows.item(i).rowid]);
455− for (j=0; j < rs2.rows.length; j++) {
456− episode = rs2.rows.item(j)
457− diff = Math.floor((today - episode.published)/dayToMs)
458− if (diff < 7 && !episode.listened) {
459− if (diff < 1) {
460− whatsNewModel.insert(todayCount, {"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : podcast.image, "artist" : podcast.artist, "audiourl" : episode.audiourl, "queued": episode.queued, "diff": "Today"})
461− todayCount++;
462− } else if (diff < 2) {
463− whatsNewModel.insert(todayCount + yesterdayCount, {"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : podcast.image, "artist" : podcast.artist, "audiourl" : episode.audiourl, "queued": episode.queued, "diff": "Yesterday"})
464− yesterdayCount++;
465− } else {
466− whatsNewModel.append({"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : podcast.image, "artist" : podcast.artist, "audiourl" : episode.audiourl, "queued": episode.queued, "diff": "Older"})
567+ if (podcast.lastupdate === null && !episodesUpdating) {
568+ updateEpisodesDatabase();
569+ }
570+ }
571+ });
572+ }
573+
574+ // Episode Model for the downloaded view
575+ else if (episodesPageHeaderSections.selectedIndex === 1) {
576+ db.transaction(function (tx) {
577+ var rs = tx.executeSql("SELECT rowid, * FROM Podcast ORDER BY name ASC");
578+ for (i=0; i < rs.rows.length; i++) {
579+ var podcast = rs.rows.item(i);
580+ var rs2 = tx.executeSql("SELECT rowid, * FROM Episode WHERE podcast=? ORDER BY published DESC", [rs.rows.item(i).rowid]);
581+ for (j=0; j < rs2.rows.length; j++) {
582+ episode = rs2.rows.item(j)
583+ if (episode.downloadedfile) {
584+ episodesModel.append({"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : podcast.image, "artist" : podcast.artist, "audiourl" : episode.audiourl, "queued": episode.queued, "favourited": episode.favourited, "diff": "Null"})
467585 }
468− } else if (diff >= 7){
469− break
586+ }
587+
588+ if (podcast.lastupdate === null && !episodesUpdating) {
589+ updateEpisodesDatabase();
470590 }
471591 }
592+ });
593+ }
594+
595+ // Episode Model for the favourites view
596+ else if (episodesPageHeaderSections.selectedIndex === 2) {
597+ db.transaction(function (tx) {
598+ var rs = tx.executeSql("SELECT rowid, * FROM Podcast ORDER BY name ASC");
599+ for (i=0; i < rs.rows.length; i++) {
600+ var podcast = rs.rows.item(i);
601+ var rs2 = tx.executeSql("SELECT rowid, * FROM Episode WHERE podcast=? ORDER BY published DESC", [rs.rows.item(i).rowid]);
602+ for (j=0; j < rs2.rows.length; j++) {
603+ episode = rs2.rows.item(j)
604+ if (episode.favourited) {
605+ episodesModel.append({"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : podcast.image, "artist" : podcast.artist, "audiourl" : episode.audiourl, "queued": episode.queued, "favourited": episode.favourited, "diff": "Null"})
606+ }
607+ }
472608
473− if (podcast.lastupdate === null && !episodesUpdating) {
474− updateEpisodesDatabase();
609+ if (podcast.lastupdate === null && !episodesUpdating) {
610+ updateEpisodesDatabase();
611+ }
475612 }
476− }
477− });
613+ });
614+ }
478615
479616 episodesUpdating = false;
480617 }
app/ui/PodcastsTab.qml+6−15
@@ -61,10 +61,10 @@ Page {
6161 }
6262 },
6363 Action {
64− iconName: podbird.settings.showListView ? "view-grid-symbolic" : "view-list-symbolic"
65− text: podbird.settings.showListView ? i18n.tr("Grid View") : i18n.tr("List View")
64+ iconName: "add"
65+ text: i18n.tr("Add New Podcasts")
6666 onTriggered: {
67− podbird.settings.showListView = !podbird.settings.showListView
67+ mainStack.push(Qt.resolvedUrl("SearchPage.qml"))
6868 }
6969 }
7070 ]
@@ -86,21 +86,13 @@ Page {
8686 anchors.verticalCenter: parent.verticalCenter
8787 }
8888
89− trailingActionBar.actions: [
89+ leadingActionBar.actions: [
9090 Action {
91− iconName: "edit-clear"
92− text: i18n.tr("Cancel")
91+ iconName: "back"
9392 onTriggered: {
9493 viewLoader.item.forceActiveFocus()
9594 podcastPage.header = standardHeader
9695 }
97− },
98− Action {
99− iconName: podbird.settings.showListView ? "view-grid-symbolic" : "view-list-symbolic"
100− text: podbird.settings.showListView ? i18n.tr("Grid View") : i18n.tr("List View")
101− onTriggered: {
102− podbird.settings.showListView = !podbird.settings.showListView
103− }
10496 }
10597 ]
10698 }
@@ -221,8 +213,7 @@ Page {
221213
222214 height: listItemLayout.height
223215 divider.visible: false
224− color: index % 2 === 0 ? podbird.appTheme.hightlightListView : "Transparent"
225− highlightColor: index % 2 === 0 ? "Transparent" : podbird.appTheme.hightlightListView
216+ highlightColor: podbird.appTheme.hightlightListView
226217
227218 ListItemLayout {
228219 id: listItemLayout
app/ui/SearchPage.qml+4−14
@@ -28,10 +28,6 @@ Page {
2828
2929 property var xhr: new XMLHttpRequest;
3030
31− TabsList {
32− id: tabsList
33− }
34−
3531 header: standardHeader
3632
3733 PageHeader {
@@ -44,11 +40,6 @@ Page {
4440 backgroundColor: podbird.appTheme.background
4541 }
4642
47− leadingActionBar {
48− numberOfSlots: 0
49− actions: tabsList.actions
50− }
51−
5243 trailingActionBar.actions: [
5344 Action {
5445 iconName: "search"
@@ -87,10 +78,9 @@ Page {
8778 anchors.verticalCenter: parent.verticalCenter
8879 }
8980
90− trailingActionBar.actions: [
81+ leadingActionBar.actions: [
9182 Action {
92− iconName: "edit-clear"
93− text: i18n.tr("Cancel")
83+ iconName: "back"
9484 onTriggered: {
9585 resultsView.forceActiveFocus()
9686 searchResults.clear()
@@ -294,7 +284,7 @@ Page {
294284 }
295285 });
296286 }
297− tabs.selectedTabIndex = 1;
287+ mainStack.pop();
298288 }
299289 }
300290 }
@@ -443,7 +433,7 @@ Page {
443433 Podcasts.subscribe(artist, name, feed, image);
444434 imageDownloader.feed = feed;
445435 imageDownloader.download(image);
446− tabs.selectedTabIndex = 1;
436+ mainStack.pop();
447437 } else {
448438 PopupUtils.open(subscribeFailedDialog);
449439 searchPage.header = addHeader
app/ui/SettingsPage.qml+14
@@ -146,6 +146,20 @@ Page {
146146 onClicked: mainStack.push(Qt.resolvedUrl("../settings/ThemeSetting.qml"))
147147 }
148148
149+ ListItem {
150+ ListItemLayout {
151+ id: gridViewLayout
152+ title.text: i18n.tr("Displays podcasts in a list view")
153+ Switch {
154+ SlotsLayout.position: SlotsLayout.Last
155+ checked: podbird.settings.showListView
156+ onClicked: podbird.settings.showListView = checked
157+ }
158+ }
159+ divider.visible: false
160+ height: gridViewLayout.height
161+ }
162+
149163 HeaderListItem {
150164 title.text: i18n.tr("Playback Settings")
151165 }
po/com.mikeasoft.podbird.pot+129−111
@@ -8,7 +8,7 @@ msgid ""
88msgstr ""
99"Project-Id-Version: \n"
1010"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2016-02-25 16:28+0530\n"
11+"POT-Creation-Date: 2016-03-19 07:47+0530\n"
1212"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,19 +18,15 @@ msgstr ""
1818"Content-Transfer-Encoding: 8bit\n"
1919"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
2020
21−#: ../app/components/TabsList.qml:11 ../app/ui/WhatsNewTab.qml:30
22−msgid "What's New"
21+#: ../app/components/TabsList.qml:29 ../app/ui/EpisodesTab.qml:48
22+msgid "Episodes"
2323msgstr ""
2424
25−#: ../app/components/TabsList.qml:19 ../app/ui/PodcastsTab.qml:42
25+#: ../app/components/TabsList.qml:37 ../app/ui/PodcastsTab.qml:42
2626msgid "Podcasts"
2727msgstr ""
2828
29−#: ../app/components/TabsList.qml:27
30−msgid "Add new podcasts"
31−msgstr ""
32−
33−#: ../app/components/TabsList.qml:35 ../app/ui/SettingsPage.qml:32
29+#: ../app/components/TabsList.qml:45 ../app/ui/SettingsPage.qml:32
3430msgid "Settings"
3531msgstr ""
3632
@@ -48,24 +44,24 @@ msgstr ""
4844msgid "No podcasts listened to today"
4945msgstr ""
5046
51−#: ../app/podcasts.js:180
47+#: ../app/podcasts.js:182
5248#, no-c-format, qt-format
5349msgid "%1 hr %2 min"
5450msgstr ""
5551
56−#: ../app/podcasts.js:189
52+#: ../app/podcasts.js:191
5753#, no-c-format, qt-format
5854msgid "%1 hr"
5955msgstr ""
6056
61−#: ../app/podcasts.js:197
57+#: ../app/podcasts.js:199
6258#, no-c-format, qt-format
6359msgid "%1 min"
6460msgstr ""
6561
6662#. TRANSLATORS: About as in information about the app
6763#: ../app/settings/About.qml:28 ../app/settings/About.qml:47
68−#: ../app/ui/SettingsPage.qml:208
64+#: ../app/ui/SettingsPage.qml:222
6965msgid "About"
7066msgstr ""
7167
@@ -143,7 +139,7 @@ msgstr ""
143139#: ../app/settings/DownloadSetting.qml:34
144140#: ../app/settings/DownloadSetting.qml:35
145141#: ../app/settings/DownloadSetting.qml:36
146−#: ../app/settings/DownloadSetting.qml:37 ../app/ui/EpisodesPage.qml:347
142+#: ../app/settings/DownloadSetting.qml:37
147143#, qt-format
148144msgid "%1 episode"
149145msgid_plural "%1 episodes"
@@ -164,72 +160,130 @@ msgstr ""
164160msgid "Dark"
165161msgstr ""
166162
167−#: ../app/ui/EpisodesPage.qml:33
163+#: ../app/ui/EpisodesPage.qml:32
168164msgid "Podcast"
169165msgstr ""
170166
171−#: ../app/ui/EpisodesPage.qml:74 ../app/ui/WhatsNewTab.qml:44
167+#: ../app/ui/EpisodesPage.qml:73 ../app/ui/EpisodesTab.qml:62
172168msgid "Search Episode"
173169msgstr ""
174170
175−#: ../app/ui/EpisodesPage.qml:83 ../app/ui/WhatsNewTab.qml:53
171+#: ../app/ui/EpisodesPage.qml:82 ../app/ui/EpisodesTab.qml:72
176172msgid "Mark all listened"
177173msgstr ""
178174
179−#: ../app/ui/EpisodesPage.qml:94 ../app/ui/EpisodesPage.qml:188
180−#: ../app/ui/SearchPage.qml:276
175+#: ../app/ui/EpisodesPage.qml:93 ../app/ui/EpisodesPage.qml:184
176+#: ../app/ui/SearchPage.qml:266
181177msgid "Unsubscribe"
182178msgstr ""
183179
184−#: ../app/ui/EpisodesPage.qml:111 ../app/ui/EpisodesPage.qml:205
185−#: ../app/ui/PodcastsTab.qml:92 ../app/ui/SearchPage.qml:93
186−#: ../app/ui/SearchPage.qml:131 ../app/ui/SettingsPage.qml:83
187−#: ../app/ui/SettingsPage.qml:118 ../app/ui/WhatsNewTab.qml:103
188−msgid "Cancel"
189−msgstr ""
190−
191−#: ../app/ui/EpisodesPage.qml:140 ../app/ui/WhatsNewTab.qml:116
180+#: ../app/ui/EpisodesPage.qml:136 ../app/ui/EpisodesTab.qml:173
192181msgid "Search episode"
193182msgstr ""
194183
195−#: ../app/ui/EpisodesPage.qml:185
184+#: ../app/ui/EpisodesPage.qml:181
196185msgid "Unsubscribe Confirmation"
197186msgstr ""
198187
199−#: ../app/ui/EpisodesPage.qml:186
188+#: ../app/ui/EpisodesPage.qml:182
200189#, qt-format
201190msgid "Are you sure you want to unsubscribe from <b>%1</b>?"
202191msgstr ""
203192
204−#: ../app/ui/EpisodesPage.qml:227 ../app/ui/WhatsNewTab.qml:216
193+#: ../app/ui/EpisodesPage.qml:201 ../app/ui/SearchPage.qml:121
194+#: ../app/ui/SettingsPage.qml:83 ../app/ui/SettingsPage.qml:118
195+msgid "Cancel"
196+msgstr ""
197+
198+#: ../app/ui/EpisodesPage.qml:223 ../app/ui/EpisodesTab.qml:295
205199msgid "Episode Description"
206200msgstr ""
207201
208−#: ../app/ui/EpisodesPage.qml:239 ../app/ui/SearchPage.qml:180
209−#: ../app/ui/WhatsNewTab.qml:228
202+#: ../app/ui/EpisodesPage.qml:234 ../app/ui/EpisodesTab.qml:306
203+#: ../app/ui/SearchPage.qml:170
210204msgid "Close"
211205msgstr ""
212206
213−#: ../app/ui/EpisodesPage.qml:267
207+#: ../app/ui/EpisodesPage.qml:262
214208msgid "No episodes found"
215209msgstr ""
216210
217−#: ../app/ui/EpisodesPage.qml:268
211+#: ../app/ui/EpisodesPage.qml:263
218212msgid "No episodes found matching the search term."
219213msgstr ""
220214
221−#: ../app/ui/EpisodesPage.qml:364
215+#: ../app/ui/EpisodesPage.qml:377
222216msgid "Unheard"
223217msgstr ""
224218
225−#: ../app/ui/EpisodesPage.qml:391
219+#: ../app/ui/EpisodesPage.qml:394
226220msgid "Listened"
227221msgstr ""
228222
229−#: ../app/ui/EpisodesPage.qml:416
223+#: ../app/ui/EpisodesPage.qml:413 ../app/ui/EpisodesTab.qml:135
230224msgid "Downloaded"
231225msgstr ""
232226
227+#: ../app/ui/EpisodesTab.qml:87
228+msgid "Download all"
229+msgstr ""
230+
231+#: ../app/ui/EpisodesTab.qml:104
232+msgid "Delete all"
233+msgstr ""
234+
235+#: ../app/ui/EpisodesTab.qml:135
236+msgid "Recent"
237+msgstr ""
238+
239+#: ../app/ui/EpisodesTab.qml:135
240+msgid "Favourites"
241+msgstr ""
242+
243+#: ../app/ui/EpisodesTab.qml:198
244+msgid "No New Episodes"
245+msgstr ""
246+
247+#: ../app/ui/EpisodesTab.qml:200
248+msgid "No Downloaded Episodes"
249+msgstr ""
250+
251+#: ../app/ui/EpisodesTab.qml:202
252+msgid "No Favourited Episodes"
253+msgstr ""
254+
255+#: ../app/ui/EpisodesTab.qml:204
256+msgid "No Episodes Found"
257+msgstr ""
258+
259+#: ../app/ui/EpisodesTab.qml:210
260+msgid "No more episodes to listen to!"
261+msgstr ""
262+
263+#: ../app/ui/EpisodesTab.qml:212
264+msgid "No episodes have been downloaded for offline listening"
265+msgstr ""
266+
267+#: ../app/ui/EpisodesTab.qml:214
268+msgid "No episodes have been favourited."
269+msgstr ""
270+
271+#: ../app/ui/EpisodesTab.qml:216
272+msgid "No Episodes found matching the search term."
273+msgstr ""
274+
275+#: ../app/ui/EpisodesTab.qml:347
276+msgid "Today"
277+msgstr ""
278+
279+#: ../app/ui/EpisodesTab.qml:351
280+msgid "Yesterday"
281+msgstr ""
282+
283+#: ../app/ui/EpisodesTab.qml:355
284+msgid "Older"
285+msgstr ""
286+
233287#: ../app/ui/NowPlayingPage.qml:29
234288msgid "Now Playing"
235289msgstr ""
@@ -246,110 +300,102 @@ msgstr ""
246300msgid "+%1s"
247301msgstr ""
248302
249−#: ../app/ui/PodcastsTab.qml:57 ../app/ui/SearchPage.qml:55
250−#: ../app/ui/SearchPage.qml:162
303+#: ../app/ui/PodcastsTab.qml:57 ../app/ui/SearchPage.qml:46
304+#: ../app/ui/SearchPage.qml:152
251305msgid "Search Podcast"
252306msgstr ""
253307
254−#: ../app/ui/PodcastsTab.qml:65 ../app/ui/PodcastsTab.qml:100
255−msgid "Grid View"
256−msgstr ""
257−
258−#: ../app/ui/PodcastsTab.qml:65 ../app/ui/PodcastsTab.qml:100
259−msgid "List View"
308+#: ../app/ui/PodcastsTab.qml:65 ../app/ui/SearchPage.qml:37
309+msgid "Add New Podcasts"
260310msgstr ""
261311
262−#: ../app/ui/PodcastsTab.qml:112
312+#: ../app/ui/PodcastsTab.qml:104
263313msgid "Search podcast"
264314msgstr ""
265315
266−#: ../app/ui/PodcastsTab.qml:142
316+#: ../app/ui/PodcastsTab.qml:134
267317msgid "No Podcast Subscriptions"
268318msgstr ""
269319
270−#: ../app/ui/PodcastsTab.qml:142
320+#: ../app/ui/PodcastsTab.qml:134
271321msgid "No Podcasts Found"
272322msgstr ""
273323
274−#: ../app/ui/PodcastsTab.qml:143
324+#: ../app/ui/PodcastsTab.qml:135
275325msgid ""
276326"You haven't subscribed to any podcasts yet, visit the 'Find New Podcasts' "
277327"page to add some."
278328msgstr ""
279329
280−#: ../app/ui/PodcastsTab.qml:144 ../app/ui/SearchPage.qml:210
330+#: ../app/ui/PodcastsTab.qml:136 ../app/ui/SearchPage.qml:200
281331msgid "No podcasts found matching the search term."
282332msgstr ""
283333
284−#: ../app/ui/PodcastsTab.qml:182 ../app/ui/PodcastsTab.qml:230
334+#: ../app/ui/PodcastsTab.qml:174 ../app/ui/PodcastsTab.qml:221
285335#, qt-format
286336msgid "%1 unheard episode"
287337msgid_plural "%1 unheard episodes"
288338msgstr[0] ""
289339msgstr[1] ""
290340
291−#: ../app/ui/SearchPage.qml:41
292−msgid "Add New Podcasts"
293−msgstr ""
294−
295−#: ../app/ui/SearchPage.qml:63
341+#: ../app/ui/SearchPage.qml:54
296342msgid "Add Podcast"
297343msgstr ""
298344
299−#: ../app/ui/SearchPage.qml:123
345+#: ../app/ui/SearchPage.qml:113
300346msgid "Save Podcast"
301347msgstr ""
302348
303−#: ../app/ui/SearchPage.qml:150
349+#: ../app/ui/SearchPage.qml:140
304350msgid "Feed URL"
305351msgstr ""
306352
307−#: ../app/ui/SearchPage.qml:177
353+#: ../app/ui/SearchPage.qml:167
308354msgid "Unable to subscribe"
309355msgstr ""
310356
311−#: ../app/ui/SearchPage.qml:178
357+#: ../app/ui/SearchPage.qml:168
312358msgid "Please check the URL and try again"
313359msgstr ""
314360
315−#: ../app/ui/SearchPage.qml:208
361+#: ../app/ui/SearchPage.qml:198
316362msgid "Looking to add a new Podcast?"
317363msgstr ""
318364
319−#: ../app/ui/SearchPage.qml:208
365+#: ../app/ui/SearchPage.qml:198
320366msgid "No Podcasts found"
321367msgstr ""
322368
323−#: ../app/ui/SearchPage.qml:209
369+#: ../app/ui/SearchPage.qml:199
324370msgid ""
325371"Click the 'magnifier' at the top to search or the 'plus' button to add by URL"
326372msgstr ""
327373
328−#: ../app/ui/SearchPage.qml:276
374+#: ../app/ui/SearchPage.qml:266
329375msgid "Subscribe"
330376msgstr ""
331377
332378#. TRANSLATORS: The first argument here is the date of when the podcast was last updated followed by
333379#. the podcast description.
334−#: ../app/ui/SearchPage.qml:315
380+#: ../app/ui/SearchPage.qml:305
335381#, qt-format
336382msgid ""
337383"Last Updated: %1\n"
338384"%2"
339385msgstr ""
340386
341−#: ../app/ui/SearchPage.qml:372
387+#: ../app/ui/SearchPage.qml:362
342388msgid "Not Available"
343389msgstr ""
344390
345391#. TRANSLATORS: This strings refers to the seeking of the episode playback. Users can set how far they
346392#. want to seek forward when pressing on this button.
347−#: ../app/ui/SettingsPage.qml:63 ../app/ui/SettingsPage.qml:155
393+#: ../app/ui/SettingsPage.qml:63 ../app/ui/SettingsPage.qml:169
348394msgid "Skip forward"
349395msgstr ""
350396
351397#: ../app/ui/SettingsPage.qml:70 ../app/ui/SettingsPage.qml:105
352−#: ../app/ui/SettingsPage.qml:156 ../app/ui/SettingsPage.qml:163
398+#: ../app/ui/SettingsPage.qml:170 ../app/ui/SettingsPage.qml:177
353399#, qt-format
354400msgid "%1 seconds"
355401msgstr ""
@@ -360,7 +406,7 @@ msgstr ""
360406
361407#. TRANSLATORS: This strings refers to the seeking of the episode playback. Users can set how far they
362408#. want to seek backward when pressing on this button.
363−#: ../app/ui/SettingsPage.qml:98 ../app/ui/SettingsPage.qml:162
409+#: ../app/ui/SettingsPage.qml:98 ../app/ui/SettingsPage.qml:176
364410msgid "Skip back"
365411msgstr ""
366412
@@ -370,73 +416,45 @@ msgstr ""
370416msgid "General Settings"
371417msgstr ""
372418
373−#: ../app/ui/SettingsPage.qml:150
419+#: ../app/ui/SettingsPage.qml:152
420+msgid "Displays podcasts in a list view"
421+msgstr ""
422+
423+#: ../app/ui/SettingsPage.qml:164
374424msgid "Playback Settings"
375425msgstr ""
376426
377−#: ../app/ui/SettingsPage.qml:168
427+#: ../app/ui/SettingsPage.qml:182
378428msgid "Podcast Episode Settings"
379429msgstr ""
380430
381−#: ../app/ui/SettingsPage.qml:174
431+#: ../app/ui/SettingsPage.qml:188
382432msgid "Automatically delete old episodes"
383433msgstr ""
384434
385−#: ../app/ui/SettingsPage.qml:176
435+#: ../app/ui/SettingsPage.qml:190
386436msgid ""
387437"Delete episodes that are older than a given number of days for each podcast"
388438msgstr ""
389439
390−#: ../app/ui/SettingsPage.qml:188
440+#: ../app/ui/SettingsPage.qml:202
391441msgid "Automatically download new episodes"
392442msgstr ""
393443
394−#: ../app/ui/SettingsPage.qml:190
444+#: ../app/ui/SettingsPage.qml:204
395445msgid "Default number of new episodes to download for each podcast"
396446msgstr ""
397447
398448#. TRANSLATORS: Shortened form of "Miscellaneous" which is shown to denote other setting options
399449#. that doesn't fit into any other category.
400−#: ../app/ui/SettingsPage.qml:202
450+#: ../app/ui/SettingsPage.qml:216
401451msgid "Misc."
402452msgstr ""
403453
404−#: ../app/ui/SettingsPage.qml:218
454+#: ../app/ui/SettingsPage.qml:232
405455msgid "Report Bug"
406456msgstr ""
407457
408−#: ../app/ui/WhatsNewTab.qml:67
409−msgid "Download all"
410−msgstr ""
411−
412−#: ../app/ui/WhatsNewTab.qml:138
413−msgid "No New Episodes"
414−msgstr ""
415−
416−#: ../app/ui/WhatsNewTab.qml:138
417−msgid "No Episodes Found"
418−msgstr ""
419−
420−#: ../app/ui/WhatsNewTab.qml:139
421−msgid "No more episodes to listen to!"
422−msgstr ""
423−
424−#: ../app/ui/WhatsNewTab.qml:139
425−msgid "No Episodes found matching the search term."
426−msgstr ""
427−
428−#: ../app/ui/WhatsNewTab.qml:277
429−msgid "Today"
430−msgstr ""
431−
432−#: ../app/ui/WhatsNewTab.qml:281
433−msgid "Yesterday"
434−msgstr ""
435−
436−#: ../app/ui/WhatsNewTab.qml:285
437−msgid "Older"
438−msgstr ""
439−
440458#: ../app/welcomewizard/Slide1.qml:42
441459msgid "Welcome to Podbird"
442460msgstr ""
@@ -511,10 +529,10 @@ msgstr ""
511529msgid "Finish"
512530msgstr ""
513531
514−#: /home/krnekhelesh/Development/uc-1.3-migrate-build/po/Podbird.desktop.in.h:1
532+#: /home/krnekhelesh/Development/devel-branch-sync-1-build/po/Podbird.desktop.in.h:1
515533msgid "The chirpiest podcast manager for Ubuntu"
516534msgstr ""
517535
518−#: /home/krnekhelesh/Development/uc-1.3-migrate-build/po/Podbird.desktop.in.h:2
536+#: /home/krnekhelesh/Development/devel-branch-sync-1-build/po/Podbird.desktop.in.h:2
519537msgid "podcast;audio;itunes;broadcast;digital;stream;podcatcher;video;vodcast;"
520538msgstr ""