Skip to content

Commit b8fc3e6

Browse files
committed
MOBILE-1357 links: Create contentlinks component and use it in mmBrowser
1 parent 7b097f9 commit b8fc3e6

File tree

11 files changed

+328
-39
lines changed

11 files changed

+328
-39
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// (C) Copyright 2015 Martin Dougiamas
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
angular.module('mm.core.contentlinks')
16+
17+
/**
18+
* Controller to choose an account to handle content links.
19+
*
20+
* @module mm.core.contentlinks
21+
* @ngdoc controller
22+
* @name mmContentLinksChooseSiteCtrl
23+
*/
24+
.controller('mmContentLinksChooseSiteCtrl', function($scope, $stateParams, $mmSitesManager, $mmUtil, $ionicHistory, $state,
25+
$mmContentLinksDelegate) {
26+
27+
$scope.url = $stateParams.url || '';
28+
29+
function leaveView() {
30+
$mmSitesManager.logout().finally(function() {
31+
$ionicHistory.nextViewOptions({
32+
disableAnimate: true,
33+
disableBack: true
34+
});
35+
$state.go('mm_login.sites');
36+
});
37+
}
38+
39+
if (!$scope.url) {
40+
leaveView();
41+
return;
42+
}
43+
44+
$mmSitesManager.getSiteIdsFromUrl($scope.url, false).then(function(ids) {
45+
if (!ids.length) {
46+
$mmUtil.showErrorModal('mm.contentlinks.errornosites', true);
47+
leaveView();
48+
return;
49+
}
50+
51+
$mmSitesManager.getSites(ids).then(function(sites) {
52+
$scope.sites = sites;
53+
});
54+
});
55+
56+
$scope.siteClicked = function(siteId) {
57+
// Get actions to treat the link.
58+
var actions = $mmContentLinksDelegate.getActionsFor($scope.url);
59+
if (actions && actions.length) {
60+
for (var i = 0; i < actions.length; i++) {
61+
if (actions[i] && angular.isFunction(actions[i].action)) {
62+
actions[i].action(siteId);
63+
return;
64+
}
65+
}
66+
}
67+
68+
// No action found.
69+
$mmUtil.showErrorModal('mm.contentlinks.errornoactions', true);
70+
$scope.cancel();
71+
};
72+
73+
$scope.cancel = function() {
74+
leaveView();
75+
};
76+
77+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"chooseaccount": "Choose account",
3+
"chooseaccounttoopenlink": "Choose an account to open the link with.",
4+
"confirmurlothersite": "This link belongs to another site. Do you want to open it?",
5+
"errornoactions": "Couldn't find an action to perform with this link.",
6+
"errornosites": "Couldn't find any site to handle this link."
7+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// (C) Copyright 2015 Martin Dougiamas
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
angular.module('mm.core.contentlinks', [])
16+
17+
.config(function($stateProvider) {
18+
19+
$stateProvider
20+
21+
.state('mm_contentlinks', {
22+
url: '/mm_contentlinks',
23+
abstract: true,
24+
templateUrl: 'core/components/contentlinks/templates/base.html',
25+
cache: false, // Disable caching to force controller reload.
26+
})
27+
28+
.state('mm_contentlinks.choosesite', {
29+
url: '/choosesite',
30+
templateUrl: 'core/components/contentlinks/templates/choosesite.html',
31+
controller: 'mmContentLinksChooseSiteCtrl',
32+
params: {
33+
url: null
34+
}
35+
});
36+
});

www/core/lib/contentlinksdelegate.js renamed to www/core/components/contentlinks/services/delegate.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
angular.module('mm.core')
15+
angular.module('mm.core.contentlinks')
1616

1717
/**
1818
* Service to handle links found in contents. Allows to capture links in content and redirect to certain parts
1919
* of the app instead of opening them in browser.
2020
*
21-
* @module mm.core
21+
* @module mm.core.contentlinks
2222
* @ngdoc provider
2323
* @name $mmContentLinksDelegate
2424
*/
@@ -29,7 +29,7 @@ angular.module('mm.core')
2929
/**
3030
* Register a link handler.
3131
*
32-
* @module mm.core
32+
* @module mm.core.contentlinks
3333
* @ngdoc method
3434
* @name $mmContentLinksDelegateProvider#registerLinkHandler
3535
* @param {String} name Handler's name.
@@ -68,23 +68,23 @@ angular.module('mm.core')
6868
/**
6969
* Get the list of possible actions to do for a URL.
7070
*
71-
* @module mm.core
71+
* @module mm.core.contentlinks
7272
* @ngdoc method
7373
* @name $mmContentLinksDelegate#getLinkHandlersFor
7474
* @param {String} url URL to handle.
75-
* @param {Number} [courseid] Course ID related to the URL. Optional but recommended since some handlers might require
75+
* @param {Number} [courseId] Course ID related to the URL. Optional but recommended since some handlers might require
7676
* to know the courseid if Moodle version is previous to 3.0.
7777
* @return {Object[]} Actions. See {@link $mmContentLinksDelegate#registerLinkHandler}.
7878
*/
79-
self.getActionsFor = function(url, courseid) {
79+
self.getActionsFor = function(url, courseId) {
8080
if (!url) {
8181
return [];
8282
}
8383

8484
var linkActions = {};
8585
angular.forEach(enabledLinkHandlers, function(handler) {
8686
if (handler.instance && angular.isFunction(handler.instance.getActions)) {
87-
var actions = handler.instance.getActions(url, courseid);
87+
var actions = handler.instance.getActions(url, courseId);
8888
if (actions && actions.length) {
8989
linkActions[handler.priority] = actions;
9090
}
@@ -120,7 +120,7 @@ angular.module('mm.core')
120120
/**
121121
* Update the enabled link handlers for the current site.
122122
*
123-
* @module mm.core
123+
* @module mm.core.contentlinks
124124
* @ngdoc method
125125
* @name $mmContentLinksDelegate#updateLinkHandler
126126
* @param {String} name The handler name.
@@ -159,7 +159,7 @@ angular.module('mm.core')
159159
/**
160160
* Update the link handlers for the current site.
161161
*
162-
* @module mm.core
162+
* @module mm.core.contentlinks
163163
* @ngdoc method
164164
* @name $mmContentLinksDelegate#updateLinkHandlers
165165
* @return {Promise} Resolved when done.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// (C) Copyright 2015 Martin Dougiamas
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
angular.module('mm.core.contentlinks')
16+
17+
/**
18+
* Service to provide some helper functionalities for the contentlinks component.
19+
*
20+
* @module mm.core.contentlinks
21+
* @ngdoc service
22+
* @name $mmContentLinksHelper
23+
*/
24+
.factory('$mmContentLinksHelper', function($log, $ionicHistory, $state, $mmSite, $mmSitesManager, $mmContentLinksDelegate, $q,
25+
$mmUtil, $translate) {
26+
27+
$log = $log.getInstance('$mmContentLinksHelper');
28+
29+
var self = {};
30+
31+
/**
32+
* Go to the view to choose a site.
33+
*
34+
* @module mm.core.contentlinks
35+
* @ngdoc method
36+
* @name $mmContentLinksHelper#goToChooseSite
37+
* @param {String} url URL to treat.
38+
* @return {Promise} Promise resolved when the state changes.
39+
*/
40+
self.goToChooseSite = function(url) {
41+
$ionicHistory.nextViewOptions({
42+
disableBack: true
43+
});
44+
return $state.go('mm_contentlinks.choosesite', {url: url});
45+
};
46+
47+
/**
48+
* Handle a link.
49+
*
50+
* @module mm.core.contentlinks
51+
* @ngdoc method
52+
* @name $mmContentLinksHelper#handleLink
53+
* @param {String} url URL to handle.
54+
* @return {Promise} Promise resolved with a boolean: true if URL was treated, false otherwise.
55+
*/
56+
self.handleLink = function(url) {
57+
58+
// Check if the link should be treated by some component/addon.
59+
// We perform this check first because it's synchronous.
60+
var actions = $mmContentLinksDelegate.getActionsFor(url);
61+
if (actions && actions.length) {
62+
for (var i = 0; i < actions.length; i++) {
63+
var action = actions[i];
64+
if (action && angular.isFunction(action.action)) {
65+
66+
// We found a valid action. We need to check if the link belongs to any site stored.
67+
return $mmSitesManager.getSiteIdsFromUrl(url, true).then(function(ids) {
68+
if (!ids.length) {
69+
// URL doesn't belong to any site.
70+
return false;
71+
} else if (ids.length == 1 && ids[0] == $mmSite.getId()) {
72+
// Current site.
73+
action.action(ids[0]);
74+
} else {
75+
// Not current site. Ask for confirmation.
76+
$mmUtil.showConfirm($translate('mm.contentlinks.confirmurlothersite')).then(function() {
77+
if (ids.length == 1) {
78+
action.action(ids[0]);
79+
} else {
80+
self.goToChooseSite(url);
81+
}
82+
});
83+
}
84+
return true;
85+
}).catch(function() {
86+
return false;
87+
});
88+
}
89+
}
90+
}
91+
92+
// No valid actions found.
93+
return $q.when(false);
94+
};
95+
96+
return self;
97+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<ion-nav-bar class="bar-content">
2+
<ion-nav-back-button></ion-nav-back-button>
3+
</ion-nav-bar>
4+
<ion-nav-view>
5+
</ion-nav-view>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<ion-view view-title="{{ 'mm.contentlinks.chooseaccount' | translate }}">
2+
<ion-content>
3+
<div class="list">
4+
<div class="item item-text-wrap">
5+
<h2>{{ 'mm.contentlinks.chooseaccounttoopenlink' | translate }}</h2>
6+
<p>{{ url }}</p>
7+
</div>
8+
<ion-item class="item item-thumbnail-left" ng-repeat="site in sites track by $index" ng-click="siteClicked(site.id)">
9+
<img ng-src="{{site.avatar}}">
10+
<h2>{{site.fullname}}</h2>
11+
<p><mm-format-text clean="true" watch="true">{{site.sitename}}</mm-format-text></p>
12+
<p>{{site.siteurl}}</p>
13+
</ion-item>
14+
<div class="item">
15+
<button class="button button-block" ng-click="cancel()">{{ 'mm.login.cancel' | translate }}</button>
16+
</div>
17+
</div>
18+
</ion-content>
19+
</ion-view>

www/core/components/login/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ angular.module('mm.core.login', [])
113113
return;
114114
}
115115

116-
if (toState.name.substr(0, 8) === 'redirect') {
116+
if (toState.name.substr(0, 8) === 'redirect' || toState.name.substr(0, 15) === 'mm_contentlinks') {
117117
return;
118118
} else if ((toState.name.substr(0, 8) !== 'mm_login' || toState.name === 'mm_login.reconnect') && !$mmSite.isLoggedIn()) {
119119
// We are not logged in.

www/core/directives/browser.js

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ angular.module('mm.core')
2121
* @ngdoc directive
2222
* @name mmBrowser
2323
*/
24-
.directive('mmBrowser', function($mmUtil, $mmContentLinksDelegate) {
24+
.directive('mmBrowser', function($mmUtil, $mmContentLinksHelper) {
25+
2526
return {
2627
restrict: 'A',
2728
priority: 100,
@@ -32,26 +33,19 @@ angular.module('mm.core')
3233
event.preventDefault();
3334
event.stopPropagation();
3435

35-
// Check if the link should be treated by some component/addon.
36-
var actions = $mmContentLinksDelegate.getActionsFor(href);
37-
if (actions && actions.length) {
38-
for (var i = 0; i < actions.length; i++) {
39-
if (actions[i] && angular.isFunction(actions[i].action)) {
40-
actions[i].action();
41-
return; // We can only execute 1 action.
36+
$mmContentLinksHelper.handleLink(href).then(function(treated) {
37+
if (!treated) {
38+
if (href.indexOf('cdvfile://') === 0 || href.indexOf('file://') === 0) {
39+
// We have a local file.
40+
$mmUtil.openFile(href).catch(function(error) {
41+
$mmUtil.showErrorModal(error);
42+
});
43+
} else {
44+
// It's an external link, we will open with browser.
45+
$mmUtil.openInBrowser(href);
4246
}
4347
}
44-
}
45-
46-
if (href.indexOf('cdvfile://') === 0 || href.indexOf('file://') === 0) {
47-
// We have a local file.
48-
$mmUtil.openFile(href).catch(function(error) {
49-
$mmUtil.showErrorModal(error);
50-
});
51-
} else {
52-
// It's an external link, we will open with browser.
53-
$mmUtil.openInBrowser(href);
54-
}
48+
});
5549
}
5650
});
5751
}

www/core/lib/sitesfactory.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ angular.module('mm.core')
766766
}
767767
var siteurl = $mmText.removeProtocolAndWWW(this.siteurl);
768768
url = $mmText.removeProtocolAndWWW(url);
769-
return url.indexOf(siteurl) > -1;
769+
return url.indexOf(siteurl) == 0;
770770
};
771771

772772
/**

0 commit comments

Comments
 (0)