Chore: roomTypes: Stop mixing client and server code together (#24536)
* [Chore] roomTypes: Stop mixing client and server code together
* Moving roomTypes
* client
* client
* livechat
* imports
* errors
* removed commented code
* Avoid typecasts
* Fixed invalid reference
* Removed typecast
* comments
* Prefer `RoomType`
* Fix weird component prop
* Prefer assertion
* Revert "Prefer assertion"
This reverts commit 08e8a58fcb.
* Imply by typing that `getRoomTypeConfig(identifier: RoomType)` returns a route
Co-authored-by: Tasso Evangelista <tasso.evangelista@rocket.chat>
pull/24573/head
parent
16a3bc9489
commit
8bf7fef9e8
@ -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,18 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { getUserPreference, RoomTypeConfig } from '../../../utils'; |
||||
|
||||
export class ConversationRoomType extends RoomTypeConfig { |
||||
constructor() { |
||||
super({ |
||||
identifier: 'merged', |
||||
order: 30, |
||||
label: 'Conversations', |
||||
}); |
||||
} |
||||
|
||||
condition() { |
||||
// returns true only if sidebarGroupByType is not set
|
||||
return !getUserPreference(Meteor.userId(), 'sidebarGroupByType'); |
||||
} |
||||
} |
||||
@ -1,215 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Session } from 'meteor/session'; |
||||
|
||||
import { ChatRoom, Subscriptions } from '../../../models'; |
||||
import { openRoom } from '../../../ui-utils'; |
||||
import { getUserPreference, RoomTypeConfig, RoomTypeRouteConfig, RoomSettingsEnum, RoomMemberActions, UiTextContext } from '../../../utils'; |
||||
import { hasPermission, hasAtLeastOnePermission } from '../../../authorization'; |
||||
import { settings } from '../../../settings'; |
||||
import { getUserAvatarURL } from '../../../utils/lib/getUserAvatarURL'; |
||||
import { getAvatarURL } from '../../../utils/lib/getAvatarURL'; |
||||
|
||||
export class DirectMessageRoomRoute extends RoomTypeRouteConfig { |
||||
constructor() { |
||||
super({ |
||||
name: 'direct', |
||||
path: '/direct/:rid/:tab?/:context?', |
||||
}); |
||||
} |
||||
|
||||
action(params) { |
||||
return openRoom('d', params.rid); |
||||
} |
||||
|
||||
link(sub) { |
||||
return { rid: sub.rid || sub.name }; |
||||
} |
||||
} |
||||
|
||||
export class DirectMessageRoomType extends RoomTypeConfig { |
||||
constructor() { |
||||
super({ |
||||
identifier: 'd', |
||||
order: 50, |
||||
icon: 'at', |
||||
label: 'Direct_Messages', |
||||
route: new DirectMessageRoomRoute(), |
||||
}); |
||||
} |
||||
|
||||
getIcon(roomData) { |
||||
if (this.isGroupChat(roomData)) { |
||||
return 'balloon'; |
||||
} |
||||
return this.icon; |
||||
} |
||||
|
||||
findRoom(identifier) { |
||||
if (!hasPermission('view-d-room')) { |
||||
return null; |
||||
} |
||||
|
||||
const query = { |
||||
t: 'd', |
||||
$or: [{ name: identifier }, { rid: identifier }], |
||||
}; |
||||
|
||||
const subscription = Subscriptions.findOne(query); |
||||
if (subscription && subscription.rid) { |
||||
return ChatRoom.findOne(subscription.rid); |
||||
} |
||||
} |
||||
|
||||
roomName(roomData) { |
||||
// this function can receive different types of data
|
||||
// if it doesn't have fname and name properties, should be a Room object
|
||||
// so, need to find the related subscription
|
||||
const subscription = roomData && (roomData.fname || roomData.name) ? roomData : Subscriptions.findOne({ rid: roomData._id }); |
||||
|
||||
if (subscription === undefined) { |
||||
return; |
||||
} |
||||
|
||||
if (settings.get('UI_Use_Real_Name') && subscription.fname) { |
||||
return subscription.fname; |
||||
} |
||||
|
||||
return subscription.name; |
||||
} |
||||
|
||||
secondaryRoomName(roomData) { |
||||
if (settings.get('UI_Use_Real_Name')) { |
||||
const subscription = Subscriptions.findOne({ rid: roomData._id }, { fields: { name: 1 } }); |
||||
return subscription && subscription.name; |
||||
} |
||||
} |
||||
|
||||
condition() { |
||||
const groupByType = getUserPreference(Meteor.userId(), 'sidebarGroupByType'); |
||||
return groupByType && hasAtLeastOnePermission(['view-d-room', 'view-joined-room']); |
||||
} |
||||
|
||||
getUserStatus(roomId) { |
||||
const subscription = Subscriptions.findOne({ rid: roomId }); |
||||
if (subscription == null) { |
||||
return; |
||||
} |
||||
|
||||
return Session.get(`user_${subscription.name}_status`); |
||||
} |
||||
|
||||
getUserStatusText(roomId) { |
||||
const subscription = Subscriptions.findOne({ rid: roomId }); |
||||
if (subscription == null) { |
||||
return; |
||||
} |
||||
|
||||
return Session.get(`user_${subscription.name}_status_text`); |
||||
} |
||||
|
||||
allowRoomSettingChange(room, setting) { |
||||
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, action) { |
||||
switch (action) { |
||||
case RoomMemberActions.BLOCK: |
||||
return !this.isGroupChat(room); |
||||
default: |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
enableMembersListProfile() { |
||||
return true; |
||||
} |
||||
|
||||
userDetailShowAll(/* room */) { |
||||
return true; |
||||
} |
||||
|
||||
getUiText(context) { |
||||
switch (context) { |
||||
case UiTextContext.HIDE_WARNING: |
||||
return 'Hide_Private_Warning'; |
||||
case UiTextContext.LEAVE_WARNING: |
||||
return 'Leave_Private_Warning'; |
||||
default: |
||||
return ''; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns details to use on notifications |
||||
* |
||||
* @param {object} room |
||||
* @param {object} user |
||||
* @param {string} notificationMessage |
||||
* @return {object} Notification details |
||||
*/ |
||||
getNotificationDetails(room, user, notificationMessage) { |
||||
if (!Meteor.isServer) { |
||||
return {}; |
||||
} |
||||
|
||||
if (this.isGroupChat(room)) { |
||||
return { |
||||
title: this.roomName(room), |
||||
text: `${(settings.get('UI_Use_Real_Name') && user.name) || user.username}: ${notificationMessage}`, |
||||
}; |
||||
} |
||||
|
||||
return { |
||||
title: (settings.get('UI_Use_Real_Name') && user.name) || user.username, |
||||
text: notificationMessage, |
||||
}; |
||||
} |
||||
|
||||
getAvatarPath(roomData, subData) { |
||||
if (!roomData && !subData) { |
||||
return ''; |
||||
} |
||||
|
||||
// if coming from sidenav search
|
||||
if (roomData.name && roomData.avatarETag) { |
||||
return getUserAvatarURL(roomData.name, roomData.avatarETag); |
||||
} |
||||
|
||||
if (this.isGroupChat(roomData)) { |
||||
return getAvatarURL({ username: roomData.uids.length + roomData.usernames.join() }); |
||||
} |
||||
|
||||
const sub = subData || Subscriptions.findOne({ rid: roomData._id }, { fields: { name: 1 } }); |
||||
|
||||
if (sub && sub.name) { |
||||
const user = Meteor.users.findOne({ username: sub.name }, { fields: { username: 1, avatarETag: 1 } }); |
||||
return getUserAvatarURL(user?.username || sub.name, user?.avatarETag); |
||||
} |
||||
|
||||
if (roomData) { |
||||
return getUserAvatarURL(roomData.name || this.roomName(roomData)); // rooms should have no name for direct messages...
|
||||
} |
||||
} |
||||
|
||||
includeInDashboard() { |
||||
return true; |
||||
} |
||||
|
||||
isGroupChat(room) { |
||||
return room && room.uids && room.uids.length > 2; |
||||
} |
||||
} |
||||
@ -1,20 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { settings } from '../../../settings'; |
||||
import { getUserPreference, RoomTypeConfig } from '../../../utils'; |
||||
|
||||
export class FavoriteRoomType extends RoomTypeConfig { |
||||
constructor() { |
||||
super({ |
||||
identifier: 'f', |
||||
order: 20, |
||||
header: 'favorite', |
||||
icon: 'star', |
||||
label: 'Favorites', |
||||
}); |
||||
} |
||||
|
||||
condition() { |
||||
return settings.get('Favorite_Rooms') && getUserPreference(Meteor.userId(), 'sidebarShowFavorites'); |
||||
} |
||||
} |
||||
@ -1,8 +0,0 @@ |
||||
import { ConversationRoomType } from './conversation'; |
||||
import { DirectMessageRoomType } from './direct'; |
||||
import { FavoriteRoomType } from './favorite'; |
||||
import { PrivateRoomType } from './private'; |
||||
import { PublicRoomType } from './public'; |
||||
import { UnreadRoomType } from './unread'; |
||||
|
||||
export { ConversationRoomType, DirectMessageRoomType, FavoriteRoomType, PrivateRoomType, PublicRoomType, UnreadRoomType }; |
||||
@ -1,126 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { ChatRoom } from '../../../models'; |
||||
import { openRoom } from '../../../ui-utils'; |
||||
import { settings } from '../../../settings'; |
||||
import { hasAtLeastOnePermission, hasPermission } from '../../../authorization'; |
||||
import { getUserPreference, RoomSettingsEnum, RoomTypeConfig, RoomTypeRouteConfig, UiTextContext, RoomMemberActions } from '../../../utils'; |
||||
import { getAvatarURL } from '../../../utils/lib/getAvatarURL'; |
||||
|
||||
export class PrivateRoomRoute extends RoomTypeRouteConfig { |
||||
constructor() { |
||||
super({ |
||||
name: 'group', |
||||
path: '/group/:name/:tab?/:context?', |
||||
}); |
||||
} |
||||
|
||||
action(params) { |
||||
return openRoom('p', params.name); |
||||
} |
||||
} |
||||
|
||||
export class PrivateRoomType extends RoomTypeConfig { |
||||
constructor() { |
||||
super({ |
||||
identifier: 'p', |
||||
order: 40, |
||||
icon: 'hashtag-lock', |
||||
label: 'Private_Groups', |
||||
route: new PrivateRoomRoute(), |
||||
}); |
||||
} |
||||
|
||||
getIcon(roomData) { |
||||
if (roomData.prid) { |
||||
return 'discussion'; |
||||
} |
||||
if (roomData.teamMain) { |
||||
return 'team-lock'; |
||||
} |
||||
return this.icon; |
||||
} |
||||
|
||||
findRoom(identifier) { |
||||
const query = { |
||||
t: 'p', |
||||
name: identifier, |
||||
}; |
||||
|
||||
return ChatRoom.findOne(query); |
||||
} |
||||
|
||||
roomName(roomData) { |
||||
if (roomData.prid) { |
||||
return roomData.fname; |
||||
} |
||||
if (settings.get('UI_Allow_room_names_with_special_chars')) { |
||||
return roomData.fname || roomData.name; |
||||
} |
||||
|
||||
return roomData.name; |
||||
} |
||||
|
||||
condition() { |
||||
const groupByType = getUserPreference(Meteor.userId(), 'sidebarGroupByType'); |
||||
return groupByType && hasPermission('view-p-room'); |
||||
} |
||||
|
||||
isGroupChat() { |
||||
return true; |
||||
} |
||||
|
||||
canAddUser(room) { |
||||
return hasAtLeastOnePermission(['add-user-to-any-p-room', 'add-user-to-joined-room'], room._id); |
||||
} |
||||
|
||||
allowRoomSettingChange(room, setting) { |
||||
switch (setting) { |
||||
case RoomSettingsEnum.JOIN_CODE: |
||||
return false; |
||||
case RoomSettingsEnum.BROADCAST: |
||||
return room.broadcast; |
||||
case RoomSettingsEnum.READ_ONLY: |
||||
return !room.broadcast; |
||||
case RoomSettingsEnum.REACT_WHEN_READ_ONLY: |
||||
return !room.broadcast && room.ro; |
||||
case RoomSettingsEnum.E2E: |
||||
return settings.get('E2E_Enable') === true; |
||||
case RoomSettingsEnum.SYSTEM_MESSAGES: |
||||
default: |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
allowMemberAction(room, action) { |
||||
switch (action) { |
||||
case RoomMemberActions.BLOCK: |
||||
return false; |
||||
default: |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
enableMembersListProfile() { |
||||
return true; |
||||
} |
||||
|
||||
getUiText(context) { |
||||
switch (context) { |
||||
case UiTextContext.HIDE_WARNING: |
||||
return 'Hide_Group_Warning'; |
||||
case UiTextContext.LEAVE_WARNING: |
||||
return 'Leave_Group_Warning'; |
||||
default: |
||||
return ''; |
||||
} |
||||
} |
||||
|
||||
getAvatarPath(roomData) { |
||||
return getAvatarURL({ roomId: roomData._id, cache: roomData.avatarETag }); |
||||
} |
||||
|
||||
includeInDashboard() { |
||||
return true; |
||||
} |
||||
} |
||||
@ -1,136 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { openRoom } from '../../../ui-utils'; |
||||
import { ChatRoom } from '../../../models'; |
||||
import { settings } from '../../../settings'; |
||||
import { hasAtLeastOnePermission } from '../../../authorization'; |
||||
import { getUserPreference, RoomTypeConfig, RoomTypeRouteConfig, RoomSettingsEnum, UiTextContext, RoomMemberActions } from '../../../utils'; |
||||
import { getAvatarURL } from '../../../utils/lib/getAvatarURL'; |
||||
|
||||
export class PublicRoomRoute extends RoomTypeRouteConfig { |
||||
constructor() { |
||||
super({ |
||||
name: 'channel', |
||||
path: '/channel/:name/:tab?/:context?', |
||||
}); |
||||
} |
||||
|
||||
action(params) { |
||||
return openRoom('c', params.name); |
||||
} |
||||
} |
||||
|
||||
export class PublicRoomType extends RoomTypeConfig { |
||||
constructor() { |
||||
super({ |
||||
identifier: 'c', |
||||
order: 30, |
||||
icon: 'hashtag', |
||||
label: 'Channels', |
||||
route: new PublicRoomRoute(), |
||||
}); |
||||
} |
||||
|
||||
getIcon(roomData) { |
||||
if (roomData.prid) { |
||||
return 'discussion'; |
||||
} |
||||
if (roomData.teamMain) { |
||||
return 'team'; |
||||
} |
||||
return this.icon; |
||||
} |
||||
|
||||
findRoom(identifier) { |
||||
const query = { |
||||
t: 'c', |
||||
name: identifier, |
||||
}; |
||||
return ChatRoom.findOne(query); |
||||
} |
||||
|
||||
roomName(roomData) { |
||||
if (roomData.prid) { |
||||
return roomData.fname; |
||||
} |
||||
if (settings.get('UI_Allow_room_names_with_special_chars')) { |
||||
return roomData.fname || roomData.name; |
||||
} |
||||
return roomData.name; |
||||
} |
||||
|
||||
condition() { |
||||
const groupByType = getUserPreference(Meteor.userId(), 'sidebarGroupByType'); |
||||
return ( |
||||
groupByType && (hasAtLeastOnePermission(['view-c-room', 'view-joined-room']) || settings.get('Accounts_AllowAnonymousRead') === true) |
||||
); |
||||
} |
||||
|
||||
showJoinLink(roomId) { |
||||
return !!ChatRoom.findOne({ _id: roomId, t: 'c' }); |
||||
} |
||||
|
||||
includeInRoomSearch() { |
||||
return true; |
||||
} |
||||
|
||||
isGroupChat() { |
||||
return true; |
||||
} |
||||
|
||||
includeInDashboard() { |
||||
return true; |
||||
} |
||||
|
||||
canAddUser(room) { |
||||
return hasAtLeastOnePermission(['add-user-to-any-c-room', 'add-user-to-joined-room'], room._id); |
||||
} |
||||
|
||||
enableMembersListProfile() { |
||||
return true; |
||||
} |
||||
|
||||
allowRoomSettingChange(room, setting) { |
||||
switch (setting) { |
||||
case RoomSettingsEnum.BROADCAST: |
||||
return room.broadcast; |
||||
case RoomSettingsEnum.READ_ONLY: |
||||
return !room.broadcast; |
||||
case RoomSettingsEnum.REACT_WHEN_READ_ONLY: |
||||
return !room.broadcast && room.ro; |
||||
case RoomSettingsEnum.E2E: |
||||
return false; |
||||
case RoomSettingsEnum.SYSTEM_MESSAGES: |
||||
default: |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
allowMemberAction(room, action) { |
||||
switch (action) { |
||||
case RoomMemberActions.BLOCK: |
||||
return false; |
||||
default: |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
getUiText(context) { |
||||
switch (context) { |
||||
case UiTextContext.HIDE_WARNING: |
||||
return 'Hide_Room_Warning'; |
||||
case UiTextContext.LEAVE_WARNING: |
||||
return 'Leave_Room_Warning'; |
||||
default: |
||||
return ''; |
||||
} |
||||
} |
||||
|
||||
getAvatarPath(roomData) { |
||||
return getAvatarURL({ roomId: roomData._id, cache: roomData.avatarETag }); |
||||
} |
||||
|
||||
getDiscussionType() { |
||||
return 'c'; |
||||
} |
||||
} |
||||
@ -1,19 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { getUserPreference, RoomTypeConfig } from '../../../utils'; |
||||
|
||||
export class UnreadRoomType extends RoomTypeConfig { |
||||
constructor() { |
||||
super({ |
||||
identifier: 'unread', |
||||
order: 10, |
||||
label: 'Unread', |
||||
}); |
||||
|
||||
this.unread = true; |
||||
} |
||||
|
||||
condition() { |
||||
return getUserPreference(Meteor.userId(), 'sidebarShowUnread'); |
||||
} |
||||
} |
||||
@ -1,16 +0,0 @@ |
||||
import { roomTypes } from '../../utils'; |
||||
import { |
||||
ConversationRoomType, |
||||
DirectMessageRoomType, |
||||
FavoriteRoomType, |
||||
PrivateRoomType, |
||||
PublicRoomType, |
||||
UnreadRoomType, |
||||
} from '../lib/roomTypes'; |
||||
|
||||
roomTypes.add(new UnreadRoomType()); |
||||
roomTypes.add(new FavoriteRoomType()); |
||||
roomTypes.add(new ConversationRoomType()); |
||||
roomTypes.add(new PublicRoomType()); |
||||
roomTypes.add(new PrivateRoomType()); |
||||
roomTypes.add(new DirectMessageRoomType()); |
||||
@ -1,4 +0,0 @@ |
||||
import { roomTypes } from '../../utils'; |
||||
import LivechatRoomType from '../lib/LivechatRoomType'; |
||||
|
||||
roomTypes.add(new LivechatRoomType()); |
||||
@ -1,133 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Session } from 'meteor/session'; |
||||
|
||||
import { ChatRoom, ChatSubscription } from '../../models'; |
||||
import { settings } from '../../settings'; |
||||
import { hasPermission } from '../../authorization'; |
||||
import { openRoom } from '../../ui-utils'; |
||||
import { RoomMemberActions, RoomSettingsEnum, UiTextContext, RoomTypeRouteConfig, RoomTypeConfig } from '../../utils'; |
||||
import { getAvatarURL } from '../../utils/lib/getAvatarURL'; |
||||
|
||||
let LivechatInquiry; |
||||
if (Meteor.isClient) { |
||||
({ LivechatInquiry } = require('../client/collections/LivechatInquiry')); |
||||
} |
||||
|
||||
class LivechatRoomRoute extends RoomTypeRouteConfig { |
||||
constructor() { |
||||
super({ |
||||
name: 'live', |
||||
path: '/live/:id/:tab?/:context?', |
||||
}); |
||||
} |
||||
|
||||
action(params) { |
||||
openRoom('l', params.id); |
||||
} |
||||
|
||||
link(sub) { |
||||
return { |
||||
id: sub.rid, |
||||
}; |
||||
} |
||||
} |
||||
|
||||
export default class LivechatRoomType extends RoomTypeConfig { |
||||
constructor() { |
||||
super({ |
||||
identifier: 'l', |
||||
order: 5, |
||||
icon: 'omnichannel', |
||||
label: 'Omnichannel', |
||||
route: new LivechatRoomRoute(), |
||||
}); |
||||
|
||||
this.notSubscribedTpl = 'livechatNotSubscribed'; |
||||
this.readOnlyTpl = 'livechatReadOnly'; |
||||
} |
||||
|
||||
enableMembersListProfile() { |
||||
return true; |
||||
} |
||||
|
||||
findRoom(identifier) { |
||||
return ChatRoom.findOne({ _id: identifier }); |
||||
} |
||||
|
||||
roomName(roomData) { |
||||
return roomData.name || roomData.fname || roomData.label; |
||||
} |
||||
|
||||
condition() { |
||||
return settings.get('Livechat_enabled') && hasPermission('view-l-room'); |
||||
} |
||||
|
||||
canSendMessage(rid) { |
||||
const room = ChatRoom.findOne({ _id: rid }, { fields: { open: 1 } }); |
||||
return room && room.open === true; |
||||
} |
||||
|
||||
getUserStatus(rid) { |
||||
const room = Session.get(`roomData${rid}`); |
||||
if (room) { |
||||
return room.v && room.v.status; |
||||
} |
||||
const inquiry = LivechatInquiry.findOne({ rid }); |
||||
return inquiry && inquiry.v && inquiry.v.status; |
||||
} |
||||
|
||||
allowRoomSettingChange(room, setting) { |
||||
switch (setting) { |
||||
case RoomSettingsEnum.JOIN_CODE: |
||||
return false; |
||||
default: |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
allowMemberAction(room, action) { |
||||
return [RoomMemberActions.INVITE, RoomMemberActions.JOIN].includes(action); |
||||
} |
||||
|
||||
getUiText(context) { |
||||
switch (context) { |
||||
case UiTextContext.HIDE_WARNING: |
||||
return 'Hide_Livechat_Warning'; |
||||
case UiTextContext.LEAVE_WARNING: |
||||
return 'Hide_Livechat_Warning'; |
||||
default: |
||||
return ''; |
||||
} |
||||
} |
||||
|
||||
readOnly(rid) { |
||||
const room = ChatRoom.findOne({ _id: rid }, { fields: { open: 1, servedBy: 1 } }); |
||||
if (!room || !room.open) { |
||||
return true; |
||||
} |
||||
|
||||
const subscription = ChatSubscription.findOne({ rid }); |
||||
return !subscription; |
||||
} |
||||
|
||||
getAvatarPath(roomData) { |
||||
return getAvatarURL({ username: `@${this.roomName(roomData)}` }); |
||||
} |
||||
|
||||
openCustomProfileTab(instance, room, username) { |
||||
if (!room || !room.v || room.v.username !== username) { |
||||
return false; |
||||
} |
||||
|
||||
instance.tabBar.openUserInfo(); |
||||
return true; |
||||
} |
||||
|
||||
showQuickActionButtons() { |
||||
return true; |
||||
} |
||||
|
||||
isLivechatRoom() { |
||||
return true; |
||||
} |
||||
} |
||||
@ -1,35 +0,0 @@ |
||||
import { LivechatRooms, LivechatVisitors } from '../../models'; |
||||
import { roomTypes } from '../../utils'; |
||||
import LivechatRoomType from '../lib/LivechatRoomType'; |
||||
|
||||
class LivechatRoomTypeServer extends LivechatRoomType { |
||||
getMsgSender(senderId) { |
||||
return LivechatVisitors.findOneById(senderId); |
||||
} |
||||
|
||||
/** |
||||
* Returns details to use on notifications |
||||
* |
||||
* @param {object} room |
||||
* @param {object} user |
||||
* @param {string} notificationMessage |
||||
* @return {object} Notification details |
||||
*/ |
||||
getNotificationDetails(room, user, notificationMessage) { |
||||
const title = `[Omnichannel] ${this.roomName(room)}`; |
||||
const text = notificationMessage; |
||||
|
||||
return { title, text }; |
||||
} |
||||
|
||||
canAccessUploadedFile({ rc_token, rc_rid } = {}) { |
||||
return rc_token && rc_rid && LivechatRooms.findOneOpenByRoomIdAndVisitorToken(rc_rid, rc_token); |
||||
} |
||||
|
||||
getReadReceiptsExtraData(message) { |
||||
const { token } = message; |
||||
return { token }; |
||||
} |
||||
} |
||||
|
||||
roomTypes.add(new LivechatRoomTypeServer()); |
||||
@ -1,23 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { roomTypes, RoomTypeConfig } from '../../utils'; |
||||
|
||||
class TokenPassRoomType extends RoomTypeConfig { |
||||
constructor() { |
||||
super({ |
||||
identifier: 'tokenpass', |
||||
order: 1, |
||||
}); |
||||
|
||||
this.customTemplate = 'tokenChannelsList'; |
||||
} |
||||
|
||||
condition() { |
||||
const user = Meteor.users.findOne(Meteor.userId(), { fields: { 'services.tokenpass': 1 } }); |
||||
const hasTokenpass = !!(user && user.services && user.services.tokenpass); |
||||
|
||||
return hasTokenpass; |
||||
} |
||||
} |
||||
|
||||
roomTypes.add(new TokenPassRoomType()); |
||||
@ -1,10 +1,10 @@ |
||||
import { Template } from 'meteor/templating'; |
||||
|
||||
import { roomTypes } from '../../../utils'; |
||||
import './messageBoxReadOnly.html'; |
||||
import { roomCoordinator } from '../../../../client/lib/rooms/roomCoordinator'; |
||||
|
||||
Template.messageBoxReadOnly.helpers({ |
||||
customTemplate() { |
||||
return roomTypes.getReadOnlyTpl(this.rid); |
||||
return roomCoordinator.getRoomTypeConfigById(this.rid).readOnlyTpl; |
||||
}, |
||||
}); |
||||
|
||||
@ -1,10 +1,10 @@ |
||||
import { Template } from 'meteor/templating'; |
||||
|
||||
import { roomTypes } from '../../../utils'; |
||||
import './messagePopupChannel.html'; |
||||
import { roomCoordinator } from '../../../../client/lib/rooms/roomCoordinator'; |
||||
|
||||
Template.messagePopupChannel.helpers({ |
||||
channelIcon() { |
||||
return roomTypes.getIcon(this); |
||||
return roomCoordinator.getIcon(this); |
||||
}, |
||||
}); |
||||
|
||||
@ -1,213 +0,0 @@ |
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
import _ from 'underscore'; |
||||
|
||||
import { RoomTypesCommon } from '../../lib/RoomTypesCommon'; |
||||
import { hasAtLeastOnePermission } from '../../../authorization'; |
||||
import { ChatRoom, ChatSubscription } from '../../../models'; |
||||
|
||||
export const roomTypes = new (class RocketChatRoomTypes extends RoomTypesCommon { |
||||
checkCondition(roomType) { |
||||
return roomType.condition == null || roomType.condition(); |
||||
} |
||||
|
||||
getTypes() { |
||||
return _.sortBy(this.roomTypesOrder, 'order') |
||||
.map((type) => this.roomTypes[type.identifier]) |
||||
.filter((type) => !type.condition || type.condition()); |
||||
} |
||||
|
||||
getIcon(roomData) { |
||||
if (!roomData || !roomData.t || !this.roomTypes[roomData.t]) { |
||||
return; |
||||
} |
||||
return (this.roomTypes[roomData.t].getIcon && this.roomTypes[roomData.t].getIcon(roomData)) || this.roomTypes[roomData.t].icon; |
||||
} |
||||
|
||||
getRoomName(roomType, roomData) { |
||||
return this.roomTypes[roomType] && this.roomTypes[roomType].roomName && this.roomTypes[roomType].roomName(roomData); |
||||
} |
||||
|
||||
getSecondaryRoomName(roomType, roomData) { |
||||
return ( |
||||
this.roomTypes[roomType] && |
||||
typeof this.roomTypes[roomType].secondaryRoomName === 'function' && |
||||
this.roomTypes[roomType].secondaryRoomName(roomData) |
||||
); |
||||
} |
||||
|
||||
getIdentifiers(e) { |
||||
const except = [].concat(e); |
||||
const list = _.reject(this.roomTypesOrder, (t) => except.indexOf(t.identifier) !== -1); |
||||
return _.map(list, (t) => t.identifier); |
||||
} |
||||
|
||||
getUserStatus(roomType, rid) { |
||||
return ( |
||||
this.roomTypes[roomType] && |
||||
typeof this.roomTypes[roomType].getUserStatus === 'function' && |
||||
this.roomTypes[roomType].getUserStatus(rid) |
||||
); |
||||
} |
||||
|
||||
getRoomType(roomId) { |
||||
const fields = { |
||||
t: 1, |
||||
}; |
||||
const room = ChatRoom.findOne( |
||||
{ |
||||
_id: roomId, |
||||
}, |
||||
{ |
||||
fields, |
||||
}, |
||||
); |
||||
return room && room.t; |
||||
} |
||||
|
||||
isLivechatRoom(roomType) { |
||||
return ( |
||||
this.roomTypes[roomType] && typeof this.roomTypes[roomType].isLivechatRoom === 'function' && this.roomTypes[roomType].isLivechatRoom() |
||||
); |
||||
} |
||||
|
||||
showQuickActionButtons(roomType) { |
||||
return ( |
||||
this.roomTypes[roomType] && |
||||
typeof this.roomTypes[roomType].showQuickActionButtons === 'function' && |
||||
this.roomTypes[roomType].showQuickActionButtons() |
||||
); |
||||
} |
||||
|
||||
getUserStatusText(roomType, rid) { |
||||
return ( |
||||
this.roomTypes[roomType] && |
||||
typeof this.roomTypes[roomType].getUserStatusText === 'function' && |
||||
this.roomTypes[roomType].getUserStatusText(rid) |
||||
); |
||||
} |
||||
|
||||
findRoom(roomType, identifier, user) { |
||||
return this.roomTypes[roomType] && this.roomTypes[roomType].findRoom(identifier, user); |
||||
} |
||||
|
||||
canSendMessage(rid) { |
||||
return ChatSubscription.find({ rid }).count() > 0; |
||||
} |
||||
|
||||
readOnly(rid, user) { |
||||
const fields = { |
||||
ro: 1, |
||||
t: 1, |
||||
}; |
||||
if (user) { |
||||
fields.muted = 1; |
||||
fields.unmuted = 1; |
||||
} |
||||
const room = ChatRoom.findOne( |
||||
{ |
||||
_id: rid, |
||||
}, |
||||
{ |
||||
fields, |
||||
}, |
||||
); |
||||
|
||||
const roomType = room && room.t; |
||||
if (roomType && this.roomTypes[roomType] && this.roomTypes[roomType].readOnly) { |
||||
return this.roomTypes[roomType].readOnly(rid, user); |
||||
} |
||||
|
||||
if (!user) { |
||||
return room && room.ro; |
||||
} |
||||
|
||||
if (room) { |
||||
if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1) { |
||||
return true; |
||||
} |
||||
|
||||
if (room.ro === true) { |
||||
if (Array.isArray(room.unmuted) && room.unmuted.indexOf(user.username) !== -1) { |
||||
return false; |
||||
} |
||||
|
||||
if (hasAtLeastOnePermission('post-readonly', room._id)) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
archived(rid) { |
||||
const room = ChatRoom.findOne({ _id: rid }, { fields: { archived: 1 } }); |
||||
return room && room.archived === true; |
||||
} |
||||
|
||||
verifyCanSendMessage(rid) { |
||||
const room = ChatRoom.findOne({ _id: rid }, { fields: { t: 1 } }); |
||||
|
||||
if (!room || !room.t) { |
||||
return; |
||||
} |
||||
|
||||
const roomType = room.t; |
||||
if (this.roomTypes[roomType] && this.roomTypes[roomType].canSendMessage) { |
||||
return this.roomTypes[roomType].canSendMessage(rid); |
||||
} |
||||
return this.canSendMessage(rid); |
||||
} |
||||
|
||||
verifyShowJoinLink(rid) { |
||||
const room = ChatRoom.findOne({ _id: rid, t: { $exists: true, $ne: null } }, { fields: { t: 1 } }); |
||||
if (!room || !room.t) { |
||||
return; |
||||
} |
||||
const roomType = room.t; |
||||
if (this.roomTypes[roomType] && !this.roomTypes[roomType].showJoinLink) { |
||||
return false; |
||||
} |
||||
return this.roomTypes[roomType].showJoinLink(rid); |
||||
} |
||||
|
||||
getNotSubscribedTpl(rid) { |
||||
const room = ChatRoom.findOne({ _id: rid, t: { $exists: true, $ne: null } }, { fields: { t: 1 } }); |
||||
if (!room || !room.t) { |
||||
return; |
||||
} |
||||
const roomType = room.t; |
||||
if (this.roomTypes[roomType] && !this.roomTypes[roomType].notSubscribedTpl) { |
||||
return false; |
||||
} |
||||
return this.roomTypes[roomType].notSubscribedTpl; |
||||
} |
||||
|
||||
getReadOnlyTpl(rid) { |
||||
const room = ChatRoom.findOne({ _id: rid, t: { $exists: true, $ne: null } }, { fields: { t: 1 } }); |
||||
if (!room || !room.t) { |
||||
return; |
||||
} |
||||
const roomType = room.t; |
||||
return this.roomTypes[roomType] && this.roomTypes[roomType].readOnlyTpl; |
||||
} |
||||
|
||||
openRouteLink(roomType, subData, queryParams) { |
||||
if (!this.roomTypes[roomType]) { |
||||
return false; |
||||
} |
||||
|
||||
let routeData = {}; |
||||
if (this.roomTypes[roomType] && this.roomTypes[roomType].route && this.roomTypes[roomType].route.link) { |
||||
routeData = this.roomTypes[roomType].route.link(subData); |
||||
} else if (subData && subData.name) { |
||||
routeData = { |
||||
name: subData.name, |
||||
}; |
||||
} |
||||
|
||||
return FlowRouter.go(this.roomTypes[roomType].route.name, routeData, queryParams); |
||||
} |
||||
})(); |
||||
@ -1,291 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Random } from 'meteor/random'; |
||||
|
||||
let Users; |
||||
let settings; |
||||
if (Meteor.isServer) { |
||||
({ settings } = require('../../settings/server')); |
||||
Users = require('../../models/server/models/Users').default; |
||||
} else { |
||||
({ settings } = require('../../settings/client')); |
||||
} |
||||
|
||||
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', |
||||
}; |
||||
|
||||
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', |
||||
}; |
||||
|
||||
export const UiTextContext = { |
||||
CLOSE_WARNING: 'closeWarning', |
||||
HIDE_WARNING: 'hideWarning', |
||||
LEAVE_WARNING: 'leaveWarning', |
||||
NO_ROOMS_SUBSCRIBED: 'noRoomsSubscribed', |
||||
}; |
||||
|
||||
export class RoomTypeRouteConfig { |
||||
constructor({ name, path }) { |
||||
if (typeof name !== 'undefined' && (typeof name !== 'string' || name.length === 0)) { |
||||
throw new Error('The name must be a string.'); |
||||
} |
||||
|
||||
if (typeof path !== 'undefined' && (typeof path !== 'string' || path.length === 0)) { |
||||
throw new Error('The path must be a string.'); |
||||
} |
||||
|
||||
this._name = name; |
||||
this._path = path; |
||||
} |
||||
|
||||
get name() { |
||||
return this._name; |
||||
} |
||||
|
||||
get path() { |
||||
return this._path; |
||||
} |
||||
} |
||||
|
||||
export class RoomTypeConfig { |
||||
constructor({ identifier = Random.id(), order, icon, header, label, route }) { |
||||
if (typeof identifier !== 'string' || identifier.length === 0) { |
||||
throw new Error('The identifier must be a string.'); |
||||
} |
||||
|
||||
if (typeof order !== 'number') { |
||||
throw new Error('The order must be a number.'); |
||||
} |
||||
|
||||
if (typeof icon !== 'undefined' && (typeof icon !== 'string' || icon.length === 0)) { |
||||
throw new Error('The icon must be a string.'); |
||||
} |
||||
|
||||
if (typeof header !== 'undefined' && (typeof header !== 'string' || header.length === 0)) { |
||||
throw new Error('The header must be a string.'); |
||||
} |
||||
|
||||
if (typeof label !== 'undefined' && (typeof label !== 'string' || label.length === 0)) { |
||||
throw new Error('The label must be a string.'); |
||||
} |
||||
|
||||
if (typeof route !== 'undefined' && !(route instanceof RoomTypeRouteConfig)) { |
||||
throw new Error('Room\'s route is not a valid route configuration. Must be an instance of "RoomTypeRouteConfig".'); |
||||
} |
||||
|
||||
this._identifier = identifier; |
||||
this._order = order; |
||||
this._icon = icon; |
||||
this._header = header; |
||||
this._label = label; |
||||
this._route = route; |
||||
} |
||||
|
||||
/** |
||||
* The room type's internal identifier. |
||||
*/ |
||||
get identifier() { |
||||
return this._identifier; |
||||
} |
||||
|
||||
/** |
||||
* The order of this room type for the display. |
||||
*/ |
||||
get order() { |
||||
return this._order; |
||||
} |
||||
|
||||
/** |
||||
* Sets the order of this room type for the display. |
||||
* |
||||
* @param {number} order the number value for the order |
||||
*/ |
||||
set order(order) { |
||||
if (typeof order !== 'number') { |
||||
throw new Error('The order must be a number.'); |
||||
} |
||||
|
||||
this._order = order; |
||||
} |
||||
|
||||
/** |
||||
* The icon class, css, to use as the visual aid. |
||||
*/ |
||||
get icon() { |
||||
return this._icon; |
||||
} |
||||
|
||||
/** |
||||
* The header name of this type. |
||||
*/ |
||||
get header() { |
||||
return this._header; |
||||
} |
||||
|
||||
/** |
||||
* The i18n label for this room type. |
||||
*/ |
||||
get label() { |
||||
return this._label; |
||||
} |
||||
|
||||
/** |
||||
* The route config for this room type. |
||||
*/ |
||||
get route() { |
||||
return this._route; |
||||
} |
||||
|
||||
allowRoomSettingChange(/* room, setting */) { |
||||
return true; |
||||
} |
||||
|
||||
allowMemberAction(/* room, action */) { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Return a room's name |
||||
* |
||||
* @abstract |
||||
* @return {string} Room's name according to it's type |
||||
*/ |
||||
roomName(/* room */) { |
||||
return ''; |
||||
} |
||||
|
||||
canBeCreated(hasPermission) { |
||||
if (!hasPermission && typeof hasPermission !== 'function') { |
||||
throw new Error('You MUST provide the "hasPermission" to canBeCreated function'); |
||||
} |
||||
return Meteor.isServer ? hasPermission(Meteor.userId(), `create-${this._identifier}`) : hasPermission([`create-${this._identifier}`]); |
||||
} |
||||
|
||||
canBeDeleted(hasPermission, room) { |
||||
if (!hasPermission && typeof hasPermission !== 'function') { |
||||
throw new Error('You MUST provide the "hasPermission" to canBeDeleted function'); |
||||
} |
||||
return Meteor.isServer ? hasPermission(Meteor.userId(), `delete-${room.t}`, room._id) : hasPermission(`delete-${room.t}`, room._id); |
||||
} |
||||
|
||||
supportMembersList(/* room */) { |
||||
return true; |
||||
} |
||||
|
||||
isGroupChat() { |
||||
return false; |
||||
} |
||||
|
||||
canAddUser(/* userId, room */) { |
||||
return false; |
||||
} |
||||
|
||||
userDetailShowAll(/* room */) { |
||||
return true; |
||||
} |
||||
|
||||
userDetailShowAdmin(/* room */) { |
||||
return true; |
||||
} |
||||
|
||||
preventRenaming(/* room */) { |
||||
return false; |
||||
} |
||||
|
||||
includeInRoomSearch() { |
||||
return false; |
||||
} |
||||
|
||||
enableMembersListProfile() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns a text which can be used in generic UIs. |
||||
* @param context The role of the text in the UI-Element |
||||
* @return {string} A text or a translation key - the consumers of this method will pass the |
||||
* returned value to an internationalization library |
||||
*/ |
||||
getUiText(/* context */) { |
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* Returns the full object of message sender |
||||
* @param {string} senderId Sender's _id |
||||
* @return {object} Sender's object from db |
||||
*/ |
||||
getMsgSender(senderId) { |
||||
if (Meteor.isServer && Users) { |
||||
return Users.findOneById(senderId); |
||||
} |
||||
return {}; |
||||
} |
||||
|
||||
/** |
||||
* Returns details to use on notifications |
||||
* |
||||
* @param {object} room |
||||
* @param {object} user |
||||
* @param {string} notificationMessage |
||||
* @return {object} Notification details |
||||
*/ |
||||
getNotificationDetails(room, user, notificationMessage) { |
||||
if (!Meteor.isServer) { |
||||
return {}; |
||||
} |
||||
|
||||
const title = `#${this.roomName(room)}`; |
||||
|
||||
const text = `${settings.get('UI_Use_Real_Name') ? user.name : user.username}: ${notificationMessage}`; |
||||
|
||||
return { title, text }; |
||||
} |
||||
|
||||
/** |
||||
* Check if there is an user with the same id and loginToken |
||||
* @param {object} allowData |
||||
* @return {object} User's object from db |
||||
*/ |
||||
canAccessUploadedFile(/* accessData */) { |
||||
return false; |
||||
} |
||||
|
||||
getReadReceiptsExtraData(/* message */) { |
||||
return {}; |
||||
} |
||||
|
||||
getAvatarPath(/* roomData */) { |
||||
return ''; |
||||
} |
||||
|
||||
openCustomProfileTab() { |
||||
return false; |
||||
} |
||||
|
||||
getDiscussionType() { |
||||
return 'p'; |
||||
} |
||||
} |
||||
@ -1,120 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
// import { Session } from 'meteor/session';
|
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
|
||||
import { RoomTypeConfig } from './RoomTypeConfig'; |
||||
import { roomExit } from './roomExit'; |
||||
|
||||
export class RoomTypesCommon { |
||||
constructor() { |
||||
this.roomTypes = {}; |
||||
this.roomTypesOrder = []; |
||||
this.mainOrder = 1; |
||||
} |
||||
|
||||
getTypesToShowOnDashboard() { |
||||
return Object.keys(this.roomTypes).filter((key) => this.roomTypes[key].includeInDashboard && this.roomTypes[key].includeInDashboard()); |
||||
} |
||||
|
||||
/** |
||||
* Adds a room type to the application. |
||||
* |
||||
* @param {RoomTypeConfig} roomConfig |
||||
* @returns {void} |
||||
*/ |
||||
add(roomConfig) { |
||||
if (!(roomConfig instanceof RoomTypeConfig)) { |
||||
throw new Error('Invalid Room Configuration object, it must extend "RoomTypeConfig"'); |
||||
} |
||||
|
||||
if (this.roomTypes[roomConfig.identifier]) { |
||||
return false; |
||||
} |
||||
|
||||
if (!roomConfig.order) { |
||||
roomConfig.order = this.mainOrder + 10; |
||||
this.mainOrder += 10; |
||||
} |
||||
|
||||
this.roomTypesOrder.push({ |
||||
identifier: roomConfig.identifier, |
||||
order: roomConfig.order, |
||||
}); |
||||
|
||||
this.roomTypes[roomConfig.identifier] = roomConfig; |
||||
|
||||
if (roomConfig.route && roomConfig.route.path && roomConfig.route.name && roomConfig.route.action) { |
||||
const routeConfig = { |
||||
name: roomConfig.route.name, |
||||
action: roomConfig.route.action, |
||||
// triggersExit: [() => Session.set('openedRoom', '')],
|
||||
}; |
||||
|
||||
if (Meteor.isClient) { |
||||
routeConfig.triggersExit = [roomExit]; |
||||
} |
||||
|
||||
return FlowRouter.route(roomConfig.route.path, routeConfig); |
||||
} |
||||
} |
||||
|
||||
hasCustomLink(roomType) { |
||||
return this.roomTypes[roomType] && this.roomTypes[roomType].route && this.roomTypes[roomType].route.link != null; |
||||
} |
||||
|
||||
/** |
||||
* @param {string} roomType room type (e.g.: c (for channels), d (for direct channels)) |
||||
* @param {object} subData the user's subscription data |
||||
*/ |
||||
getRouteLink(roomType, subData) { |
||||
const routeData = this.getRouteData(roomType, subData); |
||||
if (!routeData) { |
||||
return false; |
||||
} |
||||
|
||||
return FlowRouter.path(this.roomTypes[roomType].route.name, routeData); |
||||
} |
||||
|
||||
/** |
||||
* @param {string} roomType room type (e.g.: c (for channels), d (for direct channels)) |
||||
* @param {RoomTypeConfig} roomConfig room's type configuration |
||||
*/ |
||||
getConfig(roomType) { |
||||
return this.roomTypes[roomType]; |
||||
} |
||||
|
||||
/** |
||||
* @param {string} roomType room type (e.g.: c (for channels), d (for direct channels)) |
||||
* @param {object} subData the user's subscription data |
||||
*/ |
||||
getURL(roomType, subData) { |
||||
const routeData = this.getRouteData(roomType, subData); |
||||
if (!routeData) { |
||||
return false; |
||||
} |
||||
|
||||
return FlowRouter.url(this.roomTypes[roomType].route.name, routeData); |
||||
} |
||||
|
||||
getRelativePath(roomType, subData) { |
||||
return this.getRouteLink(roomType, subData).replace(Meteor.absoluteUrl(), ''); |
||||
} |
||||
|
||||
getRouteData(roomType, subData) { |
||||
if (!this.roomTypes[roomType]) { |
||||
return false; |
||||
} |
||||
|
||||
let routeData = {}; |
||||
if (this.roomTypes[roomType] && this.roomTypes[roomType].route && this.roomTypes[roomType].route.link) { |
||||
routeData = this.roomTypes[roomType].route.link(subData); |
||||
} else if (subData && subData.name) { |
||||
routeData = { |
||||
rid: subData.rid || subData._id, |
||||
name: subData.name, |
||||
}; |
||||
} |
||||
|
||||
return routeData; |
||||
} |
||||
} |
||||
@ -1,6 +1,6 @@ |
||||
import { getURL } from './getURL'; |
||||
|
||||
export const getAvatarURL = ({ username, roomId, cache }) => { |
||||
export const getAvatarURL = ({ username, roomId, cache }: { username?: string; roomId?: string; cache?: string }): string | undefined => { |
||||
if (username) { |
||||
return getURL(`/avatar/${encodeURIComponent(username)}${cache ? `?etag=${cache}` : ''}`); |
||||
} |
||||
@ -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(); |
||||
} |
||||
}; |
||||
@ -1,55 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { RoomTypesCommon } from '../../lib/RoomTypesCommon'; |
||||
|
||||
export const roomTypes = new (class roomTypesServer extends RoomTypesCommon { |
||||
/** |
||||
* Add a publish for a room type |
||||
* |
||||
* @param {string} roomType room type (e.g.: c (for channels), d (for direct channels)) |
||||
* @param {function} callback function that will return the publish's data |
||||
*/ |
||||
setPublish(roomType, callback) { |
||||
if (this.roomTypes[roomType] && this.roomTypes[roomType].publish != null) { |
||||
throw new Meteor.Error('route-publish-exists', 'Publish for the given type already exists'); |
||||
} |
||||
if (this.roomTypes[roomType] == null) { |
||||
this.roomTypes[roomType] = {}; |
||||
} |
||||
this.roomTypes[roomType].publish = callback; |
||||
} |
||||
|
||||
setRoomFind(roomType, callback) { |
||||
if (this.roomTypes[roomType] && this.roomTypes[roomType].roomFind != null) { |
||||
throw new Meteor.Error('room-find-exists', 'Room find for the given type already exists'); |
||||
} |
||||
if (this.roomTypes[roomType] == null) { |
||||
this.roomTypes[roomType] = {}; |
||||
} |
||||
this.roomTypes[roomType].roomFind = callback; |
||||
} |
||||
|
||||
getRoomFind(roomType) { |
||||
return this.roomTypes[roomType] && this.roomTypes[roomType].roomFind; |
||||
} |
||||
|
||||
getRoomName(roomType, roomData) { |
||||
return this.roomTypes[roomType] && this.roomTypes[roomType].roomName && this.roomTypes[roomType].roomName(roomData); |
||||
} |
||||
|
||||
/** |
||||
* Run the publish for a room type |
||||
* |
||||
* @param scope Meteor publish scope |
||||
* @param {string} roomType room type (e.g.: c (for channels), d (for direct channels)) |
||||
* @param identifier identifier of the room |
||||
*/ |
||||
runPublish(scope, roomType, identifier) { |
||||
return this.roomTypes[roomType] && this.roomTypes[roomType].publish && this.roomTypes[roomType].publish.call(scope, identifier); |
||||
} |
||||
})(); |
||||
|
||||
export const searchableRoomTypes = () => |
||||
Object.entries(roomTypes.roomTypes) |
||||
.filter((roomType) => roomType[1].includeInRoomSearch()) |
||||
.map((roomType) => roomType[0]); |
||||
@ -0,0 +1,194 @@ |
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
import type { RouteOptions } from 'meteor/kadira:flow-router'; |
||||
import _ from 'underscore'; |
||||
|
||||
import { hasPermission } from '../../../app/authorization/client'; |
||||
import { ChatRoom, ChatSubscription } from '../../../app/models/client'; |
||||
import { openRoom } from '../../../app/ui-utils/client/lib/openRoom'; |
||||
import type { IRoom, RoomType } from '../../../definition/IRoom'; |
||||
import type { IRoomTypeConfig, IRoomTypeClientDirectives, RoomIdentification } from '../../../definition/IRoomTypeConfig'; |
||||
import { RoomSettingsEnum, RoomMemberActions, UiTextContext } from '../../../definition/IRoomTypeConfig'; |
||||
import type { IUser } from '../../../definition/IUser'; |
||||
import type { AtLeast, 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: AtLeast<IRoom, '_id' | 'name' | 'fname' | 'prid'>): 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): string { |
||||
return ''; |
||||
}, |
||||
getIcon(_room: Partial<IRoom>): string | undefined { |
||||
return this.config.icon; |
||||
}, |
||||
getUserStatus(_roomId: string): string | undefined { |
||||
return undefined; |
||||
}, |
||||
findRoom(_identifier: string): IRoom | undefined { |
||||
return undefined; |
||||
}, |
||||
showJoinLink(_roomId: string): boolean { |
||||
return false; |
||||
}, |
||||
isLivechatRoom(): boolean { |
||||
return false; |
||||
}, |
||||
canSendMessage(rid: string): boolean { |
||||
return ChatSubscription.find({ rid }).count() > 0; |
||||
}, |
||||
...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; |
||||
} |
||||
|
||||
getRoomTypeById(rid: string): RoomType | undefined { |
||||
const room = ChatRoom.findOne({ _id: rid, t: { $exists: true, $ne: null } }, { fields: { t: 1 } }); |
||||
return room?.t; |
||||
} |
||||
|
||||
getRoomDirectivesById(rid: string): IRoomTypeClientDirectives | undefined { |
||||
const roomType = this.getRoomTypeById(rid); |
||||
if (roomType) { |
||||
return this.getRoomDirectives(roomType); |
||||
} |
||||
} |
||||
|
||||
getRoomTypeConfigById(rid: string): IRoomTypeConfig | undefined { |
||||
const roomType = this.getRoomTypeById(rid); |
||||
if (roomType) { |
||||
return this.getRoomTypeConfig(roomType); |
||||
} |
||||
} |
||||
|
||||
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); |
||||
} |
||||
|
||||
openRouteLink(roomType: RoomType, subData: RoomIdentification, queryParams?: Record<string, string>): void { |
||||
const config = this.getRoomTypeConfig(roomType); |
||||
if (!config?.route) { |
||||
return; |
||||
} |
||||
|
||||
let routeData = {}; |
||||
if (config.route.link) { |
||||
routeData = config.route.link(subData); |
||||
} else if (subData?.name) { |
||||
routeData = { |
||||
name: subData.name, |
||||
}; |
||||
} else { |
||||
return; |
||||
} |
||||
|
||||
FlowRouter.go(config.route.name, routeData, queryParams); |
||||
} |
||||
|
||||
isLivechatRoom(roomType: string): boolean { |
||||
return Boolean(this.getRoomDirectives(roomType)?.isLivechatRoom()); |
||||
} |
||||
|
||||
getRoomName(roomType: string, roomData: AtLeast<IRoom, '_id' | 'name' | 'fname' | 'prid'>): string { |
||||
return this.getRoomDirectives(roomType)?.roomName(roomData) ?? ''; |
||||
} |
||||
|
||||
readOnly(rid: string, user: AtLeast<IUser, 'username'>): boolean { |
||||
const fields = { |
||||
ro: 1, |
||||
t: 1, |
||||
...(user && { muted: 1, unmuted: 1 }), |
||||
}; |
||||
const room = ChatRoom.findOne({ _id: rid }, { fields }); |
||||
if (!room) { |
||||
return false; |
||||
} |
||||
|
||||
const directives = this.getRoomDirectives(room.t); |
||||
if (directives?.readOnly) { |
||||
return directives.readOnly(rid, user); |
||||
} |
||||
|
||||
if (!user?.username) { |
||||
return Boolean(room.ro); |
||||
} |
||||
|
||||
if (!room) { |
||||
return false; |
||||
} |
||||
|
||||
if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1) { |
||||
return true; |
||||
} |
||||
|
||||
if (room.ro) { |
||||
if (Array.isArray(room.unmuted) && room.unmuted.indexOf(user.username) !== -1) { |
||||
return false; |
||||
} |
||||
|
||||
if (hasPermission('post-readonly', room._id)) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
// #ToDo: Move this out of the RoomCoordinator
|
||||
archived(rid: string): boolean { |
||||
const room = ChatRoom.findOne({ _id: rid }, { fields: { archived: 1 } }); |
||||
return Boolean(room?.archived); |
||||
} |
||||
|
||||
verifyCanSendMessage(rid: string): boolean { |
||||
const room = ChatRoom.findOne({ _id: rid }, { fields: { t: 1 } }); |
||||
if (!room?.t) { |
||||
return false; |
||||
} |
||||
|
||||
return Boolean(this.getRoomDirectives(room.t)?.canSendMessage(rid)); |
||||
} |
||||
|
||||
getSortedTypes(): Array<{ config: IRoomTypeConfig; directives: IRoomTypeClientDirectives }> { |
||||
return _.sortBy(this.roomTypesOrder, 'order') |
||||
.map((type) => this.roomTypes[type.identifier] as { config: IRoomTypeConfig; directives: IRoomTypeClientDirectives }) |
||||
.filter((type) => type.directives.condition()); |
||||
} |
||||
} |
||||
|
||||
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,14 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { getUserPreference } from '../../../../app/utils/client'; |
||||
import { getConversationRoomType } from '../../../../lib/rooms/roomTypes/conversation'; |
||||
import { roomCoordinator } from '../roomCoordinator'; |
||||
|
||||
export const ConversationRoomType = getConversationRoomType(roomCoordinator); |
||||
|
||||
roomCoordinator.add(ConversationRoomType, { |
||||
condition(): boolean { |
||||
// returns true only if sidebarGroupByType is not set
|
||||
return !getUserPreference(Meteor.userId(), 'sidebarGroupByType'); |
||||
}, |
||||
}); |
||||
@ -0,0 +1,152 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Session } from 'meteor/session'; |
||||
|
||||
import { hasAtLeastOnePermission, hasPermission } from '../../../../app/authorization/client'; |
||||
import { Subscriptions, Users, ChatRoom } 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): 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): 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(), |
||||
cache: room.avatarETag, |
||||
}) as string; |
||||
} |
||||
|
||||
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'; |
||||
} |
||||
|
||||
return DirectMessageRoomType.icon; |
||||
}, |
||||
|
||||
getUserStatus(roomId: string): string | undefined { |
||||
const subscription = Subscriptions.findOne({ rid: roomId }); |
||||
if (!subscription) { |
||||
return; |
||||
} |
||||
|
||||
return Session.get(`user_${subscription.name}_status`); |
||||
}, |
||||
|
||||
findRoom(identifier: string): IRoom | undefined { |
||||
if (!hasPermission('view-d-room')) { |
||||
return; |
||||
} |
||||
|
||||
const query = { |
||||
t: 'd', |
||||
$or: [{ name: identifier }, { rid: identifier }], |
||||
}; |
||||
|
||||
const subscription = Subscriptions.findOne(query); |
||||
if (subscription?.rid) { |
||||
return ChatRoom.findOne(subscription.rid); |
||||
} |
||||
}, |
||||
} as AtLeast<IRoomTypeClientDirectives, 'isGroupChat' | 'roomName'>); |
||||
@ -0,0 +1,14 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { settings } from '../../../../app/settings/client'; |
||||
import { getUserPreference } from '../../../../app/utils/client'; |
||||
import { getFavoriteRoomType } from '../../../../lib/rooms/roomTypes/favorite'; |
||||
import { roomCoordinator } from '../roomCoordinator'; |
||||
|
||||
export const FavoriteRoomType = getFavoriteRoomType(roomCoordinator); |
||||
|
||||
roomCoordinator.add(FavoriteRoomType, { |
||||
condition(): boolean { |
||||
return settings.get('Favorite_Rooms') && getUserPreference(Meteor.userId(), 'sidebarShowFavorites'); |
||||
}, |
||||
}); |
||||
@ -0,0 +1,7 @@ |
||||
import './conversation'; |
||||
import './direct'; |
||||
import './favorite'; |
||||
import './livechat'; |
||||
import './private'; |
||||
import './public'; |
||||
import './unread'; |
||||
@ -0,0 +1,94 @@ |
||||
import { Session } from 'meteor/session'; |
||||
|
||||
import { hasPermission } from '../../../../app/authorization/client'; |
||||
import { LivechatInquiry } from '../../../../app/livechat/client/collections/LivechatInquiry'; |
||||
import { ChatRoom, ChatSubscription } from '../../../../app/models/client'; |
||||
import { settings } from '../../../../app/settings/client'; |
||||
import { getAvatarURL } from '../../../../app/utils/lib/getAvatarURL'; |
||||
import type { IRoom, IOmnichannelRoom } from '../../../../definition/IRoom'; |
||||
import type { IRoomTypeClientDirectives } from '../../../../definition/IRoomTypeConfig'; |
||||
import { RoomSettingsEnum, RoomMemberActions, UiTextContext } from '../../../../definition/IRoomTypeConfig'; |
||||
import type { AtLeast, ValueOf } from '../../../../definition/utils'; |
||||
import { getLivechatRoomType } from '../../../../lib/rooms/roomTypes/livechat'; |
||||
import { roomCoordinator } from '../roomCoordinator'; |
||||
|
||||
export const LivechatRoomType = getLivechatRoomType(roomCoordinator); |
||||
|
||||
roomCoordinator.add(LivechatRoomType, { |
||||
allowRoomSettingChange(_room: Partial<IRoom>, setting: ValueOf<typeof RoomSettingsEnum>): boolean { |
||||
switch (setting) { |
||||
case RoomSettingsEnum.JOIN_CODE: |
||||
return false; |
||||
default: |
||||
return true; |
||||
} |
||||
}, |
||||
|
||||
allowMemberAction(_room: Partial<IRoom>, action: ValueOf<typeof RoomMemberActions>): boolean { |
||||
return ([RoomMemberActions.INVITE, RoomMemberActions.JOIN] as Array<ValueOf<typeof RoomMemberActions>>).includes(action); |
||||
}, |
||||
|
||||
roomName(room: any): string | undefined { |
||||
return room.name || room.fname || room.label; |
||||
}, |
||||
|
||||
openCustomProfileTab(instance: any, room: IOmnichannelRoom, username: string): boolean { |
||||
if (!room?.v || (room.v as any).username !== username) { |
||||
return false; |
||||
} |
||||
|
||||
instance.tabBar.openUserInfo(); |
||||
return true; |
||||
}, |
||||
|
||||
getUiText(context: ValueOf<typeof UiTextContext>): string { |
||||
switch (context) { |
||||
case UiTextContext.HIDE_WARNING: |
||||
return 'Hide_Livechat_Warning'; |
||||
case UiTextContext.LEAVE_WARNING: |
||||
return 'Hide_Livechat_Warning'; |
||||
default: |
||||
return ''; |
||||
} |
||||
}, |
||||
|
||||
condition(): boolean { |
||||
return settings.get('Livechat_enabled') && hasPermission('view-l-room'); |
||||
}, |
||||
|
||||
getAvatarPath(room): string { |
||||
return getAvatarURL({ username: `@${this.roomName(room)}` }) || ''; |
||||
}, |
||||
|
||||
getUserStatus(rid: string): string | undefined { |
||||
const room = Session.get(`roomData${rid}`); |
||||
if (room) { |
||||
return room.v && room.v.status; |
||||
} |
||||
const inquiry = LivechatInquiry.findOne({ rid }); |
||||
return inquiry?.v?.status; |
||||
}, |
||||
|
||||
findRoom(identifier: string): IRoom | undefined { |
||||
return ChatRoom.findOne({ _id: identifier }); |
||||
}, |
||||
|
||||
isLivechatRoom(): boolean { |
||||
return true; |
||||
}, |
||||
|
||||
canSendMessage(rid: string): boolean { |
||||
const room = ChatRoom.findOne({ _id: rid }, { fields: { open: 1 } }); |
||||
return Boolean(room?.open); |
||||
}, |
||||
|
||||
readOnly(rid: string, _user): boolean { |
||||
const room = ChatRoom.findOne({ _id: rid }, { fields: { open: 1, servedBy: 1 } }); |
||||
if (!room || !room.open) { |
||||
return true; |
||||
} |
||||
|
||||
const subscription = ChatSubscription.findOne({ rid }); |
||||
return !subscription; |
||||
}, |
||||
} as AtLeast<IRoomTypeClientDirectives, 'roomName'>); |
||||
@ -0,0 +1,99 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { hasPermission } from '../../../../app/authorization/client'; |
||||
import { ChatRoom } from '../../../../app/models/client'; |
||||
import { settings } from '../../../../app/settings/client'; |
||||
import { getUserPreference } from '../../../../app/utils/client'; |
||||
import { getAvatarURL } from '../../../../app/utils/lib/getAvatarURL'; |
||||
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 { getPrivateRoomType } from '../../../../lib/rooms/roomTypes/private'; |
||||
import { roomCoordinator } from '../roomCoordinator'; |
||||
|
||||
export const PrivateRoomType = getPrivateRoomType(roomCoordinator); |
||||
|
||||
roomCoordinator.add(PrivateRoomType, { |
||||
allowRoomSettingChange(room: Partial<IRoom>, setting: ValueOf<typeof RoomSettingsEnum>): boolean { |
||||
switch (setting) { |
||||
case RoomSettingsEnum.JOIN_CODE: |
||||
return false; |
||||
case RoomSettingsEnum.BROADCAST: |
||||
return Boolean(room.broadcast); |
||||
case RoomSettingsEnum.READ_ONLY: |
||||
return !room.broadcast; |
||||
case RoomSettingsEnum.REACT_WHEN_READ_ONLY: |
||||
return Boolean(!room.broadcast && room.ro); |
||||
case RoomSettingsEnum.E2E: |
||||
return settings.get('E2E_Enable') === true; |
||||
case RoomSettingsEnum.SYSTEM_MESSAGES: |
||||
default: |
||||
return true; |
||||
} |
||||
}, |
||||
|
||||
allowMemberAction(_room: Partial<IRoom>, action: ValueOf<typeof RoomMemberActions>): boolean { |
||||
switch (action) { |
||||
case RoomMemberActions.BLOCK: |
||||
return false; |
||||
default: |
||||
return true; |
||||
} |
||||
}, |
||||
|
||||
roomName(roomData: AtLeast<IRoom, '_id' | 'name' | 'fname' | 'prid'>): string | undefined { |
||||
if (roomData.prid) { |
||||
return roomData.fname; |
||||
} |
||||
if (settings.get('UI_Allow_room_names_with_special_chars')) { |
||||
return roomData.fname || roomData.name; |
||||
} |
||||
|
||||
return roomData.name; |
||||
}, |
||||
|
||||
isGroupChat(_room: Partial<IRoom>): boolean { |
||||
return true; |
||||
}, |
||||
|
||||
getUiText(context: ValueOf<typeof UiTextContext>): string { |
||||
switch (context) { |
||||
case UiTextContext.HIDE_WARNING: |
||||
return 'Hide_Group_Warning'; |
||||
case UiTextContext.LEAVE_WARNING: |
||||
return 'Leave_Group_Warning'; |
||||
default: |
||||
return ''; |
||||
} |
||||
}, |
||||
|
||||
condition(): boolean { |
||||
const groupByType = getUserPreference(Meteor.userId(), 'sidebarGroupByType'); |
||||
return groupByType && hasPermission('view-p-room'); |
||||
}, |
||||
|
||||
getAvatarPath(room): string { |
||||
return getAvatarURL({ roomId: room._id, cache: room.avatarETag }) as string; |
||||
}, |
||||
|
||||
getIcon(room: Partial<IRoom>): string | undefined { |
||||
if (room.prid) { |
||||
return 'discussion'; |
||||
} |
||||
if (room.teamMain) { |
||||
return 'team-lock'; |
||||
} |
||||
|
||||
return PrivateRoomType.icon; |
||||
}, |
||||
|
||||
findRoom(identifier: string): IRoom | undefined { |
||||
const query = { |
||||
t: 'p', |
||||
name: identifier, |
||||
}; |
||||
|
||||
return ChatRoom.findOne(query); |
||||
}, |
||||
} as AtLeast<IRoomTypeClientDirectives, 'isGroupChat' | 'roomName'>); |
||||
@ -0,0 +1,102 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { hasAtLeastOnePermission } from '../../../../app/authorization/client'; |
||||
import { ChatRoom } from '../../../../app/models/client'; |
||||
import { settings } from '../../../../app/settings/client'; |
||||
import { getUserPreference } from '../../../../app/utils/client'; |
||||
import { getAvatarURL } from '../../../../app/utils/lib/getAvatarURL'; |
||||
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 { getPublicRoomType } from '../../../../lib/rooms/roomTypes/public'; |
||||
import { roomCoordinator } from '../roomCoordinator'; |
||||
|
||||
export const PublicRoomType = getPublicRoomType(roomCoordinator); |
||||
|
||||
roomCoordinator.add(PublicRoomType, { |
||||
allowRoomSettingChange(room: Partial<IRoom>, setting: ValueOf<typeof RoomSettingsEnum>): boolean { |
||||
switch (setting) { |
||||
case RoomSettingsEnum.BROADCAST: |
||||
return Boolean(room.broadcast); |
||||
case RoomSettingsEnum.READ_ONLY: |
||||
return Boolean(!room.broadcast); |
||||
case RoomSettingsEnum.REACT_WHEN_READ_ONLY: |
||||
return Boolean(!room.broadcast && room.ro); |
||||
case RoomSettingsEnum.E2E: |
||||
return false; |
||||
case RoomSettingsEnum.SYSTEM_MESSAGES: |
||||
default: |
||||
return true; |
||||
} |
||||
}, |
||||
|
||||
allowMemberAction(_room: Partial<IRoom>, action: ValueOf<typeof RoomMemberActions>): boolean { |
||||
switch (action) { |
||||
case RoomMemberActions.BLOCK: |
||||
return false; |
||||
default: |
||||
return true; |
||||
} |
||||
}, |
||||
|
||||
roomName(roomData: AtLeast<IRoom, '_id' | 'name' | 'fname' | 'prid'>): string | undefined { |
||||
if (roomData.prid) { |
||||
return roomData.fname; |
||||
} |
||||
if (settings.get('UI_Allow_room_names_with_special_chars')) { |
||||
return roomData.fname || roomData.name; |
||||
} |
||||
return roomData.name; |
||||
}, |
||||
|
||||
isGroupChat(_room: Partial<IRoom>): boolean { |
||||
return true; |
||||
}, |
||||
|
||||
getUiText(context: ValueOf<typeof UiTextContext>): string { |
||||
switch (context) { |
||||
case UiTextContext.HIDE_WARNING: |
||||
return 'Hide_Room_Warning'; |
||||
case UiTextContext.LEAVE_WARNING: |
||||
return 'Leave_Room_Warning'; |
||||
default: |
||||
return ''; |
||||
} |
||||
}, |
||||
|
||||
condition(): boolean { |
||||
const groupByType = getUserPreference(Meteor.userId(), 'sidebarGroupByType'); |
||||
return ( |
||||
groupByType && (hasAtLeastOnePermission(['view-c-room', 'view-joined-room']) || settings.get('Accounts_AllowAnonymousRead') === true) |
||||
); |
||||
}, |
||||
|
||||
getAvatarPath(room): string { |
||||
return getAvatarURL({ roomId: room._id, cache: room.avatarETag }) as string; |
||||
}, |
||||
|
||||
getIcon(room: Partial<IRoom>): string | undefined { |
||||
if (room.prid) { |
||||
return 'discussion'; |
||||
} |
||||
if (room.teamMain) { |
||||
return 'team'; |
||||
} |
||||
|
||||
return PublicRoomType.icon; |
||||
}, |
||||
|
||||
findRoom(identifier: string): IRoom | undefined { |
||||
const query = { |
||||
t: 'c', |
||||
name: identifier, |
||||
}; |
||||
|
||||
return ChatRoom.findOne(query); |
||||
}, |
||||
|
||||
showJoinLink(roomId: string): boolean { |
||||
return !!ChatRoom.findOne({ _id: roomId, t: 'c' }); |
||||
}, |
||||
} as AtLeast<IRoomTypeClientDirectives, 'isGroupChat' | 'roomName'>); |
||||
@ -0,0 +1,13 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { getUserPreference } from '../../../../app/utils/client'; |
||||
import { getUnreadRoomType } from '../../../../lib/rooms/roomTypes/unread'; |
||||
import { roomCoordinator } from '../roomCoordinator'; |
||||
|
||||
export const UnreadRoomType = getUnreadRoomType(roomCoordinator); |
||||
|
||||
roomCoordinator.add(UnreadRoomType, { |
||||
condition(): boolean { |
||||
return getUserPreference(Meteor.userId(), 'sidebarShowUnread'); |
||||
}, |
||||
}); |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue