Merge lp:~gary-wzl77/unity-scope-soundcloud/unity-scope-soundcloud into lp:unity-scope-soundcloud

Proposed by Gary.Wang
Status: Merged
Merged at revision: 40
Proposed branch: lp:~gary-wzl77/unity-scope-soundcloud/unity-scope-soundcloud
Merge into: lp:unity-scope-soundcloud
Diff against target: 2654 lines (+1539/-260)
26 files modified
CMakeLists.txt (+1/-1)
click/manifest.json.in (+1/-1)
click/soundcloud.apparmor (+1/-1)
click/soundcloud.provider.in (+1/-0)
data/com.ubuntu.scopes.soundcloud_soundcloud.ini.in (+2/-0)
include/api/client.h (+28/-0)
include/api/comment.h (+70/-0)
include/api/resource.h (+2/-1)
include/api/track.h (+21/-0)
include/api/user.h (+20/-0)
include/scope/activation.h (+64/-0)
include/scope/preview.h (+9/-1)
include/scope/query.h (+6/-0)
include/scope/scope.h (+9/-0)
po/POTFILES.in (+16/-12)
po/en_GB.po (+147/-63)
po/unity-scope-soundcloud.pot (+149/-73)
src/CMakeLists.txt (+2/-0)
src/api/client.cpp (+323/-9)
src/api/comment.cpp (+71/-0)
src/api/track.cpp (+39/-1)
src/api/user.cpp (+30/-0)
src/scope/activation.cpp (+91/-0)
src/scope/preview.cpp (+245/-73)
src/scope/query.cpp (+181/-23)
src/scope/scope.cpp (+10/-1)
To merge this branch: bzr merge lp:~gary-wzl77/unity-scope-soundcloud/unity-scope-soundcloud
Reviewer Review Type Date Requested Status
Unity API Team Pending
Review via email: mp+283759@code.launchpad.net

Commit message

Add new features offered by soundcloud which are missing in this scope.

Description of the change

Add new features offered by soundcloud which are missing in this scope.
1.Add detailed track info in card view
2.Load high resolution track picture
3.Support to retrieve comment list
4.Support to post a comment
5.Waveform image url fixed when loading auth user favorite streams
6.Support to mark a "like" for tracks
7.Support to follow an artist
8.Bump framework to ubuntu-sdk-15.04
9.Fix login failed

To post a comment you must log in.
41. By Gary.Wang

1.Show user info after login
2.Add "My favorites" department
3.Get specific user's track list

42. By Gary.Wang

