Skip to content

Commit 32024a5

Browse files
committed
MOBILE-1554 utils: Implement $mmUtil#openOnlineFile
1 parent ebb97da commit 32024a5

File tree

4 files changed

+162
-37
lines changed

4 files changed

+162
-37
lines changed

www/core/lib/filepool.js

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ angular.module('mm.core')
176176
$log = $log.getInstance('$mmFilepool');
177177

178178
var self = {},
179-
extensionRegex = new RegExp('^[a-z0-9]+$'),
180179
tokenRegex = new RegExp('(\\?|&)token=([A-Za-z0-9]+)'),
181180
queueState,
182181
urlAttributes = [
@@ -1238,7 +1237,7 @@ angular.module('mm.core')
12381237
// part of the file name. Also, we need the mimetype to open the file with web intents. The easiest way to
12391238
// provide such information is to keep the extension in the file ID. Developers should not care about it,
12401239
// but as we are using the file ID in the file path, devs and system can guess it.
1241-
candidate = self._guessExtensionFromUrl(url);
1240+
candidate = $mmText.guessExtensionFromUrl(url);
12421241
if (candidate && candidate !== 'php') {
12431242
extension = '.' + candidate;
12441243
}
@@ -1274,7 +1273,7 @@ angular.module('mm.core')
12741273
// web intents. The easiest way to provide such information is to keep the extension
12751274
// in the file ID. Developers should not care about it, but as we are using the
12761275
// file ID in the file path, devs and system can guess it.
1277-
candidate = self._guessExtensionFromUrl(url);
1276+
candidate = $mmText.guessExtensionFromUrl(url);
12781277
if (candidate && candidate !== 'php') {
12791278
extension = '.' + candidate;
12801279
}
@@ -1701,33 +1700,6 @@ angular.module('mm.core')
17011700
return self._getFileUrlByUrl(siteId, fileUrl, 'url', component, componentId, timemodified, checkSize);
17021701
};
17031702

1704-
/**
1705-
* Guess the extension of a file from its URL.
1706-
*
1707-
* This is very weak and unreliable.
1708-
*
1709-
* @module mm.core
1710-
* @ngdoc method
1711-
* @name $mmFilepool#_guessExtensionFromUrl
1712-
* @param {String} fileUrl The file URL.
1713-
* @return {String} The lowercased extension without the dot, or undefined.
1714-
* @protected
1715-
*/
1716-
self._guessExtensionFromUrl = function(fileUrl) {
1717-
var split = fileUrl.split('.'),
1718-
candidate,
1719-
extension;
1720-
1721-
if (split.length > 1) {
1722-
candidate = split.pop().toLowerCase();
1723-
if (extensionRegex.test(candidate)) {
1724-
extension = candidate;
1725-
}
1726-
}
1727-
1728-
return extension;
1729-
};
1730-
17311703
/**
17321704
* Guess the filename of a file from its URL.
17331705
*

www/core/lib/text.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ angular.module('mm.core')
2323
*/
2424
.factory('$mmText', function($q, $mmLang, $translate) {
2525

26-
var self = {};
26+
var self = {},
27+
extensionRegex = new RegExp('^[a-z0-9]+$');
2728

2829
/**
2930
* Convert size in bytes into human readable format
@@ -322,5 +323,31 @@ angular.module('mm.core')
322323
return filename;
323324
};
324325

326+
/**
327+
* Guess the extension of a file from its URL.
328+
*
329+
* This is very weak and unreliable.
330+
*
331+
* @module mm.core
332+
* @ngdoc method
333+
* @name $mmText#guessExtensionFromUrl
334+
* @param {String} fileUrl The file URL.
335+
* @return {String} The lowercased extension without the dot, or undefined.
336+
*/
337+
self.guessExtensionFromUrl = function(fileUrl) {
338+
var split = fileUrl.split('.'),
339+
candidate,
340+
extension;
341+
342+
if (split.length > 1) {
343+
candidate = split.pop().toLowerCase();
344+
if (extensionRegex.test(candidate)) {
345+
extension = candidate;
346+
}
347+
}
348+
349+
return extension;
350+
};
351+
325352
return self;
326353
});

www/core/lib/util.js

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ angular.module('mm.core')
6666
};
6767

6868
this.$get = function($ionicLoading, $ionicPopup, $injector, $translate, $http, $log, $q, $mmLang, $mmFS, $timeout, $mmApp,
69-
$mmText, mmCoreWifiDownloadThreshold, mmCoreDownloadThreshold, $ionicScrollDelegate, $cordovaInAppBrowser) {
69+
$mmText, mmCoreWifiDownloadThreshold, mmCoreDownloadThreshold, $ionicScrollDelegate, $mmWS, $cordovaInAppBrowser) {
7070

7171
$log = $log.getInstance('$mmUtil');
7272

@@ -270,7 +270,7 @@ angular.module('mm.core')
270270
*
271271
* node-webkit: Using the default application configured.
272272
* Android: Using the WebIntent plugin.
273-
* iOs: Using the window.open method.
273+
* iOs: Using handleDocumentWithURL.
274274
*
275275
* @module mm.core
276276
* @ngdoc method
@@ -423,6 +423,79 @@ angular.module('mm.core')
423423
$cordovaInAppBrowser.close();
424424
};
425425

