Merge lp:~nik90/podbird/5.5-kevin-redesign into lp:podbird

Proposed by Nekhelesh Ramananthan
Status: Merged
Merged at revision: 44
Proposed branch: lp:~nik90/podbird/5.5-kevin-redesign
Merge into: lp:podbird
Prerequisite: lp:~nik90/podbird/5-auto-download-option
Diff against target: 1344 lines (+528/-409)
11 files modified
app/podbird.qml (+12/-2)
app/podcasts.js (+16/-3)
app/themes/Dark.qml (+4/-4)
app/themes/Light.qml (+4/-4)
app/ui/ActionButton.qml (+1/-0)
app/ui/BlurredBackground.qml (+4/-21)
app/ui/EpisodesPage.qml (+269/-227)
app/ui/PlayerControls.qml (+2/-2)
app/ui/PodcastsTab.qml (+3/-8)
app/ui/SearchPage.qml (+153/-102)
po/com.mikeasoft.podbird.pot (+60/-36)
To merge this branch: bzr merge lp:~nik90/podbird/5.5-kevin-redesign
Reviewer Review Type Date Requested Status
Michael Sheldon Approve
Review via email: mp+255155@code.launchpad.net

Description of the change

This MP is a huge one brings a lot of improvements which are listed below,
- Redesigned the episodes page and search page according to the designs provided by Kevin (community designer) which is a lot of list..best would be to run this branch and check ;)

- Starting a download or deleting a download file no longer refreshes the entire episodesModel as it is expensive and jarring to the user. Instead I have used episodeModel.setProperty(), episodeModel.insert() to intelligently update only the concerned episode.

- In the episodes page, the episodes are now separated by "New" and "Listened". Again this is done intelligently using the setProperty() function. This enables us to no longer show the "tick" icon.

- The Podcasts page now shows alternating colors for listitems

- The blurred background component has been cleaned up and is now more customizable. It allow for setting the blur opacity which helps with using different values for the Light and Dark theme.

- Dark theme has received some minor color changes.

- Sqlite Schema Upgrade to v1.1. In this version I introduced a new column to every episode "Queued" which keeps track if the episode is in the download queue or not. By storing this in the database, the queue status is preserved if if the user closes the episode page and reopens another page. This is important to inform the user of what episodes are being auto-downloaded by Podbird on app startup.

To post a comment you must log in.
lp:~nik90/podbird/5.5-kevin-redesign updated
67. By Nekhelesh Ramananthan

Fixed a rare case where the downloading status was not shown properly when the user closes and reopens the episodes page

Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

Here's a screenshot of what it looks now https://imgur.com/5gKB4QG

lp:~nik90/podbird/5.5-kevin-redesign updated
68. By Nekhelesh Ramananthan

Used a cutom progress bar and tweaked theme colors

69. By Nekhelesh Ramananthan

Small UI Tweaks

70. By Nekhelesh Ramananthan

Dynamically load/unload the search tab

71. By Nekhelesh Ramananthan

Renamed search tab to search page

72. By Nekhelesh Ramananthan

merged prerequisite

73. By Nekhelesh Ramananthan

Added a new column queued to database via a schema upgrade

74. By Nekhelesh Ramananthan

Added comments and fixed alter table sqlite command

75. By Nekhelesh Ramananthan

merged prerequisite

76. By Nekhelesh Ramananthan

Tweaked bottom bar color

77. By Nekhelesh Ramananthan

Added a new application icon

78. By Nekhelesh Ramananthan

Changed New to Unheard

79. By Nekhelesh Ramananthan

Fixed issue where auto-download did not set the queue status correctly. Also fixed formatTime() function complaining about model.duration missing

80. By Nekhelesh Ramananthan

merged prerequisite fix

81. By Nekhelesh Ramananthan

Merged prerequisite

82. By Nekhelesh Ramananthan

Merged prerequisite

Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

Note: If you notice any issues while testing this branch, please list them out. Most likely they have been fixed in one of the MPs which came after this. For instance, the database scheme upgrade done in this MP is usually to its full potential only in lp:~nik90/podbird/7-mark-episode-listened MP.

Revision history for this message
Michael Sheldon (michael-sheldon) wrote :

Only found two small issues that don't appear to be covered by other branches; I've added fixes for them myself whilst merging, they were just that 1) the new download indicator doesn't show any activity when download manager gives bad progress information (I've made the progress indicator bounce back and forth under these circumstances) and 2) the redesigned episodes page shows "NaN:NaN" for podcasts that don't provide duration information.