Use deparments instead of string querying for navigation

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-12-04 15:01:39 +0000
+++ CMakeLists.txt 2016-02-02 11:41:52 +0000
@@ -55,7 +55,7 @@
55set(UBUNTU_PROJECT_TYPE "Scope" CACHE INTERNAL "Tells QtCreator this is a Scope project")55set(UBUNTU_PROJECT_TYPE "Scope" CACHE INTERNAL "Tells QtCreator this is a Scope project")
5656
57# Important project paths57# Important project paths
58set(SCOPE_VERSION "1.0.1-${BZR_REVNO}")58set(SCOPE_VERSION "1.6.0-${BZR_REVNO}")
59set(CMAKE_INSTALL_PREFIX /)59set(CMAKE_INSTALL_PREFIX /)
60set(SCOPE_INSTALL_DIR "/soundcloud")60set(SCOPE_INSTALL_DIR "/soundcloud")
61set(GETTEXT_PACKAGE "unity-scope-soundcloud")61set(GETTEXT_PACKAGE "unity-scope-soundcloud")
6262
=== modified file 'click/manifest.json.in'
--- click/manifest.json.in 2014-11-12 13:18:58 +0000
+++ click/manifest.json.in 2016-02-02 11:41:52 +0000
@@ -1,7 +1,7 @@
1{1{
2 "architecture": "@CLICK_ARCH@",2 "architecture": "@CLICK_ARCH@",
3 "description": "Listen to your favourite tracks on SoundCloud",3 "description": "Listen to your favourite tracks on SoundCloud",
4 "framework": "ubuntu-sdk-14.10-dev2",4 "framework": "ubuntu-sdk-15.04",
5 "hooks": {5 "hooks": {
6 "soundcloud": {6 "soundcloud": {
7 "apparmor": "soundcloud.apparmor",7 "apparmor": "soundcloud.apparmor",
88
=== modified file 'click/soundcloud.apparmor'
--- click/soundcloud.apparmor 2014-11-11 06:54:01 +0000
+++ click/soundcloud.apparmor 2016-02-02 11:41:52 +0000
@@ -3,7 +3,7 @@
3 "policy_groups": [3 "policy_groups": [
4 "accounts"4 "accounts"
5 ],5 ],
6 "policy_version": 1.26 "policy_version": 1.3
7}7}
88
99
1010
=== modified file 'click/soundcloud.provider.in'
--- click/soundcloud.provider.in 2014-11-17 09:44:59 +0000
+++ click/soundcloud.provider.in 2016-02-02 11:41:52 +0000
@@ -21,6 +21,7 @@
21 <setting type="as" name="Scope">['non-expiring']</setting>21 <setting type="as" name="Scope">['non-expiring']</setting>
22 <setting name="ClientId">eadbbc8380aa72be1412e2abe5f8e4ca</setting>22 <setting name="ClientId">eadbbc8380aa72be1412e2abe5f8e4ca</setting>
23 <setting type="as" name="AllowedSchemes">['https','http']</setting>23 <setting type="as" name="AllowedSchemes">['https','http']</setting>
24 <setting name="DisableStateParameter" type="b">true</setting>
24 </group>25 </group>
25 </group>26 </group>
26 </group>27 </group>
2728
=== modified file 'data/com.ubuntu.scopes.soundcloud_soundcloud.ini.in'
--- data/com.ubuntu.scopes.soundcloud_soundcloud.ini.in 2014-11-18 15:08:53 +0000
+++ data/com.ubuntu.scopes.soundcloud_soundcloud.ini.in 2016-02-02 11:41:52 +0000
@@ -13,3 +13,5 @@
13PageHeader.ForegroundColor = #ffffffff13PageHeader.ForegroundColor = #ffffffff
14PageHeader.Logo = logo.png14PageHeader.Logo = logo.png
15PageHeader.NavigationBackground = color:///#ddffffff15PageHeader.NavigationBackground = color:///#ddffffff
16PreviewButtonColor=#FF5500
17
1618
=== modified file 'include/api/client.h'
--- include/api/client.h 2014-12-04 13:39:07 +0000
+++ include/api/client.h 2016-02-02 11:41:52 +0000
@@ -14,6 +14,7 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Author: Pete Woods <pete.woods@canonical.com>16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
17 */18 */
1819
19#ifndef API_CLIENT_H_20#ifndef API_CLIENT_H_
@@ -21,6 +22,7 @@
2122
22#include <api/config.h>23#include <api/config.h>
23#include <api/track.h>24#include <api/track.h>
25#include <api/comment.h>
2426
25#include <unity/scopes/OnlineAccountClient.h>27#include <unity/scopes/OnlineAccountClient.h>
2628
@@ -62,6 +64,32 @@
6264
63 virtual std::future<std::deque<Track>> stream_tracks(int limit=0);65 virtual std::future<std::deque<Track>> stream_tracks(int limit=0);
6466
67 virtual std::future<std::deque<Comment>> track_comments(const std::string &trackid);
68
69 virtual std::future<bool> post_comment(const std::string &trackid,
70 const std::string &postmsg);
71
72 virtual std::future<std::deque<Track>> favorite_tracks();
73
74 virtual std::future<std::deque<Track>> get_user_tracks(const std::string &userid,
75 int limit = 0);
76
77 virtual std::future<bool> is_fav_track(const std::string &trackid);
78
79 virtual std::future<bool> like_track(const std::string &trackid);
80
81 virtual std::future<bool> delete_like_track(const std::string &trackid);
82
83 virtual std::future<bool> is_user_follower(const std::string &userid);
84
85 virtual std::future<bool> follow_user(const std::string &userid);
86
87 virtual std::future<bool> unfollow_user(const std::string &userid);
88
89 virtual std::future<User> get_authuser_info();
90
91 virtual std::future<User> get_user_info(const std::string &userid);
92
65 /**93 /**
66 * Cancel any pending queries (this method can be called from a different thread)94 * Cancel any pending queries (this method can be called from a different thread)
67 */95 */
6896
=== added file 'include/api/comment.h'
--- include/api/comment.h 1970-01-01 00:00:00 +0000
+++ include/api/comment.h 2016-02-02 11:41:52 +0000
@@ -0,0 +1,70 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of version 3 of the GNU Lesser General Public License as published
6 * by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 * details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
18 */
19
20#ifndef API_COMMENT_H_
21#define API_COMMENT_H_
22
23#include <api/user.h>
24
25#include <memory>
26#include <string>
27
28namespace Json {
29class Value;
30}
31
32namespace api {
33
34class Comment: public Resource {
35public:
36 typedef std::shared_ptr<Comment> Ptr;
37
38 Comment(const Json::Value &data);
39
40 virtual ~Comment() = default;
41
42 const unsigned int & id() const override;
43
44 const std::string & title() const override;
45
46 const std::string & artwork() const override;
47
48 const std::string & body() const;
49
50 const std::string & created_at() const;
51
52 const User & user() const;
53
54 Kind kind() const override;
55
56 std::string kind_str() const override;
57
58protected:
59 std::string body_;
60
61 std::string created_at_;
62
63 unsigned int id_;
64
65 User user_;
66};
67
68}
69
70#endif // API_COMMENT_H_
071
=== modified file 'include/api/resource.h'
--- include/api/resource.h 2014-11-05 16:17:51 +0000
+++ include/api/resource.h 2016-02-02 11:41:52 +0000
@@ -14,6 +14,7 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Author: Pete Woods <pete.woods@canonical.com>16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
17 */18 */
1819
19#ifndef API_RESOURCE_H_20#ifndef API_RESOURCE_H_
@@ -27,7 +28,7 @@
27class Resource {28class Resource {
28public:29public:
29 enum class Kind {30 enum class Kind {
30 track, user31 track, user, comment,
31 };32 };
3233
33 typedef std::shared_ptr<Resource> Ptr;34 typedef std::shared_ptr<Resource> Ptr;
3435
=== modified file 'include/api/track.h'
--- include/api/track.h 2014-11-06 11:40:45 +0000
+++ include/api/track.h 2016-02-02 11:41:52 +0000
@@ -14,6 +14,7 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Author: Pete Woods <pete.woods@canonical.com>16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
17 */18 */
1819
19#ifndef API_TRACK_H_20#ifndef API_TRACK_H_
@@ -76,6 +77,16 @@
7677
77 unsigned int favoritings_count() const;78 unsigned int favoritings_count() const;
7879
80 unsigned int comment_count() const;
81
82 unsigned int repost_count() const;
83
84 unsigned int likes_count() const;
85
86 const std::string & genre() const;
87
88 const std::string & original_format() const;
89
79 const User & user() const;90 const User & user() const;
8091
81 Kind kind() const override;92 Kind kind() const override;
@@ -121,6 +132,16 @@
121132
122 unsigned int favoritings_count_;133 unsigned int favoritings_count_;
123134
135 unsigned int comment_count_;
136
137 unsigned int repost_count_;
138
139 unsigned int likes_count_;
140
141 std::string genre_;
142
143 std::string original_format_;
144
124 User user_;145 User user_;
125};146};
126147
127148
=== modified file 'include/api/user.h'
--- include/api/user.h 2014-11-05 16:17:51 +0000
+++ include/api/user.h 2016-02-02 11:41:52 +0000
@@ -44,6 +44,16 @@
4444
45 const unsigned int & id() const override;45 const unsigned int & id() const override;
4646
47 const std::string & permalink_url() const;
48
49 const unsigned int & track_count() const;
50
51 const unsigned int & followers_count() const;
52
53 const unsigned int & followings_count() const;
54
55 const std::string & bio() const;
56
47 Kind kind() const override;57 Kind kind() const override;
4858
49 std::string kind_str() const override;59 std::string kind_str() const override;
@@ -54,6 +64,16 @@
54 unsigned int id_;64 unsigned int id_;
5565
56 std::string artwork_;66 std::string artwork_;
67
68 std::string permalink_;
69
70 unsigned int track_count_;
71
72 unsigned int followers_count_;
73
74 unsigned int followings_count_;
75
76 std::string bio_;
57};77};
5878
59}79}
6080
=== added file 'include/scope/activation.h'
--- include/scope/activation.h 1970-01-01 00:00:00 +0000
+++ include/scope/activation.h 2016-02-02 11:41:52 +0000
@@ -0,0 +1,64 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of version 3 of the GNU Lesser General Public License as published
6 * by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 * details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
18 */
19
20#ifndef SCOPE_ACTIVATIOIN_H_
21#define SCOPE_ACTIVATIOIN_H_
22
23#include <api/client.h>
24
25#include <unity/scopes/ActivationQueryBase.h>
26
27namespace unity {
28namespace scopes {
29class Result;
30}
31}
32
33namespace scope {
34
35/**
36 * Represents an individual action request.
37 *
38 * Each time a action is performed in the UI a new Action
39 * object is created.
40 */
41class Activation : public unity::scopes::ActivationQueryBase
42{
43public:
44 Activation(const unity::scopes::Result &result,
45 const unity::scopes::ActionMetadata & metadata,
46 std::string const& action_id,
47 std::shared_ptr<unity::scopes::OnlineAccountClient> oa_client);
48
49 ~Activation() = default;
50
51 /**
52 * Trigger the action object with action id.
53 */
54 virtual unity::scopes::ActivationResponse activate() override;
55
56private:
57 std::string const action_id_;
58
59 api::Client client_;
60};
61
62}
63
64#endif // SCOPE_ACTIVATION_H_
065
=== modified file 'include/scope/preview.h'
--- include/scope/preview.h 2014-11-10 11:54:32 +0000
+++ include/scope/preview.h 2016-02-02 11:41:52 +0000
@@ -14,12 +14,16 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Author: Pete Woods <pete.woods@canonical.com>16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
17 */18 */
1819
19#ifndef SCOPE_PREVIEW_H_20#ifndef SCOPE_PREVIEW_H_
20#define SCOPE_PREVIEW_H_21#define SCOPE_PREVIEW_H_
2122
23#include <api/client.h>
24
22#include <unity/scopes/PreviewQueryBase.h>25#include <unity/scopes/PreviewQueryBase.h>
26#include <unity/scopes/OnlineAccountClient.h>
2327
24namespace unity {28namespace unity {
25namespace scopes {29namespace scopes {
@@ -38,7 +42,8 @@
38class Preview: public unity::scopes::PreviewQueryBase {42class Preview: public unity::scopes::PreviewQueryBase {
39public:43public:
40 Preview(const unity::scopes::Result &result,44 Preview(const unity::scopes::Result &result,
41 const unity::scopes::ActionMetadata &metadata);45 const unity::scopes::ActionMetadata &metadata,
46 std::shared_ptr<unity::scopes::OnlineAccountClient> oa_client);
4247
43 ~Preview() = default;48 ~Preview() = default;
4449
@@ -48,6 +53,9 @@
48 * Populates the reply object with preview information.53 * Populates the reply object with preview information.
49 */54 */
50 void run(unity::scopes::PreviewReplyProxy const& reply) override;55 void run(unity::scopes::PreviewReplyProxy const& reply) override;
56
57private:
58 api::Client client_;
51};59};
5260
53}61}
5462
=== modified file 'include/scope/query.h'
--- include/scope/query.h 2014-12-04 13:22:43 +0000
+++ include/scope/query.h 2016-02-02 11:41:52 +0000
@@ -51,6 +51,12 @@
51 const unity::scopes::Category::SCPtr &category,51 const unity::scopes::Category::SCPtr &category,
52 const api::Track &track);52 const api::Track &track);
5353
54 bool push_user_info(const unity::scopes::SearchReplyProxy &reply,
55 const unity::scopes::Category::SCPtr &category,
56 const api::User &user);
57
58 bool show_empty_tip(const unity::scopes::SearchReplyProxy &reply);
59
54 api::Client client_;60 api::Client client_;
55};61};
5662
5763
=== modified file 'include/scope/scope.h'
--- include/scope/scope.h 2014-12-04 13:24:10 +0000
+++ include/scope/scope.h 2016-02-02 11:41:52 +0000
@@ -61,6 +61,15 @@
61 unity::scopes::CannedQuery const& q,61 unity::scopes::CannedQuery const& q,
62 unity::scopes::SearchMetadata const&) override;62 unity::scopes::SearchMetadata const&) override;
6363
64 /**
65 * Called each time a new action is requested
66 */
67 unity::scopes::ActivationQueryBase::UPtr perform_action(
68 const unity::scopes::Result &result,
69 const unity::scopes::ActionMetadata &metadata,
70 std::string const& widget_id,
71 std::string const& action_id) override;
72
64protected:73protected:
65 std::shared_ptr<unity::scopes::OnlineAccountClient> oa_client_;74 std::shared_ptr<unity::scopes::OnlineAccountClient> oa_client_;
66};75};
6776
=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2014-11-18 15:08:53 +0000
+++ po/POTFILES.in 2016-02-02 11:41:52 +0000
@@ -1,16 +1,20 @@
1[type: gettext/ini] data/com.ubuntu.scopes.soundcloud_soundcloud.ini.in1tests/unit/scope/test-scope.cpp
2include/api/resource.h2src/scope/preview.cpp
3include/api/user.h3src/scope/activation.cpp
4include/api/config.h4src/scope/scope.cpp
5include/api/track.h5src/scope/query.cpp
6include/api/client.h6src/api/user.cpp
7src/api/client.cpp
8src/api/track.cpp
9src/api/comment.cpp
7include/scope/preview.h10include/scope/preview.h
8include/scope/localization.h11include/scope/localization.h
12include/scope/activation.h
9include/scope/query.h13include/scope/query.h
10include/scope/scope.h14include/scope/scope.h
11src/api/client.cpp
12src/api/track.cpp
13src/api/user.cpp
14src/scope/query.cpp
15src/scope/scope.cpp
16src/scope/preview.cpp
17\ No newline at end of file15\ No newline at end of file
16include/api/resource.h
17include/api/track.h
18include/api/comment.h
19include/api/client.h
20include/api/config.h
21include/api/user.h
1822
=== modified file 'po/en_GB.po'
--- po/en_GB.po 2014-11-18 16:42:10 +0000
+++ po/en_GB.po 2016-02-02 11:41:52 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: unity-scope-soundcloud\n"9"Project-Id-Version: unity-scope-soundcloud\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2014-11-18 14:00+0000\n"11"POT-Creation-Date: 2016-01-26 16:58+0800\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: Pete Woods <EMAIL@ADDRESS>\n"13"Last-Translator: Pete Woods <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,226 +17,310 @@
17"Content-Type: text/plain; charset=UTF-8\n"17"Content-Type: text/plain; charset=UTF-8\n"
18"Content-Transfer-Encoding: 8bit\n"18"Content-Transfer-Encoding: 8bit\n"
1919
20#: ../src/scope/query.cpp:11220#: ../src/scope/query.cpp:416
21msgid "</b> followers"
22msgstr ""
23
24#: ../src/scope/query.cpp:417
25msgid "</b> followings"
26msgstr ""
27
28#: ../src/scope/query.cpp:415
29msgid "</b> tracks"
30msgstr ""
31
32#: ../src/scope/query.cpp:148
21msgid "Alternative Rock"33msgid "Alternative Rock"
22msgstr "Alternative Rock"34msgstr "Alternative Rock"
2335
24#: ../src/scope/query.cpp:11236#: ../src/scope/query.cpp:148
25msgid "Ambient"37msgid "Ambient"
26msgstr "Ambient"38msgstr "Ambient"
2739
28#: ../src/scope/query.cpp:9740#: ../src/scope/query.cpp:133
29msgid "Audiobooks"41msgid "Audiobooks"
30msgstr "Audiobooks"42msgstr "Audiobooks"
3143
32#: ../src/scope/query.cpp:9844#: ../src/scope/query.cpp:134
33msgid "Business"45msgid "Business"
34msgstr "Business"46msgstr "Business"
3547
36#: ../src/scope/preview.cpp:8448#: ../src/scope/preview.cpp:198
37msgid "Buy"49msgid "Buy"
38msgstr "Buy"50msgstr "Buy"
3951
40#: ../src/scope/query.cpp:11252#: ../src/scope/query.cpp:148
41msgid "Classical"53msgid "Classical"
42msgstr "Classical"54msgstr "Classical"
4355
44#: ../src/scope/query.cpp:9856#: ../src/scope/query.cpp:134
45msgid "Comedy"57msgid "Comedy"
46msgstr "Comedy"58msgstr "Comedy"
4759
48#: ../src/scope/query.cpp:11260#: ../src/scope/query.cpp:148
49msgid "Country"61msgid "Country"
50msgstr "Country"62msgstr "Country"
5163
52#: ../src/scope/query.cpp:11364#: ../src/scope/query.cpp:149
53msgid "Dance"65msgid "Dance"
54msgstr "Dance"66msgstr "Dance"
5567
56#: ../src/scope/query.cpp:11368#: ../src/scope/query.cpp:149
57msgid "Deep House"69msgid "Deep House"
58msgstr "Deep House"70msgstr "Deep House"
5971
60#: ../src/scope/query.cpp:11372#: ../src/scope/query.cpp:149
61msgid "Disco"73msgid "Disco"
62msgstr "Disco"74msgstr "Disco"
6375
64#: ../src/scope/query.cpp:11376#: ../src/scope/query.cpp:149
65msgid "Drum & Bass"77msgid "Drum & Bass"
66msgstr "Drum & Bass"78msgstr "Drum & Bass"
6779
68#: ../src/scope/query.cpp:11380#: ../src/scope/query.cpp:149
69msgid "Dubstep"81msgid "Dubstep"
70msgstr "Dubstep"82msgstr "Dubstep"
7183
72#: ../src/scope/query.cpp:11484#: ../src/scope/query.cpp:150
73msgid "Electro"85msgid "Electro"
74msgstr "Electro"86msgstr "Electro"
7587
76#: ../src/scope/query.cpp:11488#: ../src/scope/query.cpp:150
77msgid "Electronic"89msgid "Electronic"
78msgstr "Electronic"90msgstr "Electronic"
7991
80#: ../src/scope/query.cpp:9892#: ../src/scope/query.cpp:134
81msgid "Entertainment"93msgid "Entertainment"
82msgstr "Entertainment"94msgstr "Entertainment"
8395
84#: ../src/scope/query.cpp:22096#: ../src/scope/query.cpp:273
85msgid "Explore"97msgid "Explore"
86msgstr "Explore"98msgstr "Explore"
8799
88#: ../src/scope/query.cpp:114100#: ../src/scope/query.cpp:150
89msgid "Folk"101msgid "Folk"
90msgstr "Folk"102msgstr "Folk"
91103
92#: ../src/scope/query.cpp:114104#: ../src/scope/preview.cpp:249
105msgid "Follow"
106msgstr ""
107
108#: ../src/scope/preview.cpp:105
109msgid "Get my tracks"
110msgstr ""
111
112#: ../src/scope/preview.cpp:219
113msgid "Get user tracks"
114msgstr ""
115
116#: ../src/scope/query.cpp:150
93msgid "Hardcore Techno"117msgid "Hardcore Techno"
94msgstr "Hardcore Techno"118msgstr "Hardcore Techno"
95119
96#: ../src/scope/query.cpp:115120#: ../src/scope/query.cpp:151
97msgid "Hip Hop"121msgid "Hip Hop"
98msgstr "Hip Hop"122msgstr "Hip Hop"
99123
100#: ../src/scope/query.cpp:111124#: ../src/scope/query.cpp:147
101msgid "Home"125msgid "Home"
102msgstr "Home"126msgstr "Home"
103127
104#: ../src/scope/query.cpp:115128#: ../src/scope/query.cpp:151
105msgid "House"129msgid "House"
106msgstr "House"130msgstr "House"
107131
108#: ../src/scope/query.cpp:115132#: ../src/scope/query.cpp:151
109msgid "Indie Rock"133msgid "Indie Rock"
110msgstr "Indie Rock"134msgstr "Indie Rock"
111135
112#: ../src/scope/query.cpp:115136#: ../src/scope/query.cpp:151
113msgid "Jazz"137msgid "Jazz"
114msgstr "Jazz"138msgstr "Jazz"
115139
116#: ../src/scope/query.cpp:115140#: ../src/scope/query.cpp:151
117msgid "Latin"141msgid "Latin"
118msgstr "Latin"142msgstr "Latin"
119143
120#: ../src/scope/query.cpp:98144#: ../src/scope/query.cpp:134
121msgid "Learning"145msgid "Learning"
122msgstr "Learning"146msgstr "Learning"
123147
124#: ../src/scope/query.cpp:306148#: ../src/scope/preview.cpp:234
149msgid "Like"
150msgstr ""
151
152#: ../src/scope/query.cpp:459
125msgid "Log-in to SoundCloud"153msgid "Log-in to SoundCloud"
126msgstr "Log in to SoundCloud"154msgstr "Log in to SoundCloud"
127155
128#: ../src/scope/query.cpp:116156#: ../src/scope/preview.cpp:163
157#, fuzzy
158msgid "Login to soundcloud"
159msgstr "Log in to SoundCloud"
160
161#: ../src/scope/query.cpp:152
129msgid "Metal"162msgid "Metal"
130msgstr "Metal"163msgstr "Metal"
131164
132#: ../src/scope/query.cpp:116165#: ../src/scope/query.cpp:152
133msgid "Minimal Techno"166msgid "Minimal Techno"
134msgstr "Minimal Techno"167msgstr "Minimal Techno"
135168
136#: ../src/scope/query.cpp:99169#: ../src/scope/query.cpp:172
170msgid "My favorites"
171msgstr ""
172
173#: ../src/scope/query.cpp:135
137msgid "News & Politics"174msgid "News & Politics"
138msgstr "News & Politics"175msgstr "News & Politics"
139176
140#: ../src/scope/query.cpp:116177#: ../src/scope/query.cpp:445
178msgid "No tracks can be found"
179msgstr ""
180
181#: ../src/scope/query.cpp:152
141msgid "Piano"182msgid "Piano"
142msgstr "Piano"183msgstr "Piano"
143184
144#: ../src/scope/preview.cpp:103185#: ../src/scope/preview.cpp:213
145msgid "Play in browser"186msgid "Play in browser"
146msgstr "Play in browser"187msgstr "Play in browser"
147188
148#: ../src/scope/query.cpp:116189#: ../src/scope/preview.cpp:155
190msgid "Please login to post a comment "
191msgstr ""
192
193#: ../src/scope/query.cpp:152
149msgid "Pop"194msgid "Pop"
150msgstr "Pop"195msgstr "Pop"
151196
152#: ../src/scope/query.cpp:117197#: ../src/scope/preview.cpp:187
198msgid "Post"
199msgstr ""
200
201#: ../src/scope/query.cpp:153
153msgid "Progressive House"202msgid "Progressive House"
154msgstr "Progressive House"203msgstr "Progressive House"
155204
156#: ../src/scope/query.cpp:117205#: ../src/scope/query.cpp:153
157msgid "Punk"206msgid "Punk"
158msgstr "Punk"207msgstr "Punk"
159208
160#: ../src/scope/query.cpp:117209#: ../src/scope/query.cpp:153
161msgid "R&B"210msgid "R&B"
162msgstr "R&B"211msgstr "R&B"
163212
164#: ../src/scope/query.cpp:117213#: ../src/scope/query.cpp:153
165msgid "Rap"214msgid "Rap"
166msgstr "Rap"215msgstr "Rap"
167216
168#: ../src/scope/query.cpp:118217#: ../src/scope/query.cpp:154
169msgid "Reggae"218msgid "Reggae"
170msgstr "Reggae"219msgstr "Reggae"
171220
172#: ../src/scope/query.cpp:99221#: ../src/scope/query.cpp:135
173msgid "Religion & Spirituality"222msgid "Religion & Spirituality"
174msgstr "Religion & Spirituality"223msgstr "Religion & Spirituality"
175224
176#: ../src/scope/query.cpp:118225#: ../src/scope/preview.cpp:229
226msgid "Remove 'Like'"
227msgstr ""
228
229#: ../src/scope/query.cpp:154
177msgid "Rock"230msgid "Rock"
178msgstr "Rock"231msgstr "Rock"
179232
180#: ../src/scope/query.cpp:99233#: ../src/scope/query.cpp:135
181msgid "Science"234msgid "Science"
182msgstr "Science"235msgstr "Science"
183236
184#: ../src/scope/query.cpp:118237#: ../src/scope/query.cpp:154
185msgid "Singer-Songwriter"238msgid "Singer-Songwriter"
186msgstr "Singer-Songwriter"239msgstr "Singer-Songwriter"
187240
188#: ../src/scope/query.cpp:118241#: ../src/scope/query.cpp:154
189msgid "Soul"242msgid "Soul"
190msgstr "Soul"243msgstr "Soul"
191244
192#: ../data/com.ubuntu.scopes.soundcloud_soundcloud.ini.in.h:1245#: ../src/scope/query.cpp:136
193msgid "SoundCloud"
194msgstr "SoundCloud"
195
196#: ../data/com.ubuntu.scopes.soundcloud_soundcloud.ini.in.h:2
197msgid "SoundCloud scope for Unity8"
198msgstr "SoundCloud scope for Unity8"
199
200#: ../src/scope/query.cpp:100
201msgid "Sports"246msgid "Sports"
202msgstr "Sports"247msgstr "Sports"
203248
204#: ../src/scope/query.cpp:100249#: ../src/scope/query.cpp:136
205msgid "Storytelling"250msgid "Storytelling"
206msgstr "Storytelling"251msgstr "Storytelling"
207252
208#: ../src/scope/query.cpp:208253#: ../src/scope/query.cpp:260
209msgid "Stream"254msgid "Stream"
210msgstr "Stream"255msgstr "Stream"
211256
212#: ../src/scope/query.cpp:119257#: ../src/scope/query.cpp:155
213msgid "Tech House"258msgid "Tech House"
214msgstr "Tech House"259msgstr "Tech House"
215260
216#: ../src/scope/query.cpp:119261#: ../src/scope/query.cpp:155
217msgid "Techno"262msgid "Techno"
218msgstr "Techno"263msgstr "Techno"
219264
220#: ../src/scope/query.cpp:100265#: ../src/scope/query.cpp:136
221msgid "Technology"266msgid "Technology"
222msgstr "Technology"267msgstr "Technology"
223268
224#: ../src/scope/query.cpp:119269#: ../src/scope/query.cpp:155
225msgid "Trance"270msgid "Trance"
226msgstr "Trance"271msgstr "Trance"
227272
228#: ../src/scope/query.cpp:119273#: ../src/scope/query.cpp:155
229msgid "Trap"274msgid "Trap"
230msgstr "Trap"275msgstr "Trap"
231276
232#: ../src/scope/query.cpp:120277#: ../src/scope/query.cpp:156
233msgid "Trip Hop"278msgid "Trip Hop"
234msgstr "Trip Hop"279msgstr "Trip Hop"
235280
236#: ../src/scope/preview.cpp:94281#: ../src/scope/preview.cpp:244
282msgid "Unfollow"
283msgstr ""
284
285#: ../src/scope/preview.cpp:100
286#, fuzzy
287msgid "View in browser"
288msgstr "Play in browser"
289
290#: ../src/scope/preview.cpp:206
237msgid "Watch video"291msgid "Watch video"
238msgstr "Watch video"292msgstr "Watch video"
239293
240#: ../src/scope/query.cpp:120294#: ../src/scope/query.cpp:156
241msgid "World"295msgid "World"
242msgstr "World"296msgstr "World"
297
298#: ../src/scope/query.cpp:380
299msgid "create time"
300msgstr ""
301
302#: ../src/scope/query.cpp:381
303msgid "genre"
304msgstr ""
305
306#: ../src/scope/query.cpp:382
307msgid "license"
308msgstr ""
309
310#: ../src/scope/preview.cpp:162
311msgid "open"
312msgstr ""
313
314#: ../src/scope/query.cpp:399
315msgid "track"
316msgstr ""
317
318#: ../src/scope/preview.cpp:68 ../src/scope/query.cpp:431
319msgid "user"
320msgstr ""
321
322#~ msgid "SoundCloud"
323#~ msgstr "SoundCloud"
324
325#~ msgid "SoundCloud scope for Unity8"
326#~ msgstr "SoundCloud scope for Unity8"
243327
=== modified file 'po/unity-scope-soundcloud.pot'
--- po/unity-scope-soundcloud.pot 2014-11-18 15:08:53 +0000
+++ po/unity-scope-soundcloud.pot 2016-02-02 11:41:52 +0000
@@ -6,9 +6,9 @@
6#, fuzzy6#, fuzzy
7msgid ""7msgid ""
8msgstr ""8msgstr ""
9"Project-Id-Version: unity-scope-soundcloud\n"9"Project-Id-Version: PACKAGE VERSION\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2014-11-18 15:06+0000\n"11"POT-Creation-Date: 2016-01-26 16:59+0800\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,226 +17,302 @@
17"Content-Type: text/plain; charset=CHARSET\n"17"Content-Type: text/plain; charset=CHARSET\n"
18"Content-Transfer-Encoding: 8bit\n"18"Content-Transfer-Encoding: 8bit\n"
1919
20#: ../data/com.ubuntu.scopes.soundcloud_soundcloud.ini.in.h:120#: ../src/scope/preview.cpp:68 ../src/scope/query.cpp:431
21msgid "SoundCloud"21msgid "user"
22msgstr ""22msgstr ""
2323
24#: ../data/com.ubuntu.scopes.soundcloud_soundcloud.ini.in.h:224#: ../src/scope/preview.cpp:100
25msgid "SoundCloud scope for Unity8"25msgid "View in browser"
26msgstr ""26msgstr ""
2727
28#: ../src/scope/query.cpp:9728#: ../src/scope/preview.cpp:105
29msgid "Get my tracks"
30msgstr ""
31
32#: ../src/scope/preview.cpp:155
33msgid "Please login to post a comment "
34msgstr ""
35
36#: ../src/scope/preview.cpp:162
37msgid "open"
38msgstr ""
39
40#: ../src/scope/preview.cpp:163
41msgid "Login to soundcloud"
42msgstr ""
43
44#: ../src/scope/preview.cpp:187
45msgid "Post"
46msgstr ""
47
48#: ../src/scope/preview.cpp:198
49msgid "Buy"
50msgstr ""
51
52#: ../src/scope/preview.cpp:206
53msgid "Watch video"
54msgstr ""
55
56#: ../src/scope/preview.cpp:213
57msgid "Play in browser"
58msgstr ""
59
60#: ../src/scope/preview.cpp:219
61msgid "Get user tracks"
62msgstr ""
63
64#: ../src/scope/preview.cpp:229
65msgid "Remove 'Like'"
66msgstr ""
67
68#: ../src/scope/preview.cpp:234
69msgid "Like"
70msgstr ""
71
72#: ../src/scope/preview.cpp:244
73msgid "Unfollow"
74msgstr ""
75
76#: ../src/scope/preview.cpp:249
77msgid "Follow"
78msgstr ""
79
80#: ../src/scope/query.cpp:133
29msgid "Audiobooks"81msgid "Audiobooks"
30msgstr ""82msgstr ""
3183
32#: ../src/scope/query.cpp:9884#: ../src/scope/query.cpp:134
33msgid "Business"85msgid "Business"
34msgstr ""86msgstr ""
3587
36#: ../src/scope/query.cpp:9888#: ../src/scope/query.cpp:134
37msgid "Comedy"89msgid "Comedy"
38msgstr ""90msgstr ""
3991
40#: ../src/scope/query.cpp:9892#: ../src/scope/query.cpp:134
41msgid "Entertainment"93msgid "Entertainment"
42msgstr ""94msgstr ""
4395
44#: ../src/scope/query.cpp:9896#: ../src/scope/query.cpp:134
45msgid "Learning"97msgid "Learning"
46msgstr ""98msgstr ""
4799
48#: ../src/scope/query.cpp:99100#: ../src/scope/query.cpp:135
49msgid "News & Politics"101msgid "News & Politics"
50msgstr ""102msgstr ""
51103
52#: ../src/scope/query.cpp:99104#: ../src/scope/query.cpp:135
53msgid "Religion & Spirituality"105msgid "Religion & Spirituality"
54msgstr ""106msgstr ""
55107
56#: ../src/scope/query.cpp:99108#: ../src/scope/query.cpp:135
57msgid "Science"109msgid "Science"
58msgstr ""110msgstr ""
59111
60#: ../src/scope/query.cpp:100112#: ../src/scope/query.cpp:136
61msgid "Sports"113msgid "Sports"
62msgstr ""114msgstr ""
63115
64#: ../src/scope/query.cpp:100116#: ../src/scope/query.cpp:136
65msgid "Storytelling"117msgid "Storytelling"
66msgstr ""118msgstr ""
67119
68#: ../src/scope/query.cpp:100120#: ../src/scope/query.cpp:136
69msgid "Technology"121msgid "Technology"
70msgstr ""122msgstr ""
71123
72#: ../src/scope/query.cpp:111124#: ../src/scope/query.cpp:147
73msgid "Home"125msgid "Home"
74msgstr ""126msgstr ""
75127
76#: ../src/scope/query.cpp:112128#: ../src/scope/query.cpp:148
77msgid "Alternative Rock"129msgid "Alternative Rock"
78msgstr ""130msgstr ""
79131
80#: ../src/scope/query.cpp:112132#: ../src/scope/query.cpp:148
81msgid "Ambient"133msgid "Ambient"
82msgstr ""134msgstr ""
83135
84#: ../src/scope/query.cpp:112136#: ../src/scope/query.cpp:148
85msgid "Classical"137msgid "Classical"
86msgstr ""138msgstr ""
87139
88#: ../src/scope/query.cpp:112140#: ../src/scope/query.cpp:148
89msgid "Country"141msgid "Country"
90msgstr ""142msgstr ""
91143
92#: ../src/scope/query.cpp:113144#: ../src/scope/query.cpp:149
93msgid "Dance"145msgid "Dance"
94msgstr ""146msgstr ""
95147
96#: ../src/scope/query.cpp:113148#: ../src/scope/query.cpp:149
97msgid "Deep House"149msgid "Deep House"
98msgstr ""150msgstr ""
99151
100#: ../src/scope/query.cpp:113152#: ../src/scope/query.cpp:149
101msgid "Disco"153msgid "Disco"
102msgstr ""154msgstr ""
103155
104#: ../src/scope/query.cpp:113156#: ../src/scope/query.cpp:149
105msgid "Drum & Bass"157msgid "Drum & Bass"
106msgstr ""158msgstr ""
107159
108#: ../src/scope/query.cpp:113160#: ../src/scope/query.cpp:149
109msgid "Dubstep"161msgid "Dubstep"
110msgstr ""162msgstr ""
111163
112#: ../src/scope/query.cpp:114164#: ../src/scope/query.cpp:150
113msgid "Electro"165msgid "Electro"
114msgstr ""166msgstr ""
115167
116#: ../src/scope/query.cpp:114168#: ../src/scope/query.cpp:150
117msgid "Electronic"169msgid "Electronic"
118msgstr ""170msgstr ""
119171
120#: ../src/scope/query.cpp:114172#: ../src/scope/query.cpp:150
121msgid "Folk"173msgid "Folk"
122msgstr ""174msgstr ""
123175
124#: ../src/scope/query.cpp:114176#: ../src/scope/query.cpp:150
125msgid "Hardcore Techno"177msgid "Hardcore Techno"
126msgstr ""178msgstr ""
127179
128#: ../src/scope/query.cpp:115180#: ../src/scope/query.cpp:151
129msgid "Hip Hop"181msgid "Hip Hop"
130msgstr ""182msgstr ""
131183
132#: ../src/scope/query.cpp:115184#: ../src/scope/query.cpp:151
133msgid "House"185msgid "House"
134msgstr ""186msgstr ""
135187
136#: ../src/scope/query.cpp:115188#: ../src/scope/query.cpp:151
137msgid "Indie Rock"189msgid "Indie Rock"
138msgstr ""190msgstr ""
139191
140#: ../src/scope/query.cpp:115192#: ../src/scope/query.cpp:151
141msgid "Jazz"193msgid "Jazz"
142msgstr ""194msgstr ""
143195
144#: ../src/scope/query.cpp:115196#: ../src/scope/query.cpp:151
145msgid "Latin"197msgid "Latin"
146msgstr ""198msgstr ""
147199
148#: ../src/scope/query.cpp:116200#: ../src/scope/query.cpp:152
149msgid "Metal"201msgid "Metal"
150msgstr ""202msgstr ""
151203
152#: ../src/scope/query.cpp:116204#: ../src/scope/query.cpp:152
153msgid "Minimal Techno"205msgid "Minimal Techno"
154msgstr ""206msgstr ""
155207
156#: ../src/scope/query.cpp:116208#: ../src/scope/query.cpp:152
157msgid "Piano"209msgid "Piano"
158msgstr ""210msgstr ""
159211
160#: ../src/scope/query.cpp:116212#: ../src/scope/query.cpp:152
161msgid "Pop"213msgid "Pop"
162msgstr ""214msgstr ""
163215
164#: ../src/scope/query.cpp:117216#: ../src/scope/query.cpp:153
165msgid "Progressive House"217msgid "Progressive House"
166msgstr ""218msgstr ""
167219
168#: ../src/scope/query.cpp:117220#: ../src/scope/query.cpp:153
169msgid "Punk"221msgid "Punk"
170msgstr ""222msgstr ""
171223
172#: ../src/scope/query.cpp:117224#: ../src/scope/query.cpp:153
173msgid "R&B"225msgid "R&B"
174msgstr ""226msgstr ""
175227
176#: ../src/scope/query.cpp:117228#: ../src/scope/query.cpp:153
177msgid "Rap"229msgid "Rap"
178msgstr ""230msgstr ""
179231
180#: ../src/scope/query.cpp:118232#: ../src/scope/query.cpp:154
181msgid "Reggae"233msgid "Reggae"
182msgstr ""234msgstr ""
183235
184#: ../src/scope/query.cpp:118236#: ../src/scope/query.cpp:154
185msgid "Rock"237msgid "Rock"
186msgstr ""238msgstr ""
187239
188#: ../src/scope/query.cpp:118240#: ../src/scope/query.cpp:154
189msgid "Singer-Songwriter"241msgid "Singer-Songwriter"
190msgstr ""242msgstr ""
191243
192#: ../src/scope/query.cpp:118244#: ../src/scope/query.cpp:154
193msgid "Soul"245msgid "Soul"
194msgstr ""246msgstr ""
195247
196#: ../src/scope/query.cpp:119248#: ../src/scope/query.cpp:155
197msgid "Tech House"249msgid "Tech House"
198msgstr ""250msgstr ""
199251
200#: ../src/scope/query.cpp:119252#: ../src/scope/query.cpp:155
201msgid "Techno"253msgid "Techno"
202msgstr ""254msgstr ""
203255
204#: ../src/scope/query.cpp:119256#: ../src/scope/query.cpp:155
205msgid "Trance"257msgid "Trance"
206msgstr ""258msgstr ""
207259
208#: ../src/scope/query.cpp:119260#: ../src/scope/query.cpp:155
209msgid "Trap"261msgid "Trap"
210msgstr ""262msgstr ""
211263
212#: ../src/scope/query.cpp:120264#: ../src/scope/query.cpp:156
213msgid "Trip Hop"265msgid "Trip Hop"
214msgstr ""266msgstr ""
215267
216#: ../src/scope/query.cpp:120268#: ../src/scope/query.cpp:156
217msgid "World"269msgid "World"
218msgstr ""270msgstr ""
219271
220#: ../src/scope/query.cpp:208272#: ../src/scope/query.cpp:172
273msgid "My favorites"
274msgstr ""
275
276#: ../src/scope/query.cpp:260
221msgid "Stream"277msgid "Stream"
222msgstr ""278msgstr ""
223279
224#: ../src/scope/query.cpp:220280#: ../src/scope/query.cpp:273
225msgid "Explore"281msgid "Explore"
226msgstr ""282msgstr ""
227283
228#: ../src/scope/query.cpp:306284#: ../src/scope/query.cpp:380
285msgid "create time"
286msgstr ""
287
288#: ../src/scope/query.cpp:381
289msgid "genre"
290msgstr ""
291
292#: ../src/scope/query.cpp:382
293msgid "license"
294msgstr ""
295
296#: ../src/scope/query.cpp:399
297msgid "track"
298msgstr ""
299
300#: ../src/scope/query.cpp:415
301msgid "</b> tracks"
302msgstr ""
303
304#: ../src/scope/query.cpp:416
305msgid "</b> followers"
306msgstr ""
307
308#: ../src/scope/query.cpp:417
309msgid "</b> followings"
310msgstr ""
311
312#: ../src/scope/query.cpp:445
313msgid "No tracks can be found"
314msgstr ""
315
316#: ../src/scope/query.cpp:459
229msgid "Log-in to SoundCloud"317msgid "Log-in to SoundCloud"
230msgstr ""318msgstr ""
231
232#: ../src/scope/preview.cpp:84
233msgid "Buy"
234msgstr ""
235
236#: ../src/scope/preview.cpp:94
237msgid "Watch video"
238msgstr ""
239
240#: ../src/scope/preview.cpp:103
241msgid "Play in browser"
242msgstr ""
243319
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2014-11-18 15:08:53 +0000
+++ src/CMakeLists.txt 2016-02-02 11:41:52 +0000
@@ -32,9 +32,11 @@
32 api/client.cpp32 api/client.cpp
33 api/track.cpp33 api/track.cpp
34 api/user.cpp34 api/user.cpp
35 api/comment.cpp
35 scope/preview.cpp36 scope/preview.cpp
36 scope/query.cpp37 scope/query.cpp
37 scope/scope.cpp38 scope/scope.cpp
39 scope/activation.cpp
38)40)
3941
40# Find all the headers42# Find all the headers
4143
=== modified file 'src/api/client.cpp'
--- src/api/client.cpp 2014-12-04 14:09:22 +0000
+++ src/api/client.cpp 2016-02-02 11:41:52 +0000
@@ -14,13 +14,16 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Author: Pete Woods <pete.woods@canonical.com>16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
17 */18 */
1819
19#include <api/client.h>20#include <api/client.h>
20#include <api/track.h>21#include <api/track.h>
22#include <api/comment.h>
2123
22#include <boost/iostreams/filtering_stream.hpp>24#include <boost/iostreams/filtering_stream.hpp>
23#include <boost/iostreams/filter/gzip.hpp>25#include <boost/iostreams/filter/gzip.hpp>
26#include <boost/algorithm/string.hpp>
24#include <core/net/error.h>27#include <core/net/error.h>
25#include <core/net/http/client.h>28#include <core/net/http/client.h>
26#include <core/net/http/content_type.h>29#include <core/net/http/content_type.h>
@@ -70,6 +73,26 @@
70 return results;73 return results;
71}74}
7275
76template<typename T>
77static T get_typed_authuser_info(const string &filter, const json::Value &root) {
78 T results((json::Value()));
79
80 string kind = root["kind"].asString();
81
82 if (kind == filter) {
83 return T(root);
84 }
85 return results;
86}
87
88template<typename T>
89static T is_successful(const json::Value &root) {
90 T results = (boost::algorithm::contains(root["status"].asString(), "201")
91 || boost::algorithm::contains(root["status"].asString(), "200")
92 || root["id"].asUInt() > 0);
93 return results;
94}
95
73}96}
7497
75class Client::Priv {98class Client::Priv {
@@ -101,6 +124,55 @@
101 const net::Uri::QueryParameters &parameters,124 const net::Uri::QueryParameters &parameters,
102 http::Request::Handler &handler) {125 http::Request::Handler &handler) {
103 std::lock_guard<std::mutex> lock(config_mutex_);126 std::lock_guard<std::mutex> lock(config_mutex_);
127 http::Request::Configuration configuration = net_config(path, parameters);
128 configuration.header.add("User-Agent", config_.user_agent + " (gzip)");
129 configuration.header.add("Accept-Encoding", "gzip");
130
131 auto request = client_->head(configuration);
132 request->async_execute(handler);
133 }
134
135 void post(const net::Uri::Path &path,
136 const net::Uri::QueryParameters &parameters,
137 const std::string &postmsg,
138 const std::string &content_type,
139 http::Request::Handler &handler) {
140 std::lock_guard<std::mutex> lock(config_mutex_);
141 http::Request::Configuration configuration = net_config(path, parameters);
142 configuration.header.add("User-Agent", config_.user_agent);
143 configuration.header.add("Content-Type", content_type);
144
145 auto request = client_->post(configuration, postmsg, content_type);
146 request->async_execute(handler);
147 }
148
149 void put(const net::Uri::Path &path,
150 const net::Uri::QueryParameters &parameters,
151 const std::string &postmsg,
152 http::Request::Handler &handler) {
153 std::lock_guard<std::mutex> lock(config_mutex_);
154 http::Request::Configuration configuration = net_config(path, parameters);
155 configuration.header.add("User-Agent", config_.user_agent);
156 std::istringstream is(postmsg);
157
158 auto request = client_->put(configuration, is, postmsg.length());
159 request->async_execute(handler);
160 }
161
162 void del(const net::Uri::Path &path,
163 const net::Uri::QueryParameters &parameters,
164 http::Request::Handler &handler) {
165 std::lock_guard<std::mutex> lock(config_mutex_);
166 http::Request::Configuration configuration = net_config(path, parameters);
167 configuration.header.add("User-Agent", config_.user_agent);
168 configuration.header.add("X-HTTP-Method-Override", "DELETE");
169
170 auto request = client_->post(configuration, "", "");
171 request->async_execute(handler);
172 }
173
174 http::Request::Configuration net_config(const net::Uri::Path &path,
175 const net::Uri::QueryParameters &parameters) {
104 update_config();176 update_config();
105177
106 http::Request::Configuration configuration;178 http::Request::Configuration configuration;
@@ -115,12 +187,9 @@
115 net::Uri uri = net::make_uri(config_.apiroot, path,187 net::Uri uri = net::make_uri(config_.apiroot, path,
116 complete_parameters);188 complete_parameters);
117 configuration.uri = client_->uri_to_string(uri);189 configuration.uri = client_->uri_to_string(uri);
118 configuration.header.add("User-Agent", config_.user_agent + " (gzip)");
119 configuration.header.add("Accept-Encoding", "gzip");
120190
121 auto request = client_->head(configuration);191 return configuration;
122 request->async_execute(handler);192 }
123 }
124193
125 http::Request::Progress::Next progress_report(194 http::Request::Progress::Next progress_report(
126 const http::Request::Progress&) {195 const http::Request::Progress&) {
@@ -164,11 +233,13 @@
164 json::Reader reader;233 json::Reader reader;
165 reader.parse(decompressed, root);234 reader.parse(decompressed, root);
166235
167 if (response.status != http::Status::ok) {236 //Soundcloud api return 404 if track is not in auth user's favorite list
168 prom->set_exception(make_exception_ptr(domain_error(root["error"].asString())));237 //or auth user is not following one certain user.
169 } else {238// if (response.status != http::Status::ok) {
239// prom->set_exception(make_exception_ptr(domain_error(root["error"].asString())));
240// } else {
170 prom->set_value(func(root));241 prom->set_value(func(root));
171 }242// }
172 });243 });
173244
174 get(path, parameters, handler);245 get(path, parameters, handler);
@@ -176,6 +247,108 @@
176 return prom->get_future();247 return prom->get_future();
177 }248 }
178249
250 template<typename T>
251 future<T> async_post(const net::Uri::Path &path,
252 const net::Uri::QueryParameters &parameters,
253 const std::string &postmsg,
254 const std::string &content_type,
255 const function<T(const json::Value &root)> &func) {
256 auto prom = make_shared<promise<T>>();
257
258 http::Request::Handler handler;
259 handler.on_progress(
260 bind(&Client::Priv::progress_report, this, placeholders::_1));
261 handler.on_error([prom](const net::Error& e)
262 {
263 prom->set_exception(make_exception_ptr(e));
264 });
265 handler.on_response(
266 [prom,func](const http::Response& response)
267 {
268 json::Value root;
269 json::Reader reader;
270 reader.parse(response.body, root);
271
272 if (response.status != http::Status::ok &&
273 response.status != http::Status::created) {
274 prom->set_exception(make_exception_ptr(domain_error(root["error"].asString())));
275 } else {
276 prom->set_value(func(root));
277 }
278 });
279
280 post(path, parameters, postmsg, content_type, handler);
281
282 return prom->get_future();
283 }
284
285 template<typename T>
286 future<T> async_put(const net::Uri::Path &path,
287 const net::Uri::QueryParameters &parameters,
288 const std::string &msg,
289 const function<T(const json::Value &root)> &func) {
290 auto prom = make_shared<promise<T>>();
291
292 http::Request::Handler handler;
293 handler.on_progress(
294 bind(&Client::Priv::progress_report, this, placeholders::_1));
295 handler.on_error([prom](const net::Error& e)
296 {
297 prom->set_exception(make_exception_ptr(e));
298 });
299 handler.on_response(
300 [prom,func](const http::Response& response)
301 {
302 json::Value root;
303 json::Reader reader;
304 reader.parse(response.body, root);
305
306 if (response.status != http::Status::created &&
307 response.status != http::Status::ok) {
308 prom->set_exception(make_exception_ptr(domain_error(root["error"].asString())));
309 } else {
310 prom->set_value(func(root));
311 }
312 });
313
314 put(path, parameters, msg, handler);
315
316 return prom->get_future();
317 }
318
319 template<typename T>
320 future<T> async_del(const net::Uri::Path &path,
321 const net::Uri::QueryParameters &parameters,
322 const function<T(const json::Value &root)> &func) {
323 auto prom = make_shared<promise<T>>();
324
325 http::Request::Handler handler;
326 handler.on_progress(
327 bind(&Client::Priv::progress_report, this, placeholders::_1));
328 handler.on_error([prom](const net::Error& e)
329 {
330 prom->set_exception(make_exception_ptr(e));
331 });
332 handler.on_response(
333 [prom,func](const http::Response& response)
334 {
335 json::Value root;
336 json::Reader reader;
337 reader.parse(response.body, root);
338
339 if (response.status != http::Status::created &&
340 response.status != http::Status::ok) {
341 prom->set_exception(make_exception_ptr(domain_error(root["error"].asString())));
342 } else {
343 prom->set_value(func(root));
344 }
345 });
346
347 del(path, parameters, handler);
348
349 return prom->get_future();
350 }
351
179 std::string client_id() {352 std::string client_id() {
180 std::lock_guard<std::mutex> lock(config_mutex_);353 std::lock_guard<std::mutex> lock(config_mutex_);
181 update_config();354 update_config();
@@ -277,6 +450,147 @@
277 });450 });
278}451}
279452
453future<deque<Comment>> Client::track_comments(const std::string &trackid) {
454 net::Uri::QueryParameters params;
455
456 return p->async_get<deque<Comment>>(
457 { "tracks", trackid, "comments.json"}, params,
458 [](const json::Value &root) {
459 auto results = get_typed_list<Comment>("comment", root);
460 return results;
461 });
462}
463
464future<bool> Client::post_comment(const std::string &trackid,
465 const std::string &postmsg) {
466 net::Uri::QueryParameters params;
467
468 string postbody = "<comment><body>"+ postmsg + "</body></comment>";
469 std::string content_type = "application/xml";
470 return p->async_post<bool>(
471 { "tracks", trackid, "comments.json"}, params, postbody, content_type,
472 [](const json::Value &root) {
473 auto results = is_successful<bool>(root);
474 return results;
475 });
476}
477
478std::future<std::deque<Track> > Client::favorite_tracks()
479{
480 net::Uri::QueryParameters params;
481
482 return p->async_get<deque<Track>>(
483 { "me", "favorites.json"}, params,
484 [](const json::Value &root) {
485 return get_typed_list<Track>("track", root);
486 });
487}
488
489std::future<std::deque<Track> > Client::get_user_tracks(const string &userid,
490 int limit)
491{
492 net::Uri::QueryParameters params;
493 if (limit > 0) {
494 params.emplace_back("limit", std::to_string(limit));
495 }
496 return p->async_get<deque<Track>>(
497 { "users", userid, "tracks.json"}, params,
498 [](const json::Value &root) {
499 return get_typed_list<Track>("track", root);
500 });
501}
502
503future<bool> Client::is_fav_track(const std::string &trackid) {
504 net::Uri::QueryParameters params;
505
506 return p->async_get<bool>(
507 { "me", "favorites", trackid}, params,
508 [](const json::Value &root) {
509 auto results = is_successful<bool>(root);
510 return results;
511 });
512}
513
514future<bool> Client::like_track(const std::string &trackid) {
515 net::Uri::QueryParameters params;
516
517 return p->async_put<bool>(
518 { "me", "favorites", trackid}, params, "",
519 [](const json::Value &root) {
520 auto results = is_successful<bool>(root);
521 return results;
522 });
523}
524
525future<bool> Client::delete_like_track(const std::string &trackid) {
526 net::Uri::QueryParameters params;
527
528 return p->async_del<bool>(
529 { "me", "favorites", trackid}, params,
530 [](const json::Value &root) {
531 auto results = is_successful<bool>(root);
532 return results;
533 });
534}
535
536std::future<bool> Client::is_user_follower(const string &userid) {
537 net::Uri::QueryParameters params;
538
539 return p->async_get<bool>(
540 { "me", "followings", userid}, params,
541 [](const json::Value &root) {
542 auto results = is_successful<bool>(root);
543 return results;
544 });
545}
546
547future<bool> Client::follow_user(const std::string &userid) {
548 net::Uri::QueryParameters params;
549
550 return p->async_put<bool>(
551 { "me", "followings", userid}, params, "",
552 [](const json::Value &root) {
553 auto results = is_successful<bool>(root);
554 return results;
555 });
556}
557
558std::future<bool> Client::unfollow_user(const string &userid)
559{
560 net::Uri::QueryParameters params;
561
562 return p->async_del<bool>(
563 { "me", "followings", userid}, params,
564 [](const json::Value &root) {
565 auto results = is_successful<bool>(root);
566 return results;
567 });
568}
569
570std::future<User> Client::get_authuser_info()
571{
572 net::Uri::QueryParameters params;
573
574 return p->async_get<User>(
575 { "me" }, params,
576 [](const json::Value &root) {
577 auto results = get_typed_authuser_info<User>("user", root);
578 return results;
579 });
580}
581
582std::future<User> Client::get_user_info(const string &userid)
583{
584 net::Uri::QueryParameters params;
585
586 return p->async_get<User>(
587 { "users", userid}, params,
588 [](const json::Value &root) {
589 auto results = get_typed_authuser_info<User>("user", root);
590 return results;
591 });
592}
593
280void Client::cancel() {594void Client::cancel() {
281 p->cancelled_ = true;595 p->cancelled_ = true;
282}596}
283597
=== added file 'src/api/comment.cpp'
--- src/api/comment.cpp 1970-01-01 00:00:00 +0000
+++ src/api/comment.cpp 2016-02-02 11:41:52 +0000
@@ -0,0 +1,71 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of version 3 of the GNU Lesser General Public License as published
6 * by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 * details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
18 */
19
20#include <boost/algorithm/string.hpp>
21#include <api/comment.h>
22
23#include <json/json.h>
24
25namespace json = Json;
26using namespace api;
27using namespace std;
28
29Comment::Comment(const json::Value &data) :
30 user_(data["user"]) {
31 body_ = data["body"].asString();
32 created_at_ = data["created_at"].asString();
33
34 std::vector<std::string> created_time;
35 boost::split(created_time, created_at_, boost::is_any_of(" "));
36 created_at_ = created_time[0];
37
38 id_ = data["id"].asUInt();
39}
40
41const unsigned int & Comment::id() const {
42 return id_;
43}
44
45const string & Comment::body() const {
46 return body_;
47}
48
49const string & Comment::title() const {
50 return user_.title();
51}
52
53const string & Comment::artwork() const {
54 return user_.artwork();
55}
56
57const string & Comment::created_at() const {
58 return created_at_;
59}
60
61const User & Comment::user() const {
62 return user_;
63}
64
65Resource::Kind Comment::kind() const {
66 return Resource::Kind::comment;
67}
68
69std::string Comment::kind_str() const {
70 return "comment";
71}
072
=== modified file 'src/api/track.cpp'
--- src/api/track.cpp 2014-11-06 11:40:45 +0000
+++ src/api/track.cpp 2016-02-02 11:41:52 +0000
@@ -14,8 +14,10 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Author: Pete Woods <pete.woods@canonical.com>16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
17 */18 */
1819
20#include <boost/algorithm/string.hpp>
19#include <api/track.h>21#include <api/track.h>
2022
21#include <json/json.h>23#include <json/json.h>
@@ -33,13 +35,26 @@
33 duration_ = data["duration"].asUInt();35 duration_ = data["duration"].asUInt();
34 license_ = data["license"].asString();36 license_ = data["license"].asString();
35 created_at_ = data["created_at"].asString();37 created_at_ = data["created_at"].asString();
38
39 std::vector<std::string> created_time;
40 boost::split(created_time, created_at_, boost::is_any_of(" "));
41 created_at_ = created_time[0];
3642
37 playback_count_ = data["playback_count"].asUInt();43 playback_count_ = data["playback_count"].asUInt();
38 favoritings_count_ = data["favoritings_count"].asUInt();44 favoritings_count_ = data["favoritings_count"].asUInt();
45 comment_count_ = data["comment_count"].asUInt();
46 repost_count_ = data["reposts_count"].asUInt();
47 likes_count_ = data["likes_count"].asUInt();
3948
40 artwork_ = data["artwork_url"].asString();49 artwork_ = data["artwork_url"].asString();
41 waveform_ = data["waveform_url"].asString();50 waveform_ = data["waveform_url"].asString();
4251 //when loading login user stream, server gives waveform
52 //sample json file instread of image
53 if (boost::algorithm::ends_with(waveform_, "json")) {
54 boost::replace_all(waveform_, "json", "png");
55 boost::replace_all(waveform_, "is.", "1.");
56 }
57
43 streamable_ = data["streamable"].asBool();58 streamable_ = data["streamable"].asBool();
44 downloadable_ = data["downloadable"].asBool();59 downloadable_ = data["downloadable"].asBool();
4560
@@ -48,6 +63,9 @@
48 stream_url_ = data["stream_url"].asString();63 stream_url_ = data["stream_url"].asString();
49 download_url_ = data["download_url"].asString();64 download_url_ = data["download_url"].asString();
50 video_url_ = data["video_url"].asString();65 video_url_ = data["video_url"].asString();
66
67 genre_ = data["genre"].asString();
68 original_format_ = data["original_format"].asString();
51}69}
5270
53const string & Track::title() const {71const string & Track::title() const {
@@ -126,6 +144,26 @@
126 return favoritings_count_;144 return favoritings_count_;
127}145}
128146
147unsigned int Track::comment_count() const {
148 return comment_count_;
149}
150
151unsigned int Track::repost_count() const {
152 return repost_count_;
153}
154
155unsigned int Track::likes_count() const {
156 return likes_count_;
157}
158
159const string & Track::genre() const {
160 return genre_;
161}
162
163const string & Track::original_format() const {
164 return original_format_;
165}
166
129const User & Track::user() const {167const User & Track::user() const {
130 return user_;168 return user_;
131}169}
132170
=== modified file 'src/api/user.cpp'
--- src/api/user.cpp 2014-11-05 16:17:51 +0000
+++ src/api/user.cpp 2016-02-02 11:41:52 +0000
@@ -28,6 +28,11 @@
28 title_ = data["username"].asString();28 title_ = data["username"].asString();
29 id_ = data["id"].asUInt();29 id_ = data["id"].asUInt();
30 artwork_ = data["avatar_url"].asString();30 artwork_ = data["avatar_url"].asString();
31 permalink_ = data["permalink_url"].asString();
32 track_count_ = data["track_count"].asUInt();
33 followers_count_ = data["followers_count"].asUInt();
34 followings_count_ = data["followings_count"].asUInt();
35 bio_ = data["description"].asString();
31}36}
3237
33const string & User::title() const {38const string & User::title() const {
@@ -38,6 +43,31 @@
38 return id_;43 return id_;
39}44}
4045
46const string &User::permalink_url() const
47{
48 return permalink_;
49}
50
51const unsigned int &User::track_count() const
52{
53 return track_count_;
54}
55
56const unsigned int &User::followers_count() const
57{
58 return followers_count_;
59}
60
61const unsigned int &User::followings_count() const
62{
63 return followings_count_;
64}
65
66const string &User::bio() const
67{
68 return bio_;
69}
70
41const string & User::artwork() const {71const string & User::artwork() const {
42 return artwork_;72 return artwork_;
43}73}
4474
=== added file 'src/scope/activation.cpp'
--- src/scope/activation.cpp 1970-01-01 00:00:00 +0000
+++ src/scope/activation.cpp 2016-02-02 11:41:52 +0000
@@ -0,0 +1,91 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of version 3 of the GNU Lesser General Public License as published
6 * by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 * details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
18 */
19
20#include <scope/activation.h>
21#include <unity/scopes/ActivationResponse.h>
22#include <unity/scopes/ActionMetadata.h>
23
24#include <iostream>
25
26namespace sc = unity::scopes;
27
28using namespace std;
29using namespace scope;
30using namespace api;
31
32template<typename T>
33static T get_or_throw(future<T> &f) {
34 if (f.wait_for(std::chrono::seconds(10)) != future_status::ready) {
35 throw domain_error("HTTP request timeout");
36 }
37 return f.get();
38}
39
40Activation::Activation(const sc::Result &result,
41 const sc::ActionMetadata &metadata,
42 std::string const& action_id,
43 std::shared_ptr<sc::OnlineAccountClient> oa_client) :
44 sc::ActivationQueryBase(result, metadata),
45 action_id_(action_id),
46 client_(oa_client) {
47}
48
49sc::ActivationResponse Activation::activate() {
50 try {
51 string trackid = result()["id"].get_string();
52 string userid = result()["userid"].get_string();
53
54 if (action_id_ == "commented") {
55 string comments = action_metadata().scope_data().get_dict()["comment"].get_string();
56 future<bool> post_future = client_.post_comment(trackid, comments);
57 auto status = get_or_throw(post_future);
58 cout<< "auth user post a comment: " << status << endl;
59
60 return sc::ActivationResponse(sc::ActivationResponse::Status::ShowPreview);
61 } else if (action_id_ == "like") {
62 future<bool> like_future = client_.like_track(trackid);
63 auto status = get_or_throw(like_future);
64 cout<< "auth user likes track: " << status << endl;
65
66 return sc::ActivationResponse(sc::ActivationResponse::Status::ShowPreview);
67 } else if (action_id_ == "deletelike") {
68 future<bool> ret_future = client_.delete_like_track(trackid);
69 auto status = get_or_throw(ret_future);
70 cout<< "auth user delete a like track: " << status << endl;
71
72 return sc::ActivationResponse(sc::ActivationResponse::Status::ShowPreview);
73 } else if (action_id_ == "follow") {
74 future<bool> follow_future = client_.follow_user(userid);
75 auto status = get_or_throw(follow_future);
76 cout<< "auth user follow user: " << status << endl;
77
78 return sc::ActivationResponse(sc::ActivationResponse::Status::ShowPreview);
79 } else if (action_id_ == "unfollow") {
80 future<bool> unfollow_future = client_.unfollow_user(userid);
81 auto status = get_or_throw(unfollow_future);
82 cout<< "auth user unfollow user: " << status << endl;
83
84 return sc::ActivationResponse(sc::ActivationResponse::Status::ShowPreview);
85 }
86 }catch (domain_error &e) {
87 cerr << e.what() << endl;
88 return sc::ActivationResponse(sc::ActivationResponse::Status::ShowPreview);
89 }
90 return sc::ActivationResponse(sc::ActivationResponse::Status::NotHandled);
91}
092
=== modified file 'src/scope/preview.cpp'
--- src/scope/preview.cpp 2014-11-10 11:54:32 +0000
+++ src/scope/preview.cpp 2016-02-02 11:41:52 +0000
@@ -14,10 +14,15 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Author: Pete Woods <pete.woods@canonical.com>16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
17 */18 */
1819
20#include <boost/algorithm/string.hpp>
21
19#include <scope/localization.h>22#include <scope/localization.h>
20#include <scope/preview.h>23#include <scope/preview.h>
24#include <api/client.h>
25#include <api/comment.h>
2126
22#include <unity/scopes/ColumnLayout.h>27#include <unity/scopes/ColumnLayout.h>
23#include <unity/scopes/PreviewWidget.h>28#include <unity/scopes/PreviewWidget.h>
@@ -31,83 +36,250 @@
3136
32using namespace std;37using namespace std;
33using namespace scope;38using namespace scope;
3439using namespace api;
35Preview::Preview(const sc::Result &result, const sc::ActionMetadata &metadata) :40
36 sc::PreviewQueryBase(result, metadata) {41template<typename T>
42static T get_or_throw(future<T> &f) {
43 if (f.wait_for(std::chrono::seconds(10)) != future_status::ready) {
44 throw domain_error("HTTP request timeout");
45 }
46 return f.get();
47}
48
49Preview::Preview(const sc::Result &result, const sc::ActionMetadata &metadata,
50 std::shared_ptr<sc::OnlineAccountClient> oa_client) :
51 sc::PreviewQueryBase(result, metadata),
52 client_(oa_client) {
37}53}
3854
39void Preview::cancelled() {55void Preview::cancelled() {
40}56}
4157
42void Preview::run(sc::PreviewReplyProxy const& reply) {58void Preview::run(sc::PreviewReplyProxy const& reply) {
43 auto const res = result();59 try {
4460 auto const res = result();
45 // Support three different column layouts61
46 sc::ColumnLayout layout1col(1), layout2col(2), layout3col(3);62 sc::PreviewWidgetList widgets;
4763 std::vector<std::string> ids;
48 // Single column layout64 // Support three different column layouts
49 layout1col.add_column( { "header", "art", "statistics", "tracks", "actions", "description" });65 sc::ColumnLayout layout1col(1), layout2col(2), layout3col(3);
5066
51 // Register the layouts we just created67 string mode = res["mode"].get_string();
52 reply->register_layout( { layout1col }); //, layout2col, layout3col68 if (mode == _("user")) {
5369 ids = std::vector<std::string>{ "header", "art", "statistics", "description", "actions"};
54 sc::PreviewWidget header("header", "header");70 sc::PreviewWidget header("header", "header");
55 header.add_attribute_mapping("title", "title");71 header.add_attribute_mapping("title", "title");
56 header.add_attribute_mapping("subtitle", "username");72 widgets.emplace_back(header);
5773
58 sc::PreviewWidget art("art", "image");74 string artwork_url= res["art"].get_string();
59 art.add_attribute_mapping("source", "art");75 boost::replace_all(artwork_url, "large", "t500x500");
6076 sc::PreviewWidget art("art", "image");
61 sc::PreviewWidget statistics("statistics", "header");77 art.add_attribute_value("source", sc::Variant(artwork_url));
62 statistics.add_attribute_value("title", sc::Variant(res["playback-count"].get_string() + " " + res["favoritings-count"].get_string()));78 widgets.emplace_back(art);
6379
64 sc::PreviewWidget tracks("tracks", "audio");80 sc::PreviewWidget statistics("statistics", "header");
65 {81 statistics.add_attribute_value("title", sc::Variant(
66 if (res["streamable"].get_bool()) {82 res["track-count"].get_string() + " " +
67 sc::VariantBuilder builder;83 res["followers-count"].get_string() + " " +
68 builder.add_tuple({84 res["followings-count"].get_string()));
69 {"title", sc::Variant(res.title())},85 widgets.emplace_back(statistics);
70 {"source", sc::Variant(res["stream-url"])},86
71 {"length", res["duration"]}87 sc::PreviewWidget description("description", "text");
72 });88 description.add_attribute_value("text", sc::Variant(
73 tracks.add_attribute_value("tracks", builder.end());89 res["permalink-url"].get_string() + "<br>" +
74 }90 res["bio"].get_string()));
75 }91 widgets.emplace_back(description);
7692
77 sc::PreviewWidget actions("actions", "actions");93 std::string userid = res["id"].get_string();
78 {94 sc::VariantBuilder builder;
79 string purchase_url = res["purchase-url"].get_string();95 sc::PreviewWidget actions("actions", "actions");
80 if (!purchase_url.empty()) {96 {
81 sc::VariantBuilder builder;97 string permalink_url = res["permalink-url"].get_string();
82 builder.add_tuple({98 builder.add_tuple({
83 {"id", sc::Variant("buy")},99 {"id", sc::Variant("view")},
84 {"label", sc::Variant(_("Buy"))},100 {"label", sc::Variant(_("View in browser"))},
85 {"uri", sc::Variant(purchase_url)}101 {"uri", sc::Variant(permalink_url)}
86 });102 });
87 actions.add_attribute_value("actions", builder.end());103 sc::CannedQuery new_query(SCOPE_NAME);
88 }104 new_query.set_department_id("userid:" + userid);
89 string video_url = res["video-url"].get_string();105 builder.add_tuple({
90 if (!video_url.empty()) {106 {"id", sc::Variant("usertracks")},
91 sc::VariantBuilder builder;107 {"label", sc::Variant(_("Get user tracks"))},
92 builder.add_tuple({108 {"uri", sc::Variant(new_query.to_uri())}
93 {"id", sc::Variant("video")},109 });
94 {"label", sc::Variant(_("Watch video"))},110 }
95 {"uri", sc::Variant(video_url)}111 actions.add_attribute_value("actions", builder.end());
96 });112 widgets.emplace_back(actions);
97 actions.add_attribute_value("actions", builder.end());113 } else {
98 }114 ids = std::vector<std::string> { "header", "art", "statistics", "trackinfo", "tracks", "description", "actions"};
99 {115
100 sc::VariantBuilder builder;116 sc::PreviewWidget header("header", "header");
101 builder.add_tuple({117 header.add_attribute_mapping("title", "title");
102 {"id", sc::Variant("play")},118 header.add_attribute_mapping("subtitle", "username");
103 {"label", sc::Variant(_("Play in browser"))}119 widgets.emplace_back(header);
104 });120
105 actions.add_attribute_value("actions", builder.end());121 //load big track thubmail
106 }122 string artwork_url= res["art"].get_string();
107 }123 boost::replace_all(artwork_url, "large", "t500x500");
108124 sc::PreviewWidget art("art", "image");
109 sc::PreviewWidget description("description", "text");125 art.add_attribute_value("source", sc::Variant(artwork_url));
110 description.add_attribute_mapping("text", "description");126 widgets.emplace_back(art);
111127
112 reply->push( { header, art, statistics, tracks, actions, description });128 sc::PreviewWidget statistics("statistics", "header");
129 statistics.add_attribute_value("title", sc::Variant(
130 res["playback-count"].get_string() + " " +
131 res["likes-count"].get_string() + " " +
132 res["repost-count"].get_string() + " " +
133 res["favoritings-count"].get_string() + " " +
134 res["comment-count"].get_string()));
135 widgets.emplace_back(statistics);
136
137 std::string trackid = res["id"].get_string();
138 std::string userid = res["userid"].get_string();
139
140 sc::PreviewWidget tracks("tracks", "audio");
141 {
142 if (res["streamable"].get_bool()) {
143 sc::VariantBuilder builder;
144 builder.add_tuple({
145 {"title", sc::Variant(res.title())},
146 {"source", sc::Variant(res["stream-url"])},
147 {"length", res["duration"]}
148 });
149 tracks.add_attribute_value("tracks", builder.end());
150 widgets.emplace_back(tracks);
151 }
152 }
153
154 if (!client_.authenticated()) {
155 ids.emplace_back("tips-headerid");
156 sc::PreviewWidget w_tips(ids.at(ids.size() - 1), "text");
157 w_tips.add_attribute_value("text", sc::Variant(_("Please login to post a comment ")));
158 widgets.emplace_back(w_tips);
159
160 ids.emplace_back("login-actionId");
161 sc::PreviewWidget w_action(ids.at(ids.size() - 1), "actions");
162 sc::VariantBuilder builder;
163 builder.add_tuple({
164 {"id", sc::Variant(_("open"))},
165 {"label", sc::Variant(_("Login to soundcloud"))},
166 });
167
168 sc::OnlineAccountClient oa_client(SCOPE_NAME, "sharing", SCOPE_ACCOUNTS_NAME);
169
170 oa_client.register_account_login_item(w_action,
171 sc::OnlineAccountClient::InvalidateResults,
172 sc::OnlineAccountClient::DoNothing);
173
174 w_action.add_attribute_value("actions", builder.end());
175 widgets.emplace_back(w_action);
176 }
177
178 sc::PreviewWidget trackinfo("trackinfo", "table");
179 trackinfo.add_attribute_mapping("values", "trackinfo");
180 widgets.emplace_back(trackinfo);
181
182 sc::PreviewWidget description("description", "text");
183 description.add_attribute_mapping("text", "description");
184 widgets.emplace_back(description);
185
186 if (client_.authenticated()) {
187 ids.emplace_back("comment-inputid");
188 sc::PreviewWidget w_commentInput(ids.at(ids.size() - 1), "comment-input");
189 w_commentInput.add_attribute_value("submit-label", sc::Variant(_("Post")));
190 widgets.emplace_back(w_commentInput);
191 }
192
193 sc::VariantBuilder builder;
194 sc::PreviewWidget actions("actions", "actions");
195 {
196 string purchase_url = res["purchase-url"].get_string();
197 if (!purchase_url.empty()) {
198 builder.add_tuple({
199 {"id", sc::Variant("buy")},
200 {"label", sc::Variant(_("Buy"))},
201 {"uri", sc::Variant(purchase_url)}
202 });
203 }
204 string video_url = res["video-url"].get_string();
205 if (!video_url.empty()) {
206 builder.add_tuple({
207 {"id", sc::Variant("video")},
208 {"label", sc::Variant(_("Watch video"))},
209 {"uri", sc::Variant(video_url)}
210 });
211 }
212 {
213 builder.add_tuple({
214 {"id", sc::Variant("play")},
215 {"label", sc::Variant(_("Play in browser"))}
216 });
217 }
218 if (client_.authenticated()) {
219 sc::CannedQuery new_query(SCOPE_NAME);
220 new_query.set_department_id("userid:" + userid);
221 builder.add_tuple({
222 {"id", sc::Variant("usertracks")},
223 {"label", sc::Variant(_("Get user tracks"))},
224 {"uri", sc::Variant(new_query.to_uri())}
225 });
226
227 future<bool> like_future = client_.is_fav_track(trackid);
228 auto status = get_or_throw(like_future);
229 cout << "is fav stats: " << status << endl;
230 if (status == true) {
231 builder.add_tuple({
232 {"id", sc::Variant("deletelike")},
233 {"label", sc::Variant(_("Remove 'Like'"))}
234 });
235 } else {
236 builder.add_tuple({
237 {"id", sc::Variant("like")},
238 {"label", sc::Variant(_("Like"))}
239 });
240 }
241
242 future<bool> follow_future = client_.is_user_follower(userid);
243 status = get_or_throw(follow_future);
244 cout << "is users follower: " << status << endl;
245 if (status == true) {
246 builder.add_tuple({
247 {"id", sc::Variant("unfollow")},
248 {"label", sc::Variant(_("Unfollow"))}
249 });
250 } else {
251 builder.add_tuple({
252 {"id", sc::Variant("follow")},
253 {"label", sc::Variant(_("Follow"))}
254 });
255 }
256 }
257 }
258 actions.add_attribute_value("actions", builder.end());
259 widgets.emplace_back(actions);
260
261 future<deque<Comment>> comment_future;
262 comment_future = client_.track_comments(trackid);
263
264 int index = 0;
265 for (const auto &comment : get_or_throw(comment_future)) {
266 std::string id = "commentId_"+ std::to_string(index++);
267 ids.emplace_back(id);
268
269 sc::PreviewWidget w_comment(id, "comment");
270 w_comment.add_attribute_value("comment", sc::Variant(comment.body()));
271 w_comment.add_attribute_value("author", sc::Variant(comment.title()));
272 w_comment.add_attribute_value("source", sc::Variant(comment.artwork()));
273 w_comment.add_attribute_value("subtitle", sc::Variant(comment.created_at()));
274 widgets.emplace_back(w_comment);
275 }
276 }
277
278 layout1col.add_column(ids);
279 reply->register_layout( { layout1col }); //, layout2col, layout3col
280 reply->push(widgets);
281 }catch (domain_error &e) {
282 cerr << e.what() << endl;
283 reply->error(current_exception());
284 }
113}285}
114286
=== modified file 'src/scope/query.cpp'
--- src/scope/query.cpp 2014-12-04 13:39:07 +0000
+++ src/scope/query.cpp 2016-02-02 11:41:52 +0000
@@ -14,8 +14,10 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Author: Pete Woods <pete.woods@canonical.com>16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
17 */18 */
1819
20#include <boost/algorithm/string/predicate.hpp>
19#include <boost/algorithm/string/trim.hpp>21#include <boost/algorithm/string/trim.hpp>
2022
21#include <scope/localization.h>23#include <scope/localization.h>
@@ -74,19 +76,53 @@
74{76{
75 "schema-version": 1,77 "schema-version": 1,
76 "template": {78 "template": {
77 "category-layout": "grid",79 "category-layout": "vertical-journal",
78 "card-size": "large",80 "card-size": "large",
79 "card-background": "color:///#ff4200"81 "card-background": "color:///#ff5500"
82 },
83 "components": {
84 "title": "title"
85 }
86}
87)";
88
89const static string SHOW_EMPTY_TRACK_TIPS = R"(
90{
91 "schema-version": 1,
92 "template": {
93 "category-layout": "grid",
94 "card-size": "large",
95 "card-layout": "horizontal"
96 },
97 "components": {
98 "title": "title"
99 }
100}
101)";
102
103const static string USER_INFO_TEMPLATE = R"(
104{
105 "schema-version": 1,
106 "template": {
107 "category-layout": "grid",
108 "card-background": "color:///#FFFFFF",
109 "card-size": "medium",
110 "card-layout": "horizontal"
80 },111 },
81 "components": {112 "components": {
82 "title": "title",113 "title": "title",
83 "background": "background",
84 "art" : {114 "art" : {
85 "aspect-ratio": 100.0115 "field": "art"
116 },
117 "subtitle": "subtitle",
118 "attributes": {
119 "field": "attributes",
120 "max-count": 3
86 }121 }
87 }122 }
88}123}
89)";124)";
125
90// unconfuse emacs: "126// unconfuse emacs: "
91127
92static const vector<string> AUDIO_DEPARTMENT_IDS { "Audiobooks", "Business",128static const vector<string> AUDIO_DEPARTMENT_IDS { "Audiobooks", "Business",
@@ -127,9 +163,15 @@
127 return f.get();163 return f.get();
128}164}
129165
130static sc::Department::SPtr create_departments(const sc::CannedQuery &query) {166static sc::Department::SPtr create_departments(const sc::CannedQuery &query,
167 bool contains_fav) {
131 sc::Department::SPtr root_department = sc::Department::create("", query,168 sc::Department::SPtr root_department = sc::Department::create("", query,
132 MUSIC_DEPARTMENT_NAMES.front());169 MUSIC_DEPARTMENT_NAMES.front());
170 if (contains_fav) {
171 sc::Department::SPtr dept = sc::Department::create(
172 "my_fav", query, _("My favorites"));
173 root_department->add_subdepartment(dept);
174 }
133 for (size_t i = 1; i < MUSIC_DEPARTMENT_IDS.size(); ++i) {175 for (size_t i = 1; i < MUSIC_DEPARTMENT_IDS.size(); ++i) {
134 sc::Department::SPtr dept = sc::Department::create(176 sc::Department::SPtr dept = sc::Department::create(
135 MUSIC_DEPARTMENT_IDS[i], query, MUSIC_DEPARTMENT_NAMES[i]);177 MUSIC_DEPARTMENT_IDS[i], query, MUSIC_DEPARTMENT_NAMES[i]);
@@ -195,21 +237,40 @@
195 try {237 try {
196 const sc::CannedQuery &query(sc::SearchQueryBase::query());238 const sc::CannedQuery &query(sc::SearchQueryBase::query());
197 string query_string = alg::trim_copy(query.query_string());239 string query_string = alg::trim_copy(query.query_string());
198240 string department_id = query.department_id();
199 reply->register_departments(create_departments(query));241
242 bool authenticated = client_.authenticated();
243 sc::Department::SPtr root_depts = create_departments(query, authenticated);
244
245 bool is_dummy_depts = alg::starts_with(department_id, "userid:");
246 if (is_dummy_depts) {
247 sc::Department::SPtr dummy = sc::Department::create(
248 department_id, query, " ");
249 root_depts->add_subdepartment(dummy);
250 }
251
252 reply->register_departments(root_depts);
200253
201 // Avoid blocking on HTTP requests at this point254 // Avoid blocking on HTTP requests at this point
202255
203 sc::Category::SCPtr first_cat;256 sc::Category::SCPtr first_cat;
257 sc::Category::SCPtr user_cat;
204 future<deque<Track>> stream_future;258 future<deque<Track>> stream_future;
259 future<User> user_future;
205 bool reading_stream = false;260 bool reading_stream = false;
206 if (query_string.empty() && query.department_id().empty()) {261 bool reading_user_info = false;
207 if (client_.authenticated()) {262 if (query_string.empty() && department_id.empty()) {
263 if (authenticated) {
264 user_cat = reply->register_category("user", "", "",
265 sc::CategoryRenderer(USER_INFO_TEMPLATE));
266 user_future = client_.get_authuser_info();
267
208 first_cat = reply->register_category(268 first_cat = reply->register_category(
209 "stream", _("Stream"), "",269 "stream", _("Stream"), "",
210 sc::CategoryRenderer(SEARCH_CATEGORY_TEMPLATE));270 sc::CategoryRenderer(SEARCH_CATEGORY_TEMPLATE));
211 stream_future = client_.stream_tracks(30);271 stream_future = client_.stream_tracks(30);
212 reading_stream = true;272 reading_stream = true;
273 reading_user_info = true;
213 } else {274 } else {
214 add_login_nag(reply);275 add_login_nag(reply);
215 }276 }
@@ -220,22 +281,42 @@
220 if (query_string.empty()) {281 if (query_string.empty()) {
221 second_cat = reply->register_category("explore", _("Explore"), "",282 second_cat = reply->register_category("explore", _("Explore"), "",
222 sc::CategoryRenderer(SEARCH_CATEGORY_TEMPLATE));283 sc::CategoryRenderer(SEARCH_CATEGORY_TEMPLATE));
223 tracks_future = client_.search_tracks({284 if (department_id == "my_fav") {
224 { SP::query, query_string },285 tracks_future = client_.favorite_tracks();
225 { SP::limit, "15" },286 } else if (is_dummy_depts) {
226 { SP::genre, department_to_category(query.department_id()) },287 //create dummy department to pass the validation check
227 { SP::order, "hotness" }288 user_cat = reply->register_category("user", "", "",
228 });289 sc::CategoryRenderer(USER_INFO_TEMPLATE));
290
291 string userId = department_id.substr(department_id.find(':') + 1);
292 user_future = client_.get_user_info(userId);
293 tracks_future = client_.get_user_tracks(userId, 15);
294 reading_user_info = true;
295 } else {
296 tracks_future = client_.search_tracks({
297 { SP::query, query_string },
298 { SP::limit, "15" },
299 { SP::genre, department_to_category(department_id) },
300 { SP::order, "hotness" }
301 });
302 }
229 } else {303 } else {
230 second_cat = reply->register_category("search", "", "",304 second_cat = reply->register_category("search", "", "",
231 sc::CategoryRenderer(SEARCH_CATEGORY_TEMPLATE));305 sc::CategoryRenderer(SEARCH_CATEGORY_TEMPLATE));
306
232 tracks_future = client_.search_tracks( {307 tracks_future = client_.search_tracks( {
233 { SP::query, query_string },308 { SP::query, query_string },
234 { SP::limit, "30" }309 { SP::limit, "30" }
235 });310 });
236 }311 }
237312
238 // Now we come to wait for the results313 // Now we come to wait for the results
314 if (reading_user_info) {
315 User user = get_or_throw(user_future);
316 if (!push_user_info(reply, user_cat, user)) {
317 return;
318 }
319 }
239320
240 if (reading_stream) {321 if (reading_stream) {
241 for (const auto &track : get_or_throw(stream_future)) {322 for (const auto &track : get_or_throw(stream_future)) {
@@ -245,12 +326,19 @@
245 }326 }
246 }327 }
247328
248 for (const auto &track : get_or_throw(tracks_future)) {329 deque<Track> tracklist = get_or_throw(tracks_future);
330 for (const auto &track : tracklist) {
249 if (!push_track(reply, second_cat, track)) {331 if (!push_track(reply, second_cat, track)) {
250 return;332 return;
251 }333 }
252 }334 }
253335
336 if (tracklist.size() == 0) {
337 if (!show_empty_tip(reply)) {
338 return;
339 }
340 }
341
254 } catch (domain_error &e) {342 } catch (domain_error &e) {
255 cerr << e.what() << endl;343 cerr << e.what() << endl;
256 reply->error(current_exception());344 reply->error(current_exception());
@@ -269,7 +357,8 @@
269 } else {357 } else {
270 res.set_art(track.user().artwork());358 res.set_art(track.user().artwork());
271 }359 }
272360
361 res["id"] = std::to_string(track.id());
273 res["label"] = track.label_name();362 res["label"] = track.label_name();
274 res["streamable"] = track.streamable();363 res["streamable"] = track.streamable();
275 res["stream-url"] = track.stream_url() + "?client_id=" + client_.client_id();364 res["stream-url"] = track.stream_url() + "?client_id=" + client_.client_id();
@@ -277,20 +366,89 @@
277 res["video-url"] = track.video_url();366 res["video-url"] = track.video_url();
278 res["waveform"] = track.waveform();367 res["waveform"] = track.waveform();
279 res["username"] = track.user().title();368 res["username"] = track.user().title();
369 res["userid"] = std::to_string(track.user().id());
280 res["description"] = track.description();370 res["description"] = track.description();
281371
282 string duration = format_time(track.duration());372 string duration = format_time(track.duration());
283 string playback_count = u8"\u25B6 " + format_fixed(track.playback_count());373 string playback_count = u8"\u25B6 " + format_fixed(track.playback_count());
284 string favoritings_count = u8"\u2665 " + format_fixed(track.favoritings_count());374 string favoritings_count = u8"\u263B " + format_fixed(track.favoritings_count());
375 string likes_count = u8"\u2665 " + format_fixed(track.likes_count());
376 string repost_count = u8"\u2B94 " + format_fixed(track.repost_count());
377 string comment_count = u8"\u270E " + format_fixed(track.comment_count());
285 res["duration"] = (int) (track.duration() / 1000);378 res["duration"] = (int) (track.duration() / 1000);
286 res["playback-count"] = playback_count;379 res["playback-count"] = playback_count;
287 res["favoritings-count"] = favoritings_count;380 res["favoritings-count"] = favoritings_count;
381 res["likes-count"] = likes_count;
382 res["repost-count"] = repost_count;
383 res["comment-count"] = comment_count;
384
385 sc::VariantArray trackinfo {
386 sc::Variant(sc::VariantArray{sc::Variant(_("create time")), sc::Variant(track.created_at())}),
387 sc::Variant(sc::VariantArray{sc::Variant(_("genre")), sc::Variant(track.genre())}),
388 sc::Variant(sc::VariantArray{sc::Variant(_("license")), sc::Variant(track.license())})
389 };
390 res["trackinfo"] = sc::Variant(trackinfo);
288391
289 sc::VariantBuilder builder;392 sc::VariantBuilder builder;
290 builder.add_tuple({{"value", sc::Variant(duration)}});393 builder.add_tuple({{"value", sc::Variant(duration)}});
291 builder.add_tuple({{"value", sc::Variant(playback_count)}});394 builder.add_tuple({{"value", sc::Variant(playback_count)}});
292 builder.add_tuple({{"value", sc::Variant(favoritings_count)}});395
293 res["attributes"] = builder.end();396 //favorite api doesn't contains likes_count field when retrieving auth user favorites list
397 //activity api doesn't contains favoritings_count field when retrieving stream list
398 if (track.likes_count() > 0)
399 builder.add_tuple({{"value", sc::Variant(likes_count)}});
400 else
401 builder.add_tuple({{"value", sc::Variant(favoritings_count)}});
402
403 res["attributes"] = builder.end();
404
405 res["mode"] = _("track");
406
407 return reply->push(res);
408}
409
410bool Query::push_user_info(const sc::SearchReplyProxy &reply,
411 const sc::Category::SCPtr &category,
412 const User &user) {
413
414 sc::CategorisedResult res(category);
415
416 res.set_uri(user.permalink_url());
417 res.set_title(user.title());
418 res.set_art(user.artwork());
419 res["subtitle"] = user.permalink_url() + " "+ user.bio();
420
421 string track_count = "<b> "+ format_fixed(user.track_count()) + _("</b> tracks");
422 string followers_count = "<b> "+ format_fixed(user.followers_count()) + _("</b> followers");
423 string followings_count = "<b> "+ format_fixed(user.followings_count()) + _("</b> followings");
424 res["track-count"] = track_count;
425 res["followers-count"] = followers_count;
426 res["followings-count"] = followings_count;
427 res["permalink-url"] = user.permalink_url();
428 res["bio"] = user.bio();
429 res["id"] = std::to_string(user.id());
430
431 sc::VariantBuilder builder;
432 builder.add_tuple({{"value", sc::Variant(track_count)}});
433 builder.add_tuple({{"value", sc::Variant(followers_count)}});
434 builder.add_tuple({{"value", sc::Variant(followings_count)}});
435
436 res["attributes"] = builder.end();
437 res["mode"] = _("user");
438
439 return reply->push(res);
440}
441
442bool Query::show_empty_tip(const unity::scopes::SearchReplyProxy &reply)
443{
444 //Stay on surface and avoid user to enter card view if no tracks are found
445 const sc::CannedQuery &query(sc::SearchQueryBase::query());
446 sc::CategoryRenderer rdr(SHOW_EMPTY_TRACK_TIPS);
447 auto cat = reply->register_category("show_empty_tips", "", "", rdr);
448
449 sc::CategorisedResult res(cat);
450 res.set_uri(query.to_uri());
451 res.set_title(_("No tracks can be found"));
294452
295 return reply->push(res);453 return reply->push(res);
296}454}
297455
=== modified file 'src/scope/scope.cpp'
--- src/scope/scope.cpp 2014-12-04 13:39:07 +0000
+++ src/scope/scope.cpp 2016-02-02 11:41:52 +0000
@@ -14,12 +14,14 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Author: Pete Woods <pete.woods@canonical.com>16 * Author: Pete Woods <pete.woods@canonical.com>
17 * Gary Wang <gary.wang@canonical.com>
17 */18 */
1819
19#include <scope/localization.h>20#include <scope/localization.h>
20#include <scope/preview.h>21#include <scope/preview.h>
21#include <scope/query.h>22#include <scope/query.h>
22#include <scope/scope.h>23#include <scope/scope.h>
24#include <scope/activation.h>
2325
24namespace sc = unity::scopes;26namespace sc = unity::scopes;
25using namespace std;27using namespace std;
@@ -48,7 +50,14 @@
4850
49sc::PreviewQueryBase::UPtr Scope::preview(sc::Result const& result,51sc::PreviewQueryBase::UPtr Scope::preview(sc::Result const& result,
50 sc::ActionMetadata const& metadata) {52 sc::ActionMetadata const& metadata) {
51 return sc::PreviewQueryBase::UPtr(new Preview(result, metadata));53 return sc::PreviewQueryBase::UPtr(new Preview(result, metadata, oa_client_));
54}
55
56sc::ActivationQueryBase::UPtr Scope::perform_action(const sc::Result &result,
57 const sc::ActionMetadata &metadata,
58 const std::string &widget_id,
59 const std::string &action_id) {
60 return sc::ActivationQueryBase::UPtr(new Activation(result, metadata, action_id, oa_client_));
52}61}
5362
54#define EXPORT __attribute__ ((visibility ("default")))63#define EXPORT __attribute__ ((visibility ("default")))

Subscribers

People subscribed via source and target branches

to all changes: