MOBILE-2632 message: View group info
parent
6acbdff97b
commit
ea78f65656
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<ion-header>
|
||||
<ion-navbar core-back-button>
|
||||
<ion-title>{{ 'addon.messages.groupinfo' | translate }}</ion-title>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-only (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
|
||||
<ion-icon name="close"></ion-icon>
|
||||
</button>
|
||||
</ion-buttons>
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-refresher [enabled]="loaded" (ionRefresh)="refreshData($event)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<ion-item text-center *ngIf="conversation">
|
||||
<div class="item-avatar-center" *ngIf="conversation.imageurl">
|
||||
<img class="avatar" [src]="conversation.imageurl" core-external-content [alt]="conversation.name" role="presentation">
|
||||
</div>
|
||||
<h2><core-format-text [text]="conversation.name"></core-format-text></h2>
|
||||
<p><core-format-text *ngIf="conversation.subname" [text]="conversation.subname"></core-format-text></p>
|
||||
<p>{{ 'addon.messages.numparticipants' | translate:{$a: conversation.membercount} }}</p>
|
||||
</ion-item>
|
||||
|
||||
<a ion-item text-wrap *ngFor="let member of members" (click)="closeModal(member.id)">
|
||||
<ion-avatar item-start>
|
||||
<img [src]="member.profileimageurl" [alt]="member.fullname" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
||||
<!-- @todo: Display connection status.
|
||||
<span *ngIf="member.showonlinestatus" class="core-primary-circle" [ngClass]='{"addon-message-contact-online": member.isonline}'></span> -->
|
||||
</ion-avatar>
|
||||
<h2>
|
||||
<p>
|
||||
<core-format-text [text]="member.fullname"></core-format-text>
|
||||
<core-icon name="fa-ban" *ngIf="member.isblocked" [attr.aria-label]="'addon.messages.contactblocked' | translate"></core-icon>
|
||||
</p>
|
||||
</h2>
|
||||
</a>
|
||||
|
||||
<core-infinite-loading [enabled]="canLoadMore" (action)="loadMoreMembers($event)"></core-infinite-loading>
|
||||
</core-loading>
|
||||
</ion-content>
|
|
@ -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 {}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<any>} Promise resolved when done.
|
||||
*/
|
||||
protected fetchData(): Promise<any> {
|
||||
// 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<any>} Promise resolved when done.
|
||||
*/
|
||||
protected fetchMembers(loadingMore?: boolean): Promise<any> {
|
||||
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<any>} Resolved when done.
|
||||
*/
|
||||
loadMoreMembers(infiniteComplete?: any): Promise<any> {
|
||||
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<any>} Promise resolved when done.
|
||||
*/
|
||||
refreshData(refresher?: any): Promise<any> {
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@
|
|||
</ion-content>
|
||||
<ion-footer color="light" class="footer-adjustable" *ngIf="!conversationId || conversation">
|
||||
<ion-toolbar color="light" position="bottom">
|
||||
<!-- @todo: Check if the user can send messages. -->
|
||||
<core-send-message-form (onSubmit)="sendMessage($event)" [showKeyboard]="showKeyboard" [placeholder]="'addon.messages.newmessage' | translate" (onResize)="resizeContent()"></core-send-message-form>
|
||||
</ion-toolbar>
|
||||
</ion-footer>
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
|
||||
<!-- Template to render a list of conversations. -->
|
||||
<ng-template #conversationsTemplate let-conversations="conversations" let-avatarOptional="avatarOptional">
|
||||
<a ion-item text-wrap *ngFor="let conversation of conversations" [title]="conversation.name" detail-none (click)="gotoConversation(conversation.id, conversation.userid)" [class.core-split-item-selected]="(conversation.id && conversation.id == selectedConversationId) || (conversation.userid && conversation.userid == selectedUserId)">
|
||||
<a ion-item text-wrap *ngFor="let conversation of conversations" [title]="conversation.name" detail-none (click)="gotoConversation(conversation.id, conversation.userid)" [class.core-split-item-selected]="(conversation.id && conversation.id == selectedConversationId) || (conversation.userid && conversation.userid == selectedUserId)" id="addon-message-conversation-{{ conversation.id ? conversation.id : 'user-' + conversation.userid }}">
|
||||
<ion-avatar item-start *ngIf="conversation.imageurl || !avatarOptional">
|
||||
<img src="{{conversation.imageurl}}" [alt]="conversation.name" core-external-content onError="this.src='assets/img/user-avatar.png'">
|
||||
<!-- @todo: Display connection status.
|
||||
|
|
|
@ -71,6 +71,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
protected appResumeSubscription: any;
|
||||
protected readChangedObserver: any;
|
||||
protected cronObserver: any;
|
||||
protected openConversationObserver: any;
|
||||
|
||||
constructor(private eventsProvider: CoreEventsProvider, sitesProvider: CoreSitesProvider, translate: TranslateService,
|
||||
private messagesProvider: AddonMessagesProvider, private domUtils: CoreDomUtilsProvider, navParams: NavParams,
|
||||
|
@ -87,15 +88,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
// Update conversations when new message is received.
|
||||
this.newMessagesObserver = eventsProvider.on(AddonMessagesProvider.NEW_MESSAGE_EVENT, (data) => {
|
||||
// Search the conversation to update.
|
||||
let conversation;
|
||||
|
||||
if (data.conversationId) {
|
||||
conversation = this.findConversation(data.conversationId);
|
||||
} else if (data.userId) {
|
||||
conversation = this.individual.conversations && this.individual.conversations.find((conv) => {
|
||||
return conv.userid == data.userId;
|
||||
});
|
||||
}
|
||||
const conversation = this.findConversation(data.conversationId, data.userId);
|
||||
|
||||
if (typeof conversation == 'undefined') {
|
||||
// Probably a new conversation, refresh the list.
|
||||
|
@ -111,13 +104,8 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
conversation.lastmessagedate = data.timecreated / 1000;
|
||||
|
||||
// Sort the affected list.
|
||||
if (conversation.isfavourite) {
|
||||
this.favourites.conversations = this.messagesProvider.sortConversations(this.favourites.conversations);
|
||||
} else if (conversation.type == AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP) {
|
||||
this.group.conversations = this.messagesProvider.sortConversations(this.group.conversations);
|
||||
} else {
|
||||
this.individual.conversations = this.messagesProvider.sortConversations(this.individual.conversations);
|
||||
}
|
||||
const option = this.getConversationOption(conversation);
|
||||
option.conversations = this.messagesProvider.sortConversations(option.conversations);
|
||||
|
||||
if (isNewer) {
|
||||
// The last message is newer than the previous one, scroll to top to keep viewing the conversation.
|
||||
|
@ -146,6 +134,13 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
this.refreshData();
|
||||
}, this.siteId);
|
||||
|
||||
// Load a discussion if we receive an event to do so.
|
||||
this.openConversationObserver = eventsProvider.on(AddonMessagesProvider.OPEN_CONVERSATION_EVENT, (data) => {
|
||||
if (data.conversationId || data.userId) {
|
||||
this.gotoConversation(data.conversationId, data.userId, undefined, true);
|
||||
}
|
||||
}, this.siteId);
|
||||
|
||||
// Refresh the view when the app is resumed.
|
||||
this.appResumeSubscription = platform.resume.subscribe(() => {
|
||||
if (!this.loaded) {
|
||||
|
@ -227,6 +222,18 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
|
||||
if (typeof this.favourites.expanded == 'undefined') {
|
||||
// The expanded status hasn't been initialized. Do it now.
|
||||
if (this.conversationId) {
|
||||
// A certain conversation should be opened, expand its option.
|
||||
const conversation = this.findConversation(this.conversationId);
|
||||
if (conversation) {
|
||||
const option = this.getConversationOption(conversation);
|
||||
option.expanded = true;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No conversation specified or not found, determine which one should be expanded.
|
||||
this.favourites.expanded = this.favourites.count != 0;
|
||||
this.group.expanded = this.favourites.count == 0 && this.group.count != 0;
|
||||
this.individual.expanded = this.favourites.count == 0 && this.group.count == 0;
|
||||
|
@ -265,15 +272,22 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
* Find a conversation in the list of loaded conversations.
|
||||
*
|
||||
* @param {number} conversationId The conversation ID to search.
|
||||
* @param {number} userId User ID to search (if no conversationId).
|
||||
* @return {any} Conversation.
|
||||
*/
|
||||
protected findConversation(conversationId: number): any {
|
||||
const conversations = (this.favourites.conversations || []).concat(this.group.conversations || [])
|
||||
.concat(this.individual.conversations || []);
|
||||
protected findConversation(conversationId: number, userId?: number): any {
|
||||
if (conversationId) {
|
||||
const conversations = (this.favourites.conversations || []).concat(this.group.conversations || [])
|
||||
.concat(this.individual.conversations || []);
|
||||
|
||||
return conversations.find((conv) => {
|
||||
return conv.id == conversationId;
|
||||
});
|
||||
return conversations.find((conv) => {
|
||||
return conv.id == conversationId;
|
||||
});
|
||||
} else if (this.individual.conversations) {
|
||||
return this.individual.conversations.find((conv) => {
|
||||
return conv.userid == userId;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -289,8 +303,9 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
* @param {number} conversationId Conversation Id to load.
|
||||
* @param {number} userId User of the conversation. Only if there is no conversationId.
|
||||
* @param {number} [messageId] Message to scroll after loading the discussion. Used when searching.
|
||||
* @param {boolean} [scrollToConversation] Whether to scroll to the conversation.
|
||||
*/
|
||||
gotoConversation(conversationId: number, userId?: number, messageId?: number): void {
|
||||
gotoConversation(conversationId: number, userId?: number, messageId?: number, scrollToConversation?: boolean): void {
|
||||
this.selectedConversationId = conversationId;
|
||||
this.selectedUserId = userId;
|
||||
|
||||
|
@ -302,6 +317,23 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
params['message'] = messageId;
|
||||
}
|
||||
this.splitviewCtrl.push('AddonMessagesDiscussionPage', params);
|
||||
|
||||
if (scrollToConversation) {
|
||||
// Search the conversation.
|
||||
const conversation = this.findConversation(conversationId, userId);
|
||||
if (conversation) {
|
||||
// First expand the option if it isn't expanded.
|
||||
const option = this.getConversationOption(conversation);
|
||||
this.expandOption(option);
|
||||
|
||||
// Wait for the view to expand the option.
|
||||
setTimeout(() => {
|
||||
// Now scroll to the conversation.
|
||||
this.domUtils.scrollToElementBySelector(this.content, '#addon-message-conversation-' +
|
||||
(conversation.id ? conversation.id : 'user-' + conversation.userid));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -358,9 +390,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
}
|
||||
} else {
|
||||
// Its a new conversation. Check if we already created it (there is more than one message for the same user).
|
||||
const conversation = this.individual.conversations.find((conv) => {
|
||||
return conv.userid == message.touserid;
|
||||
});
|
||||
const conversation = this.findConversation(undefined, message.touserid);
|
||||
|
||||
message.text = message.smallmessage;
|
||||
|
||||
|
@ -397,13 +427,8 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
* @param {any} conversation Offline conversation to add.
|
||||
*/
|
||||
protected addOfflineConversation(conversation: any): void {
|
||||
if (conversation.isfavourite) {
|
||||
this.favourites.conversations.unshift(conversation);
|
||||
} else if (conversation.type == AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP) {
|
||||
this.group.conversations.unshift(conversation);
|
||||
} else {
|
||||
this.individual.conversations.unshift(conversation);
|
||||
}
|
||||
const option = this.getConversationOption(conversation);
|
||||
option.conversations.unshift(conversation);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -419,6 +444,22 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
conversation.sentfromcurrentuser = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a conversation, return its option (favourites, group, individual).
|
||||
*
|
||||
* @param {any} conversation Conversation to check.
|
||||
* @return {any} Option object.
|
||||
*/
|
||||
protected getConversationOption(conversation: any): any {
|
||||
if (conversation.isfavourite) {
|
||||
return this.favourites;
|
||||
} else if (conversation.type == AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP) {
|
||||
return this.group;
|
||||
} else {
|
||||
return this.individual;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the data.
|
||||
*
|
||||
|
@ -447,14 +488,23 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
// Already expanded, close it.
|
||||
option.expanded = false;
|
||||
} else {
|
||||
// Collapse all and expand the clicked one.
|
||||
this.favourites.expanded = false;
|
||||
this.group.expanded = false;
|
||||
this.individual.expanded = false;
|
||||
option.expanded = true;
|
||||
this.expandOption(option);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand a certain option.
|
||||
*
|
||||
* @param {any} option The option to expand.
|
||||
*/
|
||||
protected expandOption(option: any): void {
|
||||
// Collapse all and expand the right one.
|
||||
this.favourites.expanded = false;
|
||||
this.group.expanded = false;
|
||||
this.individual.expanded = false;
|
||||
option.expanded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear search and show conversations again.
|
||||
*/
|
||||
|
@ -497,5 +547,6 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
this.pushObserver && this.pushObserver.unsubscribe();
|
||||
this.readChangedObserver && this.readChangedObserver.off();
|
||||
this.cronObserver && this.cronObserver.off();
|
||||
this.openConversationObserver && this.openConversationObserver.off();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ export class AddonMessagesProvider {
|
|||
static NEW_MESSAGE_EVENT = 'addon_messages_new_message_event';
|
||||
static READ_CHANGED_EVENT = 'addon_messages_read_changed_event';
|
||||
static READ_CRON_EVENT = 'addon_messages_read_cron_event';
|
||||
static OPEN_CONVERSATION_EVENT = 'addon_messages_open_conversation_event'; // Notify that a conversation should be opened.
|
||||
static SPLIT_VIEW_LOAD_EVENT = 'addon_messages_split_view_load_event';
|
||||
static POLL_INTERVAL = 10000;
|
||||
static PUSH_SIMULATION_COMPONENT = 'AddonMessagesPushSimulation';
|
||||
|
@ -250,6 +251,17 @@ export class AddonMessagesProvider {
|
|||
return this.ROOT_CACHE_KEY + 'conversationBetweenUsers:' + userId + ':' + otherUserId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key for get conversation members.
|
||||
*
|
||||
* @param {number} userId User ID.
|
||||
* @param {number} conversationId Conversation ID.
|
||||
* @return {string} Cache key.
|
||||
*/
|
||||
protected getCacheKeyForConversationMembers(userId: number, conversationId: number): string {
|
||||
return this.ROOT_CACHE_KEY + 'conversationMembers:' + userId + ':' + conversationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key for get conversation messages.
|
||||
*
|
||||
|
@ -463,6 +475,54 @@ export class AddonMessagesProvider {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a conversation members.
|
||||
*
|
||||
* @param {number} conversationId Conversation ID to fetch.
|
||||
* @param {number} [limitFrom=0] Offset for members list.
|
||||
* @param {number} [limitTo] Limit of members.
|
||||
* @param {string} [siteId] Site ID. If not defined, use current site.
|
||||
* @param {number} [userId] User ID. If not defined, current user in the site.
|
||||
* @return {Promise<any>} Promise resolved with the response.
|
||||
* @since 3.6
|
||||
*/
|
||||
getConversationMembers(conversationId: number, limitFrom: number = 0, limitTo?: number, includeContactRequests?: boolean,
|
||||
siteId?: string, userId?: number): Promise<any> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
||||
if (typeof limitTo == 'undefined' || limitTo === null) {
|
||||
limitTo = this.LIMIT_MESSAGES;
|
||||
}
|
||||
|
||||
const preSets = {
|
||||
cacheKey: this.getCacheKeyForConversationMembers(userId, conversationId)
|
||||
},
|
||||
params: any = {
|
||||
userid: userId,
|
||||
conversationid: conversationId,
|
||||
limitfrom: limitFrom,
|
||||
limitnum: limitTo < 1 ? limitTo : limitTo + 1, // If there is a limit, get 1 more than requested.
|
||||
includecontactrequests: includeContactRequests ? 1 : 0
|
||||
};
|
||||
|
||||
return site.read('core_message_get_conversation_members', params, preSets).then((members) => {
|
||||
const result: any = {};
|
||||
|
||||
if (limitTo < 1) {
|
||||
result.canLoadMore = false;
|
||||
result.members = members;
|
||||
} else {
|
||||
result.canLoadMore = members.length > limitTo;
|
||||
result.members = members.slice(0, limitTo);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a conversation by the conversation ID.
|
||||
*
|
||||
|
@ -1071,6 +1131,22 @@ export class AddonMessagesProvider {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate conversation members cache.
|
||||
*
|
||||
* @param {number} conversationId Conversation ID.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @param {number} [userId] User ID. If not defined, current user in the site.
|
||||
* @return {Promise<any>} Resolved when done.
|
||||
*/
|
||||
invalidateConversationMembers(conversationId: number, siteId?: string, userId?: number): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
userId = userId || site.getUserId();
|
||||
|
||||
return site.invalidateWsCacheForKey(this.getCacheKeyForConversationMembers(userId, conversationId));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate conversation messages cache.
|
||||
*
|
||||
|
|
|
@ -178,6 +178,7 @@
|
|||
"addon.messages.nogroupmessages": "No group messages",
|
||||
"addon.messages.nomessages": "No messages",
|
||||
"addon.messages.nousersfound": "No users found",
|
||||
"addon.messages.numparticipants": "{{$a}} participants",
|
||||
"addon.messages.removecontact": "Remove contact",
|
||||
"addon.messages.removecontactconfirm": "Contact will be removed from your contacts list.",
|
||||
"addon.messages.showdeletemessages": "Show delete messages",
|
||||
|
|
Loading…
Reference in New Issue