diff --git a/src/addon/mod/chat/components/index/index.ts b/src/addon/mod/chat/components/index/index.ts index 71e646d53..4945a5ebe 100644 --- a/src/addon/mod/chat/components/index/index.ts +++ b/src/addon/mod/chat/components/index/index.ts @@ -16,7 +16,7 @@ import { Component, Injector } from '@angular/core'; import { NavController } from 'ionic-angular'; import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; -import { AddonModChatProvider } from '../../providers/chat'; +import { AddonModChatProvider, AddonModChatChat } from '../../providers/chat'; /** * Component that displays a chat. @@ -29,7 +29,7 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp component = AddonModChatProvider.COMPONENT; moduleName = 'chat'; - chat: any; + chat: AddonModChatChat; chatInfo: any; protected title: string; @@ -66,7 +66,7 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp protected fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise { return this.chatProvider.getChat(this.courseId, this.module.id).then((chat) => { this.chat = chat; - this.description = chat.intro || chat.description; + this.description = chat.intro; const now = this.timeUtils.timestamp(); const span = chat.chattime - now; diff --git a/src/addon/mod/chat/pages/chat/chat.ts b/src/addon/mod/chat/pages/chat/chat.ts index e4951d6e3..47be73f24 100644 --- a/src/addon/mod/chat/pages/chat/chat.ts +++ b/src/addon/mod/chat/pages/chat/chat.ts @@ -20,7 +20,7 @@ import { CoreLoggerProvider } from '@providers/logger'; import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; -import { AddonModChatProvider } from '../../providers/chat'; +import { AddonModChatProvider, AddonModChatMessageWithUserData } from '../../providers/chat'; import { Network } from '@ionic-native/network'; import * as moment from 'moment'; @@ -37,7 +37,7 @@ export class AddonModChatChatPage { loaded = false; title: string; - messages = []; + messages: AddonModChatMessageWithUserData[] = []; newMessage: string; polling: any; isOnline: boolean; @@ -46,7 +46,7 @@ export class AddonModChatChatPage { protected logger; protected courseId: number; protected chatId: number; - protected sessionId: number; + protected sessionId: string; protected lastTime = 0; protected oldContentHeight = 0; protected onlineObserver: any; @@ -131,9 +131,9 @@ export class AddonModChatChatPage { /** * Convenience function to login the user. * - * @return Resolved when done. + * @return Promise resolved when done. */ - protected loginUser(): Promise { + protected loginUser(): Promise { return this.chatProvider.loginUser(this.chatId).then((sessionId) => { this.sessionId = sessionId; }); @@ -144,12 +144,12 @@ export class AddonModChatChatPage { * * @return Promise resolved when done. */ - protected fetchMessages(): Promise { + protected fetchMessages(): Promise { return this.chatProvider.getLatestMessages(this.sessionId, this.lastTime).then((messagesInfo) => { this.lastTime = messagesInfo.chatnewlasttime || 0; return this.chatProvider.getMessagesUserData(messagesInfo.messages, this.courseId).then((messages) => { - this.messages = this.messages.concat(messages); + this.messages = this.messages.concat( messages); if (messages.length) { // New messages or beeps, scroll to bottom. setTimeout(() => this.scrollToBottom()); @@ -190,7 +190,7 @@ export class AddonModChatChatPage { * * @return Promised resolved when done. */ - protected fetchMessagesInterval(): Promise { + protected fetchMessagesInterval(): Promise { this.logger.debug('Polling for messages'); if (!this.isOnline || this.pollingRunning) { // Obviously we cannot check for new messages when the app is offline. @@ -225,7 +225,7 @@ export class AddonModChatChatPage { * @param prevMessage Previous message object. * @return True if messages are from diferent days, false othetwise. */ - showDate(message: any, prevMessage: any): boolean { + showDate(message: AddonModChatMessageWithUserData, prevMessage: AddonModChatMessageWithUserData): boolean { if (!prevMessage) { return true; } @@ -267,7 +267,7 @@ export class AddonModChatChatPage { }); } - reconnect(): Promise { + reconnect(): Promise { const modal = this.domUtils.showModalLoading(); // Call startPolling would take a while for the first execution, so we'll execute it manually to check if it works now. diff --git a/src/addon/mod/chat/pages/session-messages/session-messages.ts b/src/addon/mod/chat/pages/session-messages/session-messages.ts index b96ed597a..1a29a8365 100644 --- a/src/addon/mod/chat/pages/session-messages/session-messages.ts +++ b/src/addon/mod/chat/pages/session-messages/session-messages.ts @@ -15,7 +15,7 @@ import { Component } from '@angular/core'; import { IonicPage, NavParams } from 'ionic-angular'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; -import { AddonModChatProvider } from '../../providers/chat'; +import { AddonModChatProvider, AddonModChatSessionMessageWithUserData } from '../../providers/chat'; import * as moment from 'moment'; /** @@ -34,7 +34,7 @@ export class AddonModChatSessionMessagesPage { protected sessionEnd: number; protected groupId: number; protected loaded = false; - protected messages = []; + protected messages: AddonModChatSessionMessageWithUserData[] = []; constructor(navParams: NavParams, private domUtils: CoreDomUtilsProvider, private chatProvider: AddonModChatProvider) { this.courseId = navParams.get('courseId'); @@ -55,7 +55,7 @@ export class AddonModChatSessionMessagesPage { return this.chatProvider.getSessionMessages(this.chatId, this.sessionStart, this.sessionEnd, this.groupId) .then((messages) => { return this.chatProvider.getMessagesUserData(messages, this.courseId).then((messages) => { - this.messages = messages; + this.messages = messages; }); }).catch((error) => { this.domUtils.showErrorModalDefault(error, 'core.errorloadingcontent', true); @@ -84,7 +84,7 @@ export class AddonModChatSessionMessagesPage { * @param prevMessage Previous message object. * @return True if messages are from diferent days, false othetwise. */ - showDate(message: any, prevMessage: any): boolean { + showDate(message: AddonModChatSessionMessageWithUserData, prevMessage: AddonModChatSessionMessageWithUserData): boolean { if (!prevMessage) { return true; } diff --git a/src/addon/mod/chat/pages/sessions/sessions.ts b/src/addon/mod/chat/pages/sessions/sessions.ts index 6043f3f3b..1f6ddcf0d 100644 --- a/src/addon/mod/chat/pages/sessions/sessions.ts +++ b/src/addon/mod/chat/pages/sessions/sessions.ts @@ -20,7 +20,7 @@ import { CoreUserProvider } from '@core/user/providers/user'; import { CoreGroupsProvider, CoreGroupInfo } from '@providers/groups'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreUtilsProvider } from '@providers/utils/utils'; -import { AddonModChatProvider } from '../../providers/chat'; +import { AddonModChatProvider, AddonModChatSession, AddonModChatSessionUser } from '../../providers/chat'; /** * Page that displays list of chat sessions. @@ -73,13 +73,13 @@ export class AddonModChatSessionsPage { this.groupId = this.groupsProvider.validateGroupId(this.groupId, groupInfo); return this.chatProvider.getSessions(this.chatId, this.groupId, this.showAll); - }).then((sessions) => { + }).then((sessions: AddonModChatSessionFormatted[]) => { // Fetch user profiles. const promises = []; sessions.forEach((session) => { session.duration = session.sessionend - session.sessionstart; - session.sessionusers.forEach((sessionUser) => { + session.sessionusers.forEach((sessionUser: AddonModChatUserSessionFormatted) => { if (!sessionUser.userfullname) { // The WS does not return the user name, fetch user profile. promises.push(this.userProvider.getProfile(sessionUser.userid, this.courseId, true).then((user) => { @@ -156,3 +156,18 @@ export class AddonModChatSessionsPage { $event.stopPropagation(); } } + +/** + * Fields added to chat session in this view. + */ +type AddonModChatSessionFormatted = AddonModChatSession & { + duration?: number; // Session duration. + allsessionusers?: AddonModChatUserSessionFormatted[]; // All session users. +}; + +/** + * Fields added to user session in this view. + */ +type AddonModChatUserSessionFormatted = AddonModChatSessionUser & { + userfullname?: string; // User full name. +}; diff --git a/src/addon/mod/chat/pages/users/users.ts b/src/addon/mod/chat/pages/users/users.ts index 4cd59049d..f54560ba3 100644 --- a/src/addon/mod/chat/pages/users/users.ts +++ b/src/addon/mod/chat/pages/users/users.ts @@ -17,7 +17,7 @@ import { IonicPage, NavParams, ViewController } from 'ionic-angular'; import { CoreAppProvider } from '@providers/app'; import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; -import { AddonModChatProvider } from '../../providers/chat'; +import { AddonModChatProvider, AddonModChatUser } from '../../providers/chat'; import { Network } from '@ionic-native/network'; /** @@ -30,12 +30,12 @@ import { Network } from '@ionic-native/network'; }) export class AddonModChatUsersPage { - users = []; + users: AddonModChatUser[] = []; usersLoaded = false; currentUserId: number; isOnline: boolean; - protected sessionId: number; + protected sessionId: string; protected onlineObserver: any; constructor(navParams: NavParams, network: Network, zone: NgZone, private appProvider: CoreAppProvider, @@ -77,7 +77,7 @@ export class AddonModChatUsersPage { * * @param user User object. */ - talkTo(user: any): void { + talkTo(user: AddonModChatUser): void { this.viewCtrl.dismiss({talkTo: user.fullname}); } @@ -86,7 +86,7 @@ export class AddonModChatUsersPage { * * @param user User object. */ - beepTo(user: any): void { + beepTo(user: AddonModChatUser): void { this.viewCtrl.dismiss({beepTo: user.id}); } diff --git a/src/addon/mod/chat/providers/chat.ts b/src/addon/mod/chat/providers/chat.ts index 9b9a02e39..f656375a7 100644 --- a/src/addon/mod/chat/providers/chat.ts +++ b/src/addon/mod/chat/providers/chat.ts @@ -19,6 +19,7 @@ import { CoreUserProvider } from '@core/user/providers/user'; import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; +import { CoreWSExternalWarning, CoreWSExternalFile } from '@providers/ws'; /** * Service that provides some features for chats. @@ -41,7 +42,7 @@ export class AddonModChatProvider { * @param siteId Site ID. If not defined, current site. * @return Promise resolved when the chat is retrieved. */ - getChat(courseId: number, cmId: number, siteId?: string): Promise { + getChat(courseId: number, cmId: number, siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { const params = { courseids: [courseId] @@ -51,7 +52,9 @@ export class AddonModChatProvider { updateFrequency: CoreSite.FREQUENCY_RARELY }; - return site.read('mod_chat_get_chats_by_courses', params, preSets).then((response) => { + return site.read('mod_chat_get_chats_by_courses', params, preSets) + .then((response: AddonModChatGetChatsByCoursesResult): any => { + if (response.chats) { const chat = response.chats.find((chat) => chat.coursemodule == cmId); if (chat) { @@ -70,12 +73,14 @@ export class AddonModChatProvider { * @param chatId Chat instance ID. * @return Promise resolved when the WS is executed. */ - loginUser(chatId: number): Promise { + loginUser(chatId: number): Promise { const params = { chatid: chatId }; - return this.sitesProvider.getCurrentSite().write('mod_chat_login_user', params).then((response) => { + return this.sitesProvider.getCurrentSite().write('mod_chat_login_user', params) + .then((response: AddonModChatLoginUserResult): any => { + if (response.chatsid) { return response.chatsid; } @@ -108,14 +113,16 @@ export class AddonModChatProvider { * @param beepUserId Beep user ID. * @return Promise resolved when the WS is executed. */ - sendMessage(sessionId: number, message: string, beepUserId: number): Promise { + sendMessage(sessionId: string, message: string, beepUserId: number): Promise { const params = { chatsid: sessionId, messagetext: message, beepid: beepUserId }; - return this.sitesProvider.getCurrentSite().write('mod_chat_send_chat_message', params).then((response) => { + return this.sitesProvider.getCurrentSite().write('mod_chat_send_chat_message', params) + .then((response: AddonModChatSendChatMessageResult): any => { + if (response.messageid) { return response.messageid; } @@ -131,7 +138,7 @@ export class AddonModChatProvider { * @param lastTime Last time when messages were retrieved. * @return Promise resolved when the WS is executed. */ - getLatestMessages(sessionId: number, lastTime: number): Promise { + getLatestMessages(sessionId: string, lastTime: number): Promise { const params = { chatsid: sessionId, chatlasttime: lastTime @@ -149,8 +156,10 @@ export class AddonModChatProvider { * @param courseId ID of the course the messages belong to. * @return Promise always resolved with the formatted messages. */ - getMessagesUserData(messages: any[], courseId: number): Promise { - const promises = messages.map((message) => { + getMessagesUserData(messages: (AddonModChatMessage | AddonModChatSessionMessage)[], courseId: number) + : Promise<(AddonModChatMessageWithUserData | AddonModChatSessionMessageWithUserData)[]> { + + const promises = messages.map((message: AddonModChatMessageWithUserData | AddonModChatSessionMessageWithUserData) => { return this.userProvider.getProfile(message.userid, courseId, true).then((user) => { message.userfullname = user.fullname; message.userprofileimageurl = user.profileimageurl; @@ -171,7 +180,7 @@ export class AddonModChatProvider { * @param sessionId Chat sessiond ID. * @return Promise resolved when the WS is executed. */ - getChatUsers(sessionId: number): Promise { + getChatUsers(sessionId: string): Promise { const params = { chatsid: sessionId }; @@ -206,7 +215,8 @@ export class AddonModChatProvider { * @since 3.5 */ getSessions(chatId: number, groupId: number = 0, showAll: boolean = false, ignoreCache: boolean = false, siteId?: string): - Promise { + Promise { + return this.sitesProvider.getSite(siteId).then((site) => { const params = { chatid: chatId, @@ -222,7 +232,7 @@ export class AddonModChatProvider { preSets.emergencyCache = false; } - return site.read('mod_chat_get_sessions', params, preSets).then((response) => { + return site.read('mod_chat_get_sessions', params, preSets).then((response: AddonModChatGetSessionsResult): any => { if (!response || !response.sessions) { return Promise.reject(null); } @@ -245,7 +255,8 @@ export class AddonModChatProvider { * @since 3.5 */ getSessionMessages(chatId: number, sessionStart: number, sessionEnd: number, groupId: number = 0, ignoreCache: boolean = false, - siteId?: string): Promise { + siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { const params = { chatid: chatId, @@ -262,7 +273,9 @@ export class AddonModChatProvider { preSets.emergencyCache = false; } - return site.read('mod_chat_get_session_messages', params, preSets).then((response) => { + return site.read('mod_chat_get_session_messages', params, preSets) + .then((response: AddonModChatGetSessionMessagesResult): any => { + if (!response || !response.messages) { return Promise.reject(null); } @@ -390,3 +403,152 @@ export class AddonModChatProvider { return this.ROOT_CACHE_KEY + 'sessionsMessages:' + chatId + ':'; } } + +/** + * Chat returned by mod_chat_get_chats_by_courses. + */ +export type AddonModChatChat = { + id: number; // Chat id. + coursemodule: number; // Course module id. + course: number; // Course id. + name: string; // Chat name. + intro: string; // The Chat intro. + introformat: number; // Intro format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN). + introfiles?: CoreWSExternalFile[]; // @since 3.2. + chatmethod?: string; // Chat method (sockets, ajax, header_js). + keepdays?: number; // Keep days. + studentlogs?: number; // Student logs visible to everyone. + chattime?: number; // Chat time. + schedule?: number; // Schedule type. + timemodified?: number; // Time of last modification. + section?: number; // Course section id. + visible?: boolean; // Visible. + groupmode?: number; // Group mode. + groupingid?: number; // Group id. +}; + +/** + * Chat user returned by mod_chat_get_chat_users. + */ +export type AddonModChatUser = { + id: number; // User id. + fullname: string; // User full name. + profileimageurl: string; // User picture URL. +}; + +/** + * Meessage returned by mod_chat_get_chat_latest_messages. + */ +export type AddonModChatMessage = { + id: number; // Message id. + userid: number; // User id. + system: boolean; // True if is a system message (like user joined). + message: string; // Message text. + timestamp: number; // Timestamp for the message. +}; + +/** + * Message with user data + */ +export type AddonModChatMessageWithUserData = AddonModChatMessage & AddonModChatMessageUserData; + +/** + * Chat session. + */ +export type AddonModChatSession = { + sessionstart: number; // Session start time. + sessionend: number; // Session end time. + sessionusers: AddonModChatSessionUser[]; // Session users. + iscomplete: boolean; // Whether the session is completed or not. +}; + +/** + * Chat user returned by mod_chat_get_sessions. + */ +export type AddonModChatSessionUser = { + userid: number; // User id. + messagecount: number; // Number of messages in the session. +}; + +/** + * Message returned by mod_chat_get_session_messages. + */ +export type AddonModChatSessionMessage = { + id: number; // The message record id. + chatid: number; // The chat id. + userid: number; // The user who wrote the message. + groupid: number; // The group this message belongs to. + issystem: boolean; // Whether is a system message or not. + message: string; // The message text. + timestamp: number; // The message timestamp (indicates when the message was sent). +}; + +/** + * Message with user data + */ +export type AddonModChatSessionMessageWithUserData = AddonModChatSessionMessage & AddonModChatMessageUserData; + +/** + * Result of WS mod_chat_get_chats_by_courses. + */ +export type AddonModChatGetChatsByCoursesResult = { + chats: AddonModChatChat[]; + warnings?: CoreWSExternalWarning[]; +}; + +/** + * Result of WS mod_chat_get_chat_users. + */ +export type AddonModChatGetChatUsersResult = { + users: AddonModChatUser[]; // List of users. + warnings?: CoreWSExternalWarning[]; +}; + +/** + * Result of WS mod_chat_get_sessions. + */ +export type AddonModChatGetSessionsResult = { + sessions: AddonModChatSession[]; // List of sessions. + warnings?: CoreWSExternalWarning[]; +}; + +/** + * Result of WS mod_chat_get_session_messages. + */ +export type AddonModChatGetSessionMessagesResult = { + messages: AddonModChatSessionMessage[]; + warnings?: CoreWSExternalWarning[]; +}; + +/** + * Result of WS mod_chat_send_chat_message. + */ +export type AddonModChatSendChatMessageResult = { + messageid: number; // Message sent id. + warnings?: CoreWSExternalWarning[]; +}; + +/** + * Result of WS mod_chat_get_chat_latest_messages. + */ +export type AddonModChatGetChatLatestMessagesResult = { + messages: AddonModChatMessage[]; // List of messages. + chatnewlasttime: number; // New last time. + warnings?: CoreWSExternalWarning[]; +}; + +/** + * Result of WS mod_chat_login_user. + */ +export type AddonModChatLoginUserResult = { + chatsid: string; // Unique chat session id. + warnings?: CoreWSExternalWarning[]; +}; + +/** + * User data added to messages. + */ +type AddonModChatMessageUserData = { + userfullname?: string; // Calculated in the app. Full name of the user who wrote the message. + userprofileimageurl?: string; // Calculated in the app. Full name of the user who wrote the message. +}; diff --git a/src/addon/mod/chat/providers/prefetch-handler.ts b/src/addon/mod/chat/providers/prefetch-handler.ts index ca146b06d..11b3d9183 100644 --- a/src/addon/mod/chat/providers/prefetch-handler.ts +++ b/src/addon/mod/chat/providers/prefetch-handler.ts @@ -23,7 +23,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler'; import { CoreUserProvider } from '@core/user/providers/user'; -import { AddonModChatProvider } from './chat'; +import { AddonModChatProvider, AddonModChatChat } from './chat'; /** * Handler to prefetch chats. @@ -116,12 +116,12 @@ export class AddonModChatPrefetchHandler extends CoreCourseActivityPrefetchHandl */ protected prefetchChat(module: any, courseId: number, single: boolean, siteId: string): Promise { // Prefetch chat and group info. - const promises = [ + const promises: Promise[] = [ this.chatProvider.getChat(courseId, module.id, siteId), this.groupsProvider.getActivityGroupInfo(module.id, false, undefined, siteId) ]; - return Promise.all(promises).then(([chat, groupInfo]: [any, CoreGroupInfo]) => { + return Promise.all(promises).then(([chat, groupInfo]: [AddonModChatChat, CoreGroupInfo]) => { const promises = []; let groupIds = [0];