Merge lp:~mardy/shotwell/uoa-update into lp:~ubuntu-desktop/shotwell/ubuntu
- uoa-update
- Merge into ubuntu
Proposed by
Alberto Mardegan
Status: | Merged |
---|---|
Merged at revision: | 85 |
Proposed branch: | lp:~mardy/shotwell/uoa-update |
Merge into: | lp:~ubuntu-desktop/shotwell/ubuntu |
Diff against target: |
2378 lines (+1527/-382) 1 file modified
debian/patches/06_uoa.patch (+1527/-382) |
To merge this branch: | bzr merge lp:~mardy/shotwell/uoa-update |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+124659@code.launchpad.net |
Commit message
Description of the change
Update the UOA patch
* Support multiple accounts per service
* Attempt automatic login
* Remove logout buttons
To post a comment you must log in.
lp:~mardy/shotwell/uoa-update
updated
- 85. By Alberto Mardegan
-
i18n update
* Allow translating the shotwell.
application file
* Add the "Add more accounts..." string for translations. - 86. By Alberto Mardegan
-
Avoid critical warnings
Vala was generating an enumerated type, but all we want is an int.
- 87. By Alberto Mardegan
-
Do not make warnings fatal when building plugins
Gtk.Table, which is used all over the place, has been deprecated.
- 88. By Alberto Mardegan
-
* New upstream bugfix release
* debian/watch:
- Watch for stable versions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/patches/06_uoa.patch' |
2 | --- debian/patches/06_uoa.patch 2012-09-20 03:21:36 +0000 |
3 | +++ debian/patches/06_uoa.patch 2012-09-24 08:43:19 +0000 |
4 | @@ -1,12 +1,12 @@ |
5 | Description: use Ubuntu Online Accounts for Picasa, Facebook and Flickr export plugins |
6 | Author: Alberto Mardegan <alberto.mardegan@canonical.com> |
7 | |
8 | -=== modified file 'Makefile' |
9 | -Index: shotwell-0.13.0/Makefile |
10 | -=================================================================== |
11 | ---- shotwell-0.13.0.orig/Makefile 2012-09-20 15:15:16.000000000 +1200 |
12 | -+++ shotwell-0.13.0/Makefile 2012-09-20 15:16:00.929921786 +1200 |
13 | -@@ -152,6 +152,7 @@ |
14 | +--- |
15 | +diff --git a/Makefile b/Makefile |
16 | +index 70bdc96..f5ac032 100644 |
17 | +--- a/Makefile |
18 | ++++ b/Makefile |
19 | +@@ -152,6 +152,7 @@ RESOURCE_FILES = \ |
20 | trash.ui |
21 | |
22 | SYS_INTEGRATION_FILES = \ |
23 | @@ -14,7 +14,7 @@ |
24 | shotwell.desktop.head \ |
25 | shotwell-viewer.desktop.head \ |
26 | org.yorba.shotwell.gschema.xml \ |
27 | -@@ -546,6 +547,8 @@ |
28 | +@@ -546,6 +547,8 @@ install: |
29 | $(INSTALL_PROGRAM) $(PROGRAM) $(DESTDIR)$(PREFIX)/bin |
30 | $(INSTALL_PROGRAM) $(THUMBNAILER_BIN) $(DESTDIR)$(PREFIX)/bin |
31 | $(INSTALL_PROGRAM) $(MIGRATOR_BIN) $(DESTDIR)$(PREFIX)/bin |
32 | @@ -23,51 +23,36 @@ |
33 | mkdir -p $(DESTDIR)$(PREFIX)/share/shotwell/icons |
34 | $(INSTALL_DATA) icons/* $(DESTDIR)$(PREFIX)/share/shotwell/icons |
35 | mkdir -p $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps |
36 | -Index: shotwell-0.13.0/misc/org.yorba.shotwell.gschema.xml |
37 | -=================================================================== |
38 | ---- shotwell-0.13.0.orig/misc/org.yorba.shotwell.gschema.xml 2012-09-20 07:08:59.000000000 +1200 |
39 | -+++ shotwell-0.13.0/misc/org.yorba.shotwell.gschema.xml 2012-09-20 15:16:00.929921786 +1200 |
40 | -@@ -310,6 +310,12 @@ |
41 | - <description>Facebook user i.d. for the currently logged in user, if any</description> |
42 | - </key> |
43 | - |
44 | -+ <key name="auth-method" type="s"> |
45 | -+ <default>""</default> |
46 | -+ <summary>auth method</summary> |
47 | -+ <description>The authorization method for the currently logged in Picasa Web Albums user, if any</description> |
48 | -+ </key> |
49 | -+ |
50 | - <key name="user-name" type="s"> |
51 | - <default>""</default> |
52 | - <summary>user name</summary> |
53 | -Index: shotwell-0.13.0/misc/shotwell.application |
54 | -=================================================================== |
55 | ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
56 | -+++ shotwell-0.13.0/misc/shotwell.application 2012-09-20 15:16:00.929921786 +1200 |
57 | -@@ -0,0 +1,18 @@ |
58 | +diff --git a/misc/shotwell.application b/misc/shotwell.application |
59 | +new file mode 100644 |
60 | +index 0000000..815345f |
61 | +--- /dev/null |
62 | ++++ b/misc/shotwell.application |
63 | +@@ -0,0 +1,19 @@ |
64 | +<?xml version="1.0" encoding="UTF-8" ?> |
65 | +<application id="shotwell"> |
66 | + <description>Shotwell</description> |
67 | -+ <desktop-entry>shotwell.desktop</desktop-entry> |
68 | ++ <desktop-entry>shotwell.desktop</desktop-entry> |
69 | ++ <translations>shotwell</translations> |
70 | + |
71 | + <services> |
72 | -+ <service id="picasa"> |
73 | -+ <description>Publish your pictures to Picasa</description> |
74 | -+ </service> |
75 | -+ <service id="facebook-sharing"> |
76 | -+ <description>Publish your pictures to Facebook</description> |
77 | -+ </service> |
78 | -+ <service id="flickr-sharing"> |
79 | -+ <description>Publish your pictures to Flickr</description> |
80 | -+ </service> |
81 | ++ <service id="picasa"> |
82 | ++ <description>Publish your pictures to Picasa</description> |
83 | ++ </service> |
84 | ++ <service id="facebook-sharing"> |
85 | ++ <description>Publish your pictures to Facebook</description> |
86 | ++ </service> |
87 | ++ <service id="flickr-sharing"> |
88 | ++ <description>Publish your pictures to Flickr</description> |
89 | ++ </service> |
90 | + </services> |
91 | + |
92 | +</application> |
93 | -Index: shotwell-0.13.0/plugins/Makefile |
94 | -=================================================================== |
95 | ---- shotwell-0.13.0.orig/plugins/Makefile 2012-09-20 07:08:59.000000000 +1200 |
96 | -+++ shotwell-0.13.0/plugins/Makefile 2012-09-20 15:16:00.929921786 +1200 |
97 | -@@ -4,7 +4,10 @@ |
98 | +diff --git a/plugins/Makefile b/plugins/Makefile |
99 | +index c622063..255e9cc 100644 |
100 | +--- a/plugins/Makefile |
101 | ++++ b/plugins/Makefile |
102 | +@@ -4,7 +4,10 @@ include plugins.mk |
103 | DIST_FILES := \ |
104 | Makefile \ |
105 | Makefile.plugin.mk \ |
106 | @@ -79,11 +64,11 @@ |
107 | |
108 | .PHONY: all |
109 | all: $(ALL_PLUGINS) |
110 | -Index: shotwell-0.13.0/plugins/Makefile.plugin.mk |
111 | -=================================================================== |
112 | ---- shotwell-0.13.0.orig/plugins/Makefile.plugin.mk 2012-09-20 07:08:59.000000000 +1200 |
113 | -+++ shotwell-0.13.0/plugins/Makefile.plugin.mk 2012-09-20 15:16:00.929921786 +1200 |
114 | -@@ -27,6 +27,8 @@ |
115 | +diff --git a/plugins/Makefile.plugin.mk b/plugins/Makefile.plugin.mk |
116 | +index d76433b..211c02a 100644 |
117 | +--- a/plugins/Makefile.plugin.mk |
118 | ++++ b/plugins/Makefile.plugin.mk |
119 | +@@ -27,6 +27,8 @@ PKGS := $(shell sed ':a;N;$$!ba;s/\n/ /g' ../shotwell-plugin-dev-1.0.deps) $(PKG |
120 | # automatically include the shotwell-plugin-dev-1.0 package as a local dependency |
121 | EXT_PKGS := $(PKGS) |
122 | PKGS := shotwell-plugin-dev-1.0 $(PKGS) $(PLUGIN_PKGS) |
123 | @@ -92,11 +77,11 @@ |
124 | |
125 | # automatically include the Resources.vala common file |
126 | SRC_FILES := ../common/Resources.vala $(SRC_FILES) |
127 | -Index: shotwell-0.13.0/plugins/common/RESTSupport.vala |
128 | -=================================================================== |
129 | ---- shotwell-0.13.0.orig/plugins/common/RESTSupport.vala 2012-09-20 07:08:59.000000000 +1200 |
130 | -+++ shotwell-0.13.0/plugins/common/RESTSupport.vala 2012-09-20 15:16:00.929921786 +1200 |
131 | -@@ -314,7 +314,7 @@ |
132 | +diff --git a/plugins/common/RESTSupport.vala b/plugins/common/RESTSupport.vala |
133 | +index 3f5ed21..3e90828 100644 |
134 | +--- a/plugins/common/RESTSupport.vala |
135 | ++++ b/plugins/common/RESTSupport.vala |
136 | +@@ -314,7 +314,7 @@ public class Transaction { |
137 | old_url = message.get_uri().to_string(false); |
138 | url_with_query = get_endpoint_url() + "?" + formdata_string; |
139 | message.set_uri(new Soup.URI(url_with_query)); |
140 | @@ -105,22 +90,23 @@ |
141 | message.set_request("application/x-www-form-urlencoded", Soup.MemoryUse.COPY, |
142 | formdata_string.data); |
143 | } |
144 | -Index: shotwell-0.13.0/plugins/common/accounts.vala |
145 | -=================================================================== |
146 | ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
147 | -+++ shotwell-0.13.0/plugins/common/accounts.vala 2012-09-20 15:16:00.929921786 +1200 |
148 | -@@ -0,0 +1,54 @@ |
149 | +diff --git a/plugins/common/accounts.vala b/plugins/common/accounts.vala |
150 | +new file mode 100644 |
151 | +index 0000000..ee2d9da |
152 | +--- /dev/null |
153 | ++++ b/plugins/common/accounts.vala |
154 | +@@ -0,0 +1,226 @@ |
155 | +/* Copyright 2009-2011 Yorba Foundation |
156 | + * |
157 | + * This software is licensed under the GNU Lesser General Public License |
158 | -+ * (version 2.1 or later). See the COPYING file in this distribution. |
159 | ++ * (version 2.1 or later). See the COPYING file in this distribution. |
160 | + */ |
161 | + |
162 | +namespace Publishing.Accounts { |
163 | + |
164 | +public class SharingAccount { |
165 | + private Ag.AccountService account_service = null; |
166 | -+ |
167 | ++ |
168 | + public SharingAccount(Ag.AccountService account_service) { |
169 | + this.account_service = account_service; |
170 | + } |
171 | @@ -142,54 +128,297 @@ |
172 | +} |
173 | + |
174 | +public class SharingAccounts { |
175 | -+ private Ag.Manager manager = null; |
176 | -+ |
177 | -+ public SharingAccounts() { |
178 | -+ manager = new Ag.Manager.for_service_type("sharing"); |
179 | -+ } |
180 | -+ |
181 | -+ public SharingAccount? get_account_for_provider(string provider) { |
182 | ++ private static Ag.Manager manager = null; |
183 | ++ private string provider_name; |
184 | ++ private Ag.AccountService[] all_accounts; |
185 | ++ |
186 | ++ public SharingAccounts(string provider_name) { |
187 | ++ if (manager == null) { |
188 | ++ manager = new Ag.Manager.for_service_type("sharing"); |
189 | ++ } |
190 | ++ manager.enabled_event.connect(on_account_enabled); |
191 | ++ |
192 | ++ this.provider_name = provider_name; |
193 | ++ all_accounts = get_accounts(); |
194 | ++ } |
195 | ++ |
196 | ++ private void on_account_enabled(uint account_id) { |
197 | ++ /* To keep the implementation simple, just rebuild the account |
198 | ++ * list from scratch */ |
199 | ++ all_accounts = get_accounts(); |
200 | ++ } |
201 | ++ |
202 | ++ private Ag.AccountService[] get_accounts() { |
203 | + GLib.List<Ag.AccountService> accounts = |
204 | + manager.get_enabled_account_services(); |
205 | + |
206 | ++ Ag.AccountService[] list = {}; |
207 | ++ |
208 | + foreach (Ag.AccountService account_service in accounts) { |
209 | + Ag.Account account = account_service.get_account(); |
210 | -+ if (account.get_provider_name() == provider) { |
211 | ++ if (account.get_provider_name() == provider_name) { |
212 | ++ list += account_service; |
213 | ++ } |
214 | ++ } |
215 | ++ return list; |
216 | ++ } |
217 | ++ |
218 | ++ public bool has_enabled_accounts() { |
219 | ++ return all_accounts.length > 0; |
220 | ++ } |
221 | ++ |
222 | ++ public string[] list_account_names() { |
223 | ++ string[] names = {}; |
224 | ++ foreach (Ag.AccountService account_service in all_accounts) { |
225 | ++ names += account_service.get_account().get_display_name(); |
226 | ++ } |
227 | ++ return names; |
228 | ++ } |
229 | ++ |
230 | ++ public SharingAccount? find_account(string? account_name) { |
231 | ++ foreach (Ag.AccountService account_service in all_accounts) |
232 | ++ if (account_service.get_account().get_display_name() == account_name) { |
233 | + return new SharingAccount(account_service); |
234 | + } |
235 | -+ } |
236 | ++ |
237 | + return null; |
238 | + } |
239 | +} |
240 | + |
241 | -+} |
242 | -+ |
243 | -Index: shotwell-0.13.0/plugins/shotwell-publishing/FacebookPublishing.vala |
244 | -=================================================================== |
245 | ---- shotwell-0.13.0.orig/plugins/shotwell-publishing/FacebookPublishing.vala 2012-09-20 07:08:59.000000000 +1200 |
246 | -+++ shotwell-0.13.0/plugins/shotwell-publishing/FacebookPublishing.vala 2012-09-20 15:16:00.933921786 +1200 |
247 | -@@ -4,6 +4,8 @@ |
248 | ++public abstract class UOAPublishingService : Object, Spit.Pluggable, Spit.Publishing.Service { |
249 | ++ private SharingAccounts account_manager; |
250 | ++ |
251 | ++ public UOAPublishingService(string provider_name) { |
252 | ++ account_manager = new SharingAccounts(provider_name); |
253 | ++ } |
254 | ++ |
255 | ++ public virtual int get_pluggable_interface(int min_host_interface, int max_host_interface) { |
256 | ++ return Spit.negotiate_interfaces(min_host_interface, max_host_interface, |
257 | ++ Spit.Publishing.CURRENT_INTERFACE); |
258 | ++ } |
259 | ++ |
260 | ++ public abstract unowned string get_id(); |
261 | ++ |
262 | ++ public abstract unowned string get_pluggable_name(); |
263 | ++ |
264 | ++ public abstract void get_info(ref Spit.PluggableInfo info); |
265 | ++ |
266 | ++ public virtual void activation(bool enabled) { |
267 | ++ } |
268 | ++ |
269 | ++ public abstract Spit.Publishing.Publisher create_publisher(string? account_name, Spit.Publishing.PluginHost host); |
270 | ++ |
271 | ++ public abstract Spit.Publishing.Publisher.MediaType get_supported_media(); |
272 | ++ |
273 | ++ public SharingAccount? find_account(string? account_name) { |
274 | ++ return account_manager.find_account(account_name); |
275 | ++ } |
276 | ++ |
277 | ++ public bool is_enabled() { |
278 | ++ return account_manager.has_enabled_accounts(); |
279 | ++ } |
280 | ++ |
281 | ++ public string[] list_account_names() { |
282 | ++ return account_manager.list_account_names(); |
283 | ++ } |
284 | ++} |
285 | ++ |
286 | ++public class UOAPublisherAuthenticator : Object { |
287 | ++ private weak Spit.Publishing.PluginHost host = null; |
288 | ++ private Signon.AuthSession auth_session = null; |
289 | ++ private SharingAccount account = null; |
290 | ++ private bool firstLoginAttempt = true; |
291 | ++ private string welcome_message = null; |
292 | ++ |
293 | ++ public UOAPublisherAuthenticator(SharingAccount account, |
294 | ++ Spit.Publishing.PluginHost host, |
295 | ++ string welcome_message) |
296 | ++ { |
297 | ++ this.host = host; |
298 | ++ this.account = account; |
299 | ++ this.welcome_message = welcome_message; |
300 | ++ } |
301 | ++ |
302 | ++ public signal void authenticated(owned HashTable<string,Value?> session_data); |
303 | ++ |
304 | ++ public void authenticate() { |
305 | ++ debug("ACTION: authentication requested."); |
306 | ++ |
307 | ++ do_authentication(); |
308 | ++ } |
309 | ++ |
310 | ++ public HashTable<string,Value?>? get_authentication_data() { |
311 | ++ if (account == null) return null; |
312 | ++ string mechanism = null; |
313 | ++ return account.get_session_parameters(out mechanism); |
314 | ++ } |
315 | ++ |
316 | ++ private void do_authentication() { |
317 | ++ debug("ACTION: authenticating."); |
318 | ++ |
319 | ++ HashTable<string,Value?> data = null; |
320 | ++ string mechanism = null; |
321 | ++ |
322 | ++ if (account != null) { |
323 | ++ try { |
324 | ++ auth_session = account.create_auth_session(); |
325 | ++ data = account.get_session_parameters(out mechanism); |
326 | ++ debug("Got account data"); |
327 | ++ } catch (GLib.Error e) { |
328 | ++ warning("EVENT: couldn't create session for account: %s", |
329 | ++ e.message); |
330 | ++ } |
331 | ++ } |
332 | ++ |
333 | ++ if (data == null) { |
334 | ++ warning ("No account authentication data"); |
335 | ++ host.post_error(new Spit.Publishing.PublishingError.SERVICE_ERROR( |
336 | ++ "Error while accessing the account")); |
337 | ++ return; |
338 | ++ } |
339 | ++ |
340 | ++ if (firstLoginAttempt) { |
341 | ++ firstLoginAttempt = false; |
342 | ++ data.insert("UiPolicy", (int)Signon.SessionDataUiPolicy.NO_USER_INTERACTION); |
343 | ++ } else { |
344 | ++ var windowId = host.get_dialog_xid(); |
345 | ++ if (windowId != 0) { |
346 | ++ data.insert("WindowId", (uint)windowId); |
347 | ++ } |
348 | ++ } |
349 | ++ |
350 | ++ auth_session.process(data, mechanism, on_processed); |
351 | ++ host.set_service_locked(true); |
352 | ++ } |
353 | ++ |
354 | ++ private void on_processed(Signon.AuthSession self, owned HashTable<string,Value?>? session_data, GLib.Error error){ |
355 | ++ host.set_service_locked(false); |
356 | ++ if (error != null) { |
357 | ++ debug("got error: %s", error.message); |
358 | ++ if (error is Signon.Error.USER_INTERACTION) { |
359 | ++ debug("User interaction!"); |
360 | ++ do_show_service_welcome_pane(); |
361 | ++ } else { |
362 | ++ host.post_error(new Spit.Publishing.PublishingError.SERVICE_ERROR("Authentication failed")); |
363 | ++ } |
364 | ++ return; |
365 | ++ } |
366 | ++ |
367 | ++ authenticated(session_data); |
368 | ++ } |
369 | ++ |
370 | ++ private void do_show_service_welcome_pane() { |
371 | ++ debug("ACTION: showing service welcome pane."); |
372 | ++ |
373 | ++ host.install_welcome_pane(welcome_message, on_service_welcome_login); |
374 | ++ } |
375 | ++ |
376 | ++ private void on_service_welcome_login() { |
377 | ++ debug("EVENT: user clicked 'Login' in welcome pane."); |
378 | ++ |
379 | ++ do_authentication(); |
380 | ++ } |
381 | ++} |
382 | ++ |
383 | ++} |
384 | ++ |
385 | +diff --git a/plugins/shotwell-publishing-extras/TumblrPublishing.vala b/plugins/shotwell-publishing-extras/TumblrPublishing.vala |
386 | +index c65e19a..e3cfb79 100644 |
387 | +--- a/plugins/shotwell-publishing-extras/TumblrPublishing.vala |
388 | ++++ b/plugins/shotwell-publishing-extras/TumblrPublishing.vala |
389 | +@@ -48,7 +48,7 @@ public class TumblrService : Object, Spit.Pluggable, Spit.Publishing.Service { |
390 | + public void activation(bool enabled) { |
391 | + } |
392 | + |
393 | +- public Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host) { |
394 | ++ public Spit.Publishing.Publisher create_publisher(string? account, Spit.Publishing.PluginHost host) { |
395 | + return new Publishing.Tumblr.TumblrPublisher(this, host); |
396 | + } |
397 | + |
398 | +diff --git a/plugins/shotwell-publishing-extras/YandexPublishing.vala b/plugins/shotwell-publishing-extras/YandexPublishing.vala |
399 | +index 1370690..760a8f3 100644 |
400 | +--- a/plugins/shotwell-publishing-extras/YandexPublishing.vala |
401 | ++++ b/plugins/shotwell-publishing-extras/YandexPublishing.vala |
402 | +@@ -30,7 +30,7 @@ public class YandexService : Object, Spit.Pluggable, Spit.Publishing.Service { |
403 | + info.license = Resources.LICENSE; |
404 | + } |
405 | + |
406 | +- public Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host) { |
407 | ++ public Spit.Publishing.Publisher create_publisher(string? account, Spit.Publishing.PluginHost host) { |
408 | + return new Publishing.Yandex.YandexPublisher(this, host); |
409 | + } |
410 | + |
411 | +diff --git a/plugins/shotwell-publishing/FacebookPublishing.vala b/plugins/shotwell-publishing/FacebookPublishing.vala |
412 | +index fa9d8f2..bd3cd08 100644 |
413 | +--- a/plugins/shotwell-publishing/FacebookPublishing.vala |
414 | ++++ b/plugins/shotwell-publishing/FacebookPublishing.vala |
415 | +@@ -4,30 +4,28 @@ |
416 | * (version 2.1 or later). See the COPYING file in this distribution. |
417 | */ |
418 | |
419 | +-public class FacebookService : Object, Spit.Pluggable, Spit.Publishing.Service { |
420 | +using Publishing.Accounts; |
421 | + |
422 | - public class FacebookService : Object, Spit.Pluggable, Spit.Publishing.Service { |
423 | ++public class FacebookService : UOAPublishingService, Spit.Pluggable, Spit.Publishing.Service { |
424 | private const string ICON_FILENAME = "facebook.png"; |
425 | |
426 | -@@ -50,6 +52,11 @@ |
427 | + private static Gdk.Pixbuf[] icon_pixbuf_set = null; |
428 | + |
429 | + public FacebookService(GLib.File resource_directory) { |
430 | ++ base("facebook"); |
431 | + if (icon_pixbuf_set == null) |
432 | + icon_pixbuf_set = Resources.load_icon_set(resource_directory.get_child(ICON_FILENAME)); |
433 | + } |
434 | + |
435 | +- public int get_pluggable_interface(int min_host_interface, int max_host_interface) { |
436 | +- return Spit.negotiate_interfaces(min_host_interface, max_host_interface, |
437 | +- Spit.Publishing.CURRENT_INTERFACE); |
438 | +- } |
439 | +- |
440 | +- public unowned string get_id() { |
441 | ++ public override unowned string get_id() { |
442 | + return "org.yorba.shotwell.publishing.facebook"; |
443 | + } |
444 | + |
445 | +- public unowned string get_pluggable_name() { |
446 | ++ public override unowned string get_pluggable_name() { |
447 | + return "Facebook"; |
448 | + } |
449 | + |
450 | +- public void get_info(ref Spit.PluggableInfo info) { |
451 | ++ public override void get_info(ref Spit.PluggableInfo info) { |
452 | + info.authors = "Lucas Beeler"; |
453 | + info.copyright = _("Copyright 2009-2012 Yorba Foundation"); |
454 | + info.translators = Resources.TRANSLATORS; |
455 | +@@ -39,14 +37,12 @@ public class FacebookService : Object, Spit.Pluggable, Spit.Publishing.Service { |
456 | + info.icons = icon_pixbuf_set; |
457 | + } |
458 | + |
459 | +- public void activation(bool enabled) { |
460 | ++ public override Spit.Publishing.Publisher create_publisher(string? account_name, Spit.Publishing.PluginHost host) { |
461 | ++ SharingAccount account = find_account(account_name); |
462 | ++ return new Publishing.Facebook.FacebookPublisher(this, account, host); |
463 | + } |
464 | + |
465 | +- public Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host) { |
466 | +- return new Publishing.Facebook.FacebookPublisher(this, host); |
467 | +- } |
468 | +- |
469 | +- public Spit.Publishing.Publisher.MediaType get_supported_media() { |
470 | ++ public override Spit.Publishing.Publisher.MediaType get_supported_media() { |
471 | return (Spit.Publishing.Publisher.MediaType.PHOTO | |
472 | Spit.Publishing.Publisher.MediaType.VIDEO); |
473 | } |
474 | -+ |
475 | -+ public bool is_enabled() { |
476 | -+ SharingAccounts accounts = new SharingAccounts(); |
477 | -+ return accounts.get_account_for_provider("facebook") != null; |
478 | -+ } |
479 | - } |
480 | - |
481 | - namespace Publishing.Facebook { |
482 | -@@ -163,11 +170,11 @@ |
483 | +@@ -66,8 +62,6 @@ internal const string PHOTO_ENDPOINT_URL = "https://api.facebook.com/restserver. |
484 | + internal const string VIDEO_ENDPOINT_URL = "https://api-video.facebook.com/restserver.php"; |
485 | + internal const string SERVICE_WELCOME_MESSAGE = |
486 | + _("You are not currently logged into Facebook.\n\nIf you don't yet have a Facebook account, you can create one during the login process. During login, Shotwell Connect may ask you for permission to upload photos and publish to your feed. These permissions are required for Shotwell Connect to function."); |
487 | +-internal const string RESTART_ERROR_MESSAGE = |
488 | +- _("You have already logged in and out of Facebook during this Shotwell session.\nTo continue publishing to Facebook, quit and restart Shotwell, then try publishing again."); |
489 | + // as of mid-November 2010, the privacy the simple string "SELF" is no longer a valid |
490 | + // privacy value; "SELF" must be simulated by a "CUSTOM" setting; see the discussion |
491 | + // http://forum.developers.facebook.net/viewtopic.php?pid=289287 |
492 | +@@ -163,19 +157,23 @@ public class FacebookPublisher : Spit.Publishing.Publisher, GLib.Object { |
493 | private int publish_to_album = NO_ALBUM; |
494 | private weak Spit.Publishing.PluginHost host = null; |
495 | private FacebookRESTSession session = null; |
496 | @@ -198,51 +427,153 @@ |
497 | private weak Spit.Publishing.Service service = null; |
498 | private bool strip_metadata = false; |
499 | private bool running = false; |
500 | -+ private Signon.AuthSession auth_session = null; |
501 | ++ private UOAPublisherAuthenticator authenticator = null; |
502 | |
503 | private Resolution target_resolution = Resolution.HIGH; |
504 | |
505 | -@@ -402,37 +409,56 @@ |
506 | + public FacebookPublisher(Spit.Publishing.Service service, |
507 | ++ SharingAccount account, |
508 | + Spit.Publishing.PluginHost host) { |
509 | + debug("FacebookPublisher instantiated."); |
510 | + this.service = service; |
511 | + this.host = host; |
512 | ++ authenticator = new UOAPublisherAuthenticator(account, host, |
513 | ++ SERVICE_WELCOME_MESSAGE); |
514 | ++ authenticator.authenticated.connect(on_authenticator_authenticated); |
515 | + } |
516 | + |
517 | + private bool is_running() { |
518 | +@@ -190,49 +188,10 @@ public class FacebookPublisher : Spit.Publishing.Publisher, GLib.Object { |
519 | + return NO_ALBUM; |
520 | + } |
521 | + |
522 | +- private bool is_persistent_session_valid() { |
523 | +- string? access_token = get_persistent_access_token(); |
524 | +- string? uid = get_persistent_uid(); |
525 | +- string? user_name = get_persistent_user_name(); |
526 | +- |
527 | +- bool valid = ((access_token != null) && (uid != null) && (user_name != null)); |
528 | +- |
529 | +- if (valid) |
530 | +- debug("existing Facebook session for user = '%s' found in configuration database; using it.", user_name); |
531 | +- else |
532 | +- debug("no persisted Facebook session exists."); |
533 | +- |
534 | +- return valid; |
535 | +- } |
536 | +- |
537 | +- private string? get_persistent_access_token() { |
538 | +- return host.get_config_string("access_token", null); |
539 | +- } |
540 | +- |
541 | +- private string? get_persistent_uid() { |
542 | +- return host.get_config_string("uid", null); |
543 | +- } |
544 | +- |
545 | +- private string? get_persistent_user_name() { |
546 | +- return host.get_config_string("user_name", null); |
547 | +- } |
548 | +- |
549 | + private bool get_persistent_strip_metadata() { |
550 | + return host.get_config_bool("strip_metadata", false); |
551 | + } |
552 | + |
553 | +- private void set_persistent_access_token(string access_token) { |
554 | +- host.set_config_string("access_token", access_token); |
555 | +- } |
556 | +- |
557 | +- private void set_persistent_uid(string uid) { |
558 | +- host.set_config_string("uid", uid); |
559 | +- } |
560 | +- |
561 | +- private void set_persistent_user_name(string user_name) { |
562 | +- host.set_config_string("user_name", user_name); |
563 | +- } |
564 | +- |
565 | + private void set_persistent_strip_metadata(bool strip_metadata) { |
566 | + host.set_config_bool("strip_metadata", strip_metadata); |
567 | + } |
568 | +@@ -247,39 +206,6 @@ public class FacebookPublisher : Spit.Publishing.Publisher, GLib.Object { |
569 | + host.set_config_int("default_size", size); |
570 | + } |
571 | + |
572 | +- private void invalidate_persistent_session() { |
573 | +- debug("invalidating persisted Facebook session."); |
574 | +- |
575 | +- set_persistent_access_token(""); |
576 | +- set_persistent_uid(""); |
577 | +- set_persistent_user_name(""); |
578 | +- } |
579 | +- |
580 | +- private void do_show_service_welcome_pane() { |
581 | +- debug("ACTION: showing service welcome pane."); |
582 | +- |
583 | +- host.install_welcome_pane(SERVICE_WELCOME_MESSAGE, on_login_clicked); |
584 | +- host.set_service_locked(false); |
585 | +- } |
586 | +- |
587 | +- private void do_test_connection_to_endpoint() { |
588 | +- debug("ACTION: testing connection to Facebook endpoint."); |
589 | +- host.set_service_locked(true); |
590 | +- |
591 | +- host.install_static_message_pane(_("Testing connection to Facebook...")); |
592 | +- |
593 | +- FacebookEndpointTestTransaction txn = new FacebookEndpointTestTransaction(session); |
594 | +- txn.completed.connect(on_endpoint_test_completed); |
595 | +- txn.network_error.connect(on_endpoint_test_error); |
596 | +- |
597 | +- try { |
598 | +- txn.execute(); |
599 | +- } catch (Spit.Publishing.PublishingError err) { |
600 | +- if (is_running()) |
601 | +- host.post_error(err); |
602 | +- } |
603 | +- } |
604 | +- |
605 | + private void do_fetch_album_descriptions() { |
606 | + debug("ACTION: fetching album descriptions from remote endpoint."); |
607 | + |
608 | +@@ -387,7 +313,6 @@ public class FacebookPublisher : Spit.Publishing.Publisher, GLib.Object { |
609 | + PublishingOptionsPane publishing_options_pane = new PublishingOptionsPane( |
610 | + session.get_user_name(), albums, host.get_publishable_media_type(), this, builder, |
611 | + get_persistent_strip_metadata()); |
612 | +- publishing_options_pane.logout.connect(on_publishing_options_pane_logout); |
613 | + publishing_options_pane.publish.connect(on_publishing_options_pane_publish); |
614 | + host.install_dialog_pane(publishing_options_pane, |
615 | + Spit.Publishing.PluginHost.ButtonMode.CANCEL); |
616 | +@@ -396,51 +321,20 @@ public class FacebookPublisher : Spit.Publishing.Publisher, GLib.Object { |
617 | + private void do_logout() { |
618 | + debug("ACTION: clearing persistent session information and restaring interaction."); |
619 | + |
620 | +- invalidate_persistent_session(); |
621 | +- |
622 | + running = false; |
623 | start(); |
624 | } |
625 | |
626 | - private void do_hosted_web_authentication() { |
627 | - debug("ACTION: doing hosted web authentication."); |
628 | -+ public void on_processed(Signon.AuthSession self, owned HashTable<string,Value?> session_data, GLib.Error error){ |
629 | -+ /* TODO: handle errors */ |
630 | - |
631 | +- |
632 | - host.set_service_locked(false); |
633 | -+ host.set_service_locked(true); |
634 | -+ host.install_account_fetch_wait_pane(); |
635 | - |
636 | +- |
637 | - web_auth_pane = new WebAuthenticationPane(); |
638 | - web_auth_pane.login_succeeded.connect(on_web_auth_pane_login_succeeded); |
639 | - web_auth_pane.login_failed.connect(on_web_auth_pane_login_failed); |
640 | -+ session.authenticated.connect(on_session_authenticated); |
641 | -+ session.authentication_failed.connect(on_session_authentication_failed); |
642 | - |
643 | +- |
644 | - host.install_dialog_pane(web_auth_pane, |
645 | - Spit.Publishing.PluginHost.ButtonMode.CANCEL); |
646 | -+ string token = session_data.lookup("AccessToken").get_string(); |
647 | -+ debug("Access Token: %s", token); |
648 | -+ session.authenticate_with_parameters(token, null, null); |
649 | - } |
650 | - |
651 | +- } |
652 | +- |
653 | - private void do_authenticate_session(string success_url) { |
654 | - debug("ACTION: preparing to extract session information encoded in url = '%s'", |
655 | - success_url); |
656 | -+ private void do_hosted_web_authentication() { |
657 | -+ debug("ACTION: doing hosted web authentication."); |
658 | - |
659 | -- host.set_service_locked(true); |
660 | -- host.install_account_fetch_wait_pane(); |
661 | -+ HashTable<string,Value?> data = null; |
662 | -+ string mechanism = "user_agent"; |
663 | - |
664 | -- session.authenticated.connect(on_session_authenticated); |
665 | -- session.authentication_failed.connect(on_session_authentication_failed); |
666 | -+ SharingAccounts accounts = |
667 | -+ new SharingAccounts(); |
668 | +- |
669 | ++ public void on_authenticator_authenticated(owned HashTable<string,Value?> session_data) { |
670 | + host.set_service_locked(true); |
671 | + host.install_account_fetch_wait_pane(); |
672 | + |
673 | + session.authenticated.connect(on_session_authenticated); |
674 | + session.authentication_failed.connect(on_session_authentication_failed); |
675 | |
676 | - try { |
677 | - session.authenticate_from_uri(success_url); |
678 | @@ -251,40 +582,59 @@ |
679 | - // another error has already posted and caused us to stop |
680 | - if (is_running()) |
681 | - host.post_error(err); |
682 | -+ SharingAccount? account = accounts.get_account_for_provider("facebook"); |
683 | -+ if (account != null) { |
684 | -+ try { |
685 | -+ auth_session = account.create_auth_session(); |
686 | -+ data = account.get_session_parameters(out mechanism); |
687 | -+ debug("Got account data"); |
688 | -+ } catch (GLib.Error e) { |
689 | -+ warning("EVENT: couldn't create session for account: %s", |
690 | -+ e.message); |
691 | -+ return; |
692 | -+ } |
693 | - } |
694 | -+ |
695 | -+ if (data == null) { |
696 | -+ warning ("No account authentication data"); |
697 | -+ host.post_error(new Spit.Publishing.PublishingError.SERVICE_ERROR( |
698 | -+ "Error while accessing the account")); |
699 | -+ return; |
700 | -+ } |
701 | -+ |
702 | -+ var windowId = host.get_dialog_xid(); |
703 | -+ if (windowId != 0) { |
704 | -+ data.insert("WindowId", (uint)windowId); |
705 | -+ } |
706 | -+ |
707 | -+ auth_session.process(data, mechanism, on_processed); |
708 | -+ host.set_service_locked(false); |
709 | - } |
710 | - |
711 | - private void do_save_session_information() { |
712 | -@@ -562,30 +588,6 @@ |
713 | - host.post_error(err); |
714 | - } |
715 | - |
716 | +- } |
717 | +- } |
718 | +- |
719 | +- private void do_save_session_information() { |
720 | +- debug("ACTION: saving session information to configuration system."); |
721 | +- |
722 | +- set_persistent_access_token(session.get_access_token()); |
723 | +- set_persistent_uid(session.get_user_id()); |
724 | +- set_persistent_user_name(session.get_user_name()); |
725 | ++ string token = session_data.lookup("AccessToken").get_string(); |
726 | ++ debug("Access Token: %s", token); |
727 | ++ session.authenticate_with_parameters(token, null, null); |
728 | + } |
729 | + |
730 | + private void do_upload(bool strip_metadata) { |
731 | +@@ -528,64 +422,6 @@ public class FacebookPublisher : Spit.Publishing.Publisher, GLib.Object { |
732 | + host.install_success_pane(); |
733 | + } |
734 | + |
735 | +- private void on_login_clicked() { |
736 | +- if (!is_running()) |
737 | +- return; |
738 | +- |
739 | +- debug("EVENT: user clicked 'Login' on welcome pane."); |
740 | +- |
741 | +- do_test_connection_to_endpoint(); |
742 | +- } |
743 | +- |
744 | +- private void on_endpoint_test_completed(FacebookRESTTransaction txn) { |
745 | +- txn.completed.disconnect(on_endpoint_test_completed); |
746 | +- txn.network_error.disconnect(on_endpoint_test_error); |
747 | +- |
748 | +- if (!is_running()) |
749 | +- return; |
750 | +- |
751 | +- debug("EVENT: endpoint test transaction detected that the Facebook endpoint is alive."); |
752 | +- |
753 | +- do_hosted_web_authentication(); |
754 | +- } |
755 | +- |
756 | +- private void on_endpoint_test_error(FacebookRESTTransaction bad_txn, |
757 | +- Spit.Publishing.PublishingError err) { |
758 | +- bad_txn.completed.disconnect(on_endpoint_test_completed); |
759 | +- bad_txn.network_error.disconnect(on_endpoint_test_error); |
760 | +- |
761 | +- if (!is_running()) |
762 | +- return; |
763 | +- |
764 | +- debug("EVENT: endpoint test transaction failed to detect a connection to the Facebook endpoint"); |
765 | +- |
766 | +- host.post_error(err); |
767 | +- } |
768 | +- |
769 | - private void on_web_auth_pane_login_succeeded(string success_url) { |
770 | - if (!is_running()) |
771 | - return; |
772 | @@ -312,10 +662,45 @@ |
773 | private void on_session_authenticated() { |
774 | if (!is_running()) |
775 | return; |
776 | -@@ -773,14 +775,8 @@ |
777 | - get_persistent_uid(), get_persistent_user_name()); |
778 | - on_session_authenticated(); |
779 | - } else { |
780 | +@@ -593,7 +429,6 @@ public class FacebookPublisher : Spit.Publishing.Publisher, GLib.Object { |
781 | + assert(session.is_authenticated()); |
782 | + debug("EVENT: an authenticated session has become available."); |
783 | + |
784 | +- do_save_session_information(); |
785 | + do_fetch_album_descriptions(); |
786 | + } |
787 | + |
788 | +@@ -638,15 +473,6 @@ public class FacebookPublisher : Spit.Publishing.Publisher, GLib.Object { |
789 | + do_show_publishing_options_pane(); |
790 | + } |
791 | + |
792 | +- public void on_publishing_options_pane_logout() { |
793 | +- if (!is_running()) |
794 | +- return; |
795 | +- |
796 | +- debug("EVENT: user clicked 'Logout' in publishing options pane."); |
797 | +- |
798 | +- do_logout(); |
799 | +- } |
800 | +- |
801 | + public void on_publishing_options_pane_publish(string? target_album, string privacy_setting, |
802 | + Resolution target_resolution, bool strip_metadata) { |
803 | + if (!is_running()) |
804 | +@@ -762,26 +588,8 @@ public class FacebookPublisher : Spit.Publishing.Publisher, GLib.Object { |
805 | + albums = null; |
806 | + publish_to_album = NO_ALBUM; |
807 | + |
808 | +- // determine whether a user is logged in; if so, then show the publishing options pane |
809 | +- // for that user; otherwise, show the welcome pane |
810 | +- if (is_persistent_session_valid()) { |
811 | +- // if valid session information has been saved in the configuration system, build |
812 | +- // a Session object and pre-authenticate it with the saved information, then simulate an |
813 | +- // on_session_authenticated event to drive the rest of the interaction |
814 | +- session = new FacebookRESTSession(PHOTO_ENDPOINT_URL, USER_AGENT); |
815 | +- session.authenticate_with_parameters(get_persistent_access_token(), |
816 | +- get_persistent_uid(), get_persistent_user_name()); |
817 | +- on_session_authenticated(); |
818 | +- } else { |
819 | - if (WebAuthenticationPane.is_cache_dirty()) { |
820 | - host.set_service_locked(false); |
821 | - host.install_static_message_pane(RESTART_ERROR_MESSAGE, |
822 | @@ -324,12 +709,13 @@ |
823 | - session = new FacebookRESTSession(PHOTO_ENDPOINT_URL, USER_AGENT); |
824 | - do_show_service_welcome_pane(); |
825 | - } |
826 | -+ session = new FacebookRESTSession(PHOTO_ENDPOINT_URL, USER_AGENT); |
827 | -+ do_show_service_welcome_pane(); |
828 | - } |
829 | +- } |
830 | ++ session = new FacebookRESTSession(PHOTO_ENDPOINT_URL, USER_AGENT); |
831 | ++ authenticator.authenticate(); |
832 | } |
833 | |
834 | -@@ -909,39 +905,14 @@ |
835 | + public void stop() { |
836 | +@@ -909,39 +717,14 @@ internal class FacebookRESTSession { |
837 | return (access_token != null && uid != null && user_name != null); |
838 | } |
839 | |
840 | @@ -376,7 +762,7 @@ |
841 | } |
842 | |
843 | public string get_endpoint_url() { |
844 | -@@ -1335,190 +1306,6 @@ |
845 | +@@ -1335,190 +1118,6 @@ internal class FacebookCreateAlbumTransaction : FacebookRESTTransaction { |
846 | } |
847 | } |
848 | |
849 | @@ -567,11 +953,80 @@ |
850 | internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
851 | private Gtk.Builder builder; |
852 | private Gtk.Box pane_widget = null; |
853 | -Index: shotwell-0.13.0/plugins/shotwell-publishing/FlickrPublishing.vala |
854 | -=================================================================== |
855 | ---- shotwell-0.13.0.orig/plugins/shotwell-publishing/FlickrPublishing.vala 2012-09-20 07:08:59.000000000 +1200 |
856 | -+++ shotwell-0.13.0/plugins/shotwell-publishing/FlickrPublishing.vala 2012-09-20 15:16:00.933921786 +1200 |
857 | -@@ -4,6 +4,8 @@ |
858 | +@@ -1529,7 +1128,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
859 | + private Gtk.Entry new_album_entry = null; |
860 | + private Gtk.CheckButton strip_metadata_check = null; |
861 | + private Gtk.Button publish_button = null; |
862 | +- private Gtk.Button logout_button = null; |
863 | + private Gtk.Label how_to_label = null; |
864 | + private FacebookAlbum[] albums = null; |
865 | + private FacebookPublisher publisher = null; |
866 | +@@ -1546,7 +1144,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
867 | + private const int CONTENT_GROUP_SPACING = 32; |
868 | + private const int STANDARD_ACTION_BUTTON_WIDTH = 128; |
869 | + |
870 | +- public signal void logout(); |
871 | + public signal void publish(string? target_album, string privacy_setting, Resolution target_resolution, bool strip_metadata); |
872 | + |
873 | + private class PrivacyDescription { |
874 | +@@ -1586,7 +1183,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
875 | + existing_albums_combo = (Gtk.ComboBoxText) this.builder.get_object("existing_albums_combo"); |
876 | + visibility_combo = (Gtk.ComboBoxText) this.builder.get_object("visibility_combo"); |
877 | + publish_button = (Gtk.Button) this.builder.get_object("publish_button"); |
878 | +- logout_button = (Gtk.Button) this.builder.get_object("logout_button"); |
879 | + new_album_entry = (Gtk.Entry) this.builder.get_object("new_album_entry"); |
880 | + resolution_combo = (Gtk.ComboBoxText) this.builder.get_object("resolution_combo"); |
881 | + how_to_label = (Gtk.Label) this.builder.get_object("how_to_label"); |
882 | +@@ -1605,7 +1201,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
883 | + visibility_combo.set_active(0); |
884 | + |
885 | + publish_button.clicked.connect(on_publish_button_clicked); |
886 | +- logout_button.clicked.connect(on_logout_button_clicked); |
887 | + |
888 | + // Ticket #2916 - if the user is uploading photographs, allow |
889 | + // them to choose what resolution they should be uploaded at. |
890 | +@@ -1669,10 +1264,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
891 | + publisher.set_persistent_default_size(resolution_combo.get_active()); |
892 | + } |
893 | + |
894 | +- private void on_logout_button_clicked() { |
895 | +- logout(); |
896 | +- } |
897 | +- |
898 | + private void on_publish_button_clicked() { |
899 | + string album_name; |
900 | + string privacy_setting = privacy_descriptions[visibility_combo.get_active()].privacy_setting; |
901 | +@@ -1747,10 +1338,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
902 | + publish_button.grab_focus(); |
903 | + } |
904 | + |
905 | +- private void notify_logout() { |
906 | +- logout(); |
907 | +- } |
908 | +- |
909 | + private void notify_publish(string? target_album, string privacy_setting, Resolution target_resolution) { |
910 | + publish(target_album, privacy_setting, target_resolution, strip_metadata_check.get_active()); |
911 | + } |
912 | +@@ -1764,14 +1351,12 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
913 | + } |
914 | + |
915 | + public void on_pane_installed() { |
916 | +- logout.connect(notify_logout); |
917 | + publish.connect(notify_publish); |
918 | + |
919 | + installed(); |
920 | + } |
921 | + |
922 | + public void on_pane_uninstalled() { |
923 | +- logout.disconnect(notify_logout); |
924 | + publish.disconnect(notify_publish); |
925 | + } |
926 | + } |
927 | +diff --git a/plugins/shotwell-publishing/FlickrPublishing.vala b/plugins/shotwell-publishing/FlickrPublishing.vala |
928 | +index a6f8b45..abaf0b2 100644 |
929 | +--- a/plugins/shotwell-publishing/FlickrPublishing.vala |
930 | ++++ b/plugins/shotwell-publishing/FlickrPublishing.vala |
931 | +@@ -4,32 +4,30 @@ |
932 | * (version 2.1 or later). See the COPYING file in this distribution. |
933 | */ |
934 | |
935 | @@ -579,31 +1034,137 @@ |
936 | + |
937 | extern string hmac_sha1(string key, string message); |
938 | |
939 | - public class FlickrService : Object, Spit.Pluggable, Spit.Publishing.Service { |
940 | -@@ -52,6 +54,11 @@ |
941 | +-public class FlickrService : Object, Spit.Pluggable, Spit.Publishing.Service { |
942 | ++public class FlickrService : UOAPublishingService, Spit.Pluggable, Spit.Publishing.Service { |
943 | + private const string ICON_FILENAME = "flickr.png"; |
944 | + |
945 | + private static Gdk.Pixbuf[] icon_pixbuf_set = null; |
946 | + |
947 | + public FlickrService(GLib.File resource_directory) { |
948 | ++ base("flickr"); |
949 | + if (icon_pixbuf_set == null) |
950 | + icon_pixbuf_set = Resources.load_icon_set(resource_directory.get_child(ICON_FILENAME)); |
951 | + } |
952 | + |
953 | +- public int get_pluggable_interface(int min_host_interface, int max_host_interface) { |
954 | +- return Spit.negotiate_interfaces(min_host_interface, max_host_interface, |
955 | +- Spit.Publishing.CURRENT_INTERFACE); |
956 | +- } |
957 | +- |
958 | +- public unowned string get_id() { |
959 | ++ public override unowned string get_id() { |
960 | + return "org.yorba.shotwell.publishing.flickr"; |
961 | + } |
962 | + |
963 | +- public unowned string get_pluggable_name() { |
964 | ++ public override unowned string get_pluggable_name() { |
965 | + return "Flickr"; |
966 | + } |
967 | + |
968 | +- public void get_info(ref Spit.PluggableInfo info) { |
969 | ++ public override void get_info(ref Spit.PluggableInfo info) { |
970 | + info.authors = "Lucas Beeler"; |
971 | + info.copyright = _("Copyright 2009-2012 Yorba Foundation"); |
972 | + info.translators = Resources.TRANSLATORS; |
973 | +@@ -41,14 +39,12 @@ public class FlickrService : Object, Spit.Pluggable, Spit.Publishing.Service { |
974 | + info.icons = icon_pixbuf_set; |
975 | + } |
976 | + |
977 | +- public void activation(bool enabled) { |
978 | +- } |
979 | +- |
980 | +- public Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host) { |
981 | +- return new Publishing.Flickr.FlickrPublisher(this, host); |
982 | ++ public override Spit.Publishing.Publisher create_publisher(string? account_name, Spit.Publishing.PluginHost host) { |
983 | ++ SharingAccount account = find_account(account_name); |
984 | ++ return new Publishing.Flickr.FlickrPublisher(this, account, host); |
985 | + } |
986 | + |
987 | +- public Spit.Publishing.Publisher.MediaType get_supported_media() { |
988 | ++ public override Spit.Publishing.Publisher.MediaType get_supported_media() { |
989 | return (Spit.Publishing.Publisher.MediaType.PHOTO | |
990 | Spit.Publishing.Publisher.MediaType.VIDEO); |
991 | } |
992 | -+ |
993 | -+ public bool is_enabled() { |
994 | -+ SharingAccounts accounts = new SharingAccounts(); |
995 | -+ return accounts.get_account_for_provider("flickr") != null; |
996 | -+ } |
997 | - } |
998 | - |
999 | - namespace Publishing.Flickr { |
1000 | -@@ -105,6 +112,7 @@ |
1001 | +@@ -105,60 +101,33 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object { |
1002 | private bool was_started = false; |
1003 | private Session session = null; |
1004 | private PublishingOptionsPane publishing_options_pane = null; |
1005 | -+ private Signon.AuthSession auth_session = null; |
1006 | ++ private UOAPublisherAuthenticator authenticator = null; |
1007 | |
1008 | private PublishingParameters parameters = null; |
1009 | |
1010 | -@@ -173,88 +181,54 @@ |
1011 | - |
1012 | - debug("EVENT: user clicked 'Login' button in the welcome pane"); |
1013 | + public FlickrPublisher(Spit.Publishing.Service service, |
1014 | ++ SharingAccount account, |
1015 | + Spit.Publishing.PluginHost host) { |
1016 | + debug("FlickrPublisher instantiated."); |
1017 | + this.service = service; |
1018 | + this.host = host; |
1019 | + this.session = new Session(); |
1020 | ++ authenticator = new UOAPublisherAuthenticator(account, host, |
1021 | ++ SERVICE_WELCOME_MESSAGE); |
1022 | + this.parameters = new PublishingParameters(); |
1023 | |
1024 | + session.authenticated.connect(on_session_authenticated); |
1025 | ++ HashTable<string,Value?> data = |
1026 | ++ authenticator.get_authentication_data(); |
1027 | ++ session.set_api_credentials(data.lookup("ConsumerKey").get_string(), |
1028 | ++ data.lookup("ConsumerSecret").get_string()); |
1029 | ++ authenticator.authenticated.connect(on_authenticator_authenticated); |
1030 | + } |
1031 | + |
1032 | + ~FlickrPublisher() { |
1033 | + session.authenticated.disconnect(on_session_authenticated); |
1034 | + } |
1035 | + |
1036 | +- private void invalidate_persistent_session() { |
1037 | +- set_persistent_access_phase_token(""); |
1038 | +- set_persistent_access_phase_token_secret(""); |
1039 | +- set_persistent_access_phase_username(""); |
1040 | +- } |
1041 | +- |
1042 | +- private bool is_persistent_session_valid() { |
1043 | +- return (get_persistent_access_phase_username() != null && |
1044 | +- get_persistent_access_phase_token() != null && |
1045 | +- get_persistent_access_phase_token_secret() != null); |
1046 | +- } |
1047 | +- |
1048 | +- private string? get_persistent_access_phase_username() { |
1049 | +- return host.get_config_string("access_phase_username", null); |
1050 | +- } |
1051 | +- |
1052 | +- private void set_persistent_access_phase_username(string username) { |
1053 | +- host.set_config_string("access_phase_username", username); |
1054 | +- } |
1055 | +- |
1056 | +- private string? get_persistent_access_phase_token() { |
1057 | +- return host.get_config_string("access_phase_token", null); |
1058 | +- } |
1059 | +- |
1060 | +- private void set_persistent_access_phase_token(string token) { |
1061 | +- host.set_config_string("access_phase_token", token); |
1062 | +- } |
1063 | +- |
1064 | +- private string? get_persistent_access_phase_token_secret() { |
1065 | +- return host.get_config_string("access_phase_token_secret", null); |
1066 | +- } |
1067 | +- |
1068 | +- private void set_persistent_access_phase_token_secret(string secret) { |
1069 | +- host.set_config_string("access_phase_token_secret", secret); |
1070 | +- } |
1071 | +- |
1072 | + private bool get_persistent_strip_metadata() { |
1073 | + return host.get_config_bool("strip_metadata", false); |
1074 | + } |
1075 | +@@ -167,94 +136,17 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object { |
1076 | + host.set_config_bool("strip_metadata", strip_metadata); |
1077 | + } |
1078 | + |
1079 | +- private void on_welcome_pane_login_clicked() { |
1080 | +- if (!running) |
1081 | +- return; |
1082 | +- |
1083 | +- debug("EVENT: user clicked 'Login' button in the welcome pane"); |
1084 | +- |
1085 | - do_run_authentication_request_transaction(); |
1086 | - } |
1087 | - |
1088 | @@ -624,30 +1185,10 @@ |
1089 | - Spit.Publishing.PublishingError err) { |
1090 | - txn.completed.disconnect(on_auth_request_txn_completed); |
1091 | - txn.network_error.disconnect(on_auth_request_txn_error); |
1092 | -+ HashTable<string,Value?> data = null; |
1093 | -+ string mechanism = null; |
1094 | -+ SharingAccounts accounts = new SharingAccounts(); |
1095 | -+ |
1096 | -+ SharingAccount? account = accounts.get_account_for_provider("flickr"); |
1097 | -+ if (account != null) { |
1098 | -+ try { |
1099 | -+ auth_session = account.create_auth_session(); |
1100 | -+ data = account.get_session_parameters(out mechanism); |
1101 | -+ debug("Got account data"); |
1102 | -+ } catch (GLib.Error e) { |
1103 | -+ warning("EVENT: couldn't create session for account: %s", |
1104 | -+ e.message); |
1105 | -+ } |
1106 | -+ } |
1107 | - |
1108 | +- |
1109 | - if (!is_running()) |
1110 | -+ if (data == null) { |
1111 | -+ warning ("No account authentication data"); |
1112 | -+ host.post_error(new Spit.Publishing.PublishingError.SERVICE_ERROR( |
1113 | -+ "Error while accessing the account")); |
1114 | - return; |
1115 | -+ } |
1116 | - |
1117 | +- return; |
1118 | +- |
1119 | - debug("EVENT: OAuth authentication request transaction caused a network error"); |
1120 | - host.post_error(err); |
1121 | - } |
1122 | @@ -655,24 +1196,16 @@ |
1123 | - private void on_authentication_token_available(string token, string token_secret) { |
1124 | - debug("EVENT: OAuth authentication token (%s) and token secret (%s) available", |
1125 | - token, token_secret); |
1126 | -+ session.set_api_credentials(data.lookup("ConsumerKey").get_string(), |
1127 | -+ data.lookup("ConsumerSecret").get_string()); |
1128 | - |
1129 | +- |
1130 | - session.set_request_phase_credentials(token, token_secret); |
1131 | -+ var windowId = host.get_dialog_xid(); |
1132 | -+ if (windowId != 0) { |
1133 | -+ data.insert("WindowId", (uint)windowId); |
1134 | -+ } |
1135 | - |
1136 | +- |
1137 | - do_launch_system_browser(token); |
1138 | -+ auth_session.process(data, mechanism, on_processed); |
1139 | -+ host.set_service_locked(false); |
1140 | - } |
1141 | +- } |
1142 | - |
1143 | - private void on_system_browser_launched() { |
1144 | - if (!is_running()) |
1145 | - return; |
1146 | - |
1147 | +- |
1148 | - debug("EVENT: system browser launched."); |
1149 | - |
1150 | - do_show_pin_entry_pane(); |
1151 | @@ -683,13 +1216,12 @@ |
1152 | - |
1153 | - if (!is_running()) |
1154 | - return; |
1155 | -+ public void on_processed(Signon.AuthSession self, owned HashTable<string,Value?> session_data, GLib.Error error){ |
1156 | -+ /* TODO: handle errors */ |
1157 | - |
1158 | +- |
1159 | - debug("EVENT: user clicked 'Continue' in PIN entry pane."); |
1160 | - |
1161 | - do_verify_pin(pin); |
1162 | - } |
1163 | ++ public void on_authenticator_authenticated(owned HashTable<string,Value?> session_data) { |
1164 | + host.set_service_locked(true); |
1165 | + host.install_account_fetch_wait_pane(); |
1166 | |
1167 | @@ -726,10 +1258,55 @@ |
1168 | private void on_session_authenticated() { |
1169 | if (!is_running()) |
1170 | return; |
1171 | -@@ -368,141 +342,6 @@ |
1172 | - host.install_welcome_pane(SERVICE_WELCOME_MESSAGE, on_welcome_pane_login_clicked); |
1173 | - } |
1174 | - |
1175 | +@@ -263,10 +155,6 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object { |
1176 | + |
1177 | + parameters.username = session.get_username(); |
1178 | + |
1179 | +- set_persistent_access_phase_token(session.get_access_phase_token()); |
1180 | +- set_persistent_access_phase_token_secret(session.get_access_phase_token_secret()); |
1181 | +- set_persistent_access_phase_username(session.get_username()); |
1182 | +- |
1183 | + do_fetch_account_info(); |
1184 | + } |
1185 | + |
1186 | +@@ -303,7 +191,6 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object { |
1187 | + |
1188 | + private void on_publishing_options_pane_publish(bool strip_metadata) { |
1189 | + publishing_options_pane.publish.disconnect(on_publishing_options_pane_publish); |
1190 | +- publishing_options_pane.logout.disconnect(on_publishing_options_pane_logout); |
1191 | + |
1192 | + if (!is_running()) |
1193 | + return; |
1194 | +@@ -312,18 +199,6 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object { |
1195 | + do_publish(strip_metadata); |
1196 | + } |
1197 | + |
1198 | +- private void on_publishing_options_pane_logout() { |
1199 | +- publishing_options_pane.publish.disconnect(on_publishing_options_pane_publish); |
1200 | +- publishing_options_pane.logout.disconnect(on_publishing_options_pane_logout); |
1201 | +- |
1202 | +- if (!is_running()) |
1203 | +- return; |
1204 | +- |
1205 | +- debug("EVENT: user clicked the 'Logout' button in the publishing options pane"); |
1206 | +- |
1207 | +- do_logout(); |
1208 | +- } |
1209 | +- |
1210 | + private void on_upload_status_updated(int file_number, double completed_fraction) { |
1211 | + if (!is_running()) |
1212 | + return; |
1213 | +@@ -361,148 +236,6 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object { |
1214 | + host.post_error(err); |
1215 | + } |
1216 | + |
1217 | +- private void do_show_login_welcome_pane() { |
1218 | +- debug("ACTION: installing login welcome pane"); |
1219 | +- |
1220 | +- host.set_service_locked(false); |
1221 | +- host.install_welcome_pane(SERVICE_WELCOME_MESSAGE, on_welcome_pane_login_clicked); |
1222 | +- } |
1223 | +- |
1224 | - private void do_run_authentication_request_transaction() { |
1225 | - debug("ACTION: running authentication request transaction"); |
1226 | - |
1227 | @@ -868,7 +1445,41 @@ |
1228 | private void do_fetch_account_info() { |
1229 | debug("ACTION: running network transaction to fetch account information"); |
1230 | |
1231 | -@@ -772,7 +611,7 @@ |
1232 | +@@ -568,7 +301,6 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object { |
1233 | + debug("ACTION: logging user out, deauthenticating session, and erasing stored credentials"); |
1234 | + |
1235 | + session.deauthenticate(); |
1236 | +- invalidate_persistent_session(); |
1237 | + |
1238 | + running = false; |
1239 | + |
1240 | +@@ -599,7 +331,6 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object { |
1241 | + publishing_options_pane = new PublishingOptionsPane(this, parameters, |
1242 | + host.get_publishable_media_type(), builder, get_persistent_strip_metadata()); |
1243 | + publishing_options_pane.publish.connect(on_publishing_options_pane_publish); |
1244 | +- publishing_options_pane.logout.connect(on_publishing_options_pane_logout); |
1245 | + host.install_dialog_pane(publishing_options_pane); |
1246 | + } |
1247 | + |
1248 | +@@ -674,16 +405,7 @@ public class FlickrPublisher : Spit.Publishing.Publisher, GLib.Object { |
1249 | + running = true; |
1250 | + was_started = true; |
1251 | + |
1252 | +- if (is_persistent_session_valid()) { |
1253 | +- debug("attempt start: a persistent session is available; using it"); |
1254 | +- |
1255 | +- session.authenticate_from_persistent_credentials(get_persistent_access_phase_token(), |
1256 | +- get_persistent_access_phase_token_secret(), get_persistent_access_phase_username()); |
1257 | +- } else { |
1258 | +- debug("attempt start: no persistent session available; showing login welcome pane"); |
1259 | +- |
1260 | +- do_show_login_welcome_pane(); |
1261 | +- } |
1262 | ++ authenticator.authenticate(); |
1263 | + } |
1264 | + |
1265 | + public void start() { |
1266 | +@@ -772,7 +494,7 @@ internal class Transaction : Publishing.RESTSupport.Transaction { |
1267 | add_argument("oauth_version", "1.0"); |
1268 | add_argument("oauth_callback", "oob"); |
1269 | add_argument("oauth_timestamp", session.get_oauth_timestamp()); |
1270 | @@ -877,7 +1488,7 @@ |
1271 | } |
1272 | |
1273 | public Transaction.with_uri(Session session, string uri, |
1274 | -@@ -784,7 +623,7 @@ |
1275 | +@@ -784,7 +506,7 @@ internal class Transaction : Publishing.RESTSupport.Transaction { |
1276 | add_argument("oauth_version", "1.0"); |
1277 | add_argument("oauth_callback", "oob"); |
1278 | add_argument("oauth_timestamp", session.get_oauth_timestamp()); |
1279 | @@ -886,7 +1497,7 @@ |
1280 | } |
1281 | |
1282 | public override void execute() throws Spit.Publishing.PublishingError { |
1283 | -@@ -842,22 +681,6 @@ |
1284 | +@@ -842,22 +564,6 @@ internal class Transaction : Publishing.RESTSupport.Transaction { |
1285 | } |
1286 | } |
1287 | |
1288 | @@ -909,7 +1520,7 @@ |
1289 | internal class AccountInfoFetchTransaction : Transaction { |
1290 | public AccountInfoFetchTransaction(Session session) { |
1291 | base(session, Publishing.RESTSupport.HttpMethod.GET); |
1292 | -@@ -884,7 +707,7 @@ |
1293 | +@@ -884,7 +590,7 @@ private class UploadTransaction : Publishing.RESTSupport.UploadTransaction { |
1294 | add_authorization_header_field("oauth_version", "1.0"); |
1295 | add_authorization_header_field("oauth_callback", "oob"); |
1296 | add_authorization_header_field("oauth_timestamp", session.get_oauth_timestamp()); |
1297 | @@ -918,7 +1529,7 @@ |
1298 | add_authorization_header_field("oauth_token", session.get_access_phase_token()); |
1299 | |
1300 | add_argument("is_public", ("%d".printf(parameters.visibility_specification.everyone_level))); |
1301 | -@@ -944,11 +767,11 @@ |
1302 | +@@ -944,11 +650,11 @@ private class UploadTransaction : Publishing.RESTSupport.UploadTransaction { |
1303 | } |
1304 | |
1305 | internal class Session : Publishing.RESTSupport.Session { |
1306 | @@ -932,7 +1543,23 @@ |
1307 | |
1308 | public Session() { |
1309 | base(ENDPOINT_URL); |
1310 | -@@ -1008,16 +831,12 @@ |
1311 | +@@ -959,15 +665,6 @@ internal class Session : Publishing.RESTSupport.Session { |
1312 | + username != null); |
1313 | + } |
1314 | + |
1315 | +- public void authenticate_from_persistent_credentials(string token, string secret, |
1316 | +- string username) { |
1317 | +- this.access_phase_token = token; |
1318 | +- this.access_phase_token_secret = secret; |
1319 | +- this.username = username; |
1320 | +- |
1321 | +- authenticated(); |
1322 | +- } |
1323 | +- |
1324 | + public void deauthenticate() { |
1325 | + access_phase_token = null; |
1326 | + access_phase_token_secret = null; |
1327 | +@@ -1008,16 +705,12 @@ internal class Session : Publishing.RESTSupport.Session { |
1328 | if (access_phase_token_secret != null) { |
1329 | debug("access phase token secret available; using it as signing key"); |
1330 | |
1331 | @@ -952,7 +1579,7 @@ |
1332 | } |
1333 | |
1334 | string signature_base_string = http_method + "&" + Soup.URI.encode( |
1335 | -@@ -1040,11 +859,11 @@ |
1336 | +@@ -1040,11 +733,11 @@ internal class Session : Publishing.RESTSupport.Session { |
1337 | txn.add_argument("oauth_signature", signature); |
1338 | } |
1339 | |
1340 | @@ -968,7 +1595,7 @@ |
1341 | public void set_access_phase_credentials(string token, string secret, string username) { |
1342 | this.access_phase_token = token; |
1343 | this.access_phase_token_secret = secret; |
1344 | -@@ -1065,11 +884,11 @@ |
1345 | +@@ -1065,21 +758,16 @@ internal class Session : Publishing.RESTSupport.Session { |
1346 | return GLib.get_real_time().to_string().substring(0, 10); |
1347 | } |
1348 | |
1349 | @@ -984,11 +1611,84 @@ |
1350 | public string get_access_phase_token() { |
1351 | assert(access_phase_token != null); |
1352 | return access_phase_token; |
1353 | -Index: shotwell-0.13.0/plugins/shotwell-publishing/Makefile |
1354 | -=================================================================== |
1355 | ---- shotwell-0.13.0.orig/plugins/shotwell-publishing/Makefile 2012-09-20 07:08:59.000000000 +1200 |
1356 | -+++ shotwell-0.13.0/plugins/shotwell-publishing/Makefile 2012-09-20 15:16:00.933921786 +1200 |
1357 | -@@ -18,6 +18,7 @@ |
1358 | + } |
1359 | + |
1360 | +- public string get_access_phase_token_secret() { |
1361 | +- assert(access_phase_token_secret != null); |
1362 | +- return access_phase_token_secret; |
1363 | +- } |
1364 | +- |
1365 | + public string get_username() { |
1366 | + assert(is_authenticated()); |
1367 | + return username; |
1368 | +@@ -1112,7 +800,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1369 | + private Gtk.Label visibility_label = null; |
1370 | + private Gtk.Label upload_info_label = null; |
1371 | + private Gtk.Label size_label = null; |
1372 | +- private Gtk.Button logout_button = null; |
1373 | + private Gtk.Button publish_button = null; |
1374 | + private Gtk.ComboBoxText visibility_combo = null; |
1375 | + private Gtk.ComboBoxText size_combo = null; |
1376 | +@@ -1124,7 +811,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1377 | + private Spit.Publishing.Publisher.MediaType media_type; |
1378 | + |
1379 | + public signal void publish(bool strip_metadata); |
1380 | +- public signal void logout(); |
1381 | + |
1382 | + public PublishingOptionsPane(FlickrPublisher publisher, PublishingParameters parameters, |
1383 | + Spit.Publishing.Publisher.MediaType media_type, Gtk.Builder builder, bool strip_metadata) { |
1384 | +@@ -1136,7 +822,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1385 | + pane_widget = (Gtk.Box) this.builder.get_object("flickr_pane"); |
1386 | + visibility_label = (Gtk.Label) this.builder.get_object("visibility_label"); |
1387 | + upload_info_label = (Gtk.Label) this.builder.get_object("upload_info_label"); |
1388 | +- logout_button = (Gtk.Button) this.builder.get_object("logout_button"); |
1389 | + publish_button = (Gtk.Button) this.builder.get_object("publish_button"); |
1390 | + visibility_combo = (Gtk.ComboBoxText) this.builder.get_object("visibility_combo"); |
1391 | + size_combo = (Gtk.ComboBoxText) this.builder.get_object("size_combo"); |
1392 | +@@ -1183,14 +868,9 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1393 | + |
1394 | + strip_metadata_check.set_active(strip_metadata); |
1395 | + |
1396 | +- logout_button.clicked.connect(on_logout_clicked); |
1397 | + publish_button.clicked.connect(on_publish_clicked); |
1398 | + } |
1399 | + |
1400 | +- private void on_logout_clicked() { |
1401 | +- logout(); |
1402 | +- } |
1403 | +- |
1404 | + private void on_publish_clicked() { |
1405 | + parameters.visibility_specification = |
1406 | + visibilities[visibility_combo.get_active()].specification; |
1407 | +@@ -1257,10 +937,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1408 | + publish(strip_metadata_check.get_active()); |
1409 | + } |
1410 | + |
1411 | +- protected void notify_logout() { |
1412 | +- logout(); |
1413 | +- } |
1414 | +- |
1415 | + public Gtk.Widget get_widget() { |
1416 | + return pane_widget; |
1417 | + } |
1418 | +@@ -1271,12 +947,10 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1419 | + |
1420 | + public void on_pane_installed() { |
1421 | + publish.connect(notify_publish); |
1422 | +- logout.connect(notify_logout); |
1423 | + } |
1424 | + |
1425 | + public void on_pane_uninstalled() { |
1426 | + publish.disconnect(notify_publish); |
1427 | +- logout.disconnect(notify_logout); |
1428 | + } |
1429 | + } |
1430 | + |
1431 | +diff --git a/plugins/shotwell-publishing/Makefile b/plugins/shotwell-publishing/Makefile |
1432 | +index e939a77..bacfff4 100644 |
1433 | +--- a/plugins/shotwell-publishing/Makefile |
1434 | ++++ b/plugins/shotwell-publishing/Makefile |
1435 | +@@ -18,6 +18,7 @@ SRC_FILES := \ |
1436 | FlickrPublishing.vala \ |
1437 | YouTubePublishing.vala \ |
1438 | PiwigoPublishing.vala \ |
1439 | @@ -996,40 +1696,87 @@ |
1440 | ../../src/util/string.vala \ |
1441 | ../common/RESTSupport.vala \ |
1442 | ../common/ui.vala |
1443 | -Index: shotwell-0.13.0/plugins/shotwell-publishing/PicasaPublishing.vala |
1444 | -=================================================================== |
1445 | ---- shotwell-0.13.0.orig/plugins/shotwell-publishing/PicasaPublishing.vala 2012-09-20 07:08:59.000000000 +1200 |
1446 | -+++ shotwell-0.13.0/plugins/shotwell-publishing/PicasaPublishing.vala 2012-09-20 15:16:00.933921786 +1200 |
1447 | -@@ -4,6 +4,8 @@ |
1448 | +diff --git a/plugins/shotwell-publishing/PicasaPublishing.vala b/plugins/shotwell-publishing/PicasaPublishing.vala |
1449 | +index 397503d..a428a30 100644 |
1450 | +--- a/plugins/shotwell-publishing/PicasaPublishing.vala |
1451 | ++++ b/plugins/shotwell-publishing/PicasaPublishing.vala |
1452 | +@@ -4,30 +4,28 @@ |
1453 | * (version 2.1 or later). See the COPYING file in this distribution. |
1454 | */ |
1455 | |
1456 | +-public class PicasaService : Object, Spit.Pluggable, Spit.Publishing.Service { |
1457 | +using Publishing.Accounts; |
1458 | + |
1459 | - public class PicasaService : Object, Spit.Pluggable, Spit.Publishing.Service { |
1460 | ++public class PicasaService : UOAPublishingService, Spit.Pluggable, Spit.Publishing.Service { |
1461 | private const string ICON_FILENAME = "picasa.png"; |
1462 | |
1463 | -@@ -50,6 +52,11 @@ |
1464 | - |
1465 | - public void activation(bool enabled) { |
1466 | - } |
1467 | -+ |
1468 | -+ public bool is_enabled() { |
1469 | -+ SharingAccounts accounts = new SharingAccounts(); |
1470 | -+ return accounts.get_account_for_provider("google") != null; |
1471 | -+ } |
1472 | + private static Gdk.Pixbuf[] icon_pixbuf_set = null; |
1473 | + |
1474 | + public PicasaService(GLib.File resource_directory) { |
1475 | ++ base("google"); |
1476 | + if (icon_pixbuf_set == null) |
1477 | + icon_pixbuf_set = Resources.load_icon_set(resource_directory.get_child(ICON_FILENAME)); |
1478 | + } |
1479 | + |
1480 | +- public int get_pluggable_interface(int min_host_interface, int max_host_interface) { |
1481 | +- return Spit.negotiate_interfaces(min_host_interface, max_host_interface, |
1482 | +- Spit.Publishing.CURRENT_INTERFACE); |
1483 | +- } |
1484 | +- |
1485 | +- public unowned string get_id() { |
1486 | ++ public override unowned string get_id() { |
1487 | + return "org.yorba.shotwell.publishing.picasa"; |
1488 | + } |
1489 | + |
1490 | +- public unowned string get_pluggable_name() { |
1491 | ++ public override unowned string get_pluggable_name() { |
1492 | + return "Picasa Web Albums"; |
1493 | + } |
1494 | + |
1495 | +- public void get_info(ref Spit.PluggableInfo info) { |
1496 | ++ public override void get_info(ref Spit.PluggableInfo info) { |
1497 | + info.authors = "Lucas Beeler"; |
1498 | + info.copyright = _("Copyright 2009-2012 Yorba Foundation"); |
1499 | + info.translators = Resources.TRANSLATORS; |
1500 | +@@ -39,17 +37,15 @@ public class PicasaService : Object, Spit.Pluggable, Spit.Publishing.Service { |
1501 | + info.icons = icon_pixbuf_set; |
1502 | + } |
1503 | + |
1504 | +- public Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host) { |
1505 | +- return new Publishing.Picasa.PicasaPublisher(this, host); |
1506 | ++ public override Spit.Publishing.Publisher create_publisher(string? account_name, Spit.Publishing.PluginHost host) { |
1507 | ++ SharingAccount account = find_account(account_name); |
1508 | ++ return new Publishing.Picasa.PicasaPublisher(this, account, host); |
1509 | + } |
1510 | + |
1511 | +- public Spit.Publishing.Publisher.MediaType get_supported_media() { |
1512 | ++ public override Spit.Publishing.Publisher.MediaType get_supported_media() { |
1513 | + return (Spit.Publishing.Publisher.MediaType.PHOTO | |
1514 | + Spit.Publishing.Publisher.MediaType.VIDEO); |
1515 | + } |
1516 | +- |
1517 | +- public void activation(bool enabled) { |
1518 | +- } |
1519 | } |
1520 | |
1521 | namespace Publishing.Picasa { |
1522 | -@@ -72,6 +79,7 @@ |
1523 | +@@ -72,29 +68,22 @@ public class PicasaPublisher : Spit.Publishing.Publisher, GLib.Object { |
1524 | private PublishingParameters parameters = null; |
1525 | private Spit.Publishing.Publisher.MediaType media_type = |
1526 | Spit.Publishing.Publisher.MediaType.NONE; |
1527 | -+ private Signon.AuthSession auth_session = null; |
1528 | ++ private UOAPublisherAuthenticator authenticator = null; |
1529 | |
1530 | public PicasaPublisher(Spit.Publishing.Service service, |
1531 | ++ SharingAccount account, |
1532 | Spit.Publishing.PluginHost host) { |
1533 | -@@ -83,18 +91,6 @@ |
1534 | + this.service = service; |
1535 | + this.host = host; |
1536 | + this.session = new Session(); |
1537 | ++ authenticator = new UOAPublisherAuthenticator(account, host, |
1538 | ++ SERVICE_WELCOME_MESSAGE); |
1539 | ++ authenticator.authenticated.connect(on_authenticator_authenticated); |
1540 | + |
1541 | + foreach(Spit.Publishing.Publishable p in host.get_publishables()) |
1542 | media_type |= p.get_media_type(); |
1543 | } |
1544 | |
1545 | @@ -1048,7 +1795,7 @@ |
1546 | private Album[] extract_albums(Xml.Node* document_root) throws Spit.Publishing.PublishingError { |
1547 | Album[] result = new Album[0]; |
1548 | |
1549 | -@@ -133,14 +129,6 @@ |
1550 | +@@ -133,14 +122,6 @@ public class PicasaPublisher : Spit.Publishing.Publisher, GLib.Object { |
1551 | return result; |
1552 | } |
1553 | |
1554 | @@ -1063,7 +1810,7 @@ |
1555 | internal bool get_persistent_strip_metadata() { |
1556 | return host.get_config_bool("strip_metadata", false); |
1557 | } |
1558 | -@@ -149,16 +137,6 @@ |
1559 | +@@ -149,16 +130,6 @@ public class PicasaPublisher : Spit.Publishing.Publisher, GLib.Object { |
1560 | host.set_config_bool("strip_metadata", strip_metadata); |
1561 | } |
1562 | |
1563 | @@ -1080,14 +1827,19 @@ |
1564 | public bool is_running() { |
1565 | return running; |
1566 | } |
1567 | -@@ -173,92 +151,69 @@ |
1568 | - |
1569 | - debug("EVENT: user clicked 'Login' in welcome pane."); |
1570 | +@@ -167,98 +138,22 @@ public class PicasaPublisher : Spit.Publishing.Publisher, GLib.Object { |
1571 | + return service; |
1572 | + } |
1573 | |
1574 | +- private void on_service_welcome_login() { |
1575 | +- if (!is_running()) |
1576 | +- return; |
1577 | +- |
1578 | +- debug("EVENT: user clicked 'Login' in welcome pane."); |
1579 | +- |
1580 | - do_launch_browser_for_authorization(); |
1581 | -+ do_hosted_web_authentication(); |
1582 | - } |
1583 | - |
1584 | +- } |
1585 | +- |
1586 | - private void on_auth_code_entry_pane_proceed(AuthCodeEntryPane sender, string code) { |
1587 | - debug("EVENT: user clicked 'Continue' in authorization code entry pane."); |
1588 | - |
1589 | @@ -1105,18 +1857,10 @@ |
1590 | - private void on_get_access_tokens_completed(Publishing.RESTSupport.Transaction txn) { |
1591 | - txn.completed.disconnect(on_get_access_tokens_completed); |
1592 | - txn.network_error.disconnect(on_get_access_tokens_error); |
1593 | -+ public void on_processed(Signon.AuthSession self, owned HashTable<string,Value?>? session_data, GLib.Error error){ |
1594 | -+ if (error != null) { |
1595 | -+ debug("got error: %s", error.message); |
1596 | -+ /* TODO: handle errors */ |
1597 | -+ return; |
1598 | -+ } |
1599 | - |
1600 | +- |
1601 | - debug("EVENT: network transaction to exchange authorization code for access tokens " + |
1602 | - "completed successfully."); |
1603 | -+ host.set_service_locked(true); |
1604 | -+ host.install_account_fetch_wait_pane(); |
1605 | - |
1606 | +- |
1607 | - do_extract_tokens(txn.get_response()); |
1608 | - } |
1609 | - |
1610 | @@ -1124,8 +1868,7 @@ |
1611 | - Spit.Publishing.PublishingError err) { |
1612 | - txn.completed.disconnect(on_get_access_tokens_completed); |
1613 | - txn.network_error.disconnect(on_get_access_tokens_error); |
1614 | -+ session.authenticated.connect(on_session_authenticated); |
1615 | - |
1616 | +- |
1617 | - debug("EVENT: network transaction to exchange authorization code for access tokens " + |
1618 | - "failed; response = '%s'", txn.get_response()); |
1619 | - } |
1620 | @@ -1148,6 +1891,41 @@ |
1621 | - sender.proceed.disconnect(on_not_set_up_pane_proceed); |
1622 | - |
1623 | - do_launch_browser_for_authorization(); |
1624 | +- } |
1625 | +- |
1626 | +- private void on_refresh_access_token_transaction_completed(Publishing.RESTSupport.Transaction |
1627 | +- txn) { |
1628 | +- txn.completed.disconnect(on_refresh_access_token_transaction_completed); |
1629 | +- txn.network_error.disconnect(on_refresh_access_token_transaction_error); |
1630 | +- |
1631 | +- if (!is_running()) |
1632 | +- return; |
1633 | +- |
1634 | +- if (session.is_authenticated()) // ignore these events if the session is already auth'd |
1635 | +- return; |
1636 | +- |
1637 | +- debug("EVENT: refresh access token transaction completed successfully."); |
1638 | +- |
1639 | +- do_extract_tokens(txn.get_response()); |
1640 | +- } |
1641 | +- |
1642 | +- private void on_refresh_access_token_transaction_error(Publishing.RESTSupport.Transaction txn, |
1643 | +- Spit.Publishing.PublishingError err) { |
1644 | +- txn.completed.disconnect(on_refresh_access_token_transaction_completed); |
1645 | +- txn.network_error.disconnect(on_refresh_access_token_transaction_error); |
1646 | +- |
1647 | +- if (!is_running()) |
1648 | +- return; |
1649 | ++ public void on_authenticator_authenticated(owned HashTable<string,Value?> session_data) { |
1650 | ++ host.install_account_fetch_wait_pane(); |
1651 | + |
1652 | +- if (session.is_authenticated()) // ignore these events if the session is already auth'd |
1653 | +- return; |
1654 | ++ session.authenticated.connect(on_session_authenticated); |
1655 | + |
1656 | +- debug("EVENT: refresh access token transaction caused a network error."); |
1657 | +- |
1658 | +- host.post_error(err); |
1659 | + if (session_data.lookup("AccessToken") != null) { |
1660 | + string token = session_data.lookup("AccessToken").get_string(); |
1661 | + debug("OAuth Access Token: %s", token); |
1662 | @@ -1160,72 +1938,9 @@ |
1663 | + debug("Access token not present!"); |
1664 | + } |
1665 | } |
1666 | -- |
1667 | -- private void on_refresh_access_token_transaction_completed(Publishing.RESTSupport.Transaction |
1668 | -- txn) { |
1669 | -- txn.completed.disconnect(on_refresh_access_token_transaction_completed); |
1670 | -- txn.network_error.disconnect(on_refresh_access_token_transaction_error); |
1671 | -- |
1672 | -- if (!is_running()) |
1673 | -- return; |
1674 | - |
1675 | -- if (session.is_authenticated()) // ignore these events if the session is already auth'd |
1676 | -- return; |
1677 | -+ private void do_hosted_web_authentication() { |
1678 | -+ debug("ACTION: doing hosted web authentication."); |
1679 | - |
1680 | -- debug("EVENT: refresh access token transaction completed successfully."); |
1681 | -- |
1682 | -- do_extract_tokens(txn.get_response()); |
1683 | -- } |
1684 | -- |
1685 | -- private void on_refresh_access_token_transaction_error(Publishing.RESTSupport.Transaction txn, |
1686 | -- Spit.Publishing.PublishingError err) { |
1687 | -- txn.completed.disconnect(on_refresh_access_token_transaction_completed); |
1688 | -- txn.network_error.disconnect(on_refresh_access_token_transaction_error); |
1689 | -- |
1690 | -- if (!is_running()) |
1691 | -- return; |
1692 | -+ HashTable<string,Value?> data = null; |
1693 | -+ string mechanism = "user_agent"; |
1694 | -+ |
1695 | -+ SharingAccounts accounts = |
1696 | -+ new SharingAccounts(); |
1697 | - |
1698 | -- if (session.is_authenticated()) // ignore these events if the session is already auth'd |
1699 | -+ SharingAccount? account = accounts.get_account_for_provider("google"); |
1700 | -+ if (account != null) { |
1701 | -+ try { |
1702 | -+ auth_session = account.create_auth_session(); |
1703 | -+ data = account.get_session_parameters(out mechanism); |
1704 | -+ debug("Got account data"); |
1705 | -+ } catch (GLib.Error e) { |
1706 | -+ warning("EVENT: couldn't create session for account: %s", |
1707 | -+ e.message); |
1708 | -+ } |
1709 | -+ } |
1710 | -+ |
1711 | -+ if (data == null) { |
1712 | -+ warning ("No account authentication data"); |
1713 | -+ host.post_error(new Spit.Publishing.PublishingError.SERVICE_ERROR( |
1714 | -+ "Error while accessing the account")); |
1715 | - return; |
1716 | -+ } |
1717 | - |
1718 | -- debug("EVENT: refresh access token transaction caused a network error."); |
1719 | -- |
1720 | -- host.post_error(err); |
1721 | -+ var windowId = host.get_dialog_xid(); |
1722 | -+ if (windowId != 0) { |
1723 | -+ data.insert("WindowId", (uint)windowId); |
1724 | -+ } |
1725 | -+ |
1726 | -+ auth_session.process(data, mechanism, on_processed); |
1727 | -+ host.set_service_locked(false); |
1728 | - } |
1729 | |
1730 | private void on_session_authenticated() { |
1731 | -@@ -313,19 +268,7 @@ |
1732 | +@@ -313,31 +208,7 @@ public class PicasaPublisher : Spit.Publishing.Publisher, GLib.Object { |
1733 | debug("EVENT: fetching account and album information failed; response = '%s'.", |
1734 | bad_txn.get_response()); |
1735 | |
1736 | @@ -1242,22 +1957,32 @@ |
1737 | - // If we get any other kind of error, we can't recover, so just post it to the user |
1738 | - host.post_error(err); |
1739 | - } |
1740 | +- } |
1741 | +- |
1742 | +- private void on_publishing_options_logout() { |
1743 | +- if (!is_running()) |
1744 | +- return; |
1745 | +- |
1746 | +- debug("EVENT: user clicked 'Logout' in the publishing options pane."); |
1747 | +- |
1748 | +- session.deauthenticate(); |
1749 | +- invalidate_persistent_session(); |
1750 | +- |
1751 | +- do_show_service_welcome_pane(); |
1752 | + host.post_error(err); |
1753 | } |
1754 | |
1755 | - private void on_publishing_options_logout() { |
1756 | -@@ -335,7 +278,6 @@ |
1757 | - debug("EVENT: user clicked 'Logout' in the publishing options pane."); |
1758 | - |
1759 | - session.deauthenticate(); |
1760 | -- invalidate_persistent_session(); |
1761 | - |
1762 | - do_show_service_welcome_pane(); |
1763 | - } |
1764 | -@@ -453,94 +395,6 @@ |
1765 | - host.install_welcome_pane(SERVICE_WELCOME_MESSAGE, on_service_welcome_login); |
1766 | - } |
1767 | - |
1768 | + private void on_publishing_options_publish(PublishingParameters parameters, |
1769 | +@@ -447,100 +318,6 @@ public class PicasaPublisher : Spit.Publishing.Publisher, GLib.Object { |
1770 | + host.post_error(err); |
1771 | + } |
1772 | + |
1773 | +- private void do_show_service_welcome_pane() { |
1774 | +- debug("ACTION: showing service welcome pane."); |
1775 | +- |
1776 | +- host.install_welcome_pane(SERVICE_WELCOME_MESSAGE, on_service_welcome_login); |
1777 | +- } |
1778 | +- |
1779 | - private void do_launch_browser_for_authorization() { |
1780 | - string auth_url = get_user_authorization_url(); |
1781 | - |
1782 | @@ -1349,7 +2074,7 @@ |
1783 | private void do_extract_username(string response_body) { |
1784 | debug("ACTION: extracting username from body of server response"); |
1785 | |
1786 | -@@ -562,66 +416,8 @@ |
1787 | +@@ -562,66 +339,8 @@ public class PicasaPublisher : Spit.Publishing.Publisher, GLib.Object { |
1788 | if (username != "") |
1789 | this.username = username; |
1790 | } |
1791 | @@ -1416,20 +2141,29 @@ |
1792 | private void do_fetch_username() { |
1793 | debug("ACTION: running network transaction to fetch username."); |
1794 | |
1795 | -@@ -771,11 +567,7 @@ |
1796 | +@@ -701,7 +420,6 @@ public class PicasaPublisher : Spit.Publishing.Publisher, GLib.Object { |
1797 | + PublishingOptionsPane opts_pane = new PublishingOptionsPane(host, username, albums, media_type, builder, |
1798 | + get_persistent_strip_metadata()); |
1799 | + opts_pane.publish.connect(on_publishing_options_publish); |
1800 | +- opts_pane.logout.connect(on_publishing_options_logout); |
1801 | + host.install_dialog_pane(opts_pane); |
1802 | + |
1803 | + host.set_service_locked(false); |
1804 | +@@ -770,12 +488,7 @@ public class PicasaPublisher : Spit.Publishing.Publisher, GLib.Object { |
1805 | + debug("PicasaPublisher: starting interaction."); |
1806 | |
1807 | running = true; |
1808 | - |
1809 | +- |
1810 | - if (is_persistent_session_available()) { |
1811 | - do_refresh_session(get_persistent_refresh_token()); |
1812 | - } else { |
1813 | - do_show_service_welcome_pane(); |
1814 | - } |
1815 | -+ do_show_service_welcome_pane(); |
1816 | ++ authenticator.authenticate(); |
1817 | } |
1818 | |
1819 | public void stop() { |
1820 | -@@ -801,6 +593,7 @@ |
1821 | +@@ -801,6 +514,7 @@ internal class Album { |
1822 | |
1823 | internal class Session : Publishing.RESTSupport.Session { |
1824 | private string? auth_token = null; |
1825 | @@ -1437,7 +2171,7 @@ |
1826 | |
1827 | public Session() { |
1828 | } |
1829 | -@@ -809,45 +602,24 @@ |
1830 | +@@ -809,45 +523,19 @@ internal class Session : Publishing.RESTSupport.Session { |
1831 | return (auth_token != null); |
1832 | } |
1833 | |
1834 | @@ -1449,11 +2183,10 @@ |
1835 | notify_authenticated(); |
1836 | } |
1837 | |
1838 | - public void deauthenticate() { |
1839 | - auth_token = null; |
1840 | -+ auth_method = null; |
1841 | - } |
1842 | - |
1843 | +- public void deauthenticate() { |
1844 | +- auth_token = null; |
1845 | +- } |
1846 | +- |
1847 | public string? get_auth_token() { |
1848 | return auth_token; |
1849 | } |
1850 | @@ -1488,7 +2221,7 @@ |
1851 | } |
1852 | } |
1853 | |
1854 | -@@ -862,7 +634,13 @@ |
1855 | +@@ -862,7 +550,13 @@ internal class AuthenticatedTransaction : Publishing.RESTSupport.Transaction { |
1856 | base.with_endpoint_url(session, endpoint_url, method); |
1857 | assert(session.is_authenticated()); |
1858 | |
1859 | @@ -1503,7 +2236,7 @@ |
1860 | } |
1861 | } |
1862 | |
1863 | -@@ -875,7 +653,7 @@ |
1864 | +@@ -875,7 +569,7 @@ internal class UsernameFetchTransaction : AuthenticatedTransaction { |
1865 | } |
1866 | |
1867 | internal class AlbumDirectoryTransaction : AuthenticatedTransaction { |
1868 | @@ -1512,7 +2245,7 @@ |
1869 | "default"; |
1870 | |
1871 | public AlbumDirectoryTransaction(Session session) { |
1872 | -@@ -892,7 +670,7 @@ |
1873 | +@@ -892,7 +586,7 @@ internal class AlbumDirectoryTransaction : AuthenticatedTransaction { |
1874 | } |
1875 | |
1876 | private class AlbumCreationTransaction : AuthenticatedTransaction { |
1877 | @@ -1521,7 +2254,7 @@ |
1878 | "default"; |
1879 | private const string ALBUM_ENTRY_TEMPLATE = "<?xml version='1.0' encoding='utf-8'?><entry xmlns='http://www.w3.org/2005/Atom' xmlns:gphoto='http://schemas.google.com/photos/2007'><title type='text'>%s</title><gphoto:access>%s</gphoto:access><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'></category></entry>"; |
1880 | |
1881 | -@@ -971,9 +749,14 @@ |
1882 | +@@ -971,9 +665,14 @@ internal class UploadTransaction : AuthenticatedTransaction { |
1883 | // that we've been building up |
1884 | Soup.Message outbound_message = |
1885 | soup_form_request_new_from_multipart(get_endpoint_url(), message_parts); |
1886 | @@ -1538,7 +2271,7 @@ |
1887 | |
1888 | // send the message and get its response |
1889 | set_is_executed(true); |
1890 | -@@ -981,95 +764,6 @@ |
1891 | +@@ -981,95 +680,6 @@ internal class UploadTransaction : AuthenticatedTransaction { |
1892 | } |
1893 | } |
1894 | |
1895 | @@ -1634,11 +2367,284 @@ |
1896 | internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1897 | private class SizeDescription { |
1898 | public string name; |
1899 | -Index: shotwell-0.13.0/src/plugins/PublishingInterfaces.vala |
1900 | -=================================================================== |
1901 | ---- shotwell-0.13.0.orig/src/plugins/PublishingInterfaces.vala 2012-09-20 07:08:59.000000000 +1200 |
1902 | -+++ shotwell-0.13.0/src/plugins/PublishingInterfaces.vala 2012-09-20 15:16:00.933921786 +1200 |
1903 | -@@ -494,6 +494,7 @@ |
1904 | +@@ -1097,7 +707,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1905 | + private Gtk.ComboBoxText size_combo = null; |
1906 | + private Gtk.CheckButton strip_metadata_check = null; |
1907 | + private Gtk.Button publish_button = null; |
1908 | +- private Gtk.Button logout_button = null; |
1909 | + |
1910 | + private Album[] albums; |
1911 | + private SizeDescription[] size_descriptions; |
1912 | +@@ -1105,7 +714,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1913 | + private weak Spit.Publishing.PluginHost host; |
1914 | + |
1915 | + public signal void publish(PublishingParameters parameters, bool strip_metadata); |
1916 | +- public signal void logout(); |
1917 | + |
1918 | + public PublishingOptionsPane(Spit.Publishing.PluginHost host, string username, |
1919 | + Album[] albums, Spit.Publishing.Publisher.MediaType media_type, Gtk.Builder builder, |
1920 | +@@ -1131,7 +739,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1921 | + size_combo = (Gtk.ComboBoxText) builder.get_object("size_combo"); |
1922 | + strip_metadata_check = (Gtk.CheckButton) this.builder.get_object("strip_metadata_check"); |
1923 | + publish_button = (Gtk.Button) builder.get_object("publish_button"); |
1924 | +- logout_button = (Gtk.Button) builder.get_object("logout_button"); |
1925 | + |
1926 | + // populate any widgets whose contents are programmatically-generated. |
1927 | + login_identity_label.set_label(_("You are logged into Picasa Web Albums as %s.").printf(username)); |
1928 | +@@ -1157,7 +764,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1929 | + use_existing_radio.clicked.connect(on_use_existing_radio_clicked); |
1930 | + create_new_radio.clicked.connect(on_create_new_radio_clicked); |
1931 | + new_album_entry.changed.connect(on_new_album_entry_changed); |
1932 | +- logout_button.clicked.connect(on_logout_clicked); |
1933 | + publish_button.clicked.connect(on_publish_clicked); |
1934 | + } |
1935 | + |
1936 | +@@ -1200,10 +806,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1937 | + public_check.set_sensitive(true); |
1938 | + } |
1939 | + |
1940 | +- private void on_logout_clicked() { |
1941 | +- logout(); |
1942 | +- } |
1943 | +- |
1944 | + private void update_publish_button_sensitivity() { |
1945 | + string album_name = new_album_entry.get_text(); |
1946 | + publish_button.set_sensitive(!(album_name.strip() == "" && |
1947 | +@@ -1263,10 +865,6 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1948 | + publish(parameters, strip_metadata_check.get_active()); |
1949 | + } |
1950 | + |
1951 | +- protected void notify_logout() { |
1952 | +- logout(); |
1953 | +- } |
1954 | +- |
1955 | + public Gtk.Widget get_widget() { |
1956 | + return pane_widget; |
1957 | + } |
1958 | +@@ -1279,12 +877,10 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { |
1959 | + installed(); |
1960 | + |
1961 | + publish.connect(notify_publish); |
1962 | +- logout.connect(notify_logout); |
1963 | + } |
1964 | + |
1965 | + public void on_pane_uninstalled() { |
1966 | + publish.disconnect(notify_publish); |
1967 | +- logout.disconnect(notify_logout); |
1968 | + } |
1969 | + } |
1970 | + |
1971 | +diff --git a/plugins/shotwell-publishing/PiwigoPublishing.vala b/plugins/shotwell-publishing/PiwigoPublishing.vala |
1972 | +index d75b922..0fdf800 100644 |
1973 | +--- a/plugins/shotwell-publishing/PiwigoPublishing.vala |
1974 | ++++ b/plugins/shotwell-publishing/PiwigoPublishing.vala |
1975 | +@@ -42,7 +42,7 @@ public class PiwigoService : Object, Spit.Pluggable, Spit.Publishing.Service { |
1976 | + public void activation(bool enabled) { |
1977 | + } |
1978 | + |
1979 | +- public Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host) { |
1980 | ++ public Spit.Publishing.Publisher create_publisher(string? account, Spit.Publishing.PluginHost host) { |
1981 | + return new Publishing.Piwigo.PiwigoPublisher(this, host); |
1982 | + } |
1983 | + |
1984 | +diff --git a/plugins/shotwell-publishing/YouTubePublishing.vala b/plugins/shotwell-publishing/YouTubePublishing.vala |
1985 | +index 9319eb9..fc03fe7 100644 |
1986 | +--- a/plugins/shotwell-publishing/YouTubePublishing.vala |
1987 | ++++ b/plugins/shotwell-publishing/YouTubePublishing.vala |
1988 | +@@ -39,7 +39,7 @@ public class YouTubeService : Object, Spit.Pluggable, Spit.Publishing.Service { |
1989 | + info.icons = icon_pixbuf_set; |
1990 | + } |
1991 | + |
1992 | +- public Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host) { |
1993 | ++ public Spit.Publishing.Publisher create_publisher(string? account, Spit.Publishing.PluginHost host) { |
1994 | + return new Publishing.YouTube.YouTubePublisher(this, host); |
1995 | + } |
1996 | + |
1997 | +diff --git a/plugins/shotwell-publishing/facebook_publishing_options_pane.glade b/plugins/shotwell-publishing/facebook_publishing_options_pane.glade |
1998 | +index 0ba57ad..567b8c8 100644 |
1999 | +--- a/plugins/shotwell-publishing/facebook_publishing_options_pane.glade |
2000 | ++++ b/plugins/shotwell-publishing/facebook_publishing_options_pane.glade |
2001 | +@@ -196,29 +196,14 @@ anything put into this field won't display)</property> |
2002 | + <object class="GtkBox" id="box2"> |
2003 | + <property name="visible">True</property> |
2004 | + <property name="can_focus">False</property> |
2005 | ++ <property name="halign">center</property> |
2006 | + <property name="spacing">32</property> |
2007 | + <property name="homogeneous">True</property> |
2008 | + <child> |
2009 | +- <object class="GtkButton" id="logout_button"> |
2010 | +- <property name="label" translatable="yes">_Logout</property> |
2011 | +- <property name="use_action_appearance">False</property> |
2012 | +- <property name="visible">True</property> |
2013 | +- <property name="can_focus">True</property> |
2014 | +- <property name="receives_default">True</property> |
2015 | +- <property name="use_action_appearance">False</property> |
2016 | +- <property name="use_underline">True</property> |
2017 | +- </object> |
2018 | +- <packing> |
2019 | +- <property name="expand">False</property> |
2020 | +- <property name="fill">True</property> |
2021 | +- <property name="padding">80</property> |
2022 | +- <property name="position">0</property> |
2023 | +- </packing> |
2024 | +- </child> |
2025 | +- <child> |
2026 | + <object class="GtkButton" id="publish_button"> |
2027 | + <property name="label" translatable="yes">_Publish</property> |
2028 | + <property name="use_action_appearance">False</property> |
2029 | ++ <property name="width_request">96</property> |
2030 | + <property name="visible">True</property> |
2031 | + <property name="can_focus">True</property> |
2032 | + <property name="receives_default">True</property> |
2033 | +@@ -229,13 +214,13 @@ anything put into this field won't display)</property> |
2034 | + <property name="expand">False</property> |
2035 | + <property name="fill">True</property> |
2036 | + <property name="padding">80</property> |
2037 | +- <property name="position">1</property> |
2038 | ++ <property name="position">0</property> |
2039 | + </packing> |
2040 | + </child> |
2041 | + </object> |
2042 | + <packing> |
2043 | + <property name="expand">False</property> |
2044 | +- <property name="fill">True</property> |
2045 | ++ <property name="fill">False</property> |
2046 | + <property name="padding">2</property> |
2047 | + <property name="position">3</property> |
2048 | + </packing> |
2049 | +diff --git a/plugins/shotwell-publishing/flickr_publishing_options_pane.glade b/plugins/shotwell-publishing/flickr_publishing_options_pane.glade |
2050 | +index e39a52e..b9edd04 100644 |
2051 | +--- a/plugins/shotwell-publishing/flickr_publishing_options_pane.glade |
2052 | ++++ b/plugins/shotwell-publishing/flickr_publishing_options_pane.glade |
2053 | +@@ -135,24 +135,6 @@ so changes made here will not display)</property> |
2054 | + <property name="spacing">64</property> |
2055 | + <property name="homogeneous">True</property> |
2056 | + <child> |
2057 | +- <object class="GtkButton" id="logout_button"> |
2058 | +- <property name="label" translatable="yes">_Logout</property> |
2059 | +- <property name="use_action_appearance">False</property> |
2060 | +- <property name="width_request">96</property> |
2061 | +- <property name="visible">True</property> |
2062 | +- <property name="can_focus">True</property> |
2063 | +- <property name="receives_default">True</property> |
2064 | +- <property name="use_action_appearance">False</property> |
2065 | +- <property name="use_underline">True</property> |
2066 | +- </object> |
2067 | +- <packing> |
2068 | +- <property name="expand">False</property> |
2069 | +- <property name="fill">True</property> |
2070 | +- <property name="padding">24</property> |
2071 | +- <property name="position">0</property> |
2072 | +- </packing> |
2073 | +- </child> |
2074 | +- <child> |
2075 | + <object class="GtkButton" id="publish_button"> |
2076 | + <property name="label" translatable="yes">_Publish</property> |
2077 | + <property name="use_action_appearance">False</property> |
2078 | +@@ -167,7 +149,7 @@ so changes made here will not display)</property> |
2079 | + <property name="expand">False</property> |
2080 | + <property name="fill">True</property> |
2081 | + <property name="padding">24</property> |
2082 | +- <property name="position">1</property> |
2083 | ++ <property name="position">0</property> |
2084 | + </packing> |
2085 | + </child> |
2086 | + </object> |
2087 | +diff --git a/plugins/shotwell-publishing/picasa_publishing_options_pane.glade b/plugins/shotwell-publishing/picasa_publishing_options_pane.glade |
2088 | +index 07af67d..4d2cfb4 100644 |
2089 | +--- a/plugins/shotwell-publishing/picasa_publishing_options_pane.glade |
2090 | ++++ b/plugins/shotwell-publishing/picasa_publishing_options_pane.glade |
2091 | +@@ -226,32 +226,16 @@ |
2092 | + <object class="GtkBox" id="button_area_box"> |
2093 | + <property name="visible">True</property> |
2094 | + <property name="can_focus">False</property> |
2095 | +- <property name="margin_left">112</property> |
2096 | +- <property name="margin_right">112</property> |
2097 | ++ <property name="halign">center</property> |
2098 | + <property name="margin_top">48</property> |
2099 | + <property name="margin_bottom">24</property> |
2100 | + <property name="spacing">128</property> |
2101 | + <property name="homogeneous">True</property> |
2102 | + <child> |
2103 | +- <object class="GtkButton" id="logout_button"> |
2104 | +- <property name="label" translatable="yes">_Logout</property> |
2105 | +- <property name="use_action_appearance">False</property> |
2106 | +- <property name="visible">True</property> |
2107 | +- <property name="can_focus">True</property> |
2108 | +- <property name="receives_default">True</property> |
2109 | +- <property name="use_action_appearance">False</property> |
2110 | +- <property name="use_underline">True</property> |
2111 | +- </object> |
2112 | +- <packing> |
2113 | +- <property name="expand">False</property> |
2114 | +- <property name="fill">True</property> |
2115 | +- <property name="position">0</property> |
2116 | +- </packing> |
2117 | +- </child> |
2118 | +- <child> |
2119 | + <object class="GtkButton" id="publish_button"> |
2120 | + <property name="label" translatable="yes">_Publish</property> |
2121 | + <property name="use_action_appearance">False</property> |
2122 | ++ <property name="width_request">96</property> |
2123 | + <property name="visible">True</property> |
2124 | + <property name="can_focus">True</property> |
2125 | + <property name="receives_default">True</property> |
2126 | +@@ -261,13 +245,13 @@ |
2127 | + <packing> |
2128 | + <property name="expand">False</property> |
2129 | + <property name="fill">True</property> |
2130 | +- <property name="position">1</property> |
2131 | ++ <property name="position">0</property> |
2132 | + </packing> |
2133 | + </child> |
2134 | + </object> |
2135 | + <packing> |
2136 | + <property name="expand">False</property> |
2137 | +- <property name="fill">True</property> |
2138 | ++ <property name="fill">False</property> |
2139 | + <property name="position">4</property> |
2140 | + </packing> |
2141 | + </child> |
2142 | +diff --git a/po/shotwell-core/shotwell.pot b/po/shotwell-core/shotwell.pot |
2143 | +index df41958..cee8286 100644 |
2144 | +--- a/po/shotwell-core/shotwell.pot |
2145 | ++++ b/po/shotwell-core/shotwell.pot |
2146 | +@@ -2326,6 +2326,10 @@ msgstr "" |
2147 | + msgid "Publish photos and videos _to" |
2148 | + msgstr "" |
2149 | + |
2150 | ++#: src/publishing/PublishingUI.vala:238 |
2151 | ++msgid "Add more accounts..." |
2152 | ++msgstr "" |
2153 | ++ |
2154 | + #: src/publishing/PublishingUI.vala:354 |
2155 | + msgid "Unable to publish" |
2156 | + msgstr "" |
2157 | +@@ -3932,3 +3936,19 @@ msgstr "" |
2158 | + #: ui/shotwell.glade:995 |
2159 | + msgid "Plugins" |
2160 | + msgstr "" |
2161 | ++ |
2162 | ++#: misc/shotwell.application:2 |
2163 | ++msgid "Shotwell" |
2164 | ++msgstr "" |
2165 | ++ |
2166 | ++#: misc/shotwell.application:9 |
2167 | ++msgid "Publish your pictures to Picasa" |
2168 | ++msgstr "" |
2169 | ++ |
2170 | ++#: misc/shotwell.application:12 |
2171 | ++msgid "Publish your pictures to Facebook" |
2172 | ++msgstr "" |
2173 | ++ |
2174 | ++#: misc/shotwell.application:15 |
2175 | ++msgid "Publish your pictures to Flickr" |
2176 | ++msgstr "" |
2177 | +diff --git a/src/plugins/PublishingInterfaces.vala b/src/plugins/PublishingInterfaces.vala |
2178 | +index 339cc9d..4ed2bec 100644 |
2179 | +--- a/src/plugins/PublishingInterfaces.vala |
2180 | ++++ b/src/plugins/PublishingInterfaces.vala |
2181 | +@@ -494,6 +494,7 @@ public interface PluginHost : GLib.Object, Spit.HostInterface { |
2182 | */ |
2183 | public abstract Spit.Publishing.Publisher.MediaType get_publishable_media_type(); |
2184 | |
2185 | @@ -1646,7 +2652,15 @@ |
2186 | // |
2187 | // For future expansion. |
2188 | // |
2189 | -@@ -586,10 +587,14 @@ |
2190 | +@@ -579,18 +580,26 @@ public interface Service : Object, Spit.Pluggable { |
2191 | + * A factory method that instantiates and returns a new {@link Publisher} object that |
2192 | + * encapsulates a connection to the remote publishing service that this Service describes. |
2193 | + */ |
2194 | +- public abstract Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host); |
2195 | ++ public abstract Spit.Publishing.Publisher create_publisher(string? account, Spit.Publishing.PluginHost host); |
2196 | + |
2197 | + /** |
2198 | + * Returns the kinds of media that this service can work with. |
2199 | */ |
2200 | public abstract Spit.Publishing.Publisher.MediaType get_supported_media(); |
2201 | |
2202 | @@ -1655,18 +2669,43 @@ |
2203 | + */ |
2204 | + public virtual bool is_enabled() { return true; } |
2205 | + |
2206 | ++ /** |
2207 | ++ * List the accounts available for this service. |
2208 | ++ */ |
2209 | ++ public virtual string[] list_account_names() { return {}; } |
2210 | ++ |
2211 | // |
2212 | // For future expansion. |
2213 | // |
2214 | - protected virtual void reserved0() {} |
2215 | - protected virtual void reserved1() {} |
2216 | +- protected virtual void reserved1() {} |
2217 | protected virtual void reserved2() {} |
2218 | protected virtual void reserved3() {} |
2219 | -Index: shotwell-0.13.0/src/publishing/PublishingPluginHost.vala |
2220 | -=================================================================== |
2221 | ---- shotwell-0.13.0.orig/src/publishing/PublishingPluginHost.vala 2012-09-20 07:08:59.000000000 +1200 |
2222 | -+++ shotwell-0.13.0/src/publishing/PublishingPluginHost.vala 2012-09-20 15:16:00.933921786 +1200 |
2223 | -@@ -232,6 +232,13 @@ |
2224 | + protected virtual void reserved4() {} |
2225 | +diff --git a/src/publishing/PublishingPluginHost.vala b/src/publishing/PublishingPluginHost.vala |
2226 | +index 7be7bed..c0417f8 100644 |
2227 | +--- a/src/publishing/PublishingPluginHost.vala |
2228 | ++++ b/src/publishing/PublishingPluginHost.vala |
2229 | +@@ -21,7 +21,8 @@ public class ConcretePublishingHost : Plugins.StandardHostInterface, |
2230 | + private Spit.Publishing.Publisher.MediaType media_type = |
2231 | + Spit.Publishing.Publisher.MediaType.NONE; |
2232 | + |
2233 | +- public ConcretePublishingHost(Service service, PublishingUI.PublishingDialog dialog, |
2234 | ++ public ConcretePublishingHost(Service service, string? account, |
2235 | ++ PublishingUI.PublishingDialog dialog, |
2236 | + Publishable[] publishables) { |
2237 | + base(service, "sharing"); |
2238 | + this.dialog = dialog; |
2239 | +@@ -30,7 +31,7 @@ public class ConcretePublishingHost : Plugins.StandardHostInterface, |
2240 | + foreach (Publishable curr_publishable in publishables) |
2241 | + this.media_type |= curr_publishable.get_media_type(); |
2242 | + |
2243 | +- this.active_publisher = service.create_publisher(this); |
2244 | ++ this.active_publisher = service.create_publisher(account, this); |
2245 | + } |
2246 | + |
2247 | + private void on_login_clicked() { |
2248 | +@@ -232,6 +233,13 @@ public class ConcretePublishingHost : Plugins.StandardHostInterface, |
2249 | |
2250 | return report_plugin_upload_progress; |
2251 | } |
2252 | @@ -1680,11 +2719,72 @@ |
2253 | } |
2254 | |
2255 | } |
2256 | -Index: shotwell-0.13.0/src/publishing/PublishingUI.vala |
2257 | -=================================================================== |
2258 | ---- shotwell-0.13.0.orig/src/publishing/PublishingUI.vala 2012-09-20 07:08:59.000000000 +1200 |
2259 | -+++ shotwell-0.13.0/src/publishing/PublishingUI.vala 2012-09-20 15:16:00.937921786 +1200 |
2260 | -@@ -296,6 +296,7 @@ |
2261 | +diff --git a/src/publishing/PublishingUI.vala b/src/publishing/PublishingUI.vala |
2262 | +index b7f7f75..a3d404c 100644 |
2263 | +--- a/src/publishing/PublishingUI.vala |
2264 | ++++ b/src/publishing/PublishingUI.vala |
2265 | +@@ -130,6 +130,11 @@ public class LoginWaitPane : StaticMessagePane { |
2266 | + } |
2267 | + |
2268 | + public class PublishingDialog : Gtk.Dialog { |
2269 | ++ private struct AccountService { |
2270 | ++ Spit.Publishing.Service service; |
2271 | ++ string? account; |
2272 | ++ } |
2273 | ++ |
2274 | + private const int LARGE_WINDOW_WIDTH = 860; |
2275 | + private const int LARGE_WINDOW_HEIGHT = 688; |
2276 | + private const int COLOSSAL_WINDOW_WIDTH = 1024; |
2277 | +@@ -151,6 +156,8 @@ public class PublishingDialog : Gtk.Dialog { |
2278 | + private Spit.Publishing.DialogPane active_pane; |
2279 | + private Spit.Publishing.Publishable[] publishables; |
2280 | + private Spit.Publishing.ConcretePublishingHost host; |
2281 | ++ private Gee.HashMap<string,AccountService?> services; |
2282 | ++ private int service_selector_add_accounts_index; |
2283 | + |
2284 | + protected PublishingDialog(Gee.Collection<MediaSource> to_publish) { |
2285 | + assert(to_publish.size > 0); |
2286 | +@@ -158,6 +165,8 @@ public class PublishingDialog : Gtk.Dialog { |
2287 | + resizable = false; |
2288 | + delete_event.connect(on_window_close); |
2289 | + |
2290 | ++ services = new Gee.HashMap<string,AccountService?>(); |
2291 | ++ |
2292 | + publishables = new Spit.Publishing.Publishable[0]; |
2293 | + bool has_photos = false; |
2294 | + bool has_videos = false; |
2295 | +@@ -206,9 +215,28 @@ public class PublishingDialog : Gtk.Dialog { |
2296 | + if (last_used_service != null && last_used_service == curr_service_id) |
2297 | + last_used_index = ticker; |
2298 | + |
2299 | +- service_selector_box.append_text(service.get_pluggable_name()); |
2300 | +- ticker++; |
2301 | ++ var account_names = service.list_account_names(); |
2302 | ++ if (account_names.length == 0) { |
2303 | ++ account_names += null; |
2304 | ++ } |
2305 | ++ |
2306 | ++ foreach (string? account_name in account_names) { |
2307 | ++ string service_name = service.get_pluggable_name(); |
2308 | ++ if (account_name != null) { |
2309 | ++ service_name += " (%s)".printf(account_name); |
2310 | ++ } |
2311 | ++ |
2312 | ++ AccountService account_service = { |
2313 | ++ service: service, |
2314 | ++ account: account_name |
2315 | ++ }; |
2316 | ++ services.set(service_name, account_service); |
2317 | ++ service_selector_box.append_text(service_name); |
2318 | ++ ticker++; |
2319 | ++ } |
2320 | + } |
2321 | ++ service_selector_box.append_text(_("Add more accounts...")); |
2322 | ++ service_selector_add_accounts_index = ticker; |
2323 | + if (last_used_index >= 0) |
2324 | + service_selector_box.set_active(last_used_index); |
2325 | + else |
2326 | +@@ -296,6 +324,7 @@ public class PublishingDialog : Gtk.Dialog { |
2327 | Spit.Publishing.Service[] all_services = load_all_services(); |
2328 | |
2329 | foreach (Spit.Publishing.Service service in all_services) { |
2330 | @@ -1692,3 +2792,48 @@ |
2331 | |
2332 | if (has_photos && !has_videos) { |
2333 | if ((service.get_supported_media() & Spit.Publishing.Publisher.MediaType.PHOTO) != 0) |
2334 | +@@ -384,21 +413,34 @@ public class PublishingDialog : Gtk.Dialog { |
2335 | + } |
2336 | + |
2337 | + private void on_service_changed() { |
2338 | +- string service_name = service_selector_box.get_active_text(); |
2339 | +- |
2340 | +- Spit.Publishing.Service? selected_service = null; |
2341 | +- Spit.Publishing.Service[] services = load_all_services(); |
2342 | +- foreach (Spit.Publishing.Service service in services) { |
2343 | +- if (service.get_pluggable_name() == service_name) { |
2344 | +- selected_service = service; |
2345 | +- break; |
2346 | ++ if (service_selector_box.get_active() == |
2347 | ++ service_selector_add_accounts_index) { |
2348 | ++ debug("Starting Online Accounts..."); |
2349 | ++ try |
2350 | ++ { |
2351 | ++ DesktopAppInfo app_info = |
2352 | ++ new DesktopAppInfo ("gnome-credentials-panel.desktop"); |
2353 | ++ GLib.Process.spawn_command_line_async(app_info.get_commandline() + " application=shotwell"); |
2354 | ++ } |
2355 | ++ catch (Error e) |
2356 | ++ { |
2357 | ++ warning ("Error launching Online Accounts: %s", e.message); |
2358 | + } |
2359 | ++ |
2360 | ++ on_close_cancel_clicked(); |
2361 | ++ return; |
2362 | + } |
2363 | +- assert(selected_service != null); |
2364 | ++ |
2365 | ++ string service_name = service_selector_box.get_active_text(); |
2366 | ++ |
2367 | ++ AccountService account_service = services.get(service_name); |
2368 | ++ Spit.Publishing.Service? selected_service = account_service.service; |
2369 | + |
2370 | + Config.Facade.get_instance().set_last_used_service(selected_service.get_id()); |
2371 | + |
2372 | +- host = new Spit.Publishing.ConcretePublishingHost(selected_service, this, publishables); |
2373 | ++ host = new Spit.Publishing.ConcretePublishingHost(selected_service, |
2374 | ++ account_service.account, |
2375 | ++ this, publishables); |
2376 | + host.start_publishing(); |
2377 | + } |
2378 | + |