parent
d02ea1daf7
commit
0545ced64f
@ -1,13 +0,0 @@ |
||||
import { RoomTypeConfig, roomTypes } from '../../utils'; |
||||
|
||||
export class DiscussionRoomType extends RoomTypeConfig { |
||||
constructor() { |
||||
super({ |
||||
identifier: 't', |
||||
order: 25, |
||||
label: 'Discussion', |
||||
}); |
||||
} |
||||
} |
||||
|
||||
roomTypes.add(new DiscussionRoomType()); |
||||
@ -1,40 +0,0 @@ |
||||
import { Blaze } from 'meteor/blaze'; |
||||
// import { Session } from 'meteor/session';
|
||||
import { Tracker } from 'meteor/tracker'; |
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
|
||||
import { callbacks } from '../../../lib/callbacks'; |
||||
|
||||
const testIfPathAreEquals = (oldPath = '', newPath = '') => oldPath.replace(/"/g, '') === newPath; |
||||
export const roomExit = function () { |
||||
const oldRoute = FlowRouter.current(); |
||||
Tracker.afterFlush(() => { |
||||
const context = FlowRouter.current(); |
||||
|
||||
if ( |
||||
oldRoute && |
||||
testIfPathAreEquals( |
||||
oldRoute.params.name || oldRoute.params.rid || oldRoute.params.id, |
||||
context.params.name || context.params.rid || context.params.id, |
||||
) |
||||
) { |
||||
return; |
||||
} |
||||
// 7370 - Close flex-tab when opening a room on mobile UI
|
||||
if (window.matchMedia('(max-width: 500px)').matches) { |
||||
const flex = document.querySelector('.flex-tab'); |
||||
if (flex) { |
||||
const templateData = Blaze.getData(flex); |
||||
templateData && templateData.tabBar && templateData.tabBar.close(); |
||||
} |
||||
} |
||||
callbacks.run('roomExit'); |
||||
|
||||
// Session.set('lastOpenedRoom', Session.get('openedRoom'));
|
||||
// Session.set('openedRoom', null);
|
||||
// RoomManager.openedRoom = null;
|
||||
}); |
||||
if (typeof window.currentTracker !== 'undefined') { |
||||
window.currentTracker.stop(); |
||||
} |
||||
}; |
||||
@ -0,0 +1,67 @@ |
||||
import type { RouteOptions } from 'meteor/kadira:flow-router'; |
||||
|
||||
import { openRoom } from '../../../app/ui-utils/client/lib/openRoom'; |
||||
import type { IRoom } from '../../../definition/IRoom'; |
||||
import type { IRoomTypeConfig, IRoomTypeClientDirectives } from '../../../definition/IRoomTypeConfig'; |
||||
import { RoomSettingsEnum, RoomMemberActions, UiTextContext } from '../../../definition/IRoomTypeConfig'; |
||||
import type { ValueOf } from '../../../definition/utils'; |
||||
import { RoomCoordinator } from '../../../lib/rooms/coordinator'; |
||||
import { roomExit } from './roomExit'; |
||||
|
||||
class RoomCoordinatorClient extends RoomCoordinator { |
||||
add(roomConfig: IRoomTypeConfig, directives: Partial<IRoomTypeClientDirectives>): void { |
||||
this.addRoomType(roomConfig, { |
||||
allowRoomSettingChange(_room: Partial<IRoom>, _setting: ValueOf<typeof RoomSettingsEnum>): boolean { |
||||
return true; |
||||
}, |
||||
allowMemberAction(_room: Partial<IRoom>, _action: ValueOf<typeof RoomMemberActions>): boolean { |
||||
return false; |
||||
}, |
||||
roomName(_room: Partial<IRoom>): string { |
||||
return ''; |
||||
}, |
||||
isGroupChat(_room: Partial<IRoom>): boolean { |
||||
return false; |
||||
}, |
||||
openCustomProfileTab(_instance: any, _room: IRoom, _username: string): boolean { |
||||
return false; |
||||
}, |
||||
getUiText(_context: ValueOf<typeof UiTextContext>): string { |
||||
return ''; |
||||
}, |
||||
condition(): boolean { |
||||
return true; |
||||
}, |
||||
getAvatarPath(_room: Partial<IRoom> & { username?: IRoom['_id'] }): string { |
||||
return ''; |
||||
}, |
||||
getIcon(_room: Partial<IRoom>): string | undefined { |
||||
return this.config.icon; |
||||
}, |
||||
getUserStatus(_roomId: string): string | undefined { |
||||
return undefined; |
||||
}, |
||||
|
||||
...directives, |
||||
config: roomConfig, |
||||
}); |
||||
} |
||||
|
||||
protected addRoute(path: string, routeConfig: RouteOptions): void { |
||||
super.addRoute(path, { ...routeConfig, triggersExit: [roomExit] }); |
||||
} |
||||
|
||||
getRoomDirectives(roomType: string): IRoomTypeClientDirectives | undefined { |
||||
return this.roomTypes[roomType]?.directives as IRoomTypeClientDirectives; |
||||
} |
||||
|
||||
openRoom(type: string, name: string, render = true): void { |
||||
openRoom(type, name, render); |
||||
} |
||||
|
||||
getIcon(room: Partial<IRoom>): string | undefined { |
||||
return room?.t && this.getRoomDirectives(room.t)?.getIcon(room); |
||||
} |
||||
} |
||||
|
||||
export const roomCoordinator = new RoomCoordinatorClient(); |
||||
@ -0,0 +1,33 @@ |
||||
import { Blaze } from 'meteor/blaze'; |
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
const testIfPathAreEquals = (oldPath = '', newPath = ''): boolean => oldPath.replace(/"/g, '') === newPath; |
||||
export const roomExit = function (_context: { params: Record<string, string>; queryParams: Record<string, string> }): void { |
||||
const oldRoute = FlowRouter.current(); |
||||
Tracker.afterFlush(() => { |
||||
const context = FlowRouter.current(); |
||||
|
||||
if ( |
||||
oldRoute && |
||||
testIfPathAreEquals( |
||||
oldRoute.params.name || oldRoute.params.rid || oldRoute.params.id, |
||||
context.params.name || context.params.rid || context.params.id, |
||||
) |
||||
) { |
||||
return; |
||||
} |
||||
// 7370 - Close flex-tab when opening a room on mobile UI
|
||||
if (window.matchMedia('(max-width: 500px)').matches) { |
||||
const flex = document.querySelector<HTMLElement>('.flex-tab'); |
||||
if (flex) { |
||||
const templateData = Blaze.getData(flex) as any; |
||||
templateData?.tabBar?.close(); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
if (typeof (window as any).currentTracker !== 'undefined') { |
||||
(window as any).currentTracker.stop(); |
||||
} |
||||
}; |
||||
@ -0,0 +1,135 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Session } from 'meteor/session'; |
||||
|
||||
import { hasAtLeastOnePermission } from '../../../../app/authorization/client'; |
||||
import { Subscriptions, Users } from '../../../../app/models/client'; |
||||
import { settings } from '../../../../app/settings/client'; |
||||
import { getUserPreference } from '../../../../app/utils/client'; |
||||
import { getAvatarURL } from '../../../../app/utils/lib/getAvatarURL'; |
||||
import { getUserAvatarURL } from '../../../../app/utils/lib/getUserAvatarURL'; |
||||
import type { IRoom } from '../../../../definition/IRoom'; |
||||
import type { IRoomTypeClientDirectives } from '../../../../definition/IRoomTypeConfig'; |
||||
import { RoomSettingsEnum, RoomMemberActions, UiTextContext } from '../../../../definition/IRoomTypeConfig'; |
||||
import type { AtLeast, ValueOf } from '../../../../definition/utils'; |
||||
import { getDirectMessageRoomType } from '../../../../lib/rooms/roomTypes/direct'; |
||||
import { roomCoordinator } from '../roomCoordinator'; |
||||
|
||||
export const DirectMessageRoomType = getDirectMessageRoomType(roomCoordinator); |
||||
|
||||
roomCoordinator.add(DirectMessageRoomType, { |
||||
allowRoomSettingChange(_room: Partial<IRoom>, setting: ValueOf<typeof RoomSettingsEnum>): boolean { |
||||
switch (setting) { |
||||
case RoomSettingsEnum.TYPE: |
||||
case RoomSettingsEnum.NAME: |
||||
case RoomSettingsEnum.SYSTEM_MESSAGES: |
||||
case RoomSettingsEnum.DESCRIPTION: |
||||
case RoomSettingsEnum.READ_ONLY: |
||||
case RoomSettingsEnum.REACT_WHEN_READ_ONLY: |
||||
case RoomSettingsEnum.ARCHIVE_OR_UNARCHIVE: |
||||
case RoomSettingsEnum.JOIN_CODE: |
||||
return false; |
||||
case RoomSettingsEnum.E2E: |
||||
return settings.get('E2E_Enable') === true; |
||||
default: |
||||
return true; |
||||
} |
||||
}, |
||||
|
||||
allowMemberAction(room: Partial<IRoom>, action: ValueOf<typeof RoomMemberActions>): boolean { |
||||
switch (action) { |
||||
case RoomMemberActions.BLOCK: |
||||
return !this.isGroupChat(room); |
||||
default: |
||||
return false; |
||||
} |
||||
}, |
||||
|
||||
roomName(roomData: Partial<IRoom>): string | undefined { |
||||
const subscription = ((): { fname?: string; name?: string } | undefined => { |
||||
if (roomData.fname || roomData.name) { |
||||
return { |
||||
fname: roomData.fname, |
||||
name: roomData.name, |
||||
}; |
||||
} |
||||
|
||||
if (!roomData._id) { |
||||
return undefined; |
||||
} |
||||
|
||||
return Subscriptions.findOne({ rid: roomData._id }); |
||||
})(); |
||||
|
||||
if (!subscription) { |
||||
return; |
||||
} |
||||
|
||||
if (settings.get('UI_Use_Real_Name') && subscription.fname) { |
||||
return subscription.fname; |
||||
} |
||||
|
||||
return subscription.name; |
||||
}, |
||||
|
||||
isGroupChat(room: Partial<IRoom>): boolean { |
||||
return (room?.uids?.length || 0) > 2; |
||||
}, |
||||
|
||||
getUiText(context: ValueOf<typeof UiTextContext>): string { |
||||
switch (context) { |
||||
case UiTextContext.HIDE_WARNING: |
||||
return 'Hide_Private_Warning'; |
||||
case UiTextContext.LEAVE_WARNING: |
||||
return 'Leave_Private_Warning'; |
||||
default: |
||||
return ''; |
||||
} |
||||
}, |
||||
|
||||
condition(): boolean { |
||||
const groupByType = getUserPreference(Meteor.userId(), 'sidebarGroupByType'); |
||||
return groupByType && hasAtLeastOnePermission(['view-d-room', 'view-joined-room']); |
||||
}, |
||||
|
||||
getAvatarPath(room: Partial<IRoom> & { username?: IRoom['_id'] }): string { |
||||
if (!room) { |
||||
return ''; |
||||
} |
||||
|
||||
// if coming from sidenav search
|
||||
if (room.name && room.avatarETag) { |
||||
return getUserAvatarURL(room.name, room.avatarETag); |
||||
} |
||||
|
||||
if (this.isGroupChat(room)) { |
||||
return getAvatarURL({ |
||||
username: (room.uids || []).length + (room.usernames || []).join(), |
||||
roomId: undefined, |
||||
cache: room.avatarETag, |
||||
}); |
||||
} |
||||
|
||||
const sub = Subscriptions.findOne({ rid: room._id }, { fields: { name: 1 } }); |
||||
if (sub?.name) { |
||||
const user = Users.findOne({ username: sub.name }, { fields: { username: 1, avatarETag: 1 } }); |
||||
return getUserAvatarURL(user?.username || sub.name, user?.avatarETag); |
||||
} |
||||
|
||||
return getUserAvatarURL(room.name || this.roomName(room)); |
||||
}, |
||||
|
||||
getIcon(room: Partial<IRoom>): string | undefined { |
||||
if (this.isGroupChat(room)) { |
||||
return 'balloon'; |
||||
} |
||||
}, |
||||
|
||||
getUserStatus(roomId: string): string | undefined { |
||||
const subscription = Subscriptions.findOne({ rid: roomId }); |
||||
if (!subscription) { |
||||
return; |
||||
} |
||||
|
||||
return Session.get(`user_${subscription.name}_status`); |
||||
}, |
||||
} as AtLeast<IRoomTypeClientDirectives, 'isGroupChat' | 'roomName'>); |
||||
@ -0,0 +1,100 @@ |
||||
import type { RouteOptions } from 'meteor/kadira:flow-router'; |
||||
|
||||
import type { IRoom, RoomType } from './IRoom'; |
||||
import type { ISubscription } from './ISubscription'; |
||||
import type { IRocketChatRecord } from './IRocketChatRecord'; |
||||
import type { IUser } from './IUser'; |
||||
import type { IMessage } from './IMessage'; |
||||
import type { ReadReceipt } from './ReadReceipt'; |
||||
import type { ValueOf, AtLeast } from './utils'; |
||||
|
||||
export type RoomData = IRoom | ISubscription | { name: IUser['username'] }; |
||||
|
||||
export interface IRoomTypeRouteConfig { |
||||
name: string; |
||||
path?: string; |
||||
action?: RouteOptions['action']; |
||||
link?: (data: RoomData) => Record<string, string>; |
||||
} |
||||
|
||||
export const RoomSettingsEnum = { |
||||
TYPE: 'type', |
||||
NAME: 'roomName', |
||||
TOPIC: 'roomTopic', |
||||
ANNOUNCEMENT: 'roomAnnouncement', |
||||
DESCRIPTION: 'roomDescription', |
||||
READ_ONLY: 'readOnly', |
||||
REACT_WHEN_READ_ONLY: 'reactWhenReadOnly', |
||||
ARCHIVE_OR_UNARCHIVE: 'archiveOrUnarchive', |
||||
JOIN_CODE: 'joinCode', |
||||
BROADCAST: 'broadcast', |
||||
SYSTEM_MESSAGES: 'systemMessages', |
||||
E2E: 'encrypted', |
||||
} as const; |
||||
|
||||
export const RoomMemberActions = { |
||||
ARCHIVE: 'archive', |
||||
IGNORE: 'ignore', |
||||
BLOCK: 'block', |
||||
MUTE: 'mute', |
||||
SET_AS_OWNER: 'setAsOwner', |
||||
SET_AS_LEADER: 'setAsLeader', |
||||
SET_AS_MODERATOR: 'setAsModerator', |
||||
LEAVE: 'leave', |
||||
REMOVE_USER: 'removeUser', |
||||
JOIN: 'join', |
||||
INVITE: 'invite', |
||||
} as const; |
||||
|
||||
export const UiTextContext = { |
||||
CLOSE_WARNING: 'closeWarning', |
||||
HIDE_WARNING: 'hideWarning', |
||||
LEAVE_WARNING: 'leaveWarning', |
||||
NO_ROOMS_SUBSCRIBED: 'noRoomsSubscribed', |
||||
} as const; |
||||
|
||||
export interface IRoomTypeConfig { |
||||
identifier: string; |
||||
order: number; |
||||
icon?: string; |
||||
header?: string; |
||||
label?: string; |
||||
route?: IRoomTypeRouteConfig; |
||||
} |
||||
|
||||
export interface IRoomTypeClientDirectives { |
||||
config: IRoomTypeConfig; |
||||
|
||||
allowRoomSettingChange: (room: Partial<IRoom>, setting: ValueOf<typeof RoomSettingsEnum>) => boolean; |
||||
allowMemberAction: (room: Partial<IRoom>, action: ValueOf<typeof RoomMemberActions>) => boolean; |
||||
roomName: (room: Partial<IRoom>) => string | undefined; |
||||
isGroupChat: (room: Partial<IRoom>) => boolean; |
||||
openCustomProfileTab: (instance: any, room: IRoom, username: string) => boolean; |
||||
getUiText: (context: ValueOf<typeof UiTextContext>) => string; |
||||
condition: () => boolean; |
||||
getAvatarPath: (room: Partial<IRoom> & { username?: IRoom['_id'] }) => string; |
||||
getIcon: (room: Partial<IRoom>) => string | undefined; |
||||
getUserStatus: (roomId: string) => string | undefined; |
||||
} |
||||
|
||||
export interface IRoomTypeServerDirectives { |
||||
config: IRoomTypeConfig; |
||||
|
||||
allowRoomSettingChange: (room: IRoom, setting: ValueOf<typeof RoomSettingsEnum>) => boolean; |
||||
allowMemberAction: (room: IRoom, action: ValueOf<typeof RoomMemberActions>) => boolean; |
||||
roomName: (room: IRoom) => string | undefined; |
||||
isGroupChat: (room: IRoom) => boolean; |
||||
canBeDeleted: (hasPermission: (permissionId: string, rid?: string) => boolean, room: IRoom) => boolean; |
||||
preventRenaming: () => boolean; |
||||
getDiscussionType: () => RoomType; |
||||
canAccessUploadedFile: (params: { rc_uid: string; rc_rid: string; rc_token: string }) => boolean; |
||||
getNotificationDetails: ( |
||||
room: IRoom, |
||||
user: AtLeast<IUser, '_id' | 'name' | 'username'>, |
||||
notificationMessage: string, |
||||
) => { title: string | undefined; text: string }; |
||||
getMsgSender: (senderId: IRocketChatRecord['_id']) => IRocketChatRecord | undefined; |
||||
includeInRoomSearch: () => boolean; |
||||
getReadReceiptsExtraData: (message: IMessage) => Partial<ReadReceipt>; |
||||
includeInDashboard: () => boolean; |
||||
} |
||||
@ -0,0 +1,29 @@ |
||||
import type { IRoom } from '../../definition/IRoom'; |
||||
|
||||
export const adminFields: Partial<Record<keyof IRoom, 1>> = { |
||||
prid: 1, |
||||
fname: 1, |
||||
name: 1, |
||||
t: 1, |
||||
cl: 1, |
||||
u: 1, |
||||
usernames: 1, |
||||
usersCount: 1, |
||||
muted: 1, |
||||
unmuted: 1, |
||||
ro: 1, |
||||
default: 1, |
||||
favorite: 1, |
||||
featured: 1, |
||||
topic: 1, |
||||
msgs: 1, |
||||
archived: 1, |
||||
tokenpass: 1, |
||||
teamId: 1, |
||||
teamMain: 1, |
||||
announcement: 1, |
||||
description: 1, |
||||
broadcast: 1, |
||||
uids: 1, |
||||
avatarETag: 1, |
||||
} as const; |
||||
@ -0,0 +1,109 @@ |
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
import type { RouteOptions } from 'meteor/kadira:flow-router'; |
||||
|
||||
import type { IRoomTypeConfig, IRoomTypeClientDirectives, IRoomTypeServerDirectives, RoomData } from '../../definition/IRoomTypeConfig'; |
||||
import type { IRoom } from '../../definition/IRoom'; |
||||
import type { ISubscription } from '../../definition/ISubscription'; |
||||
import type { SettingValue } from '../../definition/ISetting'; |
||||
|
||||
export abstract class RoomCoordinator { |
||||
roomTypes: Record<string, { config: IRoomTypeConfig; directives: IRoomTypeClientDirectives | IRoomTypeServerDirectives }>; |
||||
|
||||
roomTypesOrder: Array<{ identifier: string; order: number }>; |
||||
|
||||
mainOrder: number; |
||||
|
||||
constructor() { |
||||
this.roomTypes = {}; |
||||
this.roomTypesOrder = []; |
||||
this.mainOrder = 1; |
||||
} |
||||
|
||||
protected addRoomType(roomConfig: IRoomTypeConfig, directives: IRoomTypeClientDirectives | IRoomTypeServerDirectives): void { |
||||
if (this.roomTypes[roomConfig.identifier]) { |
||||
return; |
||||
} |
||||
|
||||
if (!roomConfig.order) { |
||||
roomConfig.order = this.mainOrder + 10; |
||||
this.mainOrder += 10; |
||||
} |
||||
|
||||
this.roomTypesOrder.push({ |
||||
identifier: roomConfig.identifier, |
||||
order: roomConfig.order, |
||||
}); |
||||
|
||||
this.roomTypes[roomConfig.identifier] = { config: roomConfig, directives }; |
||||
|
||||
if (roomConfig.route && roomConfig.route.path && roomConfig.route.name && roomConfig.route.action) { |
||||
const routeConfig = { |
||||
name: roomConfig.route.name, |
||||
action: roomConfig.route.action, |
||||
}; |
||||
|
||||
return this.addRoute(roomConfig.route.path, routeConfig); |
||||
} |
||||
} |
||||
|
||||
protected addRoute(path: string, routeConfig: RouteOptions): void { |
||||
FlowRouter.route(path, routeConfig); |
||||
} |
||||
|
||||
getSetting(_settingId: string): SettingValue { |
||||
return undefined; |
||||
} |
||||
|
||||
getRoomTypeConfig(identifier: string): IRoomTypeConfig | undefined { |
||||
return this.roomTypes[identifier]?.config; |
||||
} |
||||
|
||||
getRouteLink(roomType: string, subData: RoomData): string | false { |
||||
const config = this.getRoomTypeConfig(roomType); |
||||
if (!config?.route) { |
||||
return false; |
||||
} |
||||
|
||||
const routeData = this.getRouteData(roomType, subData); |
||||
if (!routeData) { |
||||
return false; |
||||
} |
||||
|
||||
return FlowRouter.path(config.route.name, routeData); |
||||
} |
||||
|
||||
getURL(roomType: string, subData: IRoom | ISubscription): string | false { |
||||
const config = this.getRoomTypeConfig(roomType); |
||||
if (!config?.route) { |
||||
return false; |
||||
} |
||||
|
||||
const routeData = this.getRouteData(roomType, subData); |
||||
if (!routeData) { |
||||
return false; |
||||
} |
||||
|
||||
return FlowRouter.url(config.route.name, routeData); |
||||
} |
||||
|
||||
getRouteData(roomType: string, subData: RoomData): Record<string, string> | false { |
||||
const config = this.getRoomTypeConfig(roomType); |
||||
if (!config) { |
||||
return false; |
||||
} |
||||
|
||||
let routeData = {}; |
||||
if (config.route?.link) { |
||||
routeData = config.route.link(subData); |
||||
} else if (subData?.name) { |
||||
routeData = { |
||||
rid: (subData as ISubscription).rid || (subData as IRoom)._id, |
||||
name: subData.name, |
||||
}; |
||||
} |
||||
|
||||
return routeData; |
||||
} |
||||
|
||||
abstract openRoom(_type: string, _name: string, _render?: boolean): void; |
||||
} |
||||
@ -0,0 +1,10 @@ |
||||
import type { IRoomTypeConfig } from '../../../definition/IRoomTypeConfig'; |
||||
import type { RoomCoordinator } from '../coordinator'; |
||||
|
||||
export function getConversationRoomType(_coordinator: RoomCoordinator): IRoomTypeConfig { |
||||
return { |
||||
identifier: 'merged', |
||||
order: 30, |
||||
label: 'Conversations', |
||||
}; |
||||
} |
||||
@ -0,0 +1,22 @@ |
||||
import type { IRoomTypeConfig } from '../../../definition/IRoomTypeConfig'; |
||||
import type { RoomCoordinator } from '../coordinator'; |
||||
import type { ISubscription } from '../../../definition/ISubscription'; |
||||
|
||||
export function getDirectMessageRoomType(coordinator: RoomCoordinator): IRoomTypeConfig { |
||||
return { |
||||
identifier: 'd', |
||||
order: 50, |
||||
icon: 'at', |
||||
label: 'Direct_Messages', |
||||
route: { |
||||
name: 'direct', |
||||
path: '/direct/:rid/:tab?/:context?', |
||||
action: ({ rid } = {}): void => { |
||||
return coordinator.openRoom('d', rid); |
||||
}, |
||||
link(sub): Record<string, string> { |
||||
return { rid: (sub as ISubscription).rid || sub.name || '' }; |
||||
}, |
||||
}, |
||||
}; |
||||
} |
||||
@ -0,0 +1,10 @@ |
||||
import type { IRoomTypeConfig } from '../../../definition/IRoomTypeConfig'; |
||||
import type { RoomCoordinator } from '../coordinator'; |
||||
|
||||
export function getDiscussionRoomType(_coordinator: RoomCoordinator): IRoomTypeConfig { |
||||
return { |
||||
identifier: 't', |
||||
order: 25, |
||||
label: 'Discussion', |
||||
}; |
||||
} |
||||
@ -0,0 +1,12 @@ |
||||
import type { IRoomTypeConfig } from '../../../definition/IRoomTypeConfig'; |
||||
import type { RoomCoordinator } from '../coordinator'; |
||||
|
||||
export function getFavoriteRoomType(_coordinator: RoomCoordinator): IRoomTypeConfig { |
||||
return { |
||||
identifier: 'f', |
||||
order: 20, |
||||
header: 'favorite', |
||||
icon: 'star', |
||||
label: 'Favorites', |
||||
}; |
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
import type { IRoomTypeConfig } from '../../../definition/IRoomTypeConfig'; |
||||
import type { RoomCoordinator } from '../coordinator'; |
||||
|
||||
export function getPrivateRoomType(coordinator: RoomCoordinator): IRoomTypeConfig { |
||||
return { |
||||
identifier: 'p', |
||||
order: 40, |
||||
icon: 'hashtag-lock', |
||||
label: 'Private_Groups', |
||||
route: { |
||||
name: 'group', |
||||
path: '/group/:name/:tab?/:context?', |
||||
action: ({ name } = {}): void => { |
||||
return coordinator.openRoom('p', name); |
||||
}, |
||||
}, |
||||
}; |
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
import type { IRoomTypeConfig } from '../../../definition/IRoomTypeConfig'; |
||||
import type { RoomCoordinator } from '../coordinator'; |
||||
|
||||
export function getPublicRoomType(coordinator: RoomCoordinator): IRoomTypeConfig { |
||||
return { |
||||
identifier: 'c', |
||||
order: 30, |
||||
icon: 'hashtag', |
||||
label: 'Channels', |
||||
route: { |
||||
name: 'channel', |
||||
path: '/channel/:name/:tab?/:context?', |
||||
action: ({ name } = {}): void => { |
||||
return coordinator.openRoom('c', name); |
||||
}, |
||||
}, |
||||
}; |
||||
} |
||||
@ -0,0 +1,10 @@ |
||||
import type { IRoomTypeConfig } from '../../../definition/IRoomTypeConfig'; |
||||
import type { RoomCoordinator } from '../coordinator'; |
||||
|
||||
export function getUnreadRoomType(_coordinator: RoomCoordinator): IRoomTypeConfig { |
||||
return { |
||||
identifier: 'unread', |
||||
order: 10, |
||||
label: 'Unread', |
||||
}; |
||||
} |
||||
@ -0,0 +1,82 @@ |
||||
import type { IRoomTypeConfig, IRoomTypeServerDirectives } from '../../../definition/IRoomTypeConfig'; |
||||
import type { IRoom, RoomType } from '../../../definition/IRoom'; |
||||
import type { IUser } from '../../../definition/IUser'; |
||||
import type { IMessage } from '../../../definition/IMessage'; |
||||
import type { ReadReceipt } from '../../../definition/ReadReceipt'; |
||||
import type { IRocketChatRecord } from '../../../definition/IRocketChatRecord'; |
||||
import type { ValueOf, AtLeast } from '../../../definition/utils'; |
||||
import { Users } from '../../../app/models/server'; |
||||
import { RoomSettingsEnum, RoomMemberActions } from '../../../definition/IRoomTypeConfig'; |
||||
import { RoomCoordinator } from '../../../lib/rooms/coordinator'; |
||||
import { settings } from '../../../app/settings/server'; |
||||
|
||||
class RoomCoordinatorServer extends RoomCoordinator { |
||||
add(roomConfig: IRoomTypeConfig, directives: Partial<IRoomTypeServerDirectives>): void { |
||||
this.addRoomType(roomConfig, { |
||||
allowRoomSettingChange(_room: IRoom, _setting: ValueOf<typeof RoomSettingsEnum>): boolean { |
||||
return true; |
||||
}, |
||||
allowMemberAction(_room: IRoom, _action: ValueOf<typeof RoomMemberActions>): boolean { |
||||
return false; |
||||
}, |
||||
roomName(_room: IRoom): string { |
||||
return ''; |
||||
}, |
||||
isGroupChat(_room: IRoom): boolean { |
||||
return false; |
||||
}, |
||||
canBeDeleted(hasPermission: (permissionId: string, rid?: string) => boolean, room: IRoom): boolean { |
||||
if (!hasPermission && typeof hasPermission !== 'function') { |
||||
throw new Error('You MUST provide the "hasPermission" to canBeDeleted function'); |
||||
} |
||||
return hasPermission(`delete-${room.t}`, room._id); |
||||
}, |
||||
preventRenaming(): boolean { |
||||
return false; |
||||
}, |
||||
getDiscussionType(): RoomType { |
||||
return 'p'; |
||||
}, |
||||
canAccessUploadedFile(_params: { rc_uid: string; rc_rid: string; rc_token: string }): boolean { |
||||
return false; |
||||
}, |
||||
getNotificationDetails( |
||||
room: IRoom, |
||||
user: AtLeast<IUser, '_id' | 'name' | 'username'>, |
||||
notificationMessage: string, |
||||
): { title: string | undefined; text: string } { |
||||
const title = `#${this.roomName(room)}`; |
||||
const name = settings.get<boolean>('UI_Use_Real_Name') ? user.name : user.username; |
||||
|
||||
const text = `${name}: ${notificationMessage}`; |
||||
|
||||
return { title, text }; |
||||
}, |
||||
getMsgSender(senderId: IRocketChatRecord['_id']): IRocketChatRecord | undefined { |
||||
return Users.findOneById(senderId); |
||||
}, |
||||
includeInRoomSearch(): boolean { |
||||
return false; |
||||
}, |
||||
getReadReceiptsExtraData(_message: IMessage): Partial<ReadReceipt> { |
||||
return {}; |
||||
}, |
||||
includeInDashboard(): boolean { |
||||
return false; |
||||
}, |
||||
|
||||
...directives, |
||||
config: roomConfig, |
||||
}); |
||||
} |
||||
|
||||
getRoomDirectives(roomType: string): IRoomTypeServerDirectives | undefined { |
||||
return this.roomTypes[roomType]?.directives as IRoomTypeServerDirectives; |
||||
} |
||||
|
||||
openRoom(_type: string, _name: string, _render = true): void { |
||||
// Nothing to do on the server side.
|
||||
} |
||||
} |
||||
|
||||
export const roomCoordinator = new RoomCoordinatorServer(); |
||||
@ -0,0 +1,75 @@ |
||||
import { settings } from '../../../../app/settings/server'; |
||||
import type { IRoom } from '../../../../definition/IRoom'; |
||||
import type { IUser } from '../../../../definition/IUser'; |
||||
import type { IRoomTypeServerDirectives } from '../../../../definition/IRoomTypeConfig'; |
||||
import { RoomSettingsEnum, RoomMemberActions } from '../../../../definition/IRoomTypeConfig'; |
||||
import type { AtLeast, ValueOf } from '../../../../definition/utils'; |
||||
import { getDirectMessageRoomType } from '../../../../lib/rooms/roomTypes/direct'; |
||||
import { roomCoordinator } from '../roomCoordinator'; |
||||
|
||||
export const DirectMessageRoomType = getDirectMessageRoomType(roomCoordinator); |
||||
|
||||
roomCoordinator.add(DirectMessageRoomType, { |
||||
allowRoomSettingChange(_room: IRoom, setting: ValueOf<typeof RoomSettingsEnum>): boolean { |
||||
switch (setting) { |
||||
case RoomSettingsEnum.TYPE: |
||||
case RoomSettingsEnum.NAME: |
||||
case RoomSettingsEnum.SYSTEM_MESSAGES: |
||||
case RoomSettingsEnum.DESCRIPTION: |
||||
case RoomSettingsEnum.READ_ONLY: |
||||
case RoomSettingsEnum.REACT_WHEN_READ_ONLY: |
||||
case RoomSettingsEnum.ARCHIVE_OR_UNARCHIVE: |
||||
case RoomSettingsEnum.JOIN_CODE: |
||||
return false; |
||||
case RoomSettingsEnum.E2E: |
||||
return settings.get('E2E_Enable') === true; |
||||
default: |
||||
return true; |
||||
} |
||||
}, |
||||
|
||||
allowMemberAction(room: IRoom, action: ValueOf<typeof RoomMemberActions>): boolean { |
||||
switch (action) { |
||||
case RoomMemberActions.BLOCK: |
||||
return !this.isGroupChat(room); |
||||
default: |
||||
return false; |
||||
} |
||||
}, |
||||
|
||||
roomName(room: IRoom): string | undefined { |
||||
if (settings.get('UI_Use_Real_Name') && room.fname) { |
||||
return room.fname; |
||||
} |
||||
|
||||
return room.name; |
||||
}, |
||||
|
||||
isGroupChat(room: IRoom): boolean { |
||||
return (room?.uids?.length || 0) > 2; |
||||
}, |
||||
|
||||
getNotificationDetails( |
||||
room: IRoom, |
||||
user: AtLeast<IUser, '_id' | 'name' | 'username'>, |
||||
notificationMessage: string, |
||||
): { title: string | undefined; text: string } { |
||||
const useRealName = settings.get<boolean>('UI_Use_Real_Name'); |
||||
|
||||
if (!this.isGroupChat(room)) { |
||||
return { |
||||
title: this.roomName(room), |
||||
text: `${(useRealName && user.name) || user.username}: ${notificationMessage}`, |
||||
}; |
||||
} |
||||
|
||||
return { |
||||
title: (useRealName && user.name) || user.username, |
||||
text: notificationMessage, |
||||
}; |
||||
}, |
||||
|
||||
includeInDashboard(): boolean { |
||||
return true; |
||||
}, |
||||
} as AtLeast<IRoomTypeServerDirectives, 'isGroupChat' | 'roomName'>); |
||||
Loading…
Reference in new issue