Like I said, I've fixed these though, so have now merged this branch :).

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'app/podbird.qml'
2--- app/podbird.qml 2015-04-15 23:06:20 +0000
3+++ app/podbird.qml 2015-04-18 14:12:52 +0000
4@@ -167,9 +167,18 @@
5 objectName: "podcastsTab"
6 }
7
8- SearchTab {
9+ Tab {
10 id: searchTab
11- objectName: "searchTab"
12+
13+ title: i18n.tr("Find New Podcasts")
14+
15+ page: Loader {
16+ parent: searchTab
17+ anchors.left: parent.left
18+ anchors.right: parent.right
19+ anchors.bottom: parent.bottom
20+ source: (tabs.selectedTab === searchTab) ? Qt.resolvedUrl("ui/SearchPage.qml") : ""
21+ }
22 }
23
24 Tab {
25@@ -248,6 +257,7 @@
26 for (var j=0; j < loopCount; j++) {
27 if (!rs2.rows.item(j).downloadedfile && !rs2.rows.item(j).listened) {
28 downloader.addDownload(rs2.rows.item(j).guid, rs2.rows.item(j).audiourl)
29+ tx.executeSql("UPDATE Episode SET queued=1 WHERE guid = ?", [rs2.rows.item(j).guid]);
30 }
31 }
32 }
33
34=== modified file 'app/podcasts.js'
35--- app/podcasts.js 2015-02-28 09:46:48 +0000
36+++ app/podcasts.js 2015-04-18 14:12:52 +0000
37@@ -1,5 +1,5 @@
38 /*
39- * Copyright 2015 Michael Sheldon <mike@mikeasoft.com>
40+ * Copyright 2015 Podbird Team
41 *
42 * This file is part of Podbird.
43 *
44@@ -17,11 +17,24 @@
45 */
46
47 function init() {
48- var db = LocalStorage.openDatabaseSync("Podbird", "1.0", "Database of subscribed podcasts and their episodes", 1000000);
49+ var db = LocalStorage.openDatabaseSync("Podbird", "", "Database of subscribed podcasts and their episodes", 1000000);
50+
51 db.transaction(function(tx) {
52 tx.executeSql('CREATE TABLE IF NOT EXISTS Podcast(artist TEXT, name TEXT, description TEXT, feed TEXT, image TEXT, lastupdate TIMESTAMP)');
53- 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, listened BOOLEAN, position INTEGER, FOREIGN KEY(podcast) REFERENCES Podcast(rowid))');
54+ 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, listened BOOLEAN, queued BOOLEAN, position INTEGER, FOREIGN KEY(podcast) REFERENCES Podcast(rowid))');
55 });
56+
57+ /*
58+ Schema Upgrade to v1.1 which adds a new queued boolean variable which is needed to track the queued status
59+ of a episode properly.
60+ */
61+ if (db.version == "1.0") {
62+ db.changeVersion("1.0", "1.1", function(tx) {
63+ tx.executeSql('ALTER TABLE Episode ADD queued BOOLEAN');
64+ tx.executeSql('UPDATE Episode SET queued=0');
65+ });
66+ }
67+
68 return db;
69 }
70
71
72=== modified file 'app/themes/Dark.qml'
73--- app/themes/Dark.qml 2015-03-04 02:58:36 +0000
74+++ app/themes/Dark.qml 2015-04-18 14:12:52 +0000
75@@ -21,12 +21,12 @@
76
77 QtObject {
78 // MainView
79- property color background: "#1E1E23"
80+ property color background: "#242423"
81
82 // Main Text Colors
83 property color baseText: "White"
84 property color baseSubText: "#999999"
85- property color focusText: "#FF9900"
86+ property color focusText: "#35AF44"
87
88 // Icon Colors
89 property color baseIcon: "White"
90@@ -37,8 +37,8 @@
91 property color neutralActionButton: UbuntuColors.coolGrey
92
93 // Bottom Player Bar Colors
94- property color bottomBarBackground: "#0F0F0F"
95+ property color bottomBarBackground: "#15141A"
96
97 // Highlight Color
98- property color hightlightListView: "#2C2C34"
99+ property color hightlightListView: "#333533"
100 }
101
102=== modified file 'app/themes/Light.qml'
103--- app/themes/Light.qml 2015-03-04 02:58:36 +0000
104+++ app/themes/Light.qml 2015-04-18 14:12:52 +0000
105@@ -21,12 +21,12 @@
106
107 QtObject {
108 // MainView
109- property color background: "#EEEEEE"
110+ property color background: "#ECECEC"
111
112 // Main Text Colors
113 property color baseText: UbuntuColors.darkGrey
114 property color baseSubText: "#999999"
115- property color focusText: UbuntuColors.orange
116+ property color focusText: "#35AF44"
117
118 // Icon Colors
119 property color baseIcon: UbuntuColors.darkGrey
120@@ -37,8 +37,8 @@
121 property color neutralActionButton: UbuntuColors.coolGrey
122
123 // Bottom Player Bar Colors
124- property color bottomBarBackground: "#0F0F0F"
125+ property color bottomBarBackground: "#323435"
126
127 // Highlight Color
128- property color hightlightListView: "#D8D8D8"
129+ property color hightlightListView: "#F5F5F5"
130 }
131
132=== modified file 'app/ui/ActionButton.qml'
133--- app/ui/ActionButton.qml 2015-03-08 11:10:07 +0000
134+++ app/ui/ActionButton.qml 2015-04-18 14:12:52 +0000
135@@ -23,6 +23,7 @@
136 id: abstractButton
137
138 property string iconName
139+ property alias color: _icon.color
140
141 Rectangle {
142 visible: abstractButton.pressed
143
144=== modified file 'app/ui/BlurredBackground.qml'
145--- app/ui/BlurredBackground.qml 2015-02-10 06:57:54 +0000
146+++ app/ui/BlurredBackground.qml 2015-04-18 14:12:52 +0000
147@@ -25,15 +25,8 @@
148 Item {
149 width: parent.width
150
151- property string art // : player.currentMetaFile === "" ? Qt.resolvedUrl("../images/music-app-cover@30.png") : player.currentMetaArt
152-
153- // dark layer
154- Rectangle {
155- anchors {
156- fill: parent
157- }
158- color: "black"
159- }
160+ property string art
161+ property real backgroundStrength: 0.4
162
163 // the album art
164 Image {
165@@ -44,16 +37,6 @@
166 fillMode: Image.PreserveAspectCrop
167 height: parent.height
168 source: art // this has to be fixed for the default cover art to work - cant find in this dir
169-
170- // TODO: This should be investigated once http://pad.lv/1391368
171- // is resolved. Once it is, these can either be set to
172- // "height" and "width" or a property exposed via the
173- // SDK or Thumbnailer to avoid a regression caused by
174- // these hardcoded values changing in the Thumbnailer.
175- // 512 is size of the "xlarge" thumbnails in pixels.
176- sourceSize.height: 512
177- sourceSize.width: 512
178-
179 visible: false
180 width: Math.max(parent.height, parent.width)
181 }
182@@ -63,8 +46,8 @@
183 id: backgroundBlur
184 anchors.fill: backgroundImage
185 source: backgroundImage
186- radius: units.dp(42)
187- opacity: 0.2
188+ radius: units.dp(30)
189+ opacity: backgroundStrength
190 }
191 onArtChanged: {
192 // TODO: This is a work around for LP:1261078 and LP:1306845. Ideally,
193
194=== modified file 'app/ui/EpisodesPage.qml'
195--- app/ui/EpisodesPage.qml 2015-03-29 15:33:26 +0000
196+++ app/ui/EpisodesPage.qml 2015-04-18 14:12:52 +0000
197@@ -30,17 +30,21 @@
198 id: episodesPage
199
200 visible: false
201- title: episodeName
202+ title: i18n.tr("Podcast")
203+ flickable: null
204
205 property string episodeName
206 property string episodeId
207 property string episodeArtist
208 property string episodeImage
209+ property string tempGuid: "NULL"
210
211 property bool episodesUpdating: false;
212
213 Component.onCompleted: {
214 loadEpisodes(episodeId, episodeArtist, episodeImage)
215+ if (downloader.downloadingGuid != "")
216+ tempGuid = downloader.downloadingGuid
217 }
218
219 /*
220@@ -95,7 +99,7 @@
221 onTriggered: {
222 var db = Podcasts.init();
223 db.transaction(function (tx) {
224- tx.executeSql("UPDATE Episode SET listened=1 WHERE podcast=?", [episodeModel.pid]);
225+ tx.executeSql("UPDATE Episode SET listened=1 WHERE podcast=?", [episodeId]);
226 refreshModel();
227 });
228 }
229@@ -122,6 +126,7 @@
230 episodeList.forceActiveFocus()
231 searchField.text = ""
232 episodesPage.state = "default"
233+ episodeList.positionViewAtBeginning()
234 }
235 }
236
237@@ -139,7 +144,36 @@
238 Connections {
239 target: downloader
240 onDownloadingGuidChanged: {
241- loadEpisodes(episodeId, episodeArtist, episodeImage);
242+ var db = Podcasts.init();
243+ db.transaction(function (tx) {
244+ /*
245+ If tempGuid is NULL, then the episode currently being downloaded is not found within
246+ this podcast. On the other hand, if it is within this podcast, then update the episodeModel
247+ with the downloadedfile location we just received from the downloader.
248+ */
249+ if (tempGuid != "NULL") {
250+ var rs2 = tx.executeSql("SELECT downloadedfile, podcast FROM Episode WHERE guid=?", [tempGuid]);
251+ for (var i=0; i<episodeModel.count; i++) {
252+ if (episodeModel.get(i).guid == tempGuid) {
253+ console.log("[LOG]: Setting episode download URL to " + rs2.rows.item(0).downloadedfile)
254+ episodeModel.setProperty(i, "downloadedfile", rs2.rows.item(0).downloadedfile)
255+ break
256+ }
257+ }
258+ tempGuid = "NULL"
259+ }
260+
261+ /*
262+ Here it is checked if the currently downloaded episode belongs to the podcast
263+ page being currently displayed. If it is, then the downloaded episode guid is
264+ stored in the tempGuid variable to track it.
265+ */
266+ var rs = tx.executeSql("SELECT podcast FROM Episode WHERE guid=?", [downloader.downloadingGuid]);
267+
268+ if (downloader.downloadingGuid != "" && rs.rows.item(0).podcast == episodeId && tempGuid == "NULL") {
269+ tempGuid = downloader.downloadingGuid
270+ }
271+ });
272 }
273 }
274
275@@ -155,12 +189,12 @@
276 onClicked: {
277 var db = Podcasts.init();
278 db.transaction(function (tx) {
279- var rs = tx.executeSql("SELECT downloadedfile FROM Episode WHERE downloadedfile NOT NULL AND podcast=?", [episodeModel.pid]);
280+ var rs = tx.executeSql("SELECT downloadedfile FROM Episode WHERE downloadedfile NOT NULL AND podcast=?", [episodeId]);
281 for(var i = 0; i < rs.rows.length; i++) {
282 fileManager.deleteFile(rs.rows.item(i).downloadedfile);
283 }
284- tx.executeSql("DELETE FROM Episode WHERE podcast=?", [episodeModel.pid]);
285- tx.executeSql("DELETE FROM Podcast WHERE rowid=?", [episodeModel.pid]);
286+ tx.executeSql("DELETE FROM Episode WHERE podcast=?", [episodeId]);
287+ tx.executeSql("DELETE FROM Podcast WHERE rowid=?", [episodeId]);
288 mainStack.pop()
289 PopupUtils.close(dialogInternal)
290 });
291@@ -187,9 +221,6 @@
292
293 ListModel {
294 id: episodeModel
295- property string pid;
296- property string artist;
297- property string image;
298 }
299
300 SortFilterModel {
301@@ -199,12 +230,118 @@
302 filter.pattern: RegExp(searchField.text, "gi")
303 }
304
305- ListView {
306+ function formatTime(seconds) {
307+ var time = Podcasts.getTimeDiff(seconds)
308+ var hour = time[0]
309+ var minute = time[1]
310+ // TRANSLATORS: the first argument is the number of hours,
311+ // followed by minute (eg. 20h 3m)
312+ if(hour > 0 && minute > 0) {
313+ // xgettext: no-c-format
314+ return (i18n.tr("%1 hr %2 min"))
315+ .arg(hour)
316+ .arg(minute)
317+ }
318+
319+ // TRANSLATORS: this string indicates the number of hours
320+ // eg. 20h (no plural state required)
321+ else if(hour > 0 && minute === 0) {
322+ // xgettext: no-c-format
323+ return (i18n.tr("%1 hr"))
324+ .arg(hour)
325+ }
326+
327+ // TRANSLATORS: this string indicates the number of minutes
328+ // eg. 15m (no plural state required)
329+ else if(hour === 0 && minute > 0) {
330+ // xgettext: no-c-format
331+ return (i18n.tr("%1 min"))
332+ .arg(minute)
333+ }
334+
335+ else {
336+ return Podcasts.formatTime(seconds)
337+ }
338+ }
339+
340+ UbuntuListView {
341 id: episodeList
342
343+ anchors.fill: parent
344+ model: sortedEpisodeModel
345+
346 clip: true
347- anchors.fill: parent
348- model: sortedEpisodeModel
349+ section.property: "listened"
350+ section.labelPositioning: ViewSection.InlineLabels
351+
352+ section.delegate: Rectangle {
353+ width: parent.width
354+ color: section === "0" ? podbird.theme.hightlightListView : "Transparent"
355+ height: header.implicitHeight + units.gu(2)
356+ Label {
357+ id: header
358+ anchors {
359+ left: parent.left
360+ right: parent.right
361+ margins: units.gu(2)
362+ verticalCenter: parent.verticalCenter
363+ }
364+ fontSize: "x-large"
365+ text: section === "0" ? i18n.tr("Unheard") : i18n.tr("Listened")
366+ }
367+ }
368+
369+ header: BlurredBackground {
370+ id: blurredBackground
371+
372+ art: episodeImage
373+ width: parent.width
374+ visible: episodesPage.state !== "search"
375+ height: episodesPage.state !== "search" ? cover.height + units.gu(4) : 0
376+ backgroundStrength: podbird.settings.themeName === "Light.qml" ? 0.3 : 0.6
377+
378+ Image {
379+ id:cover
380+ width: units.gu(12)
381+ height: width
382+ sourceSize.height: width
383+ sourceSize.width: width
384+ source: episodeImage
385+ anchors {
386+ left: parent.left
387+ top: parent.top
388+ margins: units.gu(2)
389+ }
390+ }
391+
392+ Column {
393+ id: podcastTitle
394+
395+ anchors {
396+ left: cover.right
397+ right: parent.right
398+ bottom: parent.bottom
399+ margins: units.gu(2)
400+ }
401+
402+ Label {
403+ text: episodeName
404+ width: parent.width
405+ wrapMode: Text.WordWrap
406+ maximumLineCount: 2
407+ elide: Text.ElideRight
408+ color: podbird.theme.baseText
409+ }
410+
411+ Label {
412+ text: i18n.tr("%1 episode", "%1 episodes", episodeList.count).arg(episodeList.count)
413+ width: parent.width
414+ elide: Text.ElideRight
415+ fontSize: "x-small"
416+ color: podbird.theme.baseText
417+ }
418+ }
419+ }
420
421 footer: Item {
422 width: parent.width
423@@ -214,51 +351,41 @@
424 delegate: ListItem.Empty {
425 id: listItem
426
427- property bool expanded: false
428+ property bool expanded
429
430- width: parent.width
431- height: mainColumn.height
432+ height: dataColumn.height + units.gu(2)
433 highlightWhenPressed: false
434+ showDivider: false
435
436- onClicked: listItem.expanded = !listItem.expanded
437+ onClicked: {
438+ expanded = !expanded;
439+ }
440
441 Rectangle {
442- anchors.fill: parent
443- color: listItem.pressed ? podbird.theme.hightlightListView : "transparent"
444+ visible: !model.listened
445+ width: parent.width
446+ height: dataColumn.height + units.gu(2)
447+ color: podbird.theme.hightlightListView
448 }
449
450 Column {
451- id: mainColumn
452-
453- anchors {
454- top: parent.top
455- left: parent.left
456- right: parent.right
457- margins: units.gu(2)
458- topMargin: units.gu(1)
459- }
460+ id: dataColumn
461
462 spacing: units.gu(1)
463+ anchors.left: parent.left
464+ anchors.right: parent.right
465+ anchors.margins: units.gu(2)
466+ anchors.top: parent.top
467+ anchors.topMargin: units.gu(0.5)
468
469 RowLayout {
470- id: titleRow
471+ id: rowlayout
472
473 width: parent.width
474- spacing: units.gu(2)
475-
476- Image {
477- id: imgFrame
478- width: units.gu(6)
479- height: width
480- sourceSize.height: width
481- sourceSize.width: width
482- source: model.image
483- }
484+ height: titleColumn.height
485
486 Column {
487- id: detailColumn
488-
489- anchors.verticalCenter: imgFrame.verticalCenter
490+ id: titleColumn
491 Layout.fillWidth: true
492
493 Label {
494@@ -267,19 +394,97 @@
495 maximumLineCount: 2
496 wrapMode: Text.WordWrap
497 elide: Text.ElideRight
498- color: currentGuid === model.guid ? podbird.theme.focusText
499- : podbird.theme.baseText
500+ color: listItem.expanded || currentGuid === model.guid || downloader.downloadingGuid === model.guid ? podbird.theme.focusText
501+ : podbird.theme.baseText
502 }
503
504 Label {
505 id: episodePublishDate
506 width: parent.width
507- text: Qt.formatDate(new Date(model.published), "MMM d, yyyy")
508+ text: formatTime(model.duration) + " | " + Qt.formatDate(new Date(model.published), "MMM d, yyyy")
509 fontSize: "x-small"
510- color: currentGuid === model.guid ? podbird.theme.focusText
511- : podbird.theme.baseText
512 elide: Text.ElideRight
513- }
514+ color: podbird.theme.baseSubText
515+ }
516+ }
517+
518+ ActionButton {
519+ id: downloadButton
520+
521+ width: units.gu(5)
522+ height: units.gu(4)
523+
524+ property bool queued: false
525+
526+ iconName: model.downloadedfile ? "delete" : (queued && downloader.downloadingGuid !== model.guid ? "history" : "save")
527+ enabled: downloader.downloadingGuid !== model.guid
528+ color: downloader.downloadingGuid === model.guid ? podbird.theme.focusText
529+ : podbird.theme.baseText
530+
531+ onClicked: {
532+ if (model.downloadedfile) {
533+ fileManager.deleteFile(model.downloadedfile);
534+ var db = Podcasts.init();
535+ db.transaction(function (tx) {
536+ tx.executeSql("UPDATE Episode SET downloadedfile = NULL WHERE guid = ?", [model.guid]);
537+ });
538+ episodeModel.setProperty(index, "downloadedfile", "")
539+ downloadButton.queued = false
540+ } else {
541+ downloadButton.queued = true;
542+ downloader.addDownload(model.guid, model.audiourl);
543+ }
544+ }
545+ }
546+
547+ ActionButton {
548+ width: units.gu(4)
549+ height: units.gu(4)
550+
551+ iconName: player.playbackState === MediaPlayer.PlayingState && currentGuid === model.guid ? "media-playback-pause"
552+ : "media-playback-start"
553+ color: player.playbackState === MediaPlayer.PlayingState && currentGuid === model.guid ? podbird.theme.focusText
554+ : podbird.theme.baseIcon
555+
556+ onClicked: {
557+ var db = Podcasts.init();
558+ db.transaction(function (tx) {
559+ if (currentGuid === model.guid) {
560+ if (player.playbackState === MediaPlayer.PlayingState) {
561+ player.pause()
562+ } else {
563+ player.play()
564+ }
565+ } else {
566+ currentGuid = "";
567+ player.source = model.downloadedfile ? model.downloadedfile : model.audiourl;
568+ var rs = tx.executeSql("SELECT position FROM Episode WHERE guid=?", [model.guid]);
569+ player.play();
570+ player.seek(rs.rows.item(0).position);
571+ currentName = model.name;
572+ currentArtist = model.artist;
573+ currentImage = model.image;
574+ currentGuid = model.guid;
575+ }
576+ });
577+ }
578+ }
579+ }
580+
581+ Rectangle {
582+ id: progressBar
583+ radius: width/3
584+ width: parent.width
585+ height: units.dp(5)
586+ color: Theme.palette.normal.base
587+ visible: downloader.downloadingGuid === model.guid
588+ Rectangle {
589+ height: parent.height
590+ radius: parent.radius
591+ anchors.left: parent.left
592+ anchors.top: parent.top
593+ color: podbird.theme.focusText
594+ width: downloader.progress > 0 ? Math.min((downloader.progress / 100) * parent.width, parent.width) : 0
595 }
596 }
597
598@@ -288,184 +493,15 @@
599 text: model.description
600 textFormat: Text.RichText
601 clip: true
602- height: listItem.expanded ? contentHeight : units.gu(4)
603+ height: listItem.expanded ? contentHeight : 0
604 wrapMode: Text.WordWrap
605 width: parent.width
606- elide: Text.ElideRight
607 fontSize: "small"
608 color: podbird.theme.baseSubText
609 Behavior on height {
610 UbuntuNumberAnimation {
611- duration: UbuntuAnimation.SlowDuration
612- }
613- }
614-
615- }
616-
617- Item {
618- id: statusBox
619-
620- width: parent.width
621- height: units.gu(6)
622-
623- function formatTime(seconds) {
624- var time = Podcasts.getTimeDiff(seconds)
625- var hour = time[0]
626- var minute = time[1]
627- // TRANSLATORS: the first argument is the number of hours,
628- // followed by minute (eg. 20h 3m)
629- if(hour > 0 && minute > 0) {
630- // xgettext: no-c-format
631- return (i18n.tr("%1h %2m"))
632- .arg(hour)
633- .arg(minute)
634- }
635-
636- // TRANSLATORS: this string indicates the number of hours
637- // eg. 20h (no plural state required)
638- else if(hour > 0 && minute === 0) {
639- // xgettext: no-c-format
640- return (i18n.tr("%1h"))
641- .arg(hour)
642- }
643-
644- // TRANSLATORS: this string indicates the number of minutes
645- // eg. 15m (no plural state required)
646- else if(hour === 0 && minute > 0) {
647- // xgettext: no-c-format
648- return (i18n.tr("%1m"))
649- .arg(minute)
650- }
651-
652- else {
653- return Podcasts.formatTime(model.duration)
654- }
655- }
656-
657- Rectangle {
658- id: listened
659- border.color: UbuntuColors.lightGrey
660- height: units.gu(2.5)
661- width: height
662- radius: width / 2
663- anchors.right: durationIcon.left
664- anchors.rightMargin: units.gu(2)
665- anchors.verticalCenter: actionRow.verticalCenter
666- visible: model.listened
667- Icon {
668- id: tick
669- name: "tick"
670- anchors.centerIn: parent
671- anchors.verticalCenterOffset: units.gu(0.1)
672- height: units.gu(1.4)
673- width: height
674- }
675- }
676-
677- Icon {
678- id: durationIcon
679- width: units.gu(2.5)
680- height: width
681- name: "alarm-clock"
682- visible: duration.text !== ""
683- anchors.right: duration.left
684- anchors.rightMargin: units.gu(0.5)
685- anchors.verticalCenter: actionRow.verticalCenter
686- color: podbird.theme.baseIcon
687- }
688-
689- Label {
690- id: duration
691- color: podbird.theme.baseText
692- anchors.right: parent.right
693- anchors.verticalCenter: durationIcon.verticalCenter
694- fontSize: "small"
695- text: !isNaN(model.duration) && model.duration !== 0 ? statusBox.formatTime(model.duration) : ""
696- }
697-
698- Row {
699- id: actionRow
700-
701- anchors.left: parent.left
702- anchors.leftMargin: units.gu(-1.5)
703-
704- ActionButton {
705- width: units.gu(5)
706- height: units.gu(4)
707-
708- iconName: player.playbackState === MediaPlayer.PlayingState && currentGuid === model.guid ? "media-playback-pause"
709- : "media-playback-start"
710-
711- onClicked: {
712- var db = Podcasts.init();
713- db.transaction(function (tx) {
714- if (currentGuid === model.guid) {
715- if (player.playbackState === MediaPlayer.PlayingState) {
716- player.pause()
717- } else {
718- player.play()
719- }
720- } else {
721- currentGuid = "";
722- player.source = model.downloadedfile ? model.downloadedfile : model.audiourl;
723- var rs = tx.executeSql("SELECT position FROM Episode WHERE guid=?", [model.guid]);
724- player.play();
725- player.seek(rs.rows.item(0).position);
726- currentName = model.name;
727- currentArtist = model.artist;
728- currentImage = model.image;
729- currentGuid = model.guid;
730- }
731- });
732- }
733- }
734-
735- ActionButton {
736- id: downloadButton
737-
738- width: units.gu(5)
739- height: units.gu(4)
740-
741- property bool queued: false
742-
743- iconName: model.downloadedfile ? "delete" : (queued && downloader.downloadingGuid !== model.guid ? "history" : "save")
744- opacity: downloader.downloadingGuid === model.guid ? 0.4 : 1.0
745- enabled: downloader.downloadingGuid !== model.guid
746-
747- ActivityIndicator {
748- anchors.centerIn: parent
749- visible: downloader.downloadingGuid === model.guid
750- running: visible
751- }
752-
753- onClicked: {
754- if (model.downloadedfile) {
755- fileManager.deleteFile(model.downloadedfile);
756- var db = Podcasts.init();
757- db.transaction(function (tx) {
758- tx.executeSql("UPDATE Episode SET downloadedfile = NULL WHERE guid = ?", [model.guid]);
759- });
760- loadEpisodes(episodeModel.pid, episodeModel.artist, episodeModel.image);
761- } else {
762- downloadButton.queued = true;
763- downloader.addDownload(model.guid, model.audiourl);
764- }
765- }
766- }
767- }
768-
769-
770- ProgressBar {
771- visible: downloader.downloadingGuid === model.guid
772- minimumValue: 0
773- maximumValue: 100
774- anchors.left: actionRow.right
775- anchors.right: model.listened ? listened.left : durationIcon.left
776- anchors.leftMargin: units.gu(2)
777- anchors.rightMargin: units.gu(2)
778- anchors.verticalCenter: actionRow.verticalCenter
779- height: units.gu(2.6)
780- value: downloader.progress
781+ duration: UbuntuAnimation.BriskDuration
782+ }
783 }
784 }
785 }
786@@ -483,21 +519,27 @@
787
788 function refreshModel() {
789 var db = Podcasts.init();
790- loadEpisodes(episodeModel.pid, episodeModel.artist, episodeModel.image);
791+ loadEpisodes(episodeId, episodeArtist, episodeImage);
792 episodesUpdating = false;
793 }
794
795 function loadEpisodes(pid, artist, img) {
796+ var i, episode;
797+ var newCount = 0;
798+
799+ episodeModel.clear();
800+
801 var db = Podcasts.init();
802 db.transaction(function (tx) {
803- episodeModel.clear();
804 var rs = tx.executeSql("SELECT rowid, * FROM Episode WHERE podcast=? ORDER BY published DESC", [pid]);
805- for(var i = 0; i < rs.rows.length; i++) {
806- var episode = rs.rows.item(i);
807- episodeModel.pid = pid;
808- episodeModel.artist = artist;
809- episodeModel.image = img;
810- episodeModel.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" : img, "artist" : artist, "audiourl" : episode.audiourl});
811+ for(i = 0; i < rs.rows.length; i++) {
812+ episode = rs.rows.item(i);
813+ if (!episode.listened) {
814+ 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});
815+ newCount++;
816+ } else {
817+ 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});
818+ }
819 }
820 });
821 }
822
823=== modified file 'app/ui/PlayerControls.qml'
824--- app/ui/PlayerControls.qml 2015-03-08 11:10:07 +0000
825+++ app/ui/PlayerControls.qml 2015-04-18 14:12:52 +0000
826@@ -53,7 +53,7 @@
827 id: progressBarHint
828 anchors.left: parent.left
829 anchors.top: cover.bottom
830- color: UbuntuColors.orange
831+ color: podbird.theme.focusText
832 height: units.gu(0.25)
833 width: player.duration > 0 ? (player.position / player.duration) * parent.width : 0
834 }
835@@ -72,7 +72,7 @@
836 color: "white"
837 elide: Text.ElideRight
838 maximumLineCount: 2
839- wrapMode: Text.WrapAnywhere
840+ wrapMode: Text.WordWrap
841 text: currentName
842 }
843
844
845=== modified file 'app/ui/PodcastsTab.qml'
846--- app/ui/PodcastsTab.qml 2015-03-29 15:33:26 +0000
847+++ app/ui/PodcastsTab.qml 2015-04-18 14:12:52 +0000
848@@ -186,13 +186,6 @@
849 filter.pattern: RegExp(searchField.text, "gi")
850 }
851
852- ListModel {
853- id: episodeModel
854- property string pid;
855- property string artist;
856- property string image;
857- }
858-
859 ListView {
860 id: view
861
862@@ -213,6 +206,7 @@
863 height: units.gu(8)
864 removable: true
865 confirmRemoval: true
866+ showDivider: false
867 highlightWhenPressed: false
868
869 onItemRemoved: {
870@@ -230,7 +224,8 @@
871
872 Rectangle {
873 anchors.fill: parent
874- color: listItem.pressed ? podbird.theme.hightlightListView : "transparent"
875+ opacity: 0.3
876+ color: index % 2 === 0 ? podbird.theme.hightlightListView : "Transparent"
877 }
878
879 onClicked: {
880
881=== renamed file 'app/ui/SearchTab.qml' => 'app/ui/SearchPage.qml'
882--- app/ui/SearchTab.qml 2015-03-29 15:33:26 +0000
883+++ app/ui/SearchPage.qml 2015-04-18 14:12:52 +0000
884@@ -23,24 +23,64 @@
885 import Ubuntu.Components.ListItems 1.0 as ListItem
886 import "../podcasts.js" as Podcasts
887
888-Tab {
889- title: i18n.tr("Find New Podcasts")
890+Page {
891+ id: searchPage
892
893 property var xhr: new XMLHttpRequest;
894
895- page: Page {
896- Column {
897- spacing: units.gu(2)
898- anchors.fill: parent
899- anchors.topMargin: units.gu(2)
900-
901- TextField {
902+ /*
903+ #FIXME: The following lines of code is necessary due to a upstream bug
904+ in the SDK http://pad.lv/1400297. This bug is still present in the rtm.
905+ Once it is fixed, this following property and connection can be remvoed.
906+ */
907+ property Item __oldContents: null
908+ Connections {
909+ target: searchPage.head
910+ onContentsChanged: {
911+ if (searchPage.__oldContents) {
912+ searchPage.__oldContents.parent = null;
913+ }
914+ searchPage.__oldContents = searchPage.head.contents;
915+ }
916+ }
917+
918+ state: "default"
919+ states: [
920+ PageHeadState {
921+ name: "default"
922+ head: searchPage.head
923+ actions: [
924+ Action {
925+ iconName: "search"
926+ text: i18n.tr("Search Episode")
927+ onTriggered: {
928+ searchPage.state = "search"
929+ searchField.forceActiveFocus()
930+ }
931+ }
932+ ]
933+ },
934+
935+ PageHeadState {
936+ name: "search"
937+ head: searchPage.head
938+ backAction: Action {
939+ iconName: "back"
940+ text: i18n.tr("Back")
941+ onTriggered: {
942+ resultsView.forceActiveFocus()
943+ searchField.text = ""
944+ searchPage.state = "default"
945+ }
946+ }
947+
948+ contents: TextField {
949 id: searchField
950- anchors.left: parent.left
951- anchors.right: parent.right
952- anchors.margins: units.gu(2)
953+ inputMethodHints: Qt.ImhNoPredictiveText
954 placeholderText: i18n.tr("Search...")
955- inputMethodHints: Qt.ImhNoPredictiveText;
956+ anchors.left: parent ? parent.left : undefined
957+ anchors.right: parent ? parent.right : undefined
958+ anchors.rightMargin: units.gu(2)
959 onTextChanged: {
960 if (text.length > 2) {
961 search(text)
962@@ -49,95 +89,106 @@
963 }
964 }
965 }
966-
967- ListView {
968- id: resultsView
969- clip: true
970- width: parent.width
971- model: searchResults
972- height: parent.height - searchField.height - units.gu(2)
973-
974- footer: Item {
975- width: parent.width
976- height: units.gu(7)
977- }
978-
979- delegate: ListItem.Empty {
980- id: listItem
981-
982- height: units.gu(8)
983- highlightWhenPressed: false
984-
985- Rectangle {
986- anchors.fill: parent
987- color: listItem.pressed ? podbird.theme.hightlightListView : "transparent"
988- }
989-
990- RowLayout {
991- id: titleRow
992-
993- anchors.left: parent.left
994- anchors.right: parent.right
995- anchors.margins: units.gu(2)
996- anchors.verticalCenter: parent.verticalCenter
997-
998- spacing: units.gu(2)
999-
1000- Image {
1001- id: imgFrame
1002- width: units.gu(6)
1003- height: width
1004- sourceSize.height: width
1005- sourceSize.width: width
1006- source: model.image
1007- }
1008-
1009- Column {
1010- id: detailColumn
1011-
1012- anchors.verticalCenter: imgFrame.verticalCenter
1013- Layout.fillWidth: true
1014-
1015- Label {
1016- id: podcastTitle
1017- textFormat: Text.PlainText
1018- text: model.name
1019- width: parent.width
1020- fontSize: "small"
1021- elide: Text.ElideRight
1022- }
1023-
1024- Label {
1025- id: episodeCount
1026- width: parent.width
1027- color: "#999999"
1028- text: model.artist
1029- fontSize: "x-small"
1030- elide: Text.ElideRight
1031- }
1032- }
1033-
1034- Button {
1035- anchors.right: parent.right
1036- text: i18n.tr("Subscribe")
1037- color: UbuntuColors.green
1038- onClicked: {
1039- Podcasts.subscribe(model.artist, model.name, model.feed, model.image);
1040- imageDownloader.feed = model.feed;
1041- imageDownloader.download(model.image);
1042- tabs.selectedTabIndex = 0;
1043- searchField.text = ""
1044- }
1045- }
1046- }
1047- }
1048-
1049- Scrollbar {
1050- flickableItem: resultsView
1051- }
1052-
1053- }
1054- }
1055+ }
1056+ ]
1057+
1058+ EmptyState {
1059+ anchors.centerIn: parent
1060+ anchors.verticalCenterOffset: Qt.inputMethod.visible ? units.gu(4) : 0
1061+ visible: searchResults.count === 0
1062+ iconName: "search"
1063+ title: searchPage.state !== "search" ? i18n.tr("Looking for a new Podcast?") : i18n.tr("No Podcasts found")
1064+ subTitle: searchPage.state !== "search" ? i18n.tr("Click the 'magnifier' at the top to search.") : i18n.tr("No podcasts found matching the search term.")
1065+ }
1066+
1067+ ListView {
1068+ id: resultsView
1069+
1070+ clip: true
1071+ model: searchResults
1072+ anchors.fill: parent
1073+
1074+ footer: Item {
1075+ width: parent.width
1076+ height: units.gu(7)
1077+ }
1078+
1079+ delegate: ListItem.Empty {
1080+ id: listItem
1081+
1082+ height: units.gu(8)
1083+ showDivider: false
1084+ highlightWhenPressed: false
1085+
1086+ Rectangle {
1087+ anchors.fill: parent
1088+ opacity: 0.3
1089+ color: index % 2 === 0 ? podbird.theme.hightlightListView : "Transparent"
1090+ }
1091+
1092+ RowLayout {
1093+ id: titleRow
1094+
1095+ anchors.left: parent.left
1096+ anchors.right: parent.right
1097+ anchors.margins: units.gu(2)
1098+ anchors.verticalCenter: parent.verticalCenter
1099+
1100+ spacing: units.gu(2)
1101+
1102+ Image {
1103+ id: imgFrame
1104+ width: units.gu(6)
1105+ height: width
1106+ sourceSize.height: width
1107+ sourceSize.width: width
1108+ source: model.image
1109+ }
1110+
1111+ Column {
1112+ id: detailColumn
1113+
1114+ anchors.verticalCenter: imgFrame.verticalCenter
1115+ Layout.fillWidth: true
1116+
1117+ Label {
1118+ id: podcastTitle
1119+ textFormat: Text.PlainText
1120+ text: model.name
1121+ width: parent.width
1122+ fontSize: "medium"
1123+ elide: Text.ElideRight
1124+ }
1125+
1126+ Label {
1127+ id: episodeCount
1128+ width: parent.width
1129+ color: "#999999"
1130+ text: model.artist
1131+ fontSize: "x-small"
1132+ elide: Text.ElideRight
1133+ }
1134+ }
1135+
1136+ Button {
1137+ anchors.right: parent.right
1138+ text: i18n.tr("Subscribe")
1139+ color: UbuntuColors.green
1140+ onClicked: {
1141+ Podcasts.subscribe(model.artist, model.name, model.feed, model.image);
1142+ imageDownloader.feed = model.feed;
1143+ imageDownloader.download(model.image);
1144+ tabs.selectedTabIndex = 0;
1145+ searchField.text = ""
1146+ }
1147+ }
1148+ }
1149+ }
1150+
1151+ Scrollbar {
1152+ flickableItem: resultsView
1153+ }
1154+
1155 }
1156
1157 ListModel {
1158
1159=== modified file 'po/com.mikeasoft.podbird.pot'
1160--- po/com.mikeasoft.podbird.pot 2015-04-16 10:18:41 +0000
1161+++ po/com.mikeasoft.podbird.pot 2015-04-18 14:12:52 +0000
1162@@ -8,7 +8,7 @@
1163 msgstr ""
1164 "Project-Id-Version: \n"
1165 "Report-Msgid-Bugs-To: \n"
1166-"POT-Creation-Date: 2015-04-16 12:16+0200\n"
1167+"POT-Creation-Date: 2015-04-16 12:43+0200\n"
1168 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1169 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1170 "Language-Team: LANGUAGE <LL@li.org>\n"
1171@@ -18,7 +18,11 @@
1172 "Content-Transfer-Encoding: 8bit\n"
1173 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
1174
1175-#: ../app/podbird.qml:178
1176+#: ../app/podbird.qml:173
1177+msgid "Find New Podcasts"
1178+msgstr ""
1179+
1180+#: ../app/podbird.qml:187
1181 msgid "Settings"
1182 msgstr ""
1183
1184@@ -59,7 +63,7 @@
1185 #: ../app/settings/DownloadSetting.qml:34
1186 #: ../app/settings/DownloadSetting.qml:35
1187 #: ../app/settings/DownloadSetting.qml:36
1188-#: ../app/settings/DownloadSetting.qml:37
1189+#: ../app/settings/DownloadSetting.qml:37 ../app/ui/EpisodesPage.qml:337
1190 #, qt-format
1191 msgid "%1 episode"
1192 msgid_plural "%1 episodes"
1193@@ -78,61 +82,73 @@
1194 msgid "Dark"
1195 msgstr ""
1196
1197-#: ../app/ui/EpisodesPage.qml:85
1198+#: ../app/ui/EpisodesPage.qml:33
1199+msgid "Podcast"
1200+msgstr ""
1201+
1202+#: ../app/ui/EpisodesPage.qml:89 ../app/ui/SearchPage.qml:55
1203 msgid "Search Episode"
1204 msgstr ""
1205
1206-#: ../app/ui/EpisodesPage.qml:94
1207+#: ../app/ui/EpisodesPage.qml:98
1208 msgid "Mark all listened"
1209 msgstr ""
1210
1211-#: ../app/ui/EpisodesPage.qml:105 ../app/ui/EpisodesPage.qml:153
1212+#: ../app/ui/EpisodesPage.qml:109 ../app/ui/EpisodesPage.qml:187
1213 msgid "Unsubscribe"
1214 msgstr ""
1215
1216-#: ../app/ui/EpisodesPage.qml:120 ../app/ui/PodcastsTab.qml:86
1217-#: ../app/ui/PodcastsTab.qml:109
1218+#: ../app/ui/EpisodesPage.qml:124 ../app/ui/PodcastsTab.qml:86
1219+#: ../app/ui/PodcastsTab.qml:109 ../app/ui/SearchPage.qml:69
1220 msgid "Back"
1221 msgstr ""
1222
1223-#: ../app/ui/EpisodesPage.qml:131
1224+#: ../app/ui/EpisodesPage.qml:136
1225 msgid "Search episode"
1226 msgstr ""
1227
1228-#: ../app/ui/EpisodesPage.qml:150
1229+#: ../app/ui/EpisodesPage.qml:184
1230 msgid "Unsubscribe Confirmation"
1231 msgstr ""
1232
1233-#: ../app/ui/EpisodesPage.qml:151
1234+#: ../app/ui/EpisodesPage.qml:185
1235 #, qt-format
1236 msgid "Are you sure you want to unsubscribe from <b>%1</b>?"
1237 msgstr ""
1238
1239-#: ../app/ui/EpisodesPage.qml:170
1240+#: ../app/ui/EpisodesPage.qml:204
1241 msgid "Cancel"
1242 msgstr ""
1243
1244-#: ../app/ui/EpisodesPage.qml:184
1245+#: ../app/ui/EpisodesPage.qml:218
1246 msgid "No Episodes found"
1247 msgstr ""
1248
1249-#: ../app/ui/EpisodesPage.qml:185
1250+#: ../app/ui/EpisodesPage.qml:219
1251 msgid "No episodes found matching the search term."
1252 msgstr ""
1253
1254-#: ../app/ui/EpisodesPage.qml:319
1255-#, no-c-format, qt-format
1256-msgid "%1h %2m"
1257-msgstr ""
1258-
1259-#: ../app/ui/EpisodesPage.qml:328
1260-#, no-c-format, qt-format
1261-msgid "%1h"
1262-msgstr ""
1263-
1264-#: ../app/ui/EpisodesPage.qml:336
1265-#, no-c-format, qt-format
1266-msgid "%1m"
1267+#: ../app/ui/EpisodesPage.qml:241
1268+#, no-c-format, qt-format
1269+msgid "%1 hr %2 min"
1270+msgstr ""
1271+
1272+#: ../app/ui/EpisodesPage.qml:250
1273+#, no-c-format, qt-format
1274+msgid "%1 hr"
1275+msgstr ""
1276+
1277+#: ../app/ui/EpisodesPage.qml:258
1278+#, no-c-format, qt-format
1279+msgid "%1 min"
1280+msgstr ""
1281+
1282+#: ../app/ui/EpisodesPage.qml:290
1283+msgid "Unheard"
1284+msgstr ""
1285+
1286+#: ../app/ui/EpisodesPage.qml:290
1287+msgid "Listened"
1288 msgstr ""
1289
1290 #: ../app/ui/NowPlayingPage.qml:28
1291@@ -197,26 +213,34 @@
1292 "page to add some."
1293 msgstr ""
1294
1295-#: ../app/ui/PodcastsTab.qml:175
1296+#: ../app/ui/PodcastsTab.qml:175 ../app/ui/SearchPage.qml:101
1297 msgid "No podcasts found matching the search term."
1298 msgstr ""
1299
1300-#: ../app/ui/PodcastsTab.qml:291
1301+#: ../app/ui/PodcastsTab.qml:286
1302 #, qt-format
1303 msgid "%1 unheard episode"
1304 msgid_plural "%1 unheard episodes"
1305 msgstr[0] ""
1306 msgstr[1] ""
1307
1308-#: ../app/ui/SearchTab.qml:27
1309-msgid "Find New Podcasts"
1310-msgstr ""
1311-
1312-#: ../app/ui/SearchTab.qml:42
1313+#: ../app/ui/SearchPage.qml:80
1314 msgid "Search..."
1315 msgstr ""
1316
1317-#: ../app/ui/SearchTab.qml:122
1318+#: ../app/ui/SearchPage.qml:100
1319+msgid "Looking for a new Podcast?"
1320+msgstr ""
1321+
1322+#: ../app/ui/SearchPage.qml:100
1323+msgid "No Podcasts found"
1324+msgstr ""
1325+
1326+#: ../app/ui/SearchPage.qml:101
1327+msgid "Click the 'magnifier' at the top to search."
1328+msgstr ""
1329+
1330+#: ../app/ui/SearchPage.qml:175
1331 msgid "Subscribe"
1332 msgstr ""
1333
1334@@ -323,6 +347,6 @@
1335 msgid "Finish"
1336 msgstr ""
1337
1338-#: /home/krnekhelesh/Documents/Ubuntu-Projects/MP-Reviews/builddir/build-5-auto-download-option-UbuntuSDK_for_armhf_GCC_ubuntu_sdk_14_10_utopic-Default/po/Podbird.desktop.in.h:1
1339+#: /home/krnekhelesh/Documents/Ubuntu-Projects/MP-Reviews/builddir/build-5.5-kevin-episodes-design-UbuntuSDK_for_armhf_GCC_ubuntu_sdk_14_10_utopic-Default/po/Podbird.desktop.in.h:1
1340 msgid "Podbird"
1341 msgstr ""
1342
1343=== modified file 'podbird.png'
1344Binary files podbird.png 2015-03-30 00:28:42 +0000 and podbird.png 2015-04-18 14:12:52 +0000 differ

Subscribers

People subscribed via source and target branches