426+
/**
427+
* Open an online file using platform specific method.
428+
*
429+
* node-webkit: Using the default application configured.
430+
* Android: Using the WebIntent plugin.
431+
* iOs: Using the window.open method.
432+
*
433+
* @module mm.core
434+
* @ngdoc method
435+
* @name $mmUtil#openOnlineFile
436+
* @param {String} url The URL of the file.
437+
* @return {Promise} Promise resolved when opened.
438+
*/
439+
self.openOnlineFile = function(url) {
440+
var deferred = $q.defer();
441+
442+
if (false) {
443+
// @todo Restore node-webkit support.
444+
445+
// Link is the file path in the file system.
446+
// We use the node-webkit shell for open the file (pdf, doc) using the default application configured in the os.
447+
// var gui = require('nw.gui');
448+
// gui.Shell.openItem(path);
449+
deferred.resolve();
450+
451+
} else if (ionic.Platform.isAndroid() && window.plugins && window.plugins.webintent) {
452+
// In Android we need the mimetype to open it.
453+
var extension,
454+
iParams;
455+
456+
$mmWS.getRemoteFileMimeType(url).then(function(mimetype) {
457+
if (!mimetype) {
458+
// Couldn't retireve mimetype. Try to guess it.
459+
extension = $mmText.guessExtensionFromUrl(url);
460+
mimetype = $mmFS.getMimeType(extension);
461+
}
462+
463+
iParams = {
464+
action: "android.intent.action.VIEW",
465+
url: url,
466+
type: mimetype
467+
};
468+
469+
window.plugins.webintent.startActivity(
470+
iParams,
471+
function() {
472+
$log.debug('Intent launched');
473+
deferred.resolve();
474+
},
475+
function() {
476+
$log.debug('Intent launching failed.');
477+
$log.debug('action: ' + iParams.action);
478+
$log.debug('url: ' + iParams.url);
479+
$log.debug('type: ' + iParams.type);
480+
481+
if (!extension || extension.indexOf('/') > -1 || extension.indexOf('\\') > -1) {
482+
// Extension not found.
483+
$mmLang.translateAndRejectDeferred(deferred, 'mm.core.erroropenfilenoextension');
484+
} else {
485+
$mmLang.translateAndRejectDeferred(deferred, 'mm.core.erroropenfilenoapp');
486+
}
487+
}
488+
);
489+
});
490+
} else {
491+
$log.debug('Opening remote file using window.open()');
492+
window.open(url, '_blank');
493+
deferred.resolve();
494+
}
495+
496+
return deferred.promise;
497+
};
498+
426499
/**
427500
* Displays a loading modal window.
428501
*

www/core/lib/ws.js

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ angular.module('mm.core')
2121
* @ngdoc service
2222
* @name $mmWS
2323
*/
24-
.factory('$mmWS', function($http, $q, $log, $mmLang, $cordovaFileTransfer, $mmApp, $mmFS, $mmText, mmCoreSessionExpired,
25-
mmCoreUserDeleted, $translate, $window, $mmUtil) {
24+
.factory('$mmWS', function($http, $q, $log, $mmLang, $cordovaFileTransfer, $mmApp, $mmFS, mmCoreSessionExpired,
25+
mmCoreUserDeleted, $translate, $window) {
2626

2727
$log = $log.getInstance('$mmWS');
2828

@@ -216,7 +216,7 @@ angular.module('mm.core')
216216
* @module mm.core
217217
* @ngdoc method
218218
* @name $mmWS#getRemoteFileSize
219-
* @param {Object} uri File URI.
219+
* @param {Object} url File URL.
220220
* @return {Promise} Promise resolved with the size or -1 if failure.
221221
*/
222222
self.getRemoteFileSize = function(url) {
@@ -231,6 +231,23 @@ angular.module('mm.core')
231231
});
232232
};
233233

234+
/*
235+
* Perform a HEAD request to get the mimetype of a remote file.
236+
*
237+
* @module mm.core
238+
* @ngdoc method
239+
* @name $mmWS#getRemoteFileMimeType
240+
* @param {Object} url File URL.
241+
* @return {Promise} Promise resolved with the mimetype or '' if failure.
242+
*/
243+
self.getRemoteFileMimeType = function(url) {
244+
return $http.head(url).then(function(data) {
245+
return data.headers('Content-Type') || '';
246+
}).catch(function() {
247+
return '';
248+
});
249+
};
250+
234251
/**
235252
* A wrapper function for a synchronous Moodle WebService call.
236253
* Warning: This function should only be used if synchronous is a must. It's recommended to use $mmWS#call.
@@ -276,7 +293,7 @@ angular.module('mm.core')
276293
siteurl = preSets.siteurl + '/webservice/rest/server.php?moodlewsrestformat=json';
277294

278295
// Serialize data.
279-
data = $mmUtil.param(data);
296+
data = serializeParams(data);
280297

281298
// Perform sync request using XMLHttpRequest.
282299
xhr = new $window.XMLHttpRequest();
@@ -331,6 +348,42 @@ angular.module('mm.core')
331348
return data;
332349
};
333350

351+
/**
352+
* Serialize an object to be used in a request.
353+
*
354+
* @param {Object} obj Object to serialize.
355+
* @return {String} Serialization of the object.
356+
*/
357+
function serializeParams(obj) {
358+
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
359+
360+
for (name in obj) {
361+
value = obj[name];
362+
363+
if (value instanceof Array) {
364+
for (i = 0; i < value.length; ++i) {
365+
subValue = value[i];
366+
fullSubName = name + '[' + i + ']';
367+
innerObj = {};
368+
innerObj[fullSubName] = subValue;
369+
query += serializeParams(innerObj) + '&';
370+
}
371+
}
372+
else if (value instanceof Object) {
373+
for (subName in value) {
374+
subValue = value[subName];
375+
fullSubName = name + '[' + subName + ']';
376+
innerObj = {};
377+
innerObj[fullSubName] = subValue;
378+
query += serializeParams(innerObj) + '&';
379+
}
380+
}
381+
else if (value !== undefined && value !== null) query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
382+
}
383+
384+
return query.length ? query.substr(0, query.length - 1) : query;
385+
}
386+
334387
return self;
335388

336389
});

0 commit comments

Comments
 (0)