Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 80 additions & 43 deletions www/addons/mod_chat/controllers/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ angular.module('mm.addons.mod_chat')
* @name mmaModChatChatCtrl
*/
.controller('mmaModChatChatCtrl', function($scope, $stateParams, $mmApp, $mmaModChat, $log, $ionicModal, $mmUtil, $ionicHistory,
$ionicScrollDelegate, $timeout, $mmSite, $interval, mmaChatPollInterval) {
$ionicScrollDelegate, $timeout, $mmSite, $interval, mmaChatPollInterval, $q) {

$log = $log.getInstance('mmaModChatChatCtrl');

var chatId = $stateParams.chatid,
courseId = $stateParams.courseid,
title = $stateParams.title,
polling;
chatLastTime = 0,
pollingRunning = false;

$scope.loaded = false;
$scope.title = title;
Expand All @@ -42,7 +43,6 @@ angular.module('mm.addons.mod_chat')
$scope.newMessage = {
text: ''
};
chatLastTime = 0;

// Chat users modal.
$ionicModal.fromTemplateUrl('addons/mod_chat/templates/users.html', {
Expand Down Expand Up @@ -87,13 +87,69 @@ angular.module('mm.addons.mod_chat')
return !$mmApp.isOnline();
};

// Convenience function to login the user.
function loginUser() {
return $mmaModChat.loginUser(chatId).then(function(chatsid) {
$scope.chatsid = chatsid;
});
}

// Convenience function to get chat messages.
function getMessages() {
return $mmaModChat.getLatestMessages($scope.chatsid, chatLastTime).then(function(messagesInfo) {
chatLastTime = messagesInfo.chatnewlasttime;
return $mmaModChat.getMessagesUserData(messagesInfo.messages, courseId).then(function(messages) {
$scope.messages = $scope.messages.concat(messages);
});
});
}

// Show error modal.
function showError(error, defaultMessage) {
if (typeof error === 'string') {
$mmUtil.showErrorModal(error);
} else {
$mmUtil.showErrorModal(defaultMessage, true);
}
return $q.reject();
}

// Start the polling to get chat messages periodically.
function startPolling() {
// We already have the polling in place.
if ($scope.polling) {
return;
}

// Start polling.
$scope.polling = $interval(getMessagesInterval, mmaChatPollInterval);
}

// Convenience function to be called every certain time to get chat messages.
function getMessagesInterval() {
$log.debug('Polling for messages');
if (!$mmApp.isOnline() || pollingRunning) {
// Obviously we cannot check for new messages when the app is offline.
return $q.reject();
}

pollingRunning = true;

return getMessages().catch(function() {
// Try to login, it might have failed because the session expired.
return loginUser().then(function() {
return getMessages();
}).catch(function(error) {
// Fail again. Stop polling if needed.
if ($scope.polling) {
$interval.cancel($scope.polling);
$scope.polling = undefined;
}
return showError(error, 'mma.mod_chat.errorwhileretrievingmessages');
});
}).finally(function() {
pollingRunning = false;
});
}

// Check if the date should be displayed between messages (when the day changes at midnight for example).
Expand Down Expand Up @@ -123,6 +179,7 @@ angular.module('mm.addons.mod_chat')
if (beep === '') {
$scope.newMessage.text = '';
}
getMessagesInterval(); // Update messages to show the sent message.
}, function(error) {
// Only close the keyboard if an error happens, we want the user to be able to send multiple
// messages withoutthe keyboard being closed.
Expand All @@ -132,16 +189,24 @@ angular.module('mm.addons.mod_chat')
});
};

$scope.reconnect = function() {
var modal = $mmUtil.showModalLoading();

// Call startPolling would take a while for the first execution, so we'll execute it manually to check if it works now.
return getMessagesInterval().then(function() {
// It works, start the polling again.
startPolling();
}).finally(function() {
modal.dismiss();
});
};

