Merge lp:~abreu-alexandre/unity-webapps-qml/new-content-hub-api into lp:unity-webapps-qml

Proposed by Alexandre Abreu
Status: Merged
Approved by: Alberto Mardegan
Approved revision: 101
Merged at revision: 98
Proposed branch: lp:~abreu-alexandre/unity-webapps-qml/new-content-hub-api
Merge into: lp:unity-webapps-qml
Diff against target: 1352 lines (+828/-191)
6 files modified
examples/api-bindings/content-hub/www/js/app.js (+30/-53)
examples/api-bindings/content-peer-picker/main.qml.in (+32/-0)
examples/api-bindings/content-peer-picker/www/index.html (+33/-0)
examples/api-bindings/content-peer-picker/www/js/app.js (+104/-0)
src/Ubuntu/UnityWebApps/UnityWebAppsBackendComponents.js (+342/-66)
src/Ubuntu/UnityWebApps/bindings/content-hub/client/content-hub.js (+287/-72)
To merge this branch: bzr merge lp:~abreu-alexandre/unity-webapps-qml/new-content-hub-api
Reviewer Review Type Date Requested Status
Alberto Mardegan (community) Approve
PS Jenkins bot (community) continuous-integration Approve
WebApps Pending
Review via email: mp+211165@code.launchpad.net

Commit message

Add support for the new content hub api

Description of the change

Add support for the new content hub api.

You need https://code.launchpad.net/~michael-sheldon/content-hub/peer_picker_ui (new implementation for content hub)

- Testing the feature
---------------------

you have the examples/api-bindings/:

- content-hub: example of an import application. It lists the potential sources for images,

- content-hub-exporter: exmaple of an exporter application (exporting pictures). The click package should be installed locally (see the README file in the local folder) and it should be listed as peer by the importer (if not make sure that you killed the content-hub service and registered the new peer w/ by running the content-hub-peer-hook /usr/lib/x86_64-linux-gnu/content-hub/content-hub-peer-hook). What usually happens is that I manually start the app before testing the importers, to avoid upstart issues & crashes on the desktop w/ e.g.:

APP_ID=com.ubuntu.developer.alexandre-abreu.content-hub-html5-exporter_content-hub-html5-exporter_0.6 qmlscene -I `pwd`/../../../src main.qml

- content-hub-picker: example of an application that uses the Content Peer Picker UI,

- Automated/unit tests
----------------------

Another branch will land that adds integration tests for all API components, which is why
no tests have been added/updated,

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alberto Mardegan (mardy) wrote :

