diff --git a/scripts/langindex.json b/scripts/langindex.json index e096f7155..9f1566add 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -178,6 +178,7 @@ "addon.messages.nogroupmessages": "message", "addon.messages.nomessages": "message", "addon.messages.nousersfound": "local_moodlemobileapp", + "addon.messages.numparticipants": "message", "addon.messages.removecontact": "message", "addon.messages.removecontactconfirm": "local_moodlemobileapp", "addon.messages.showdeletemessages": "local_moodlemobileapp", @@ -188,6 +189,7 @@ "addon.messages.type_strangers": "local_moodlemobileapp", "addon.messages.unblockuser": "message", "addon.messages.unblockuserconfirm": "message", + "addon.messages.warningconversationmessagenotsent": "local_moodlemobileapp", "addon.messages.warningmessagenotsent": "local_moodlemobileapp", "addon.messages.you": "message", "addon.mod_assign.acceptsubmissionstatement": "local_moodlemobileapp", diff --git a/src/addon/messages/lang/en.json b/src/addon/messages/lang/en.json index 1311eb52a..a95948ee2 100644 --- a/src/addon/messages/lang/en.json +++ b/src/addon/messages/lang/en.json @@ -30,6 +30,7 @@ "nogroupmessages": "No group messages", "nomessages": "No messages", "nousersfound": "No users found", + "numparticipants": "{{$a}} participants", "removecontact": "Remove contact", "removecontactconfirm": "Contact will be removed from your contacts list.", "showdeletemessages": "Show delete messages", diff --git a/src/addon/messages/pages/conversation-info/conversation-info.html b/src/addon/messages/pages/conversation-info/conversation-info.html new file mode 100644 index 000000000..0aaee5df7 --- /dev/null +++ b/src/addon/messages/pages/conversation-info/conversation-info.html @@ -0,0 +1,42 @@ + + + {{ 'addon.messages.groupinfo' | translate }} + + + + + + + + + + + + + + + + + + + + {{ 'addon.messages.numparticipants' | translate:{$a: conversation.membercount} }} + + + + + + + + + + + + + + + + + + diff --git a/src/addon/messages/pages/conversation-info/conversation-info.module.ts b/src/addon/messages/pages/conversation-info/conversation-info.module.ts new file mode 100644 index 000000000..f2b0cb96c --- /dev/null +++ b/src/addon/messages/pages/conversation-info/conversation-info.module.ts @@ -0,0 +1,33 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { AddonMessagesConversationInfoPage } from './conversation-info'; +import { CoreComponentsModule } from '@components/components.module'; +import { CoreDirectivesModule } from '@directives/directives.module'; + +@NgModule({ + declarations: [ + AddonMessagesConversationInfoPage, + ], + imports: [ + CoreComponentsModule, + CoreDirectivesModule, + IonicPageModule.forChild(AddonMessagesConversationInfoPage), + TranslateModule.forChild() + ], +}) +export class AddonMessagesConversationInfoPageModule {} diff --git a/src/addon/messages/pages/conversation-info/conversation-info.scss b/src/addon/messages/pages/conversation-info/conversation-info.scss new file mode 100644 index 000000000..26a039907 --- /dev/null +++ b/src/addon/messages/pages/conversation-info/conversation-info.scss @@ -0,0 +1,17 @@ +ion-app.app-root page-addon-messages-group-conversations { + h2 { + display: flex; + justify-content: space-between; + + .note { + margin: 0; + align-self: flex-end; + display: inline-flex; + font-size: initial; + } + } + + core-format-text.addon-message-last-message { + display: inline; + } +} diff --git a/src/addon/messages/pages/conversation-info/conversation-info.ts b/src/addon/messages/pages/conversation-info/conversation-info.ts new file mode 100644 index 000000000..c35856e4a --- /dev/null +++ b/src/addon/messages/pages/conversation-info/conversation-info.ts @@ -0,0 +1,130 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component, OnInit } from '@angular/core'; +import { IonicPage, NavParams, ViewController } from 'ionic-angular'; +import { AddonMessagesProvider } from '../../providers/messages'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; + +/** + * Page that displays the list of conversations, including group conversations. + */ +@IonicPage({ segment: 'addon-messages-conversation-info' }) +@Component({ + selector: 'page-addon-messages-conversation-info', + templateUrl: 'conversation-info.html', +}) +export class AddonMessagesConversationInfoPage implements OnInit { + + loaded = false; + conversation: any; + members = []; + canLoadMore = false; + + protected conversationId: number; + + constructor(private messagesProvider: AddonMessagesProvider, private domUtils: CoreDomUtilsProvider, navParams: NavParams, + protected viewCtrl: ViewController) { + this.conversationId = navParams.get('conversationId'); + } + + /** + * Component loaded. + */ + ngOnInit(): void { + this.fetchData().finally(() => { + this.loaded = true; + }); + } + + /** + * Fetch the required data. + * + * @return {Promise} Promise resolved when done. + */ + protected fetchData(): Promise { + // Get the conversation data first. + return this.messagesProvider.getConversation(this.conversationId, false, false, 0, 0).then((conversation) => { + this.conversation = conversation; + + // Now get the members. + return this.fetchMembers(); + }).catch((error) => { + this.domUtils.showErrorModalDefault(error, 'Error getting members.'); + }); + } + + /** + * Get conversation members. + * + * @param {boolean} [loadingMore} Whether we are loading more data or just the first ones. + * @return {Promise} Promise resolved when done. + */ + protected fetchMembers(loadingMore?: boolean): Promise { + const limitFrom = loadingMore ? this.members.length : 0; + + return this.messagesProvider.getConversationMembers(this.conversationId, limitFrom).then((data) => { + if (loadingMore) { + this.members = this.members.concat(data.members); + } else { + this.members = data.members; + } + + this.canLoadMore = data.canLoadMore; + }); + } + + /** + * Function to load more members. + * + * @param {any} [infiniteComplete] Infinite scroll complete function. Only used from core-infinite-loading. + * @return {Promise} Resolved when done. + */ + loadMoreMembers(infiniteComplete?: any): Promise { + return this.fetchMembers(true).catch((error) => { + this.domUtils.showErrorModalDefault(error, 'Error getting members.'); + this.canLoadMore = false; + }).finally(() => { + infiniteComplete && infiniteComplete(); + }); + } + + /** + * Refresh the data. + * + * @param {any} [refresher] Refresher. + * @return {Promise} Promise resolved when done. + */ + refreshData(refresher?: any): Promise { + const promises = []; + + promises.push(this.messagesProvider.invalidateConversation(this.conversationId)); + promises.push(this.messagesProvider.invalidateConversationMembers(this.conversationId)); + + return Promise.all(promises).then(() => { + return this.fetchData().finally(() => { + refresher && refresher.complete(); + }); + }); + } + + /** + * Close modal. + * + * @param {number} [userId] User conversation to load. + */ + closeModal(userId?: number): void { + this.viewCtrl.dismiss(userId); + } +} diff --git a/src/addon/messages/pages/discussion/discussion.html b/src/addon/messages/pages/discussion/discussion.html index c9a42162c..0629928fc 100644 --- a/src/addon/messages/pages/discussion/discussion.html +++ b/src/addon/messages/pages/discussion/discussion.html @@ -56,6 +56,7 @@ + diff --git a/src/addon/messages/pages/discussion/discussion.ts b/src/addon/messages/pages/discussion/discussion.ts index e2f2100b2..7cbe7df9f 100644 --- a/src/addon/messages/pages/discussion/discussion.ts +++ b/src/addon/messages/pages/discussion/discussion.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Component, OnDestroy, ViewChild, Optional } from '@angular/core'; -import { IonicPage, NavParams, NavController, Content } from 'ionic-angular'; +import { IonicPage, NavParams, NavController, Content, ModalController } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; @@ -80,7 +80,9 @@ export class AddonMessagesDiscussionPage implements OnDestroy { private userProvider: CoreUserProvider, private navCtrl: NavController, private messagesSync: AddonMessagesSyncProvider, private domUtils: CoreDomUtilsProvider, private messagesProvider: AddonMessagesProvider, logger: CoreLoggerProvider, private utils: CoreUtilsProvider, private appProvider: CoreAppProvider, private translate: TranslateService, - @Optional() private svComponent: CoreSplitViewComponent, private messagesOffline: AddonMessagesOfflineProvider) { + @Optional() private svComponent: CoreSplitViewComponent, private messagesOffline: AddonMessagesOfflineProvider, + private modalCtrl: ModalController) { + this.siteId = sitesProvider.getCurrentSiteId(); this.currentUserId = sitesProvider.getCurrentSiteUserId(); this.groupMessagingEnabled = this.messagesProvider.isGroupMessagingEnabled(); @@ -351,7 +353,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy { }); this.loadMessages(messages); - } else if (error.errorcode != 'conversationdoesntexist') { + } else if (error.errorcode != 'errorconversationdoesnotexist') { // Display the error. return Promise.reject(error); } @@ -913,8 +915,26 @@ export class AddonMessagesDiscussionPage implements OnDestroy { */ viewInfo(): void { if (this.isGroup) { - // @todo + // Display the group information. + const modal = this.modalCtrl.create('AddonMessagesConversationInfoPage', { + conversationId: this.conversationId + }); + + modal.present(); + modal.onDidDismiss((userId) => { + if (typeof userId != 'undefined') { + // Open user conversation. + if (this.svComponent) { + // Notify the left pane to load it, this way the right conversation will be highlighted. + this.eventsProvider.trigger(AddonMessagesProvider.OPEN_CONVERSATION_EVENT, {userId: userId}, this.siteId); + } else { + // Open the discussion in a new view. + this.navCtrl.push('AddonMessagesDiscussionPage', {userId: userId}); + } + } + }); } else { + // Open the user profile. const navCtrl = this.svComponent ? this.svComponent.getMasterNav() : this.navCtrl; navCtrl.push('CoreUserProfilePage', { userId: this.userId }); } diff --git a/src/addon/messages/pages/group-conversations/group-conversations.html b/src/addon/messages/pages/group-conversations/group-conversations.html index fa9281a0b..130477f88 100644 --- a/src/addon/messages/pages/group-conversations/group-conversations.html +++ b/src/addon/messages/pages/group-conversations/group-conversations.html @@ -105,7 +105,7 @@ - +
{{ 'addon.messages.numparticipants' | translate:{$a: conversation.membercount} }}
+ + +