// Login the user.
$mmaModChat.loginUser(chatId).then(function(chatsid) {
return $mmaModChat.getLatestMessages(chatsid, 0).then(function(messagesInfo) {
$scope.chatsid = chatsid;
chatLastTime = messagesInfo.chatnewlasttime;
return $mmaModChat.getMessagesUserData(messagesInfo.messages, courseId).then(function(messages) {
$scope.messages = $scope.messages.concat(messages);
});
}).catch(function(message) {
showError(message, 'mma.mod_chat.errorwhileretrievingmessages');
loginUser().then(function() {
return getMessages().then(function() {
startPolling();
}).catch(function(error) {
return showError(error, 'mma.mod_chat.errorwhileretrievingmessages');
});
}, function(error) {
showError(error, 'mma.mod_chat.errorwhileconnecting');
Expand All @@ -161,39 +226,11 @@ angular.module('mm.addons.mod_chat')
}
};

// Set up the polling on a view enter, this allows for the user to go back and resume the polling.
$scope.$on('$ionicView.enter', function() {
// Strange case, we already have the polling in place.
if (polling) {
return;
}

// Start polling.
polling = $interval(function() {
$log.debug('Polling for messages');
if (!$mmApp.isOnline()) {
// Obviously we cannot check for new messages when the app is offline.
return;
}

$mmaModChat.getLatestMessages($scope.chatsid, chatLastTime).then(function(data) {
chatLastTime = data.chatnewlasttime;
$mmaModChat.getMessagesUserData(data.messages, courseId).then(function(messages) {
$scope.messages = $scope.messages.concat(messages);
});
}, function(error) {
$interval.cancel(polling);
showError(error, 'mma.mod_chat.errorwhileretrievingmessages');
});

}, mmaChatPollInterval);
});

// Removing the polling as we leave the page.
$scope.$on('$ionicView.leave', function(e) {
if (polling) {
$scope.$on('$ionicView.leave', function() {
if ($scope.polling) {
$log.debug('Cancelling polling for conversation');
$interval.cancel(polling);
$interval.cancel($scope.polling);
}
});

Expand Down
8 changes: 8 additions & 0 deletions www/addons/mod_chat/scss/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@ $mma-chat-notice-badge: "stable" !default;
margin: 0;
width: 100%;
}

.mma-chat-send-form {
width: 100%;
}

.mma-chat-reconnect-button, .button.mma-chat-reconnect-button {
margin: 0;
}
9 changes: 5 additions & 4 deletions www/addons/mod_chat/services/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,13 @@ angular.module('mm.addons.mod_chat')
var params = {
chatsid: chatsid,
chatlasttime: lasttime
};
var preSets = {
getFromCache: false
}, preSets = {
emergencyCache: false
};

return $mmSite.read('mod_chat_get_chat_latest_messages', params, preSets);
// We use write to not use cache. It doesn't make sense to store the messages in cache
// because we won't be able to retireve them if $mmaModChat#loginUser fails.
return $mmSite.write('mod_chat_get_chat_latest_messages', params, preSets);
};

/**
Expand Down
3 changes: 2 additions & 1 deletion www/addons/mod_chat/templates/chat.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ <h2>{{ message.userfullname }}</h2>

<ion-footer-bar>
<p class="mma-chat-footer-note" ng-if="isAppOffline()">{{ 'mma.mod_chat.mustbeonlinetosendmessages' | translate }}</p>
<form ng-if="!isAppOffline()" ng-submit="sendMessage(newMessage.text);" style="width: 100%">
<form ng-if="!isAppOffline() && polling && loaded" class="mma-chat-send-form" ng-submit="sendMessage(newMessage.text);">
<div class="mma-chat-input-inset item-input-inset">
<label class="item-input-wrapper">
<input type="text" placeholder="{{ 'mma.mod_chat.entermessage' | translate }}" ng-model="newMessage.text" style="width: 100%;">
</label>
<button type="submit" class="button button-clear" ng-disabled="!newMessage.text">{{ 'mma.mod_chat.send' | translate}}</button>
</div>
</form>
<button ng-if="!isAppOffline() && !polling && loaded" class="button button-block mma-chat-reconnect-button" ng-click="reconnect()">{{ 'mm.login.reconnect' | translate }}</button>
</ion-footer-bar>