L646: + if (this._modelAdaptor) {
I guess you wanted "if (!..."

L670: Isn't it possible to avoid building the code this way, and use backendDelegate.createQmlObject() as you did for the AccountServiceModel? (I guess you had your reasons not to do it this way, please explain :-) )

L673-678 (but also later): I'd put the ";" at the end of the line, rather than at the beginning. Otherwise if the first filter is not set and the second one is, you'd end up with code like "ContentPeerModel { ; handler: ..."

L952: I guess the result of the expression must be a boolean, so maybe write it as
  this._isDefaultPeer = content && content.isDefaultPeer

I didn't test it yet, will do that soon.

review: Needs Fixing
Revision history for this message
Alberto Mardegan (mardy) wrote :

I tested it, and the examples work.

101. By Alexandre Abreu

fixes

Revision history for this message
Alexandre Abreu (abreu-alexandre) wrote :

> L646: + if (this._modelAdaptor) {
> I guess you wanted "if (!..."

right, done

> L670: Isn't it possible to avoid building the code this way, and use
> backendDelegate.createQmlObject() as you did for the AccountServiceModel? (I
> guess you had your reasons not to do it this way, please explain :-) )

sure, the issue is w/ the plugin specific types that are not js builtins.
Things work find w/ the backend.create[..] when you have builtin types but
it is not really meant to specify custom type params like ContentType.Pictures, etc.
Those have to be handled specifically, hence the lousy creation steps,

>
> L673-678 (but also later): I'd put the ";" at the end of the line, rather than
> at the beginning. Otherwise if the first filter is not set and the second one
> is, you'd end up with code like "ContentPeerModel { ; handler: ..."

right, done

> L952: I guess the result of the expression must be a boolean, so maybe write
> it as
> this._isDefaultPeer = content && content.isDefaultPeer

done

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alberto Mardegan (mardy) wrote :

LGTM!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'examples/api-bindings/content-hub/www/js/app.js'
--- examples/api-bindings/content-hub/www/js/app.js 2014-02-11 09:18:34 +0000
+++ examples/api-bindings/content-hub/www/js/app.js 2014-03-18 13:59:59 +0000
@@ -6,32 +6,18 @@
6 var pictureContentType = hub.ContentType.Pictures;6 var pictureContentType = hub.ContentType.Pictures;
77
8 var sourcePeers = {};8 var sourcePeers = {};
9 hub.knownSourcesForType(9 hub.getPeers(
10 pictureContentType10 {contentType: hub.ContentType.Pictures}
11 , function (peers) {11 , function (peers) {
12 if ( ! peers.length)
13 return;
14
12 for (var j = 0; j < peers.length; ++j) {15 for (var j = 0; j < peers.length; ++j) {
13 addPeerElement(peers[j].appId(), peers[j].name());16 addPeerElement(peers[j].appId(), peers[j].name());
14 sourcePeers[peers[j].appId()] = peers[j];17 sourcePeers[peers[j].appId()] = peers[j];
15 }18 }
1619 document.getElementById('importdiv').style.display = 'block';
17 console.log('peers defaultSourceForType: ' + peers)20 document.getElementById('lowLevelImportdiv').style.display = 'block';
18
19 hub.defaultSourceForType(
20 pictureContentType
21 , function(peer) {
22 if (peer) {
23 addPeerElement(peer.appId(), peer.name());
24 sourcePeers[peer.appId()] = peer;
25 }
26
27 if (Object.keys(sourcePeers).length === 0) {
28 nopeers();
29 return;
30 }
31 document.getElementById('importdiv').style.display = 'block';
32 document.getElementById('lowLevelImportdiv').style.display = 'block';
33 }
34 );
35 });21 });
3622
37 document.getElementById('import').addEventListener('click', doSimpleApiImport);23 document.getElementById('import').addEventListener('click', doSimpleApiImport);
@@ -132,7 +118,7 @@
132118
133 hub.api.importContent(pictureContentType119 hub.api.importContent(pictureContentType
134 , peer120 , peer
135 , {importToLocalStore: true}121 , {scope: hub.ContentScope.App}
136 , function(items) {122 , function(items) {
137 for (var i = 0; i < items.length; ++i) {123 for (var i = 0; i < items.length; ++i) {
138 addResult(items[i]);124 addResult(items[i]);
@@ -159,40 +145,31 @@
159 return;145 return;
160 }146 }
161147
162 hub.importContentForPeer(148 hub.getStore(hub.ContentScope.App, function(store) {
163 pictureContentType,149 peer.requestForStore(store, function(transfer) {
164 peer,150 transfer.start(function(state) {
165 function(transfer) {151 if (transferState.Aborted === state) {
166152 transfer.finalize();
167 hub.defaultStoreForType(pictureContentType, function(store) {153 peer.destroy();
168 transfer.setStore(store, function() {154 transfer.destroy();
169155 aborted();
170 transfer.start(function(state) {156 return;
171 if (transferState.Aborted === state) {157 }
172 transfer.finalize();158
173 peer.destroy();159 if (transferState.Charged === state) {
174 transfer.destroy();160 transfer.items(function(items) {
175 aborted();161 for (var i = 0; i < items.length; ++i) {
176 return;162 addResult(items[i]);
177 }163 }
178164 transfer.finalize();
179 if (transferState.Charged === state) {165 peer.destroy();
180 transfer.items(function(items) {166 transfer.destroy();
181 for (var i = 0; i < items.length; ++i) {
182 addResult(items[i]);
183 }
184 transfer.finalize();
185 peer.destroy();
186 transfer.destroy();
187 });
188 }
189 });167 });
190 });168 }
191
192 });169 });
193170
194 }171 });
195 );172 });
196 };173 };
197};174};
198175
199176
=== added directory 'examples/api-bindings/content-peer-picker'
=== added file 'examples/api-bindings/content-peer-picker/main.qml.in'
--- examples/api-bindings/content-peer-picker/main.qml.in 1970-01-01 00:00:00 +0000
+++ examples/api-bindings/content-peer-picker/main.qml.in 2014-03-18 13:59:59 +0000
@@ -0,0 +1,32 @@
1import QtQuick 2.0
2import QtWebKit 3.0
3import QtWebKit.experimental 1.0
4import Ubuntu.Components 0.1
5import Ubuntu.UnityWebApps 0.1
6
7MainView {
8 id: root
9 focus: true
10 applicationName: \"helloworld\"
11
12 width: units.gu(100)
13 height: units.gu(100)
14
15 WebView {
16 id: webview
17 anchors.fill: parent
18 url: \"file://$$OUT_PWD/content-hub/www/index.html\"
19
20 experimental.preferences.navigatorQtObjectEnabled: true
21 experimental.preferences.developerExtrasEnabled: true
22
23 function getUnityWebappsProxies() {
24 return UnityWebAppsUtils.makeProxiesForQtWebViewBindee(webview);
25 }
26
27 UnityWebApps {
28 id: webapps
29 bindee: webview
30 }
31 }
32}
033
=== added directory 'examples/api-bindings/content-peer-picker/www'
=== added file 'examples/api-bindings/content-peer-picker/www/index.html'
--- examples/api-bindings/content-peer-picker/www/index.html 1970-01-01 00:00:00 +0000
+++ examples/api-bindings/content-peer-picker/www/index.html 2014-03-18 13:59:59 +0000
@@ -0,0 +1,33 @@
1<html>
2
3 <head>
4 <title>Content Hub: Content Peer Picker example</title>
5 <script src="./js/app.js"></script>
6 </head>
7
8 <style>
9
10 .selected { background-color: red; }
11
12 </style>
13
14 <body>
15 <div>
16 Start Content Peer picking to import content: <input type="button" id="pick"></input>
17 </div>
18
19 <div>
20 Selected peer:
21 <div id="selected-peer">
22 </div>
23 </div>
24
25 <div>
26 Imported Image:
27 <div id="results">
28 </div>
29 </div>
30
31 </body>
32
33</html>
034
=== added directory 'examples/api-bindings/content-peer-picker/www/js'
=== added file 'examples/api-bindings/content-peer-picker/www/js/app.js'
--- examples/api-bindings/content-peer-picker/www/js/app.js 1970-01-01 00:00:00 +0000
+++ examples/api-bindings/content-peer-picker/www/js/app.js 2014-03-18 13:59:59 +0000
@@ -0,0 +1,104 @@
1window.onload = function() {
2 var api = external.getUnityObject('1.0');
3 var hub = api.ContentHub;
4
5 var transferState = hub.ContentTransfer.State;
6 var pictureContentType = hub.ContentType.Pictures;
7
8 document.getElementById('pick').addEventListener('click', doContentPeerPicking);
9 function doContentPeerPicking() {
10 hub.launchContentPeerPicker(
11 {
12 contentType: hub.ContentType.Pictures,
13 handler: hub.ContentHandler.Source,
14 },
15 function(peer) {
16 if ( ! peer) {
17 nopeers();
18 return;
19 }
20 addPeerElement(peer.appId(), peer.name());
21 doSimpleApiImport(peer);
22 },
23 function() {
24 aborted();
25 });
26 };
27
28 function addPeerElement(appId, name) {
29 var selectedpeer = document.querySelector('#selected-peer');
30 var span = document.createElement('span');
31
32 var text = document.createTextNode('appId: ' + appId + ', name: ' + name)
33 span.appendChild(text);
34 selectedpeer.appendChild(span);
35 };
36
37 var results = [];
38 function addResult(item) {
39 results.push({name: item.name, url: item.url});
40 renderResults(results);
41 };
42
43 function displayImages(images) {
44 var res = document.getElementById('results');
45 for (var i = 0; i < images.length; ++i) {
46 var img = document.createElement('img');
47
48 img.setAttribute('src', images[i].url);
49 img.setAttribute('height', '100px');
50 img.setAttribute('width', '100px');
51
52 if (images[i].name && images[i].name.length !== 0)
53 img.setAttribute('alt', images[i].name);
54
55 res.appendChild(img);
56 }
57 };
58
59 function aborted() {
60 setResults('Transfer aborted');
61 };
62
63 function nopeers() {
64 setResults('No peers found');
65 };
66
67 function setResults(results) {
68 var resultEl = document.getElementById('results');
69 resultEl.innerHTML = results;
70 };
71
72 function formatResults(results) {
73 var content = '<ul>';
74 for (var i = 0; i < results.length; ++i) {
75 content += '<li>'
76 + results[i].name
77 + ', '
78 + results[i].url
79 + '</li>';
80 }
81 content += '</ul>';
82 return content;
83 };
84
85 function renderResults(results) {
86 setResults(formatResults(results));
87 displayImages(results);
88 };
89
90 function doSimpleApiImport(peer) {
91 hub.api.importContent(pictureContentType
92 , peer
93 , {scope: hub.ContentScope.App}
94 , function(items) {
95 for (var i = 0; i < items.length; ++i) {
96 addResult(items[i]);
97 }
98 }
99 , function() {
100 aborted();
101 });
102 };
103};
104
0105
=== modified file 'src/Ubuntu/UnityWebApps/UnityWebAppsBackendComponents.js'
--- src/Ubuntu/UnityWebApps/UnityWebAppsBackendComponents.js 2014-02-26 13:21:37 +0000
+++ src/Ubuntu/UnityWebApps/UnityWebAppsBackendComponents.js 2014-03-18 13:59:59 +0000
@@ -201,6 +201,14 @@
201 return {object: this._objects[id], id: id};201 return {object: this._objects[id], id: id};
202 },202 },
203203
204 parent: function() {
205 return this._parent;
206 },
207
208 parentView: function() {
209 return this._parent ? this._parent.bindee : null;
210 },
211
204 isObjectProxyInfo: function(info) {212 isObjectProxyInfo: function(info) {
205 return 'type' in info &&213 return 'type' in info &&
206 info.type === 'object-proxy' &&214 info.type === 'object-proxy' &&
@@ -1308,14 +1316,32 @@
1308 // TODO find a better way1316 // TODO find a better way
1309 function _nameToContentType(name) {1317 function _nameToContentType(name) {
1310 var contentTypePerName = {1318 var contentTypePerName = {
1319 "All": ContentHubBridge.ContentType.All,
1320 "Unknown": ContentHubBridge.ContentType.Unknown,
1311 "Pictures": ContentHubBridge.ContentType.Pictures,1321 "Pictures": ContentHubBridge.ContentType.Pictures,
1312 "Documents": ContentHubBridge.ContentType.Pictures,1322 "Documents": ContentHubBridge.ContentType.Documents,
1313 "Music": ContentHubBridge.ContentType.Pictures,1323 "Music": ContentHubBridge.ContentType.Music,
1324 "Contacts": ContentHubBridge.ContentType.Contacts,
1314 };1325 };
1315 return name in contentTypePerName ?1326 return name in contentTypePerName ?
1316 contentTypePerName[name]1327 contentTypePerName[name]
1317 : ContentHubBridge.ContentType.Unknown;1328 : ContentHubBridge.ContentType.Unknown;
1318 };1329 };
1330 function _contentTypeToName(state) {
1331 if (state === ContentHubBridge.ContentType.All)
1332 return "All";
1333 else if (state === ContentHubBridge.ContentType.Unknown)
1334 return "Unknown";
1335 else if (state === ContentHubBridge.ContentType.Pictures)
1336 return "Pictures";
1337 else if (state === ContentHubBridge.ContentType.Documents)
1338 return "Documents";
1339 else if (state === ContentHubBridge.ContentType.Music)
1340 return "Music";
1341 else if (state === ContentHubBridge.ContentType.Contacts)
1342 return "Contacts";
1343 return "Unknown";
1344 };
13191345
1320 function _nameToContentTransferSelection(name) {1346 function _nameToContentTransferSelection(name) {
1321 var contentTypePerName = {1347 var contentTypePerName = {
@@ -1334,10 +1360,31 @@
1334 return "Single";1360 return "Single";
1335 };1361 };
13361362
1363 function _nameToContentHandler(name) {
1364 var contentHandlerPerName = {
1365 "Source": ContentHubBridge.ContentHandler.Source,
1366 "Destination": ContentHubBridge.ContentHandler.Destination,
1367 "Share": ContentHubBridge.ContentHandler.Share,
1368 };
1369 return name in contentHandlerPerName ?
1370 contentHandlerPerName[name]
1371 : ContentHubBridge.ContentHandler.Source;
1372 };
1373 function _contentHandlerToName(state) {
1374 if (state === ContentHubBridge.ContentHandler.Source)
1375 return "Source";
1376 else if (state === ContentHubBridge.ContentHandler.Destination)
1377 return "Destination";
1378 else if (state === ContentHubBridge.ContentHandler.Share)
1379 return "Share";
1380 return "Source";
1381 };
1382
1337 function _nameToContentTransferDirection(name) {1383 function _nameToContentTransferDirection(name) {
1338 var contentTypePerName = {1384 var contentTypePerName = {
1339 "Import": ContentHubBridge.ContentTransfer.Import,1385 "Import": ContentHubBridge.ContentTransfer.Import,
1340 "Export": ContentHubBridge.ContentTransfer.Export,1386 "Export": ContentHubBridge.ContentTransfer.Export,
1387 "Share": ContentHubBridge.ContentTransfer.Share,
1341 };1388 };
1342 return name in contentTypePerName ?1389 return name in contentTypePerName ?
1343 contentTypePerName[name]1390 contentTypePerName[name]
@@ -1348,9 +1395,31 @@
1348 return "Import";1395 return "Import";
1349 else if (state === ContentHubBridge.ContentTransfer.Export)1396 else if (state === ContentHubBridge.ContentTransfer.Export)
1350 return "Export";1397 return "Export";
1398 else if (state === ContentHubBridge.ContentTransfer.Share)
1399 return "Share";
1351 return "Import";1400 return "Import";
1352 };1401 };
13531402
1403 function _nameToContentScope(name) {
1404 var contentScopePerName = {
1405 "System": ContentHubBridge.ContentScope.System,
1406 "User": ContentHubBridge.ContentScope.User,
1407 "App": ContentHubBridge.ContentScope.App,
1408 };
1409 return name in contentScopePerName ?
1410 contentScopePerName[name]
1411 : ContentHubBridge.ContentScope.App;
1412 };
1413 function _contentScopeToName(state) {
1414 if (state === ContentHubBridge.ContentScope.System)
1415 return "System";
1416 else if (state === ContentHubBridge.ContentScope.User)
1417 return "User";
1418 else if (state === ContentHubBridge.ContentScope.App)
1419 return "App";
1420 return "App";
1421 };
1422
1354 function _nameToContentTransferState(name) {1423 function _nameToContentTransferState(name) {
1355 var contentTransferStatePerName = {1424 var contentTransferStatePerName = {
1356 "Created": ContentHubBridge.ContentTransfer.Created,1425 "Created": ContentHubBridge.ContentTransfer.Created,
@@ -1426,6 +1495,8 @@
1426 content: {1495 content: {
1427 store: self._object.store,1496 store: self._object.store,
1428 state: self._object.state,1497 state: self._object.state,
1498 selectionType: self._object.selectionType,
1499 direction: self._object.direction,
1429 }1500 }
1430 }1501 }
1431 },1502 },
@@ -1461,6 +1532,15 @@
1461 if (callback && typeof(callback) === 'function')1532 if (callback && typeof(callback) === 'function')
1462 callback();1533 callback();
1463 },1534 },
1535 onStateChanged: function(callback) {
1536 if (!callback || typeof(callback) !== 'function')
1537 return;
1538 this._validate();
1539 var self = this;
1540 this._object.onStateChanged.connect(function() {
1541 callback(_contentTransferStateToName(self._object.state));
1542 });
1543 },
14641544
1465 selectionType: function(callback) {1545 selectionType: function(callback) {
1466 this._validate();1546 this._validate();
@@ -1504,16 +1584,11 @@
1504 item.object.name = items[i].name;1584 item.object.name = items[i].name;
1505 item.object.url = items[i].url;1585 item.object.url = items[i].url;
15061586
1507 console.debug('setItems: adding item ' + item.object.name.toString()
1508 + ', ' + item.object.url.toString());
1509
1510 contentItems.push(item.object);1587 contentItems.push(item.object);
1511 }1588 }
15121589
1513 this._object.items = contentItems;1590 this._object.items = contentItems;
15141591
1515 console.debug('setItems: grand total of ' + this._object.items.length + ' added');
1516
1517 if (callback && typeof(callback) === 'function')1592 if (callback && typeof(callback) === 'function')
1518 callback();1593 callback();
1519 },1594 },
@@ -1593,12 +1668,24 @@
15931668
1594 content: {1669 content: {
1595 uri: self._object.uri,1670 uri: self._object.uri,
1671 scope: _contentScopeToName(self._object.scope),
1596 }1672 }
1597 }1673 }
1598 },1674 },
15991675
1600 // properties1676 // properties
16011677
1678 scope: function(callback) {
1679 this._validate();
1680 callback(_contentScopeToName(this._object.scope));
1681 },
1682 setScope: function(scope, callback) {
1683 this._validate();
1684 this._object.scope = _nameToContentScope(scope);
1685 if (callback && typeof(callback) === 'function')
1686 callback();
1687 },
1688
1602 //immutable1689 //immutable
1603 uri: function(callback) {1690 uri: function(callback) {
1604 this._validate();1691 this._validate();
@@ -1648,23 +1735,165 @@
1648 content: {1735 content: {
1649 appId: self._object.appId,1736 appId: self._object.appId,
1650 name: self._object.name,1737 name: self._object.name,
1738 handler: self._object.handler,
1739 contentType: self._object.contentType,
1740 selectionType: self._object.selectionType,
1741 isDefaultPeer: self._object.isDefaultPeer,
1651 },1742 },
1652 }1743 }
1653 },1744 },
16541745
1655 // properties1746 // properties
16561747
1657 // immutable
1658 appId: function(callback) {1748 appId: function(callback) {
1659 this._validate();1749 this._validate();
1660 callback(this._object.appId);1750 callback(this._object.appId);
1661 },1751 },
1752 setAppId: function(appId, callback) {
1753 this._validate();
1754 this._object.appId = appId;
1755 if (callback && typeof(callback) === 'function')
1756 callback();
1757 },
1758
1759 handler: function(callback) {
1760 this._validate();
1761 callback(_contentHandlerToName(this._object.handler));
1762 },
1763 setHandler: function(handler, callback) {
1764 this._validate();
1765 this._object.handler = _nameToContentHandler(handler);
1766 if (callback && typeof(callback) === 'function')
1767 callback();
1768 },
1769
1770 contentType: function(callback) {
1771 this._validate();
1772 callback(_contentTypeToName(this._object.contentType));
1773 },
1774 setContentType: function(contentType, callback) {
1775 this._validate();
1776 this._object.contentType = _nameToContentType(contentType);
1777 if (callback && typeof(callback) === 'function')
1778 callback();
1779 },
1780
1781 selectionType: function(callback) {
1782 this._validate();
1783 callback(_contentTransferSelectionToName(this._object.selectionType));
1784 },
1785 setSelectionType: function(selectionType, callback) {
1786 this._validate();
1787 this._object.selectionType = _nameToContentTransferSelection(selectionType);
1788 if (callback && typeof(callback) === 'function')
1789 callback();
1790 },
16621791
1663 // immutable1792 // immutable
1664 name: function(callback) {1793 name: function(callback) {
1665 this._validate();1794 this._validate();
1666 callback(this._object.name);1795 callback(this._object.name);
1667 },1796 },
1797
1798 isDefaultPeer: function(callback) {
1799 this._validate();
1800 callback(this._object.isDefaultPeer);
1801 },
1802
1803 // methods
1804
1805 request: function(callback) {
1806 this._validate();
1807 var transfer = new ContentTransfer(this._object.request());
1808
1809 if (callback && typeof(callback) === 'function')
1810 callback(transfer.serialize());
1811 },
1812
1813 requestForStore: function(store, callback) {
1814 if ( ! store) {
1815 callback(null);
1816 return;
1817 }
1818
1819 if (! backendDelegate.isObjectProxyInfo(store)) {
1820 console.debug('requestForStore: invalid store object proxy')
1821 callback("Invalid store");
1822 return;
1823 }
1824
1825 var _store = backendDelegate.objectFromId(store.objectid);
1826 if ( ! _store) {
1827 callback("Invalid store object (NULL)");
1828 return;
1829 }
1830 this._validate();
1831
1832 var transfer = new ContentTransfer(this._object.request(_store));
1833 if (callback && typeof(callback) === 'function')
1834 callback(transfer.serialize());
1835 },
1836
1837 // internal
1838
1839 internal: {
1840 request: function(self) {
1841 return self._object.request();
1842 }
1843 }
1844 };
1845
1846 function ContentPeerModel(filterParams) {
1847 var result = backendDelegate.createQmlObject(
1848 PLUGIN_URI, VERSION, 'ContentPeerModel', filterParams);
1849 this._id = result.id;
1850 this._object = result.object;
1851
1852 this._modelAdaptor = backendDelegate.createModelAdaptorFor(this._object);
1853 this._roles = this._modelAdaptor.roles();
1854 };
1855 ContentPeerModel.prototype = {
1856 _validate: function() {
1857 if (! this._object)
1858 throw new TypeError("Invalid object null");
1859 },
1860
1861 destroy: function() {
1862 if (! this._object)
1863 return;
1864 this._object.destroy();
1865 this._modelAdaptor.destroy();
1866 backendDelegate.deleteId(this._id);
1867 },
1868
1869 // properties
1870 setContentType: function(contentType, callback) {
1871 this._validate();
1872 this._object.contentType = contentType;
1873 if (callback)
1874 callback();
1875 },
1876
1877 setHandler: function(handler, callback) {
1878 this._validate();
1879 this._object.handler = handler;
1880 if (callback)
1881 callback();
1882 },
1883
1884 peers: function() {
1885 this._validate();
1886 return this._object.peers;
1887 },
1888
1889 // QAbtractListModel prototype
1890 count: function(callback) {
1891 if (!this._modelAdaptor) {
1892 callback(-1);
1893 return;
1894 }
1895 callback(this._modelAdaptor.rowCount());
1896 },
1668 };1897 };
16691898
1670 function _constructorFromName(className) {1899 function _constructorFromName(className) {
@@ -1679,33 +1908,95 @@
1679 }1908 }
16801909
1681 return {1910 return {
1682 defaultSourceForType: function(type, callback) {1911 getPeers: function(filters, callback) {
1683 var _type = _nameToContentType(type);1912 if ( ! filters){
1684 var peer = _contenthub.defaultSourceForType(_type)1913 callback(null);
1685 var source = new ContentPeer(peer);1914 return;
1686 callback(source.serialize());1915 }
1916
1917 var statement = "import QtQuick 2.0; import Ubuntu.Content 0.1; ContentPeerModel {";
1918 var filterParams = {};
1919 if (filters.contentType) {
1920 statement += " contentType: ContentType." + filters.contentType + ";";
1921 }
1922 if (filters.handler) {
1923 statement += " handler: ContentHandler." + filters.handler + ";";
1924 }
1925 statement += " }";
1926
1927 var peerModel = Qt.createQmlObject(statement, backendDelegate.parent());
1928 var onPeersFound = function() {
1929 var peers = peerModel.peers;
1930
1931 var wrappedPeers = [];
1932 for (var i = 0; i < peers.length; ++i) {
1933 var wrappedPeer = new ContentPeer(peers[i]);
1934 wrappedPeers.push(wrappedPeer.serialize());
1935 }
1936 peerModel.onFindPeersCompleted.disconnect(onPeersFound);
1937 callback(wrappedPeers);
1938 };
1939 peerModel.onFindPeersCompleted.connect(onPeersFound);
1687 },1940 },
16881941
1689 defaultStoreForType: function(type, callback) {1942 getStore: function(scope, callback) {
1690 var store = new ContentStore(_contenthub.defaultStoreForType(_nameToContentType(type)));1943 if ( ! scope){
1944 callback(null);
1945 return;
1946 }
1947 var store = new ContentStore();
1948 store.setScope(scope);
1691 callback(store.serialize());1949 callback(store.serialize());
1692 },1950 },
16931951
1694 importContent: function(type, callback) {1952 launchContentPeerPicker: function(filters, onPeerSelected, onCancelPressed) {
1695 var transfer = new ContentTransfer(_contenthub.importContent(_nameToContentType(type)));1953 if ( ! filters){
1696 callback(transfer.serialize());1954 callback(null);
1697 },1955 return;
16981956 }
1699 knownSourcesForType: function(type, callback) {1957
1700 var peers = _contenthub.knownSourcesForType(_nameToContentType(type));1958 var parentItem = backendDelegate.parentView();
1701 var wrappedPeers = [];1959 if ( ! parentItem || ! parentItem.visible || ! parentItem.height || ! parentItem.width) {
17021960 console.debug("Cannot launch the content peer picker UI, invalid parent item: " + parentItem);
1703 for (var i = 0; i < peers.length; ++i) {1961 onCancelPressed();
1704 var wrappedPeer = new ContentPeer(peers[i]);1962 return;
1705 wrappedPeers.push(wrappedPeer.serialize());1963 }
1706 }1964
17071965 var statement = "import QtQuick 2.0; import Ubuntu.Content 0.1; ContentPeerPicker {";
1708 callback(wrappedPeers);1966 var filterParams = {};
1967 if (filters.contentType) {
1968 statement += " contentType: ContentType." + filters.contentType + "";
1969 }
1970 if (filters.handler) {
1971 statement += "; handler: ContentHandler." + filters.handler + "";
1972 }
1973 if (filters.showTitle) {
1974 statement += "; showTitle: " + filters.showTitle === false ? "false" : "true";
1975 }
1976 statement += "; visible: true; }";
1977
1978 if (parentItem.parent)
1979 parentItem.visible = false;
1980 var contentPeerPicker = Qt.createQmlObject(statement,
1981 parentItem.parent ? parentItem.parent : parentItem);
1982 function _onPeerSelected() {
1983 var peer = new ContentPeer(contentPeerPicker.peer);
1984 contentPeerPicker.visible = false;
1985 parentItem.visible = true;
1986 onPeerSelected(peer.serialize());
1987 contentPeerPicker.onPeerSelected.disconnect(_onPeerSelected);
1988 contentPeerPicker.destroy();
1989 }
1990 function _onCancelPressed() {
1991 contentPeerPicker.visible = false;
1992 parentItem.visible = true;
1993 onCancelPressed();
1994 contentPeerPicker.onPeerSelected.disconnect(_onCancelPressed);
1995 contentPeerPicker.destroy();
1996 }
1997
1998 contentPeerPicker.onPeerSelected.connect(_onPeerSelected);
1999 contentPeerPicker.onCancelPressed.connect(_onCancelPressed);
1709 },2000 },
17102001
1711 apiImportContent: function(type, peer, transferOptions, onSuccess, onFailure) {2002 apiImportContent: function(type, peer, transferOptions, onSuccess, onFailure) {
@@ -1714,59 +2005,44 @@
1714 onError("Invalid peer");2005 onError("Invalid peer");
1715 return;2006 return;
1716 }2007 }
2008
1717 var _type = _nameToContentType(type);2009 var _type = _nameToContentType(type);
1718 var _peer = backendDelegate.objectFromId(peer.objectid);2010 var _peer = backendDelegate.objectFromId(peer.objectid);
1719 if ( ! _peer) {2011 if ( ! _peer) {
1720 onError("Invalid peer object (NULL)");2012 onError("Invalid peer object (NULL)");
1721 return;2013 return;
1722 }2014 }
2015 var _transfer = null;
2016 if (transferOptions.scope) {
2017 var store = new ContentStore();
2018 store.setScope(transferOptions.scope);
2019 _transfer = _peer.request(store._object);
2020 }
2021 else {
2022 _transfer = _peer.request();
2023 }
17232024
1724 var transfer = _contenthub.importContent(_type, _peer);
1725 console.log('*** Transfer object: ' + transfer + '')
1726 if (transferOptions.multipleFiles) {2025 if (transferOptions.multipleFiles) {
1727 transfer.selectionType = ContentHubBridge.ContentTransfer.Multiple;2026 _transfer.selectionType = ContentHubBridge.ContentTransfer.Multiple;
1728 }2027 }
1729 else {2028 else {
1730 transfer.selectionType = ContentHubBridge.ContentTransfer.Single;2029 _transfer.selectionType = ContentHubBridge.ContentTransfer.Single;
1731 }2030 }
17322031
1733 if (transferOptions.importToLocalStore) {2032 var transfer = new ContentTransfer(_transfer)
1734 var store = _contenthub.defaultStoreForType(_type);2033 _transfer.stateChanged.connect(function() {
1735 transfer.setStore(store);2034 if (_transfer.state === ContentHubBridge.ContentTransfer.Aborted) {
1736 }
1737
1738 var _transfer = new ContentTransfer(transfer)
1739 transfer.stateChanged.connect(function() {
1740 console.log('** Transfer state change: ' + transfer + ', state: ' + _contentTransferStateToName(transfer.state));
1741 if (transfer.state === ContentHubBridge.ContentTransfer.Aborted) {
1742 onFailure("Aborted");2035 onFailure("Aborted");
1743 return;2036 return;
1744 }2037 }
1745 else if (transfer.state === ContentHubBridge.ContentTransfer.Charged) {2038 else if (_transfer.state === ContentHubBridge.ContentTransfer.Charged) {
1746 console.log('*** Transfer complete: got: ' + transfer.items.length + ' items (' + transfer + ')')2039 var d = transfer.internal.serializeItems(_transfer);
1747 for (var i = 0; i < transfer.items.length; ++i) {
1748 console.log('** item ' + i + ' : ' + transfer.items[i].url);
1749 }
1750
1751 var d = _transfer.internal.serializeItems(transfer);
1752 onSuccess(d);2040 onSuccess(d);
1753 transfer.finalize();2041 _transfer.finalize();
1754 return;2042 return;
1755 }2043 }
1756 });2044 });
1757 transfer.start();2045 _transfer.start();
1758 },
1759
1760 importContentForPeer: function(type, peerProxy, callback) {
1761 if (! backendDelegate.isObjectProxyInfo(peerProxy)) {
1762 console.debug('importContentForPeer: invalid peer object proxy')
1763 callback();
1764 return;
1765 }
1766 var peer = backendDelegate.objectFromId(peerProxy.objectid);
1767 var transfer = new ContentTransfer(_contenthub.importContent(_nameToContentType(type), peer));
1768
1769 callback(transfer.serialize());
1770 },2046 },
17712047
1772 onExportRequested: function(callback) {2048 onExportRequested: function(callback) {
17732049
=== modified file 'src/Ubuntu/UnityWebApps/bindings/content-hub/client/content-hub.js'
--- src/Ubuntu/UnityWebApps/bindings/content-hub/client/content-hub.js 2014-03-04 20:40:16 +0000
+++ src/Ubuntu/UnityWebApps/bindings/content-hub/client/content-hub.js 2014-03-18 13:59:59 +0000
@@ -42,6 +42,10 @@
42 ? content.store : null;42 ? content.store : null;
43 this._state = content && content.state43 this._state = content && content.state
44 ? content.state : null;44 ? content.state : null;
45 this._selectionType = content && content.selectionType
46 ? content.selectionType : null;
47 this._direction = content && content.direction
48 ? content.direction : null;
45 };49 };
46 ContentTransfer.prototype = {50 ContentTransfer.prototype = {
47 // object methods51 // object methods
@@ -77,7 +81,7 @@
77 *81 *
78 * @method setStore82 * @method setStore
79 * @param store {ContentStore}83 * @param store {ContentStore}
80 * @param callback (optional) {Function()}84 * @param callback (optional) {Function()} called when the store has been updated
81 */85 */
82 setStore: function(store, callback) {86 setStore: function(store, callback) {
83 this._proxy.call('setStore', [store.serialize(), callback]);87 this._proxy.call('setStore', [store.serialize(), callback]);
@@ -108,6 +112,15 @@
108 setState: function(state, callback) {112 setState: function(state, callback) {
109 this._proxy.call('setState', [state, callback]);113 this._proxy.call('setState', [state, callback]);
110 },114 },
115 /**
116 * Notifies the listener when the state of the transfer changes.
117 *
118 * @method onStateChanged
119 * @param callback {Function(ContentTransfer.State)}
120 */
121 onStateChanged: function(callback) {
122 this._proxy.call('onStateChanged', [callback]);
123 },
111124
112 /**125 /**
113 * Retrieves the current selection type.126 * Retrieves the current selection type.
@@ -116,7 +129,11 @@
116 * @param callback {Function(ContentTransfer.SelectionType)}129 * @param callback {Function(ContentTransfer.SelectionType)}
117 */130 */
118 selectionType: function(callback) {131 selectionType: function(callback) {
119 this._proxy.call('selectionType', [], callback);132 if (callback && typeof(callback) === 'function') {
133 this._proxy.call('selectionType', [], callback);
134 return;
135 }
136 return this._selectionType;
120 },137 },
121 /**138 /**
122 * Sets the selection type (single or multiple).139 * Sets the selection type (single or multiple).
@@ -126,17 +143,24 @@
126 * @param callback {Function()} called when the state has been updated143 * @param callback {Function()} called when the state has been updated
127 */144 */
128 setSelectionType: function(selectionType, callback) {145 setSelectionType: function(selectionType, callback) {
146 this._selectionType = selectionType;
129 this._proxy.call('setSelectionType', [selectionType, callback]);147 this._proxy.call('setSelectionType', [selectionType, callback]);
130 },148 },
131149
132 /**150 /**
133 * Retrieves the current transfer direction.151 * Retrieves the current transfer direction.
134 *152 *
153 * If the callback parameter is not set, the current "local" value is retrieved.
154 *
135 * @method direction155 * @method direction
136 * @param callback {Function(ContentTransfer.Direction)}156 * @param callback (optional) {Function(ContentTransfer.Direction)}
137 */157 */
138 direction: function(callback) {158 direction: function(callback) {
139 this._proxy.call('direction', [], callback);159 if (callback && typeof(callback) === 'function') {
160 this._proxy.call('direction', [], callback);
161 return;
162 }
163 return this._direction;
140 },164 },
141 /**165 /**
142 * Sets the transfer direction (import or export).166 * Sets the transfer direction (import or export).
@@ -146,6 +170,7 @@
146 * @param callback {Function()} called when the state has been updated170 * @param callback {Function()} called when the state has been updated
147 */171 */
148 setDirection: function(direction, callback) {172 setDirection: function(direction, callback) {
173 this._direction = direction;
149 this._proxy.call('setDirection', [direction, callback]);174 this._proxy.call('setDirection', [direction, callback]);
150 },175 },
151176
@@ -231,6 +256,13 @@
231 ? content.appId : null;256 ? content.appId : null;
232 this._name = content && content.name257 this._name = content && content.name
233 ? content.name : null;258 ? content.name : null;
259 this._handler = content && content.handler
260 ? content.handler : null;
261 this._contentType = content && content.contentType
262 ? content.contentType : null;
263 this._selectionType = content && content.selectionType
264 ? content.selectionType : null;
265 this._isDefaultPeer = content && content.isDefaultPeer;
234 };266 };
235 ContentPeer.prototype = {267 ContentPeer.prototype = {
236 // object methods268 // object methods
@@ -246,14 +278,13 @@
246278
247 // properties279 // properties
248280
249 // immutable
250
251 /**281 /**
252 * Retrieves the app Id of the associated peer.282 * Retrieves the app Id of the associated peer.
253 *283 *
254 * If the callback parameter is not set, the current "local" value is retrieved.284 * If the callback parameter is not set, the current "local" value is retrieved.
255 *285 *
256 * @method appId286 * @method appId
287 * @return {String} Application Id for this peer
257 * @param callback (optional) {Function(String)}288 * @param callback (optional) {Function(String)}
258 */289 */
259 appId: function(callback) {290 appId: function(callback) {
@@ -263,8 +294,97 @@
263 }294 }
264 return this._appId;295 return this._appId;
265 },296 },
266297 /**
267 // immutable298 * Sets the app Id of the associated peer.
299 *
300 * @method setAppId
301 * @param appId {String}
302 * @param callback {Function()} called when the appId has been updated
303 */
304 setAppId: function(appId, callback) {
305 this._proxy.call('setAppId', [appId, callback]);
306 },
307
308 /**
309 * Retrieves the specific ContentHandler for this peer.
310 *
311 * If the callback parameter is not set, the current "local" value is retrieved.
312 *
313 * @method handler
314 * @return {String} ContentHandler for this peer
315 * @param callback (optional) {Function(String)}
316 */
317 handler: function(callback) {
318 if (callback && typeof(callback) === 'function') {
319 this._proxy.call('handler', [], callback);
320 return;
321 }
322 return this._handler;
323 },
324 /**
325 * Sets specific ContentHandler for this peer.
326 *
327 * @method setHandler
328 * @param handler {ContentHandler}
329 * @param callback {Function()} called when the appId has been updated
330 */
331 setHandler: function(handler, callback) {
332 this._proxy.call('setHandler', [handler, callback]);
333 },
334
335 /**
336 * Retrieves the specific ContentType for this peer.
337 *
338 * If the callback parameter is not set, the current "local" value is retrieved.
339 *
340 * @method contentType
341 * @return {String} ContentType for this peer
342 * @param callback (optional) {Function(String)}
343 */
344 contentType: function(callback) {
345 if (callback && typeof(callback) === 'function') {
346 this._proxy.call('contentType', [], callback);
347 return;
348 }
349 return this._contentType;
350 },
351 /**
352 * Sets specific ContentType for this peer.
353 *
354 * @method setContentType
355 * @param contentType {ContentType}
356 * @param callback {Function()} called when the content type has been updated
357 */
358 setContentType: function(contentType, callback) {
359 this._proxy.call('setContentType', [contentType, callback]);
360 },
361
362 /**
363 * Retrieves the specific SelectionType for this peer.
364 *
365 * If the callback parameter is not set, the current "local" value is retrieved.
366 *
367 * @method selectionType
368 * @return {String} ContentTransfer.SelectionType for this peer
369 * @param callback (optional) {Function(String)}
370 */
371 selectionType: function(callback) {
372 if (callback && typeof(callback) === 'function') {
373 this._proxy.call('selectionType', [], callback);
374 return;
375 }
376 return this._selectionType;
377 },
378 /**
379 * Sets specific SelectionType for this peer.
380 *
381 * @method setSelectionType
382 * @param selectionType {ContentTransfer.SelectionType}
383 * @param callback {Function()} called when the content type has been updated
384 */
385 setSelectionType: function(selectionType, callback) {
386 this._proxy.call('setSelectionType', [selectionType, callback]);
387 },
268388
269 /**389 /**
270 * Retrieves the name of the associated peer.390 * Retrieves the name of the associated peer.
@@ -282,6 +402,45 @@
282 return this._name;402 return this._name;
283 },403 },
284404
405 /**
406 * Returns true if the peer is a default one, false otherwise.
407 *
408 * If the callback parameter is not set, the current "local" value is retrieved.
409 *
410 * @method isDefaultPeer
411 * @param callback (optional) {Function(Bool)}
412 */
413 isDefaultPeer: function(callback) {
414 if (callback && typeof(callback) === 'function') {
415 this._proxy.call('isDefaultPeer', [], callback);
416 return;
417 }
418 return this._isDefaultPeer;
419 },
420
421 // methods
422
423 /**
424 * Request to import data from this ContentPeer.
425 *
426 * @method request
427 * @param callback {Function(ContentTransfer)} Called with the resulting content transfer
428 */
429 request: function(callback) {
430 this._proxy.call('request', [], callback);
431 },
432
433 /**
434 * Request to import data from this ContentPeer and use a ContentStore for permanent storage.
435 *
436 * @method requestForStore
437 * @param store {ContentStore} Store used as a permanent storage
438 * @param callback {Function(ContentTransfer)} Called with the resulting content transfer
439 */
440 requestForStore: function(store, callback) {
441 this._proxy.call('requestForStore', [store.serialize()], callback);
442 },
443
285 // extras444 // extras
286445
287 /**446 /**
@@ -321,6 +480,8 @@
321480
322 this._uri = content && content.uri481 this._uri = content && content.uri
323 ? content.uri : null;482 ? content.uri : null;
483 this._scope = content && content.scope
484 ? content.scope : null;
324 };485 };
325 ContentStore.prototype = {486 ContentStore.prototype = {
326 // object methods487 // object methods
@@ -343,6 +504,7 @@
343 * If the callback parameter is not set, the current "local" value is retrieved.504 * If the callback parameter is not set, the current "local" value is retrieved.
344 *505 *
345 * @method uri506 * @method uri
507 * @return {String} current uri
346 * @param callback (optional) {Function(String)}508 * @param callback (optional) {Function(String)}
347 */509 */
348 uri: function(callback) {510 uri: function(callback) {
@@ -353,6 +515,33 @@
353 return this._uri;515 return this._uri;
354 },516 },
355517
518 /**
519 * Retrieves the current scope.
520 *
521 * If the callback parameter is not set, the current "local" value is retrieved.
522 *
523 * @method scope
524 * @return {ContentScope} current scope
525 * @param callback (optional) {Function(ContentScope)}
526 */
527 scope: function(callback) {
528 if (callback && typeof(callback) === 'function') {
529 this._proxy.call('scope', [], callback);
530 return;
531 }
532 return this._scope;
533 },
534 /**
535 * Sets the current scope.
536 *
537 * @method setScope
538 * @param scope {ContentScope}
539 * @param callback {Function()} called when the scope has been updated
540 */
541 setScope: function(scope, callback) {
542 this._proxy.call('setScope', [scope, callback]);
543 },
544
356 // extras545 // extras
357546
358 /**547 /**
@@ -394,7 +583,9 @@
394 Documents583 Documents
395 584
396 Music585 Music
397 586
587 Contacts
588
398 @static589 @static
399 @property ContentType {String}590 @property ContentType {String}
400 591
@@ -406,9 +597,52 @@
406 var pictureContentType = hub.ContentType.Pictures;597 var pictureContentType = hub.ContentType.Pictures;
407 */598 */
408 ContentType: {599 ContentType: {
600 All: "All",
601 Unknown: "Unknown",
409 Pictures: "Pictures",602 Pictures: "Pictures",
410 Documents: "Documents",603 Documents: "Documents",
411 Music: "Music"604 Music: "Music",
605 Contacts: "Contacts",
606 },
607
608 /**
609 ContentHandler is an enumeration of well known content handlers.
610
611 Values:
612
613 Source
614
615 Destination
616
617 Share
618
619 @static
620 @property ContentHandler {String}
621 */
622 ContentHandler: {
623 Source: "Source",
624 Destination: "Destination",
625 Share: "Share",
626 },
627
628 /**
629 ContentScope is an enumeration of well known scope types.
630
631 Values:
632
633 System
634
635 User
636
637 App
638
639 @static
640 @property ContentScope {String}
641 */
642 ContentScope: {
643 System: "System",
644 User: "User",
645 App: "App",
412 },646 },
413647
414 ContentTransfer: {648 ContentTransfer: {
@@ -527,67 +761,46 @@
527 /**761 /**
528 * Creates a ContentPeer object for the given source type.762 * Creates a ContentPeer object for the given source type.
529 *763 *
530 * @method defaultSourceForType764 * @method getPeers
531 * @param type {ContentType} Content type.765 * @param filters {Object} A dictionary of parameters to filter the result. The filtering keys are:
532 * @param callback {Function (ContentPeer)} Function called with the created ContentPeer.766 * - contentType: desired ContentType
533 */767 * - handler: desired ContentHandler
534 defaultSourceForType: function(type, callback) {768 *
535 backendBridge.call('ContentHub.defaultSourceForType',769 * @param callback {Function(List of ContentPeer objects)} Callback that receives the result or null
536 [type],770 */
537 callback);771 getPeers: function(filter, callback) {
538 },772 backendBridge.call('ContentHub.getPeers',
539773 [filter],
540 /**774 callback);
541 * Creates a ContentStore object for the given content type.775 },
542 *776
543 * @method defaultStoreForType777 /**
544 * @param type {ContentType} Content type.778 * Creates a ContentStore object for the given scope type.
545 * @param callback {Function (ContentStore)} Function called with the created ContentStore.779 *
546 */780 * @method getStore
547 defaultStoreForType: function(type, callback) {781 * @param scope {ContentScope} The content scope for the store
548 backendBridge.call('ContentHub.defaultStoreForType',782 * @param callback {Function(ContentStore)} Callback that receives the result or null
549 [type],783 */
550 callback);784 getStore: function(scope, callback) {
551 },785 backendBridge.call('ContentHub.getStore',
552786 [scope],
553 /**787 callback);
554 * Returns all possible peers for the given ContentType.788 },
555 *789
556 * @method knownSourcesForType790 /**
557 * @param type {ContentType} Content type.791 * Launches the content peer picker ui that allows the user to select a peer.
558 * @param callback {Function (Array of ContentPeer)} Function called with the possible ContentPeers.792 *
559 */793 * @method launchContentPeerPicker
560 knownSourcesForType: function(type, callback) {794 * @param filters {Object} A dictionary of parameters to filter the result. The filtering keys are:
561 backendBridge.call('ContentHub.knownSourcesForType',795 * - contentType: desired ContentType
562 [type],796 * - handler: desired ContentHandler
563 callback);797 * - showTitle: boolean value indicating if the title should be visible
564 },798 * @param onPeerSelected {Function(ContentPeer)} Called when the user has selected a peer
565799 * @param onCancelPressed {Function()} Called when the user has pressed cancel
566 /**800 */
567 * Creates a ContentTransfer object for the given content type.801 launchContentPeerPicker: function(filters, onPeerSelected, onCancelPressed) {
568 *802 backendBridge.call('ContentHub.launchContentPeerPicker',
569 * @method importContent803 [filters, onPeerSelected, onCancelPressed]);
570 * @param type {ContentType} Content type.
571 * @param callback {Function(ContentTransfer)} Function called with the created ContentTransfer.
572 */
573 importContent: function(type, callback) {
574 backendBridge.call('ContentHub.importContent',
575 [type],
576 callback);
577 },
578
579 /**
580 * Creates a ContentTransfer object for the given ContentPeer.
581 *
582 * @method importContentForPeer
583 * @param type {ContentType} Content type.
584 * @param peer {ContentPeer} Content peer.
585 * @param callback {Function(ContentTransfer)} Function called with the created ContentTransfer.
586 */
587 importContentForPeer: function(type, peer, callback) {
588 backendBridge.call('ContentHub.importContentForPeer',
589 [type, peer.serialize()],
590 callback);
591 },804 },
592805
593 /**806 /**
@@ -631,7 +844,9 @@
631 * @method api.importContent844 * @method api.importContent
632 * @param type {ContentType} type of the content to import845 * @param type {ContentType} type of the content to import
633 * @param peer {ContentPeer} peer whos content should be imported846 * @param peer {ContentPeer} peer whos content should be imported
634 * @param transferOptions {Object {multipleFiles: {Bool}, importToLocalStore: {Bool}} } the set of options for the transfer847 * @param transferOptions {Object} a dictionary of transfer options. The options are the following:
848 * - multipleFiles {Bool}: specified if a transfer should involve multiple files or not
849 * - scope {ContentScope}: specifies the location where the transferred files should be copied to
635 * @param onError {Function(reason:)} called when the transfer has failed850 * @param onError {Function(reason:)} called when the transfer has failed
636 * @param onSuccess {Function(Array of {ContentItem})} called when the transfer has been a success and items are available851 * @param onSuccess {Function(Array of {ContentItem})} called when the transfer has been a success and items are available
637 */852 */

Subscribers

People subscribed via source and target branches

to all changes: