MOBILE-4528 chat: Decouple from initial bundle
parent
1c93299467
commit
181c4d9ee3
|
@ -19,12 +19,11 @@ import { CoreCourseHelper } from '@features/course/services/course-helper';
|
|||
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
|
||||
import { AddonModChatComponentsModule } from './components/components.module';
|
||||
import { AddonModChatProvider } from './services/chat';
|
||||
import { AddonModChatIndexLinkHandler } from './services/handlers/index-link';
|
||||
import { AddonModChatListLinkHandler } from './services/handlers/list-link';
|
||||
import { AddonModChatModuleHandler, AddonModChatModuleHandlerService } from './services/handlers/module';
|
||||
import { AddonModChatPrefetchHandler } from './services/handlers/prefetch';
|
||||
import { AddonModChatModuleHandler } from './services/handlers/module';
|
||||
import { getPrefetchHandlerInstance } from './services/handlers/prefetch';
|
||||
import { ADDON_MOD_CHAT_COMPONENT, ADDON_MOD_CHAT_PAGE_NAME } from './constants';
|
||||
|
||||
/**
|
||||
* Get mod chat services.
|
||||
|
@ -41,9 +40,20 @@ export async function getModChatServices(): Promise<Type<unknown>[]> {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mod chat component modules.
|
||||
*
|
||||
* @returns Chat component modules.
|
||||
*/
|
||||
export async function getModChatComponentModules(): Promise<unknown[]> {
|
||||
const { AddonModChatComponentsModule } = await import('@addons/mod/chat/components/components.module');
|
||||
|
||||
return [AddonModChatComponentsModule];
|
||||
}
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: AddonModChatModuleHandlerService.PAGE_NAME,
|
||||
path: ADDON_MOD_CHAT_PAGE_NAME,
|
||||
loadChildren: () => import('./chat-lazy.module').then(m => m.AddonModChatLazyModule),
|
||||
},
|
||||
];
|
||||
|
@ -51,19 +61,19 @@ const routes: Routes = [
|
|||
@NgModule({
|
||||
imports: [
|
||||
CoreMainMenuTabRoutingModule.forChild(routes),
|
||||
AddonModChatComponentsModule,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
multi: true,
|
||||
useValue: () => {
|
||||
CoreCourseModulePrefetchDelegate.registerHandler(getPrefetchHandlerInstance());
|
||||
|
||||
CoreCourseModuleDelegate.registerHandler(AddonModChatModuleHandler.instance);
|
||||
CoreContentLinksDelegate.registerHandler(AddonModChatIndexLinkHandler.instance);
|
||||
CoreContentLinksDelegate.registerHandler(AddonModChatListLinkHandler.instance);
|
||||
CoreCourseModulePrefetchDelegate.registerHandler(AddonModChatPrefetchHandler.instance);
|
||||
|
||||
CoreCourseHelper.registerModuleReminderClick(AddonModChatProvider.COMPONENT);
|
||||
CoreCourseHelper.registerModuleReminderClick(ADDON_MOD_CHAT_COMPONENT);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -19,8 +19,8 @@ import { IonContent } from '@ionic/angular';
|
|||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreTimeUtils } from '@services/utils/time';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { AddonModChat, AddonModChatChat, AddonModChatProvider } from '../../services/chat';
|
||||
import { AddonModChatModuleHandlerService } from '../../services/handlers/module';
|
||||
import { AddonModChat, AddonModChatChat } from '../../services/chat';
|
||||
import { ADDON_MOD_CHAT_COMPONENT, ADDON_MOD_CHAT_PAGE_NAME } from '../../constants';
|
||||
|
||||
/**
|
||||
* Component that displays a chat.
|
||||
|
@ -31,7 +31,7 @@ import { AddonModChatModuleHandlerService } from '../../services/handlers/module
|
|||
})
|
||||
export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit {
|
||||
|
||||
component = AddonModChatProvider.COMPONENT;
|
||||
component = ADDON_MOD_CHAT_COMPONENT;
|
||||
pluginName = 'chat';
|
||||
chat?: AddonModChatChat;
|
||||
chatTime?: string;
|
||||
|
@ -88,7 +88,7 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
const title = this.chat?.name || this.moduleName;
|
||||
|
||||
CoreNavigator.navigateToSitePath(
|
||||
AddonModChatModuleHandlerService.PAGE_NAME + `/${this.courseId}/${this.module.id}/chat`,
|
||||
`${ADDON_MOD_CHAT_PAGE_NAME}/${this.courseId}/${this.module.id}/chat`,
|
||||
{
|
||||
params: {
|
||||
title,
|
||||
|
@ -103,7 +103,7 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
*/
|
||||
viewSessions(): void {
|
||||
CoreNavigator.navigateToSitePath(
|
||||
AddonModChatModuleHandlerService.PAGE_NAME + `/${this.courseId}/${this.module.id}/sessions`,
|
||||
`${ADDON_MOD_CHAT_PAGE_NAME}/${this.courseId}/${this.module.id}/sessions`,
|
||||
{
|
||||
params: {
|
||||
chatId: this.chat!.id,
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// 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.
|
||||
|
||||
export const ADDON_MOD_CHAT_COMPONENT = 'mmaModChat';
|
||||
|
||||
// Routing.
|
||||
export const ADDON_MOD_CHAT_PAGE_NAME = 'mod_chat';
|
||||
|
||||
// Handlers.
|
||||
export const ADDON_MOD_CHAT_PREFETCH_NAME = 'AddonModChat';
|
||||
export const ADDON_MOD_CHAT_PREFETCH_MODNAME = 'chat';
|
||||
export const ADDON_MOD_CHAT_PREFETCH_COMPONENT = ADDON_MOD_CHAT_PAGE_NAME;
|
|
@ -26,7 +26,7 @@ import { NgZone, Translate } from '@singletons';
|
|||
import { CoreEvents } from '@singletons/events';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { AddonModChatUsersModalComponent, AddonModChatUsersModalResult } from '../../components/users-modal/users-modal';
|
||||
import { AddonModChat, AddonModChatProvider, AddonModChatUser } from '../../services/chat';
|
||||
import { AddonModChat, AddonModChatUser } from '../../services/chat';
|
||||
import { AddonModChatFormattedMessage, AddonModChatHelper } from '../../services/chat-helper';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||
|
@ -41,6 +41,8 @@ import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
|||
})
|
||||
export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave {
|
||||
|
||||
protected static readonly POLL_INTERVAL = 4000;
|
||||
|
||||
@ViewChild(IonContent) content?: IonContent;
|
||||
@ViewChild(CoreSendMessageFormComponent) sendMessageForm?: CoreSendMessageFormComponent;
|
||||
|
||||
|
@ -252,7 +254,7 @@ export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave {
|
|||
// Start polling.
|
||||
this.polling = window.setInterval(() => {
|
||||
CoreUtils.ignoreErrors(this.fetchMessagesInterval());
|
||||
}, AddonModChatProvider.POLL_INTERVAL);
|
||||
}, AddonModChatChatPage.POLL_INTERVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,8 +22,7 @@ import { CoreUser } from '@features/user/services/user';
|
|||
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
|
||||
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
||||
import { makeSingleton, Translate } from '@singletons';
|
||||
|
||||
const ROOT_CACHE_KEY = 'AddonModChat:';
|
||||
import { ADDON_MOD_CHAT_COMPONENT } from '../constants';
|
||||
|
||||
/**
|
||||
* Service that provides some features for chats.
|
||||
|
@ -31,8 +30,7 @@ const ROOT_CACHE_KEY = 'AddonModChat:';
|
|||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModChatProvider {
|
||||
|
||||
static readonly COMPONENT = 'mmaModChat';
|
||||
static readonly POLL_INTERVAL = 4000;
|
||||
protected static readonly ROOT_CACHE_KEY = 'AddonModChat:';
|
||||
|
||||
/**
|
||||
* Get a chat.
|
||||
|
@ -51,7 +49,7 @@ export class AddonModChatProvider {
|
|||
const preSets: CoreSiteWSPreSets = {
|
||||
cacheKey: this.getChatsCacheKey(courseId),
|
||||
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
||||
component: AddonModChatProvider.COMPONENT,
|
||||
component: ADDON_MOD_CHAT_COMPONENT,
|
||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||
};
|
||||
|
||||
|
@ -99,7 +97,7 @@ export class AddonModChatProvider {
|
|||
await CoreCourseLogHelper.log(
|
||||
'mod_chat_view_chat',
|
||||
params,
|
||||
AddonModChatProvider.COMPONENT,
|
||||
ADDON_MOD_CHAT_COMPONENT,
|
||||
id,
|
||||
siteId,
|
||||
);
|
||||
|
@ -126,7 +124,7 @@ export class AddonModChatProvider {
|
|||
await CoreCourseLogHelper.log(
|
||||
'mod_chat_view_sessions',
|
||||
params,
|
||||
AddonModChatProvider.COMPONENT,
|
||||
ADDON_MOD_CHAT_COMPONENT,
|
||||
id,
|
||||
);
|
||||
}
|
||||
|
@ -232,7 +230,7 @@ export class AddonModChatProvider {
|
|||
chatsid: sessionId,
|
||||
};
|
||||
const preSets: CoreSiteWSPreSets = {
|
||||
component: AddonModChatProvider.COMPONENT,
|
||||
component: ADDON_MOD_CHAT_COMPONENT,
|
||||
componentId: options.cmId,
|
||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||
};
|
||||
|
@ -265,7 +263,7 @@ export class AddonModChatProvider {
|
|||
const preSets: CoreSiteWSPreSets = {
|
||||
cacheKey: this.getSessionsCacheKey(chatId, groupId, showAll),
|
||||
updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
|
||||
component: AddonModChatProvider.COMPONENT,
|
||||
component: ADDON_MOD_CHAT_COMPONENT,
|
||||
componentId: options.cmId,
|
||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||
};
|
||||
|
@ -303,7 +301,7 @@ export class AddonModChatProvider {
|
|||
const preSets: CoreSiteWSPreSets = {
|
||||
cacheKey: this.getSessionMessagesCacheKey(chatId, sessionStart, groupId),
|
||||
updateFrequency: CoreSite.FREQUENCY_RARELY,
|
||||
component: AddonModChatProvider.COMPONENT,
|
||||
component: ADDON_MOD_CHAT_COMPONENT,
|
||||
componentId: options.cmId,
|
||||
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
|
||||
};
|
||||
|
@ -393,7 +391,7 @@ export class AddonModChatProvider {
|
|||
* @returns Cache key.
|
||||
*/
|
||||
protected getChatsCacheKey(courseId: number): string {
|
||||
return ROOT_CACHE_KEY + 'chats:' + courseId;
|
||||
return AddonModChatProvider.ROOT_CACHE_KEY + 'chats:' + courseId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -415,7 +413,7 @@ export class AddonModChatProvider {
|
|||
* @returns Cache key prefix.
|
||||
*/
|
||||
protected getSessionsCacheKeyPrefix(chatId: number): string {
|
||||
return ROOT_CACHE_KEY + 'sessions:' + chatId + ':';
|
||||
return AddonModChatProvider.ROOT_CACHE_KEY + 'sessions:' + chatId + ':';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -437,7 +435,7 @@ export class AddonModChatProvider {
|
|||
* @returns Cache key prefix.
|
||||
*/
|
||||
protected getSessionMessagesCacheKeyPrefix(chatId: number): string {
|
||||
return ROOT_CACHE_KEY + 'sessionsMessages:' + chatId + ':';
|
||||
return AddonModChatProvider.ROOT_CACHE_KEY + 'sessionsMessages:' + chatId + ':';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import { Injectable, Type } from '@angular/core';
|
|||
import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler';
|
||||
import { CoreCourseModuleHandler } from '@features/course/services/module-delegate';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { AddonModChatIndexComponent } from '../../components/index';
|
||||
import { ADDON_MOD_CHAT_PAGE_NAME } from '../../constants';
|
||||
|
||||
/**
|
||||
* Handler to support chat modules.
|
||||
|
@ -25,11 +25,9 @@ import { AddonModChatIndexComponent } from '../../components/index';
|
|||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModChatModuleHandlerService extends CoreModuleHandlerBase implements CoreCourseModuleHandler {
|
||||
|
||||
static readonly PAGE_NAME = 'mod_chat';
|
||||
|
||||
name = 'AddonModChat';
|
||||
modName = 'chat';
|
||||
protected pageName = AddonModChatModuleHandlerService.PAGE_NAME;
|
||||
protected pageName = ADDON_MOD_CHAT_PAGE_NAME;
|
||||
|
||||
supportedFeatures = {
|
||||
[CoreConstants.FEATURE_GROUPS]: true,
|
||||
|
@ -47,6 +45,8 @@ export class AddonModChatModuleHandlerService extends CoreModuleHandlerBase impl
|
|||
* @inheritdoc
|
||||
*/
|
||||
async getMainComponent(): Promise<Type<unknown>> {
|
||||
const { AddonModChatIndexComponent } = await import('@addons/mod/chat/components/index');
|
||||
|
||||
return AddonModChatIndexComponent;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// 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 { Injectable } from '@angular/core';
|
||||
import { AddonModChatPrefetchHandlerService } from './prefetch';
|
||||
import { AddonModChat, AddonModChatSession } from '../chat';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreCourse, CoreCourseAnyModuleData, CoreCourseCommonModWSOptions } from '@features/course/services/course';
|
||||
import { CoreSitesReadingStrategy } from '@services/sites';
|
||||
import { CoreGroups } from '@services/groups';
|
||||
import { CoreUser } from '@features/user/services/user';
|
||||
import { makeSingleton } from '@singletons';
|
||||
|
||||
/**
|
||||
* Handler to prefetch workshops.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModChatPrefetchHandlerLazyService extends AddonModChatPrefetchHandlerService {
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async invalidateContent(moduleId: number, courseId: number): Promise<void> {
|
||||
const chat = await AddonModChat.getChat(courseId, moduleId);
|
||||
|
||||
await CoreUtils.allPromises([
|
||||
AddonModChat.invalidateAllSessions(chat.id),
|
||||
AddonModChat.invalidateAllSessionMessages(chat.id),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async invalidateModule(module: CoreCourseAnyModuleData, courseId: number): Promise<void> {
|
||||
await CoreUtils.allPromises([
|
||||
AddonModChat.invalidateChats(courseId),
|
||||
CoreCourse.invalidateModule(module.id),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> {
|
||||
return this.prefetchPackage(module, courseId, (siteId) => this.prefetchChat(module, courseId, siteId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetch a chat.
|
||||
*
|
||||
* @param module The module object returned by WS.
|
||||
* @param courseId Course ID the module belongs to.
|
||||
* @param siteId Site ID.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
protected async prefetchChat(module: CoreCourseAnyModuleData, courseId: number, siteId: string): Promise<void> {
|
||||
const options = {
|
||||
readingStrategy: CoreSitesReadingStrategy.ONLY_NETWORK,
|
||||
siteId,
|
||||
};
|
||||
const modOptions = {
|
||||
...options,
|
||||
cmId: module.id,
|
||||
};
|
||||
|
||||
// Prefetch chat and group info.
|
||||
const [chat, groupInfo] = await Promise.all([
|
||||
AddonModChat.getChat(courseId, module.id, options),
|
||||
CoreGroups.getActivityGroupInfo(module.id, false, undefined, siteId),
|
||||
]);
|
||||
|
||||
const promises: Promise<void>[] = [];
|
||||
|
||||
let groupIds = [0];
|
||||
if (groupInfo.groups && groupInfo.groups.length > 0) {
|
||||
groupIds = groupInfo.groups.map((group) => group.id);
|
||||
}
|
||||
|
||||
groupIds.forEach((groupId) => {
|
||||
// Prefetch complete sessions.
|
||||
promises.push(this.prefetchSessions(chat.id, groupId, courseId, false, modOptions));
|
||||
|
||||
// Prefetch all sessions.
|
||||
promises.push(this.prefetchSessions(chat.id, groupId, courseId, true, modOptions));
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetch chat sessions.
|
||||
*
|
||||
* @param chatId Chat ID.
|
||||
* @param groupId Group ID, 0 means that the function will determine the user group.
|
||||
* @param courseId Course ID.
|
||||
* @param showAll Whether to include incomplete sessions or not.
|
||||
* @param modOptions Other options.
|
||||
* @returns Promise resolved with the list of sessions.
|
||||
*/
|
||||
protected async prefetchSessions(
|
||||
chatId: number,
|
||||
groupId: number,
|
||||
courseId: number,
|
||||
showAll: boolean,
|
||||
modOptions: CoreCourseCommonModWSOptions,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const sessions = await AddonModChat.getSessions(chatId, groupId, showAll, modOptions);
|
||||
|
||||
if (showAll) {
|
||||
// Prefetch each session data too.
|
||||
await Promise.all(sessions.map((session) => this.prefetchSession(chatId, session, groupId, courseId, modOptions)));
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore group error.
|
||||
if (error && error.errorcode == 'notingroup') {
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetch chat session messages and user profiles.
|
||||
*
|
||||
* @param chatId Chat ID.
|
||||
* @param session Session object.
|
||||
* @param groupId Group ID.
|
||||
* @param courseId Course ID the module belongs to.
|
||||
* @param modOptions Other options.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
protected async prefetchSession(
|
||||
chatId: number,
|
||||
session: AddonModChatSession,
|
||||
groupId: number,
|
||||
courseId: number,
|
||||
modOptions: CoreCourseCommonModWSOptions,
|
||||
): Promise<void> {
|
||||
const messages = await AddonModChat.getSessionMessages(
|
||||
chatId,
|
||||
session.sessionstart,
|
||||
session.sessionend,
|
||||
groupId,
|
||||
modOptions,
|
||||
);
|
||||
|
||||
const users: Record<number, number> = {};
|
||||
session.sessionusers.forEach((user) => {
|
||||
users[user.userid] = user.userid;
|
||||
});
|
||||
messages.forEach((message) => {
|
||||
users[message.userid] = message.userid;
|
||||
});
|
||||
const userIds = Object.values(users);
|
||||
|
||||
await CoreUser.prefetchProfiles(userIds, courseId, modOptions.siteId);
|
||||
}
|
||||
|
||||
}
|
||||
export const AddonModChatPrefetchHandler = makeSingleton(AddonModChatPrefetchHandlerLazyService);
|
|
@ -12,168 +12,42 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler';
|
||||
import { CoreCourse, CoreCourseAnyModuleData, CoreCourseCommonModWSOptions } from '@features/course/services/course';
|
||||
import { CoreUser } from '@features/user/services/user';
|
||||
import { CoreGroups } from '@services/groups';
|
||||
import { CoreSitesReadingStrategy } from '@services/sites';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { AddonModChat, AddonModChatProvider, AddonModChatSession } from '../chat';
|
||||
import { ADDON_MOD_CHAT_PREFETCH_COMPONENT, ADDON_MOD_CHAT_PREFETCH_MODNAME, ADDON_MOD_CHAT_PREFETCH_NAME } from '../../constants';
|
||||
import { CoreCourseModulePrefetchHandler } from '@features/course/services/module-prefetch-delegate';
|
||||
import { asyncInstance } from '@/core/utils/async-instance';
|
||||
import type { AddonModChatPrefetchHandlerLazyService } from './prefetch-lazy';
|
||||
|
||||
/**
|
||||
* Handler to prefetch chats.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModChatPrefetchHandlerService extends CoreCourseActivityPrefetchHandlerBase {
|
||||
|
||||
name = 'AddonModChat';
|
||||
modName = 'chat';
|
||||
component = AddonModChatProvider.COMPONENT;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async invalidateContent(moduleId: number, courseId: number): Promise<void> {
|
||||
const chat = await AddonModChat.getChat(courseId, moduleId);
|
||||
|
||||
await CoreUtils.allPromises([
|
||||
AddonModChat.invalidateAllSessions(chat.id),
|
||||
AddonModChat.invalidateAllSessionMessages(chat.id),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async invalidateModule(module: CoreCourseAnyModuleData, courseId: number): Promise<void> {
|
||||
await CoreUtils.allPromises([
|
||||
AddonModChat.invalidateChats(courseId),
|
||||
CoreCourse.invalidateModule(module.id),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> {
|
||||
return this.prefetchPackage(module, courseId, (siteId) => this.prefetchChat(module, courseId, siteId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetch a chat.
|
||||
*
|
||||
* @param module The module object returned by WS.
|
||||
* @param courseId Course ID the module belongs to.
|
||||
* @param siteId Site ID.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
protected async prefetchChat(module: CoreCourseAnyModuleData, courseId: number, siteId: string): Promise<void> {
|
||||
const options = {
|
||||
readingStrategy: CoreSitesReadingStrategy.ONLY_NETWORK,
|
||||
siteId,
|
||||
};
|
||||
const modOptions = {
|
||||
...options,
|
||||
cmId: module.id,
|
||||
};
|
||||
|
||||
// Prefetch chat and group info.
|
||||
const [chat, groupInfo] = await Promise.all([
|
||||
AddonModChat.getChat(courseId, module.id, options),
|
||||
CoreGroups.getActivityGroupInfo(module.id, false, undefined, siteId),
|
||||
]);
|
||||
|
||||
const promises: Promise<void>[] = [];
|
||||
|
||||
let groupIds = [0];
|
||||
if (groupInfo.groups && groupInfo.groups.length > 0) {
|
||||
groupIds = groupInfo.groups.map((group) => group.id);
|
||||
}
|
||||
|
||||
groupIds.forEach((groupId) => {
|
||||
// Prefetch complete sessions.
|
||||
promises.push(this.prefetchSessions(chat.id, groupId, courseId, false, modOptions));
|
||||
|
||||
// Prefetch all sessions.
|
||||
promises.push(this.prefetchSessions(chat.id, groupId, courseId, true, modOptions));
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetch chat sessions.
|
||||
*
|
||||
* @param chatId Chat ID.
|
||||
* @param groupId Group ID, 0 means that the function will determine the user group.
|
||||
* @param courseId Course ID.
|
||||
* @param showAll Whether to include incomplete sessions or not.
|
||||
* @param modOptions Other options.
|
||||
* @returns Promise resolved with the list of sessions.
|
||||
*/
|
||||
protected async prefetchSessions(
|
||||
chatId: number,
|
||||
groupId: number,
|
||||
courseId: number,
|
||||
showAll: boolean,
|
||||
modOptions: CoreCourseCommonModWSOptions,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const sessions = await AddonModChat.getSessions(chatId, groupId, showAll, modOptions);
|
||||
|
||||
if (showAll) {
|
||||
// Prefetch each session data too.
|
||||
await Promise.all(sessions.map((session) => this.prefetchSession(chatId, session, groupId, courseId, modOptions)));
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore group error.
|
||||
if (error && error.errorcode == 'notingroup') {
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetch chat session messages and user profiles.
|
||||
*
|
||||
* @param chatId Chat ID.
|
||||
* @param session Session object.
|
||||
* @param groupId Group ID.
|
||||
* @param courseId Course ID the module belongs to.
|
||||
* @param modOptions Other options.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
protected async prefetchSession(
|
||||
chatId: number,
|
||||
session: AddonModChatSession,
|
||||
groupId: number,
|
||||
courseId: number,
|
||||
modOptions: CoreCourseCommonModWSOptions,
|
||||
): Promise<void> {
|
||||
const messages = await AddonModChat.getSessionMessages(
|
||||
chatId,
|
||||
session.sessionstart,
|
||||
session.sessionend,
|
||||
groupId,
|
||||
modOptions,
|
||||
);
|
||||
|
||||
const users: Record<number, number> = {};
|
||||
session.sessionusers.forEach((user) => {
|
||||
users[user.userid] = user.userid;
|
||||
});
|
||||
messages.forEach((message) => {
|
||||
users[message.userid] = message.userid;
|
||||
});
|
||||
const userIds = Object.values(users);
|
||||
|
||||
await CoreUser.prefetchProfiles(userIds, courseId, modOptions.siteId);
|
||||
}
|
||||
name = ADDON_MOD_CHAT_PREFETCH_NAME;
|
||||
modName = ADDON_MOD_CHAT_PREFETCH_MODNAME;
|
||||
component = ADDON_MOD_CHAT_PREFETCH_COMPONENT;
|
||||
|
||||
}
|
||||
|
||||
export const AddonModChatPrefetchHandler = makeSingleton(AddonModChatPrefetchHandlerService);
|
||||
/**
|
||||
* Get prefetch handler instance.
|
||||
*
|
||||
* @returns Prefetch handler.
|
||||
*/
|
||||
export function getPrefetchHandlerInstance(): CoreCourseModulePrefetchHandler {
|
||||
const lazyHandler = asyncInstance<
|
||||
AddonModChatPrefetchHandlerLazyService,
|
||||
AddonModChatPrefetchHandlerService
|
||||
>(async () => {
|
||||
const { AddonModChatPrefetchHandler } = await import('./prefetch-lazy');
|
||||
|
||||
return AddonModChatPrefetchHandler.instance;
|
||||
});
|
||||
|
||||
lazyHandler.setEagerInstance(new AddonModChatPrefetchHandlerService());
|
||||
lazyHandler.setLazyMethods([]);
|
||||
lazyHandler.setLazyOverrides([
|
||||
'prefetch',
|
||||
'invalidateModule',
|
||||
'invalidateContent',
|
||||
]);
|
||||
|
||||
return lazyHandler;
|
||||
}
|
||||
|
|
|
@ -77,3 +77,10 @@ Feature: Test basic usage of chat in app
|
|||
And I press "david student" near "(2)" in the app
|
||||
Then I should find "Hi!" in the app
|
||||
And I should find "I am David" in the app
|
||||
|
||||
Scenario: Prefetch chat
|
||||
# Only check that the chat is marked as downloaded to test that lazy handler is working.
|
||||
Given I entered the course "Course 1" as "student1" in the app
|
||||
When I press "Course downloads" in the app
|
||||
And I press "Download" within "Test chat name" "ion-item" in the app
|
||||
Then I should not be able to press "Download" within "Test chat name" "ion-item" in the app
|
||||
|
|
|
@ -131,7 +131,7 @@ import { getMessageOutputServices } from '@addons/messageoutput/messageoutput.mo
|
|||
import { getMessagesServices } from '@addons/messages/messages.module';
|
||||
import { getModAssignServices } from '@addons/mod/assign/assign.module';
|
||||
import { getModBookServices } from '@addons/mod/book/book.module';
|
||||
import { getModChatServices } from '@addons/mod/chat/chat.module';
|
||||
import { getModChatServices, getModChatComponentModules } from '@addons/mod/chat/chat.module';
|
||||
import { getModChoiceServices } from '@addons/mod/choice/choice.module';
|
||||
import { getModFeedbackServices } from '@addons/mod/feedback/feedback.module';
|
||||
import { getModFolderServices } from '@addons/mod/folder/folder.module';
|
||||
|
@ -185,6 +185,7 @@ export class CoreCompileProvider {
|
|||
protected readonly LAZY_IMPORTS = [
|
||||
getModWorkshopComponentModules,
|
||||
getModSurveyComponentModules,
|
||||
getModChatComponentModules,
|
||||
];
|
||||
|
||||
constructor(protected injector: Injector) {
|
||||
|
|
Loading…
Reference in New Issue