MOBILE-4565 messages: Use new Ionic accordion component on groups
parent
7dfb3c13df
commit
404cb9129a
|
@ -159,7 +159,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View loaded.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loadUpcoming = !!CoreNavigator.getRouteBooleanParam('upcoming');
|
this.loadUpcoming = !!CoreNavigator.getRouteBooleanParam('upcoming');
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
AddonMessages,
|
AddonMessages,
|
||||||
AddonMessagesConversationMessageFormatted,
|
AddonMessagesConversationMessageFormatted,
|
||||||
AddonMessagesSendMessageResults,
|
AddonMessagesSendMessageResults,
|
||||||
|
AddonMessagesUpdateConversationAction,
|
||||||
} from '../../services/messages';
|
} from '../../services/messages';
|
||||||
import { AddonMessagesOffline, AddonMessagesOfflineMessagesDBRecordFormatted } from '../../services/messages-offline';
|
import { AddonMessagesOffline, AddonMessagesOfflineMessagesDBRecordFormatted } from '../../services/messages-offline';
|
||||||
import { AddonMessagesSync, AddonMessagesSyncProvider } from '../../services/messages-sync';
|
import { AddonMessagesSync, AddonMessagesSyncProvider } from '../../services/messages-sync';
|
||||||
|
@ -1298,7 +1299,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
|
||||||
|
|
||||||
CoreEvents.trigger(AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT, {
|
CoreEvents.trigger(AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT, {
|
||||||
conversationId: this.conversation.id,
|
conversationId: this.conversation.id,
|
||||||
action: 'favourite',
|
action: AddonMessagesUpdateConversationAction.FAVOURITE,
|
||||||
value: this.conversation.isfavourite,
|
value: this.conversation.isfavourite,
|
||||||
}, this.siteId);
|
}, this.siteId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -1330,7 +1331,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
|
||||||
|
|
||||||
CoreEvents.trigger(AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT, {
|
CoreEvents.trigger(AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT, {
|
||||||
conversationId: this.conversation.id,
|
conversationId: this.conversation.id,
|
||||||
action: 'mute',
|
action: AddonMessagesUpdateConversationAction.MUTE,
|
||||||
value: this.conversation.ismuted,
|
value: this.conversation.ismuted,
|
||||||
}, this.siteId);
|
}, this.siteId);
|
||||||
|
|
||||||
|
@ -1446,7 +1447,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
|
||||||
AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT,
|
AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT,
|
||||||
{
|
{
|
||||||
conversationId: this.conversation.id,
|
conversationId: this.conversation.id,
|
||||||
action: 'delete',
|
action: AddonMessagesUpdateConversationAction.DELETE,
|
||||||
},
|
},
|
||||||
this.siteId,
|
this.siteId,
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<core-split-view>
|
<core-split-view>
|
||||||
<ion-refresher slot="fixed" [disabled]="!loaded || !currentListEl" (ionRefresh)="refreshData($event.target)">
|
<ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="refreshData($event.target)">
|
||||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}" />
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}" />
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
|
|
||||||
|
@ -30,110 +30,46 @@
|
||||||
<ion-item class="ion-text-wrap addon-message-discussion" (click)="gotoContacts()" [detail]="true" button>
|
<ion-item class="ion-text-wrap addon-message-discussion" (click)="gotoContacts()" [detail]="true" button>
|
||||||
<ion-icon name="fas-address-book" slot="start" aria-hidden="true" />
|
<ion-icon name="fas-address-book" slot="start" aria-hidden="true" />
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.messages.contacts' | translate }}</h2>
|
<p class="item-heading">{{ 'addon.messages.contacts' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-badge *ngIf="contactRequestsCount > 0" slot="end" aria-hidden="true">{{contactRequestsCount}}</ion-badge>
|
<ion-badge *ngIf="contactRequestsCount > 0" slot="end"
|
||||||
<span *ngIf="contactRequestsCount > 0" class="sr-only">
|
[attr.aria-label]="'addon.messages.pendingcontactrequests' | translate:{$a: contactRequestsCount}">
|
||||||
{{ 'addon.messages.pendingcontactrequests' | translate:{$a: contactRequestsCount} }}
|
{{contactRequestsCount}}
|
||||||
</span>
|
</ion-badge>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<!-- Favourite conversations. -->
|
<ion-accordion-group (ionChange)="accordionGroupChange($event.detail)" #accordionGroup>
|
||||||
<ion-item button class="ion-text-wrap divider" (click)="toggle(favourites)"
|
<ion-accordion *ngFor="let option of groupConversations" [value]="option.optionName" toggleIconSlot="start">
|
||||||
[attr.aria-label]="(favourites.expanded ? 'core.collapse' : 'core.expand') | translate"
|
<ion-item slot="header" class="ion-text-wrap divider">
|
||||||
[attr.aria-expanded]="favourites.expanded" aria-controls="addon-messages-groupconversations-favourite" role="heading"
|
|
||||||
[detail]="false">
|
|
||||||
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
|
||||||
[class.expandable-status-icon-expanded]="favourites.expanded" />
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'core.favourites' | translate }} ({{ favourites.count }})</h2>
|
<h2>{{ option.titleString | translate }} ({{ option.count }})</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-badge slot="end" *ngIf="favourites.unread" aria-hidden="true">{{ favourites.unread }}</ion-badge>
|
<ion-badge slot="end" *ngIf="option.unread"
|
||||||
<span *ngIf="favourites.unread" class="sr-only">
|
[attr.aria-label]="'addon.messages.unreadconversations' | translate:{$a: option.unread}">
|
||||||
{{ 'addon.messages.unreadconversations' | translate:{$a: favourites.unread} }}
|
{{ option.unread }}
|
||||||
</span>
|
</ion-badge>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<div [hidden]="!favourites.conversations || !favourites.expanded || favourites.loading" #favlist
|
<div slot="content">
|
||||||
id="addon-messages-groupconversations-favourite">
|
<ng-container *ngIf="!option.loading">
|
||||||
<ng-container *ngTemplateOutlet="conversationsTemplate; context: {conversations: favourites.conversations}" />
|
<ng-container *ngTemplateOutlet="conversationsTemplate;
|
||||||
<!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
|
context: {conversations: option.conversations}" />
|
||||||
<core-infinite-loading [enabled]="favourites.canLoadMore" (action)="loadMoreConversations(favourites, $event)"
|
<!-- The infinite loading cannot be inside the ng-template,
|
||||||
[error]="favourites.loadMoreError" />
|
it fails because it doesn't find ion-content. -->
|
||||||
<ion-item class="ion-text-wrap" *ngIf="favourites.conversations && favourites.conversations.length === 0">
|
<core-infinite-loading [enabled]="option.canLoadMore" (action)="loadMoreConversations(option, $event)"
|
||||||
|
[error]="option.loadMoreError" />
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="option.conversations && option.conversations.length === 0">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ 'addon.messages.nofavourites' | translate }}</p>
|
<p>{{ option.emptyString| translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</div>
|
</ng-container>
|
||||||
<ion-item class="ion-text-center" *ngIf="favourites.loading">
|
<ion-item class="ion-text-center" *ngIf="option.loading">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<ion-spinner [attr.aria-label]="'core.loading' | translate" />
|
<ion-spinner [attr.aria-label]="'core.loading' | translate" />
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Group conversations. -->
|
|
||||||
<ion-item button class="divider ion-text-wrap" (click)="toggle(group)"
|
|
||||||
[attr.aria-label]="(group.expanded ? 'core.collapse' : 'core.expand') | translate" [attr.aria-expanded]="group.expanded"
|
|
||||||
aria-controls="addon-messages-groupconversations-group" role="heading" [detail]="false">
|
|
||||||
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
|
||||||
[class.expandable-status-icon-expanded]="group.expanded" />
|
|
||||||
<ion-label>
|
|
||||||
<h2>{{ 'addon.messages.groupconversations' | translate }} ({{ group.count }})</h2>
|
|
||||||
</ion-label>
|
|
||||||
<ion-badge slot="end" *ngIf="group.unread" aria-hidden="true">{{ group.unread }}</ion-badge>
|
|
||||||
<span *ngIf="group.unread" class="sr-only">
|
|
||||||
{{ 'addon.messages.unreadconversations' | translate:{$a: group.unread} }}
|
|
||||||
</span>
|
|
||||||
</ion-item>
|
|
||||||
<div [hidden]="!group.conversations || !group.expanded || group.loading" #grouplist
|
|
||||||
id="addon-messages-groupconversations-group">
|
|
||||||
<ng-container *ngTemplateOutlet="conversationsTemplate; context: {conversations: group.conversations}" />
|
|
||||||
<!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
|
|
||||||
<core-infinite-loading [enabled]="group.canLoadMore" (action)="loadMoreConversations(group, $event)"
|
|
||||||
[error]="group.loadMoreError" />
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="group.conversations && group.conversations.length === 0">
|
|
||||||
<ion-label>
|
|
||||||
<p>{{ 'addon.messages.nogroupconversations' | translate }}</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
</div>
|
</div>
|
||||||
<ion-item class="ion-text-center" *ngIf="group.loading">
|
</ion-accordion>
|
||||||
<ion-label>
|
</ion-accordion-group>
|
||||||
<ion-spinner [attr.aria-label]="'core.loading' | translate" />
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item button class="divider ion-text-wrap" (click)="toggle(individual)"
|
|
||||||
[attr.aria-label]="(individual.expanded ? 'core.collapse' : 'core.expand') | translate"
|
|
||||||
[attr.aria-expanded]="individual.expanded" aria-controls="addon-messages-groupconversations-individual" role="heading"
|
|
||||||
[detail]="false">
|
|
||||||
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
|
||||||
[class.expandable-status-icon-expanded]="individual.expanded" />
|
|
||||||
<ion-label>
|
|
||||||
<h2>{{ 'addon.messages.individualconversations' | translate }} ({{ individual.count }})</h2>
|
|
||||||
</ion-label>
|
|
||||||
<ion-badge slot="end" *ngIf="individual.unread" aria-hidden="true">{{ individual.unread }}</ion-badge>
|
|
||||||
<span *ngIf="individual.unread" class="sr-only">
|
|
||||||
{{ 'addon.messages.unreadconversations' | translate:{$a: individual.unread} }}
|
|
||||||
</span>
|
|
||||||
</ion-item>
|
|
||||||
<div [hidden]="!individual.conversations || !individual.expanded || individual.loading" #indlist
|
|
||||||
id="addon-messages-groupconversations-individual">
|
|
||||||
<ng-container *ngTemplateOutlet="conversationsTemplate; context: {conversations: individual.conversations}" />
|
|
||||||
<!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
|
|
||||||
<core-infinite-loading [enabled]="individual.canLoadMore" (action)="loadMoreConversations(individual, $event)"
|
|
||||||
[error]="individual.loadMoreError" />
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="individual.conversations && individual.conversations.length === 0">
|
|
||||||
<ion-label>
|
|
||||||
<p>{{ 'addon.messages.noindividualconversations' | translate }}</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
</div>
|
|
||||||
<ion-item class="ion-text-center" *ngIf="individual.loading">
|
|
||||||
<ion-label>
|
|
||||||
<ion-spinner [attr.aria-label]="'core.loading' | translate" />
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</core-split-view>
|
</core-split-view>
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { IonContent } from '@ionic/angular';
|
import { AccordionGroupChangeEventDetail, IonAccordionGroup, IonContent } from '@ionic/angular';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import {
|
import {
|
||||||
|
@ -21,6 +21,8 @@ import {
|
||||||
AddonMessagesConversationFormatted,
|
AddonMessagesConversationFormatted,
|
||||||
AddonMessages,
|
AddonMessages,
|
||||||
AddonMessagesNewMessagedEventData,
|
AddonMessagesNewMessagedEventData,
|
||||||
|
AddonMessagesUnreadConversationCountsEventData,
|
||||||
|
AddonMessagesUpdateConversationAction,
|
||||||
} from '../../services/messages';
|
} from '../../services/messages';
|
||||||
import {
|
import {
|
||||||
AddonMessagesOffline,
|
AddonMessagesOffline,
|
||||||
|
@ -40,6 +42,12 @@ import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-lin
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
|
|
||||||
|
const enum AddonMessagesGroupConversationOptionNames {
|
||||||
|
FAVOURITES = 'favourites',
|
||||||
|
GROUP = 'group',
|
||||||
|
INDIVIDUAL = 'individual',
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays the list of conversations, including group conversations.
|
* Page that displays the list of conversations, including group conversations.
|
||||||
*/
|
*/
|
||||||
|
@ -51,43 +59,49 @@ import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
|
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
|
||||||
|
|
||||||
@ViewChild(IonContent) content?: IonContent;
|
@ViewChild(IonContent) content?: IonContent;
|
||||||
@ViewChild('favlist') favListEl?: ElementRef;
|
@ViewChild('accordionGroup', { static: true }) accordionGroup!: IonAccordionGroup;
|
||||||
@ViewChild('grouplist') groupListEl?: ElementRef;
|
|
||||||
@ViewChild('indlist') indListEl?: ElementRef;
|
|
||||||
|
|
||||||
loaded = false;
|
loaded = false;
|
||||||
loadingMessage: string;
|
loadingMessage: string;
|
||||||
selectedConversationId?: number;
|
selectedConversationId?: number;
|
||||||
selectedUserId?: number;
|
selectedUserId?: number;
|
||||||
contactRequestsCount = 0;
|
contactRequestsCount = 0;
|
||||||
favourites: AddonMessagesGroupConversationOption = {
|
|
||||||
|
groupConversations: AddonMessagesGroupConversationOption[] = [
|
||||||
|
{
|
||||||
|
optionName: AddonMessagesGroupConversationOptionNames.FAVOURITES,
|
||||||
|
titleString: 'core.favourites',
|
||||||
|
emptyString: 'addon.messages.nofavourites',
|
||||||
type: undefined,
|
type: undefined,
|
||||||
favourites: true,
|
favourites: true,
|
||||||
count: 0,
|
count: 0,
|
||||||
unread: 0,
|
unread: 0,
|
||||||
conversations: [],
|
conversations: [],
|
||||||
};
|
},
|
||||||
|
{
|
||||||
group: AddonMessagesGroupConversationOption = {
|
optionName: AddonMessagesGroupConversationOptionNames.GROUP,
|
||||||
|
titleString: 'addon.messages.groupconversations',
|
||||||
|
emptyString: 'addon.messages.nogroupconversations',
|
||||||
type: AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP,
|
type: AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP,
|
||||||
favourites: false,
|
favourites: false,
|
||||||
count: 0,
|
count: 0,
|
||||||
unread: 0,
|
unread: 0,
|
||||||
conversations: [],
|
conversations: [],
|
||||||
};
|
},
|
||||||
|
{
|
||||||
individual: AddonMessagesGroupConversationOption = {
|
optionName: AddonMessagesGroupConversationOptionNames.INDIVIDUAL,
|
||||||
|
titleString: 'addon.messages.individualconversations',
|
||||||
|
emptyString: 'addon.messages.noindividualconversations',
|
||||||
type: AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
type: AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||||
favourites: false,
|
favourites: false,
|
||||||
count: 0,
|
count: 0,
|
||||||
unread: 0,
|
unread: 0,
|
||||||
conversations: [],
|
conversations: [],
|
||||||
};
|
},
|
||||||
|
];
|
||||||
|
|
||||||
typeGroup = AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP;
|
typeGroup = AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP;
|
||||||
currentListEl?: HTMLElement;
|
|
||||||
|
|
||||||
protected siteId: string;
|
protected siteId: string;
|
||||||
protected currentUserId: number;
|
protected currentUserId: number;
|
||||||
|
@ -100,6 +114,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
protected updateConversationListObserver: CoreEventObserver;
|
protected updateConversationListObserver: CoreEventObserver;
|
||||||
protected contactRequestsCountObserver: CoreEventObserver;
|
protected contactRequestsCountObserver: CoreEventObserver;
|
||||||
protected memberInfoObserver: CoreEventObserver;
|
protected memberInfoObserver: CoreEventObserver;
|
||||||
|
protected firstExpand = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
|
@ -114,9 +129,9 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
(data) => {
|
(data) => {
|
||||||
// Check if the new message belongs to the option that is currently expanded.
|
// Check if the new message belongs to the option that is currently expanded.
|
||||||
const expandedOption = this.getExpandedOption();
|
const expandedOption = this.getExpandedOption();
|
||||||
const messageOption = this.getConversationOption(data);
|
const messageOptionName = this.getConversationOptionName(data);
|
||||||
|
|
||||||
if (expandedOption != messageOption) {
|
if (expandedOption?.optionName !== messageOptionName) {
|
||||||
return; // Message doesn't belong to current list, stop.
|
return; // Message doesn't belong to current list, stop.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +170,9 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the affected list.
|
// Sort the affected list.
|
||||||
const option = this.getConversationOption(conversation);
|
const optionName = this.getConversationOptionName(conversation);
|
||||||
option.conversations = AddonMessages.sortConversations(option.conversations || []);
|
const option = this.getConversationGroupByName(optionName);
|
||||||
|
option.conversations = AddonMessages.sortConversations(option.conversations);
|
||||||
|
|
||||||
if (isNewer) {
|
if (isNewer) {
|
||||||
// The last message is newer than the previous one, scroll to top to keep viewing the conversation.
|
// The last message is newer than the previous one, scroll to top to keep viewing the conversation.
|
||||||
|
@ -209,11 +225,11 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
this.updateConversationListObserver = CoreEvents.on(
|
this.updateConversationListObserver = CoreEvents.on(
|
||||||
AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT,
|
AddonMessagesProvider.UPDATE_CONVERSATION_LIST_EVENT,
|
||||||
(data) => {
|
(data) => {
|
||||||
if (data && data.action == 'mute') {
|
if (data?.action === AddonMessagesUpdateConversationAction.MUTE) {
|
||||||
// If the conversation is displayed, change its muted value.
|
// If the conversation is displayed, change its muted value.
|
||||||
const expandedOption = this.getExpandedOption();
|
const expandedOption = this.getExpandedOption();
|
||||||
|
|
||||||
if (expandedOption && expandedOption.conversations) {
|
if (expandedOption?.conversations) {
|
||||||
const conversation = this.findConversation(data.conversationId, undefined, expandedOption);
|
const conversation = this.findConversation(data.conversationId, undefined, expandedOption);
|
||||||
if (conversation) {
|
if (conversation) {
|
||||||
conversation.ismuted = !!data.value;
|
conversation.ismuted = !!data.value;
|
||||||
|
@ -233,7 +249,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
this.pushObserver = CorePushNotificationsDelegate.on<CorePushNotificationsNotificationBasicData>('receive')
|
this.pushObserver = CorePushNotificationsDelegate.on<CorePushNotificationsNotificationBasicData>('receive')
|
||||||
.subscribe((notification) => {
|
.subscribe((notification) => {
|
||||||
// New message received. If it's from current site, refresh the data.
|
// New message received. If it's from current site, refresh the data.
|
||||||
if (CoreUtils.isFalseOrZero(notification.notif) && notification.site == this.siteId) {
|
if (CoreUtils.isFalseOrZero(notification.notif) && notification.site === this.siteId) {
|
||||||
// Don't refresh unread counts, it's refreshed from the main menu handler in this case.
|
// Don't refresh unread counts, it's refreshed from the main menu handler in this case.
|
||||||
this.refreshData(undefined, false);
|
this.refreshData(undefined, false);
|
||||||
}
|
}
|
||||||
|
@ -243,9 +259,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
this.cronObserver = CoreEvents.on(
|
this.cronObserver = CoreEvents.on(
|
||||||
AddonMessagesProvider.UNREAD_CONVERSATION_COUNTS_EVENT,
|
AddonMessagesProvider.UNREAD_CONVERSATION_COUNTS_EVENT,
|
||||||
(data) => {
|
(data) => {
|
||||||
this.favourites.unread = data.favourites;
|
this.setCounts(data, 'unread');
|
||||||
this.individual.unread = data.individual + data.self; // Self is only returned if it's not favourite.
|
|
||||||
this.group.unread = data.group;
|
|
||||||
},
|
},
|
||||||
this.siteId,
|
this.siteId,
|
||||||
);
|
);
|
||||||
|
@ -269,8 +283,8 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
const expandedOption = this.getExpandedOption();
|
const expandedOption = this.getExpandedOption();
|
||||||
if (expandedOption == this.individual || expandedOption == this.favourites) {
|
if (expandedOption?.optionName === AddonMessagesGroupConversationOptionNames.GROUP ||
|
||||||
if (!expandedOption.conversations || expandedOption.conversations.length <= 0) {
|
!expandedOption?.conversations.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,14 +292,13 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
if (conversation) {
|
if (conversation) {
|
||||||
conversation.isblocked = data.userBlocked;
|
conversation.isblocked = data.userBlocked;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
this.siteId,
|
this.siteId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component loaded.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
this.route.queryParams.subscribe(async (params) => {
|
this.route.queryParams.subscribe(async (params) => {
|
||||||
|
@ -305,17 +318,13 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
if (!this.selectedConversationId && !this.selectedUserId && CoreScreen.isTablet) {
|
if (!this.selectedConversationId && !this.selectedUserId && CoreScreen.isTablet) {
|
||||||
// Load the first conversation.
|
// Load the first conversation.
|
||||||
let conversation: AddonMessagesConversationForList;
|
|
||||||
const expandedOption = this.getExpandedOption();
|
const expandedOption = this.getExpandedOption();
|
||||||
|
|
||||||
if (expandedOption && expandedOption.conversations.length) {
|
const conversation = expandedOption?.conversations[0];
|
||||||
conversation = expandedOption.conversations[0];
|
|
||||||
|
|
||||||
if (conversation) {
|
if (conversation) {
|
||||||
await this.gotoConversation(conversation.id);
|
await this.gotoConversation(conversation.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Treat deep link now that the conversation route has been loaded if needed.
|
// Treat deep link now that the conversation route has been loaded if needed.
|
||||||
deepLinkManager.treatLink();
|
deepLinkManager.treatLink();
|
||||||
|
@ -341,22 +350,19 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
|
|
||||||
// The expanded status hasn't been initialized. Do it now.
|
// The expanded status hasn't been initialized. Do it now.
|
||||||
if (this.favourites.expanded === undefined && (this.selectedConversationId || this.selectedUserId)) {
|
if (!this.firstExpand && (this.selectedConversationId || this.selectedUserId)) {
|
||||||
// A certain conversation should be opened.
|
// A certain conversation should be opened.
|
||||||
// We don't know which option it belongs to, so we need to fetch the data for all of them.
|
// We don't know which option it belongs to, so we need to fetch the data for all of them.
|
||||||
const promises: Promise<void>[] = [];
|
const promises = this.groupConversations.map((option) =>
|
||||||
|
this.fetchDataForOption(option, false));
|
||||||
promises.push(this.fetchDataForOption(this.favourites, false));
|
|
||||||
promises.push(this.fetchDataForOption(this.group, false));
|
|
||||||
promises.push(this.fetchDataForOption(this.individual, false));
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
// All conversations have been loaded, find the one we need to load and expand its option.
|
// All conversations have been loaded, find the one we need to load and expand its option.
|
||||||
const conversation = this.findConversation(this.selectedConversationId, this.selectedUserId);
|
const conversation = this.findConversation(this.selectedConversationId, this.selectedUserId);
|
||||||
if (conversation) {
|
if (conversation) {
|
||||||
const option = this.getConversationOption(conversation);
|
const optionName = this.getConversationOptionName(conversation);
|
||||||
|
const option = this.getConversationGroupByName(optionName);
|
||||||
|
|
||||||
await this.expandOption(option);
|
await this.expandOption(option);
|
||||||
|
|
||||||
|
@ -376,18 +382,24 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch data for the expanded option.
|
* Fetch data for the expanded option.
|
||||||
*
|
|
||||||
* @returns Promise resolved when done.
|
|
||||||
*/
|
*/
|
||||||
protected async fetchDataForExpandedOption(): Promise<void> {
|
protected async fetchDataForExpandedOption(): Promise<void> {
|
||||||
if (this.favourites.expanded === undefined) {
|
if (!this.firstExpand) {
|
||||||
// Calculate which option should be expanded initially.
|
// Calculate which option should be expanded initially.
|
||||||
this.favourites.expanded = this.favourites.count != 0 && !this.group.unread && !this.individual.unread;
|
let expandOption = this.groupConversations.find((option) => option.unread);
|
||||||
this.group.expanded = !this.favourites.expanded && this.group.count != 0 && !this.individual.unread;
|
|
||||||
this.individual.expanded = !this.favourites.expanded && !this.group.expanded;
|
if (!expandOption) {
|
||||||
|
expandOption = this.groupConversations.find((option) => option.count > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadCurrentListElement();
|
if (!expandOption) {
|
||||||
|
expandOption = this.getConversationGroupByName(AddonMessagesGroupConversationOptionNames.INDIVIDUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.accordionGroup.value = expandOption.optionName;
|
||||||
|
|
||||||
|
this.firstExpand = true;
|
||||||
|
}
|
||||||
|
|
||||||
const expandedOption = this.getExpandedOption();
|
const expandedOption = this.getExpandedOption();
|
||||||
|
|
||||||
|
@ -418,8 +430,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
conversations: <AddonMessagesConversationForList[]> [],
|
conversations: <AddonMessagesConversationForList[]> [],
|
||||||
canLoadMore: false,
|
canLoadMore: false,
|
||||||
};
|
};
|
||||||
let offlineMessages:
|
let offlineMessages: AddonMessagesOfflineAnyMessagesFormatted[] = [];
|
||||||
AddonMessagesOfflineAnyMessagesFormatted[] = [];
|
|
||||||
|
|
||||||
// Get the conversations and, if needed, the offline messages. Always try to get the latest data.
|
// Get the conversations and, if needed, the offline messages. Always try to get the latest data.
|
||||||
promises.push(AddonMessages.invalidateConversations(this.siteId).then(async () => {
|
promises.push(AddonMessages.invalidateConversations(this.siteId).then(async () => {
|
||||||
|
@ -469,9 +480,36 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
await AddonMessages.invalidateConversationCounts(this.siteId);
|
await AddonMessages.invalidateConversationCounts(this.siteId);
|
||||||
|
|
||||||
const counts = await AddonMessages.getConversationCounts(this.siteId);
|
const counts = await AddonMessages.getConversationCounts(this.siteId);
|
||||||
this.favourites.count = counts.favourites;
|
this.setCounts(counts);
|
||||||
this.individual.count = counts.individual + counts.self; // Self is only returned if it's not favourite.
|
}
|
||||||
this.group.count = counts.group;
|
|
||||||
|
/**
|
||||||
|
* Set conversation counts.
|
||||||
|
*
|
||||||
|
* @param counts Counts to set.
|
||||||
|
* @param valueToSet Value to set count or unread.
|
||||||
|
*/
|
||||||
|
protected setCounts(
|
||||||
|
counts: AddonMessagesUnreadConversationCountsEventData,
|
||||||
|
valueToSet: 'count' | 'unread' = 'count',
|
||||||
|
): void {
|
||||||
|
this.getConversationGroupByName(AddonMessagesGroupConversationOptionNames.FAVOURITES)[valueToSet] = counts.favourites;
|
||||||
|
this.getConversationGroupByName(AddonMessagesGroupConversationOptionNames.INDIVIDUAL)[valueToSet] =
|
||||||
|
counts.individual + counts.self; // Self is only returned if it's not favourite.
|
||||||
|
this.getConversationGroupByName(AddonMessagesGroupConversationOptionNames.GROUP)[valueToSet] = counts.group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a conversation group by its name.
|
||||||
|
*
|
||||||
|
* @param name Name of the group.
|
||||||
|
* @returns The conversation group.
|
||||||
|
*/
|
||||||
|
protected getConversationGroupByName(name: AddonMessagesGroupConversationOptionNames): AddonMessagesGroupConversationOption {
|
||||||
|
const option = this.groupConversations.find((group) => group.optionName === name);
|
||||||
|
|
||||||
|
// Option should always be defined.
|
||||||
|
return option ?? this.groupConversations[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -491,16 +529,19 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
if (conversationId) {
|
if (conversationId) {
|
||||||
const conversations: AddonMessagesConversationForList[] = option
|
const conversations: AddonMessagesConversationForList[] = option
|
||||||
? option.conversations
|
? option.conversations
|
||||||
: (this.favourites.conversations.concat(this.group.conversations).concat(this.individual.conversations));
|
: this.groupConversations.flatMap((option) => option.conversations);
|
||||||
|
|
||||||
return conversations.find((conv) => conv.id == conversationId);
|
return conversations.find((conv) => conv.id === conversationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const conversations = option
|
let conversations = option?.conversations;
|
||||||
? option.conversations
|
if (!conversations) {
|
||||||
: this.favourites.conversations.concat(this.individual.conversations);
|
// Only check on favourites and individual conversations.
|
||||||
|
conversations = this.getConversationGroupByName(AddonMessagesGroupConversationOptionNames.FAVOURITES).conversations
|
||||||
|
.concat(this.getConversationGroupByName(AddonMessagesGroupConversationOptionNames.INDIVIDUAL).conversations);
|
||||||
|
}
|
||||||
|
|
||||||
return conversations.find((conv) => conv.userid == userId);
|
return conversations.find((conv) => conv.userid === userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -509,12 +550,8 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
* @returns Option currently expanded.
|
* @returns Option currently expanded.
|
||||||
*/
|
*/
|
||||||
protected getExpandedOption(): AddonMessagesGroupConversationOption | undefined {
|
protected getExpandedOption(): AddonMessagesGroupConversationOption | undefined {
|
||||||
if (this.favourites.expanded) {
|
if (this.accordionGroup.value) {
|
||||||
return this.favourites;
|
return this.getConversationGroupByName(this.accordionGroup.value as AddonMessagesGroupConversationOptionNames);
|
||||||
} else if (this.group.expanded) {
|
|
||||||
return this.group;
|
|
||||||
} else if (this.individual.expanded) {
|
|
||||||
return this.individual;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,7 +609,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
option.loadMoreError = true;
|
option.loadMoreError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
infiniteComplete && infiniteComplete();
|
infiniteComplete?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -617,13 +654,13 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
imageurl: message.conversation?.imageurl || '',
|
imageurl: message.conversation?.imageurl || '',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.getConversationOption(conversation) == option) {
|
if (this.getConversationOptionName(conversation) === option.optionName) {
|
||||||
// Message belongs to current option, add the conversation.
|
// Message belongs to current option, add the conversation.
|
||||||
this.addLastOfflineMessage(conversation, message);
|
this.addLastOfflineMessage(conversation, message);
|
||||||
this.addOfflineConversation(conversation);
|
this.addOfflineConversation(conversation, option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (option.type == AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_INDIVIDUAL) {
|
} else if (option.type === AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_INDIVIDUAL) {
|
||||||
// It's a new conversation. Check if we already created it (there is more than one message for the same user).
|
// It's a new conversation. Check if we already created it (there is more than one message for the same user).
|
||||||
const conversation = this.findConversation(undefined, message.touserid, option);
|
const conversation = this.findConversation(undefined, message.touserid, option);
|
||||||
|
|
||||||
|
@ -655,7 +692,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addLastOfflineMessage(conversation, message);
|
this.addLastOfflineMessage(conversation, message);
|
||||||
this.addOfflineConversation(conversation);
|
this.addOfflineConversation(conversation, option);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}));
|
}));
|
||||||
|
@ -670,9 +707,12 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
* Add an offline conversation into the right list of conversations.
|
* Add an offline conversation into the right list of conversations.
|
||||||
*
|
*
|
||||||
* @param conversation Offline conversation to add.
|
* @param conversation Offline conversation to add.
|
||||||
|
* @param option Option where to add the conversation.
|
||||||
*/
|
*/
|
||||||
protected addOfflineConversation(conversation: AddonMessagesConversationForList): void {
|
protected addOfflineConversation(
|
||||||
const option = this.getConversationOption(conversation);
|
conversation: AddonMessagesConversationForList,
|
||||||
|
option: AddonMessagesGroupConversationOption,
|
||||||
|
): void {
|
||||||
option.conversations.unshift(conversation);
|
option.conversations.unshift(conversation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,23 +733,23 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a conversation, return its option (favourites, group, individual).
|
* Given a conversation, return its option name.
|
||||||
*
|
*
|
||||||
* @param conversation Conversation to check.
|
* @param conversation Conversation to check.
|
||||||
* @returns Option object.
|
* @returns Option name.
|
||||||
*/
|
*/
|
||||||
protected getConversationOption(
|
protected getConversationOptionName(
|
||||||
conversation: AddonMessagesConversationForList | AddonMessagesNewMessagedEventData,
|
conversation: AddonMessagesConversationForList | AddonMessagesNewMessagedEventData,
|
||||||
): AddonMessagesGroupConversationOption {
|
): AddonMessagesGroupConversationOptionNames {
|
||||||
if (conversation.isfavourite) {
|
if (conversation.isfavourite) {
|
||||||
return this.favourites;
|
return AddonMessagesGroupConversationOptionNames.FAVOURITES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conversation.type == AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP) {
|
if (conversation.type === AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_GROUP) {
|
||||||
return this.group;
|
return AddonMessagesGroupConversationOptionNames.GROUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.individual;
|
return AddonMessagesGroupConversationOptionNames.INDIVIDUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -727,30 +767,29 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
try {
|
try {
|
||||||
await this.fetchData(refreshUnreadCounts);
|
await this.fetchData(refreshUnreadCounts);
|
||||||
} finally {
|
} finally {
|
||||||
if (refresher) {
|
|
||||||
refresher?.complete();
|
refresher?.complete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toogle the visibility of an option (expand/collapse).
|
* Toogle the visibility of an option (expand/collapse).
|
||||||
*
|
*
|
||||||
* @param option The option to expand/collapse.
|
* @param ev The event of the accordion.
|
||||||
*/
|
*/
|
||||||
toggle(option: AddonMessagesGroupConversationOption): void {
|
accordionGroupChange(ev: AccordionGroupChangeEventDetail): void {
|
||||||
if (option.expanded) {
|
const optionName = ev.value as AddonMessagesGroupConversationOptionNames;
|
||||||
// Already expanded, close it.
|
if (!optionName) {
|
||||||
option.expanded = false;
|
return;
|
||||||
this.loadCurrentListElement();
|
}
|
||||||
} else {
|
|
||||||
|
const option = this.getConversationGroupByName(optionName);
|
||||||
|
|
||||||
// Pass getCounts=true to update the counts everytime the user expands an option.
|
// Pass getCounts=true to update the counts everytime the user expands an option.
|
||||||
this.expandOption(option, true).catch((error) => {
|
this.expandOption(option, true).catch((error) => {
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingdiscussions', true);
|
CoreDomUtils.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingdiscussions', true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expand a certain option.
|
* Expand a certain option.
|
||||||
|
@ -761,40 +800,18 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
*/
|
*/
|
||||||
protected async expandOption(option: AddonMessagesGroupConversationOption, getCounts = false): Promise<void> {
|
protected async expandOption(option: AddonMessagesGroupConversationOption, getCounts = false): Promise<void> {
|
||||||
// Collapse all and expand the right one.
|
// Collapse all and expand the right one.
|
||||||
this.favourites.expanded = false;
|
|
||||||
this.group.expanded = false;
|
|
||||||
this.individual.expanded = false;
|
|
||||||
|
|
||||||
option.expanded = true;
|
|
||||||
option.loading = true;
|
option.loading = true;
|
||||||
|
this.accordionGroup.value = option.optionName;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.fetchDataForOption(option, false, getCounts);
|
await this.fetchDataForOption(option, false, getCounts);
|
||||||
|
|
||||||
this.loadCurrentListElement();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
option.expanded = false;
|
this.accordionGroup.value = undefined;
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
option.loading = false;
|
option.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the current list element based on the expanded list.
|
|
||||||
*/
|
|
||||||
protected loadCurrentListElement(): void {
|
|
||||||
if (this.favourites.expanded) {
|
|
||||||
this.currentListEl = this.favListEl && this.favListEl.nativeElement;
|
|
||||||
} else if (this.group.expanded) {
|
|
||||||
this.currentListEl = this.groupListEl && this.groupListEl.nativeElement;
|
|
||||||
} else if (this.individual.expanded) {
|
|
||||||
this.currentListEl = this.indListEl && this.indListEl.nativeElement;
|
|
||||||
} else {
|
|
||||||
this.currentListEl = undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -805,7 +822,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page destroyed.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.newMessagesObserver?.off();
|
this.newMessagesObserver?.off();
|
||||||
|
@ -825,11 +842,13 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
* Conversation options.
|
* Conversation options.
|
||||||
*/
|
*/
|
||||||
export type AddonMessagesGroupConversationOption = {
|
export type AddonMessagesGroupConversationOption = {
|
||||||
|
optionName: AddonMessagesGroupConversationOptionNames;
|
||||||
|
titleString: string;
|
||||||
|
emptyString: string;
|
||||||
type?: number; // Option type.
|
type?: number; // Option type.
|
||||||
favourites: boolean; // Whether it contains favourites conversations.
|
favourites: boolean; // Whether it contains favourites conversations.
|
||||||
count: number; // Number of conversations.
|
count: number; // Number of conversations.
|
||||||
unread?: number; // Number of unread conversations.
|
unread?: number; // Number of unread conversations.
|
||||||
expanded?: boolean; // Whether the option is currently expanded.
|
|
||||||
loading?: boolean; // Whether the option is being loaded.
|
loading?: boolean; // Whether the option is being loaded.
|
||||||
canLoadMore?: boolean; // Whether it can load more data.
|
canLoadMore?: boolean; // Whether it can load more data.
|
||||||
loadMoreError?: boolean; // Whether there was an error loading more conversations.
|
loadMoreError?: boolean; // Whether there was an error loading more conversations.
|
||||||
|
|
|
@ -35,8 +35,6 @@ import { CoreWSError } from '@classes/errors/wserror';
|
||||||
import { AddonNotificationsPreferencesNotificationProcessorState } from '@addons/notifications/services/notifications';
|
import { AddonNotificationsPreferencesNotificationProcessorState } from '@addons/notifications/services/notifications';
|
||||||
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
||||||
|
|
||||||
const ROOT_CACHE_KEY = 'mmaMessages:';
|
|
||||||
|
|
||||||
declare module '@singletons/events' {
|
declare module '@singletons/events' {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,12 +55,20 @@ declare module '@singletons/events' {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const enum AddonMessagesUpdateConversationAction {
|
||||||
|
MUTE = 'mute',
|
||||||
|
FAVOURITE = 'favourite',
|
||||||
|
DELETE = 'delete',
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to handle messages.
|
* Service to handle messages.
|
||||||
*/
|
*/
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class AddonMessagesProvider {
|
export class AddonMessagesProvider {
|
||||||
|
|
||||||
|
protected static readonly ROOT_CACHE_KEY = 'mmaMessages:';
|
||||||
|
|
||||||
static readonly NEW_MESSAGE_EVENT = 'addon_messages_new_message_event';
|
static readonly NEW_MESSAGE_EVENT = 'addon_messages_new_message_event';
|
||||||
static readonly READ_CHANGED_EVENT = 'addon_messages_read_changed_event';
|
static readonly READ_CHANGED_EVENT = 'addon_messages_read_changed_event';
|
||||||
static readonly OPEN_CONVERSATION_EVENT = 'addon_messages_open_conversation_event'; // Notify a conversation should be opened.
|
static readonly OPEN_CONVERSATION_EVENT = 'addon_messages_open_conversation_event'; // Notify a conversation should be opened.
|
||||||
|
@ -396,7 +402,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForBlockedContacts(userId: number): string {
|
protected getCacheKeyForBlockedContacts(userId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'blockedContacts:' + userId;
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'blockedContacts:' + userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -405,7 +411,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForContacts(): string {
|
protected getCacheKeyForContacts(): string {
|
||||||
return ROOT_CACHE_KEY + 'contacts';
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'contacts';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -414,7 +420,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForUserContacts(): string {
|
protected getCacheKeyForUserContacts(): string {
|
||||||
return ROOT_CACHE_KEY + 'userContacts';
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'userContacts';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -423,7 +429,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForContactRequests(): string {
|
protected getCacheKeyForContactRequests(): string {
|
||||||
return ROOT_CACHE_KEY + 'contactRequests';
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'contactRequests';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -432,7 +438,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForContactRequestsCount(): string {
|
protected getCacheKeyForContactRequestsCount(): string {
|
||||||
return ROOT_CACHE_KEY + 'contactRequestsCount';
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'contactRequestsCount';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -442,7 +448,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
getCacheKeyForDiscussion(userId: number): string {
|
getCacheKeyForDiscussion(userId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'discussion:' + userId;
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'discussion:' + userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -452,7 +458,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForMessageCount(userId: number): string {
|
protected getCacheKeyForMessageCount(userId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'count:' + userId;
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'count:' + userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -461,7 +467,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForUnreadConversationCounts(): string {
|
protected getCacheKeyForUnreadConversationCounts(): string {
|
||||||
return ROOT_CACHE_KEY + 'unreadConversationCounts';
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'unreadConversationCounts';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -470,7 +476,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForDiscussions(): string {
|
protected getCacheKeyForDiscussions(): string {
|
||||||
return ROOT_CACHE_KEY + 'discussions';
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'discussions';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -481,7 +487,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForConversation(userId: number, conversationId: number): string {
|
protected getCacheKeyForConversation(userId: number, conversationId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'conversation:' + userId + ':' + conversationId;
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'conversation:' + userId + ':' + conversationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -492,7 +498,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForConversationBetweenUsers(userId: number, otherUserId: number): string {
|
protected getCacheKeyForConversationBetweenUsers(userId: number, otherUserId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'conversationBetweenUsers:' + userId + ':' + otherUserId;
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'conversationBetweenUsers:' + userId + ':' + otherUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -503,7 +509,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForConversationMembers(userId: number, conversationId: number): string {
|
protected getCacheKeyForConversationMembers(userId: number, conversationId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'conversationMembers:' + userId + ':' + conversationId;
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'conversationMembers:' + userId + ':' + conversationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -514,7 +520,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForConversationMessages(userId: number, conversationId: number): string {
|
protected getCacheKeyForConversationMessages(userId: number, conversationId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'conversationMessages:' + userId + ':' + conversationId;
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'conversationMessages:' + userId + ':' + conversationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -535,7 +541,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForConversationCounts(): string {
|
protected getCacheKeyForConversationCounts(): string {
|
||||||
return ROOT_CACHE_KEY + 'conversationCounts';
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'conversationCounts';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -546,7 +552,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForMemberInfo(userId: number, otherUserId: number): string {
|
protected getCacheKeyForMemberInfo(userId: number, otherUserId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'memberInfo:' + userId + ':' + otherUserId;
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'memberInfo:' + userId + ':' + otherUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -556,7 +562,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getCacheKeyForSelfConversation(userId: number): string {
|
protected getCacheKeyForSelfConversation(userId: number): string {
|
||||||
return ROOT_CACHE_KEY + 'selfconversation:' + userId;
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'selfconversation:' + userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -575,7 +581,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getRootCacheKeyForConversations(): string {
|
protected getRootCacheKeyForConversations(): string {
|
||||||
return ROOT_CACHE_KEY + 'conversations:';
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'conversations:';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1388,7 +1394,7 @@ export class AddonMessagesProvider {
|
||||||
* @returns Cache key.
|
* @returns Cache key.
|
||||||
*/
|
*/
|
||||||
protected getMessagePreferencesCacheKey(): string {
|
protected getMessagePreferencesCacheKey(): string {
|
||||||
return ROOT_CACHE_KEY + 'messagePreferences';
|
return AddonMessagesProvider.ROOT_CACHE_KEY + 'messagePreferences';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2706,7 +2712,7 @@ export class AddonMessagesProvider {
|
||||||
* @param conversations Array of conversations.
|
* @param conversations Array of conversations.
|
||||||
* @returns Conversations sorted with most recent last.
|
* @returns Conversations sorted with most recent last.
|
||||||
*/
|
*/
|
||||||
sortConversations(conversations: AddonMessagesConversationFormatted[]): AddonMessagesConversationFormatted[] {
|
sortConversations(conversations: AddonMessagesConversationFormatted[] = []): AddonMessagesConversationFormatted[] {
|
||||||
return conversations.sort((a, b) => {
|
return conversations.sort((a, b) => {
|
||||||
const timeA = Number(a.lastmessagedate);
|
const timeA = Number(a.lastmessagedate);
|
||||||
const timeB = Number(b.lastmessagedate);
|
const timeB = Number(b.lastmessagedate);
|
||||||
|
@ -3684,7 +3690,7 @@ export type AddonMessagesNewMessagedEventData = {
|
||||||
*/
|
*/
|
||||||
export type AddonMessagesUpdateConversationListEventData = {
|
export type AddonMessagesUpdateConversationListEventData = {
|
||||||
conversationId: number;
|
conversationId: number;
|
||||||
action: string;
|
action: AddonMessagesUpdateConversationAction;
|
||||||
value?: boolean;
|
value?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Loading…
Reference in New Issue