mattermost-mobile/app/utils/user/index.ts
Kyriakos Z 675d8495b3
[Gekidou]: MM-39757 - Recent mentions (#5823)
* [Gekidou]: MM-39757 - Recent mentions

* Refactor channel_info to a separate component

* Fixes schema tests

* Fixes channel_info theme color

* Removes RECEIVED_MENTIONS table and model

Removes RECEIVED_MENTIONS table and model and saves recent_mentions in
the SYSTEM table under the recentMentions ID.

* Cleanup recent_mentions handler

* Adds i18n in recent_mentions screen

* Observe changes on the post messages

* Addresses review comments

* Batches records

* Addresses review comments

* Addresses review comments

* Addresses review comments

* Addresses review comments

* Fetches channels and users needed for mentions

Fetching mentions from all teams might result in missing info like user
profiles, and channels missing from the DB.
This commit fetches all missing users and channels.

* Adds empty state for recent mentions

* Prepares all missing models for channels

* Addresses review comments

* Fixes mention keys for recent mentions

User mention keys when asking for mentions should not include general
purpose ones, like @channel, @all, @here.

Fixes ActivityIndicator color in recent mentions screen.

* Removes top margin of mention message

* Addresses review comments

* Fixes group.name undefined
2021-12-16 12:26:43 +02:00

213 lines
6.7 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import moment from 'moment-timezone';
import {Alert} from 'react-native';
import {Permissions, Preferences} from '@constants';
import {CustomStatusDuration} from '@constants/custom_status';
import {UserModel} from '@database/models/server';
import {DEFAULT_LOCALE, getLocalizedMessage, t} from '@i18n';
import {toTitleCase} from '@utils/helpers';
import type GroupModel from '@typings/database/models/servers/group';
import type GroupMembershipModel from '@typings/database/models/servers/group_membership';
import type {IntlShape} from 'react-intl';
export function displayUsername(user?: UserProfile | UserModel, locale?: string, teammateDisplayNameSetting?: string, useFallbackUsername = true) {
let name = useFallbackUsername ? getLocalizedMessage(locale || DEFAULT_LOCALE, t('channel_loader.someone'), 'Someone') : '';
if (user) {
if (teammateDisplayNameSetting === Preferences.DISPLAY_PREFER_NICKNAME) {
name = user.nickname || getFullName(user);
} else if (teammateDisplayNameSetting === Preferences.DISPLAY_PREFER_FULL_NAME) {
name = getFullName(user);
} else {
name = user.username;
}
if (!name || name.trim().length === 0) {
name = user.username;
}
}
return name;
}
export function displayGroupMessageName(users: UserProfile[], locale?: string, teammateDisplayNameSetting?: string, excludeUserId?: string) {
const names: string[] = [];
const sortUsernames = (a: string, b: string) => {
return a.localeCompare(b, locale || DEFAULT_LOCALE, {numeric: true});
};
users.forEach((u) => {
if (u.id !== excludeUserId) {
names.push(displayUsername(u, locale, teammateDisplayNameSetting));
}
});
return names.sort(sortUsernames).join(', ');
}
export function getFullName(user: UserProfile | UserModel): string {
let firstName: string;
let lastName: string;
if (user instanceof UserModel) {
firstName = user.firstName;
lastName = user.lastName;
} else {
firstName = user.first_name;
lastName = user.last_name;
}
if (firstName && lastName) {
return `${firstName} ${lastName}`;
} else if (firstName) {
return firstName;
} else if (lastName) {
return lastName;
}
return '';
}
export function getUserIdFromChannelName(knownUserId: string, channelName: string): string {
const ids = channelName.split('__');
if (ids[0] === knownUserId) {
return ids[1];
}
return ids[0];
}
export function isRoleInRoles(roles: string, role: string): boolean {
const rolesArray = roles.split(' ');
return rolesArray.includes(role);
}
export function isGuest(roles: string): boolean {
return isRoleInRoles(roles, Permissions.SYSTEM_GUEST_ROLE);
}
export function isSystemAdmin(roles: string): boolean {
return isRoleInRoles(roles, Permissions.SYSTEM_ADMIN_ROLE);
}
export const getUsersByUsername = (users: UserModel[]) => {
const usersByUsername: Dictionary<UserModel> = {};
for (const user of users) {
usersByUsername[user.username] = user;
}
return usersByUsername;
};
export const getUserMentionKeys = (user: UserModel, groups: GroupModel[], userGroups: GroupMembershipModel[]) => {
const keys = user.mentionKeys;
if (groups.length && userGroups.length) {
const groupMentions = userGroups.reduce((result: Array<{key: string}>, ug: GroupMembershipModel) => {
const group = groups.find((g) => ug.groupId === g.id);
if (group) {
result.push({key: `@${group.name}`});
}
return result;
}, []);
keys.push(...groupMentions);
}
return keys;
};
export const getUserTimezone = (user: UserModel) => {
return getTimezone(user.timezone);
};
export const getTimezone = (timezone: UserTimezone | null) => {
if (!timezone) {
return '';
}
const {useAutomaticTimezone} = timezone;
let useAutomatic = useAutomaticTimezone;
if (typeof useAutomaticTimezone === 'string') {
useAutomatic = useAutomaticTimezone === 'true';
}
if (useAutomatic) {
return timezone.automaticTimezone;
}
return timezone.manualTimezone;
};
export const getUserCustomStatus = (user: UserModel): UserCustomStatus | undefined => {
try {
if (typeof user.props?.customStatus === 'string') {
return JSON.parse(user.props.customStatus) as UserCustomStatus;
}
return user.props?.customStatus;
} catch {
return undefined;
}
};
export function isCustomStatusExpired(user: UserModel) {
const customStatus = getUserCustomStatus(user);
if (!customStatus) {
return true;
}
if (customStatus.duration === CustomStatusDuration.DONT_CLEAR || !customStatus.duration) {
return false;
}
const expiryTime = moment(customStatus.expires_at);
const timezone = getUserTimezone(user);
const currentTime = timezone ? moment.tz(timezone) : moment();
return currentTime.isSameOrAfter(expiryTime);
}
export function confirmOutOfOfficeDisabled(intl: IntlShape, status: string, updateStatus: (status: string) => void) {
const userStatusId = 'modal.manual_status.auto_responder.message_' + status;
t('modal.manual_status.auto_responder.message_');
t('modal.manual_status.auto_responder.message_away');
t('modal.manual_status.auto_responder.message_dnd');
t('modal.manual_status.auto_responder.message_offline');
t('modal.manual_status.auto_responder.message_online');
let translatedStatus;
if (status === 'dnd') {
translatedStatus = intl.formatMessage({
id: 'mobile.set_status.dnd',
defaultMessage: 'Do Not Disturb',
});
} else {
translatedStatus = intl.formatMessage({
id: `mobile.set_status.${status}`,
defaultMessage: toTitleCase(status),
});
}
Alert.alert(
intl.formatMessage({
id: 'mobile.reset_status.title_ooo',
defaultMessage: 'Disable "Out Of Office"?',
}),
intl.formatMessage({
id: userStatusId,
defaultMessage: 'Would you like to switch your status to "{status}" and disable Automatic Replies?',
}, {status: translatedStatus}),
[{
text: intl.formatMessage({id: 'mobile.reset_status.alert_cancel', defaultMessage: 'Cancel'}),
style: 'cancel',
}, {
text: intl.formatMessage({id: 'mobile.reset_status.alert_ok', defaultMessage: 'OK'}),
onPress: () => updateStatus(status),
}],
);
}