[Gekidou] Add custom status to user profile sheet (#6670)
* Add custom status to user profile sheet * add missing translations
This commit is contained in:
parent
3e7ebfe95c
commit
d201035a89
10 changed files with 125 additions and 10 deletions
|
|
@ -29,6 +29,7 @@ type HeaderProps = {
|
|||
enablePostUsernameOverride: boolean;
|
||||
isAutoResponse: boolean;
|
||||
isCRTEnabled?: boolean;
|
||||
isCustomStatusEnabled: boolean;
|
||||
isEphemeral: boolean;
|
||||
isMilitaryTime: boolean;
|
||||
isPendingOrFailed: boolean;
|
||||
|
|
@ -76,7 +77,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
|
|||
|
||||
const Header = (props: HeaderProps) => {
|
||||
const {
|
||||
author, commentCount = 0, currentUser, enablePostUsernameOverride, isAutoResponse, isCRTEnabled,
|
||||
author, commentCount = 0, currentUser, enablePostUsernameOverride, isAutoResponse, isCRTEnabled, isCustomStatusEnabled,
|
||||
isEphemeral, isMilitaryTime, isPendingOrFailed, isPostPriorityEnabled, isSystemPost, isTimezoneEnabled, isWebHook,
|
||||
location, post, rootPostAuthor, shouldRenderReplyButton, teammateNameDisplay,
|
||||
} = props;
|
||||
|
|
@ -90,7 +91,7 @@ const Header = (props: HeaderProps) => {
|
|||
const customStatus = getUserCustomStatus(author);
|
||||
const customStatusExpired = isCustomStatusExpired(author);
|
||||
const showCustomStatusEmoji = Boolean(
|
||||
displayName && customStatus &&
|
||||
isCustomStatusEnabled && displayName && customStatus &&
|
||||
!(isSystemPost || author.isBot || isAutoResponse || isWebHook),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ const withHeaderProps = withObservables(
|
|||
const isMilitaryTime = preferences.pipe(map((prefs) => getPreferenceAsBool(prefs, Preferences.CATEGORY_DISPLAY_SETTINGS, 'use_military_time', false)));
|
||||
const teammateNameDisplay = observeTeammateNameDisplay(database);
|
||||
const commentCount = queryPostReplies(database, post.rootId || post.id).observeCount();
|
||||
const isCustomStatusEnabled = observeConfigBooleanValue(database, 'EnableCustomUserStatuses');
|
||||
const rootPostAuthor = differentThreadSequence ? post.root.observe().pipe(switchMap((root) => {
|
||||
if (root.length) {
|
||||
return root[0].author.observe();
|
||||
|
|
@ -46,6 +47,7 @@ const withHeaderProps = withObservables(
|
|||
author,
|
||||
commentCount,
|
||||
enablePostUsernameOverride,
|
||||
isCustomStatusEnabled,
|
||||
isMilitaryTime,
|
||||
isTimezoneEnabled,
|
||||
rootPostAuthor,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ type ChannelProps = {
|
|||
channelId: string;
|
||||
channelType: ChannelType;
|
||||
customStatus?: UserCustomStatus;
|
||||
isCustomStatusEnabled: boolean;
|
||||
isCustomStatusExpired: boolean;
|
||||
componentId?: string;
|
||||
displayName: string;
|
||||
|
|
@ -66,7 +67,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
|||
|
||||
const ChannelHeader = ({
|
||||
channelId, channelType, componentId, customStatus, displayName,
|
||||
isCustomStatusExpired, isOwnDirectMessage, memberCount,
|
||||
isCustomStatusEnabled, isCustomStatusExpired, isOwnDirectMessage, memberCount,
|
||||
searchTerm, teamId, callsEnabledInChannel, callsFeatureRestricted,
|
||||
}: ChannelProps) => {
|
||||
const intl = useIntl();
|
||||
|
|
@ -194,7 +195,7 @@ const ChannelHeader = ({
|
|||
} else if (customStatus && customStatus.text) {
|
||||
return (
|
||||
<View style={styles.customStatusContainer}>
|
||||
{Boolean(customStatus.emoji) &&
|
||||
{isCustomStatusEnabled && Boolean(customStatus.emoji) &&
|
||||
<CustomStatusEmoji
|
||||
customStatus={customStatus}
|
||||
emojiSize={13}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {combineLatestWith, switchMap} from 'rxjs/operators';
|
|||
import {observeIsCallsFeatureRestricted} from '@calls/observers';
|
||||
import {General} from '@constants';
|
||||
import {observeChannel, observeChannelInfo} from '@queries/servers/channel';
|
||||
import {observeCurrentTeamId, observeCurrentUserId} from '@queries/servers/system';
|
||||
import {observeConfigBooleanValue, observeCurrentTeamId, observeCurrentUserId} from '@queries/servers/system';
|
||||
import {observeUser} from '@queries/servers/user';
|
||||
import {
|
||||
getUserCustomStatus,
|
||||
|
|
@ -60,6 +60,8 @@ const enhanced = withObservables(['channelId'], ({serverUrl, channelId, database
|
|||
switchMap((dm) => of$(checkCustomStatusIsExpired(dm))),
|
||||
);
|
||||
|
||||
const isCustomStatusEnabled = observeConfigBooleanValue(database, 'EnableCustomUserStatuses');
|
||||
|
||||
const searchTerm = channel.pipe(
|
||||
combineLatestWith(dmUser),
|
||||
switchMap(([c, dm]) => {
|
||||
|
|
@ -82,6 +84,7 @@ const enhanced = withObservables(['channelId'], ({serverUrl, channelId, database
|
|||
channelType,
|
||||
customStatus,
|
||||
displayName,
|
||||
isCustomStatusEnabled,
|
||||
isCustomStatusExpired,
|
||||
isOwnDirectMessage,
|
||||
memberCount,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ type Props = {
|
|||
createdBy: string;
|
||||
customStatus?: UserCustomStatus;
|
||||
header?: string;
|
||||
isCustomStatusEnabled: boolean;
|
||||
}
|
||||
|
||||
const headerMetadata = {header: {width: 1, height: 1}};
|
||||
|
|
@ -65,7 +66,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
|||
},
|
||||
}));
|
||||
|
||||
const Extra = ({channelId, createdAt, createdBy, customStatus, header}: Props) => {
|
||||
const Extra = ({channelId, createdAt, createdBy, customStatus, header, isCustomStatusEnabled}: Props) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
const blockStyles = getMarkdownBlockStyles(theme);
|
||||
|
|
@ -82,7 +83,7 @@ const Extra = ({channelId, createdAt, createdBy, customStatus, header}: Props) =
|
|||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{Boolean(customStatus) &&
|
||||
{isCustomStatusEnabled && Boolean(customStatus) &&
|
||||
<View style={styles.item}>
|
||||
<FormattedText
|
||||
id='channel_info.custom_status'
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {combineLatestWith, switchMap} from 'rxjs/operators';
|
|||
|
||||
import {General} from '@constants';
|
||||
import {observeChannel, observeChannelInfo} from '@queries/servers/channel';
|
||||
import {observeConfigBooleanValue} from '@queries/servers/system';
|
||||
import {observeCurrentUser, observeTeammateNameDisplay, observeUser} from '@queries/servers/user';
|
||||
import {displayUsername, getUserCustomStatus, getUserIdFromChannelName, isCustomStatusExpired as checkCustomStatusIsExpired} from '@utils/user';
|
||||
|
||||
|
|
@ -48,11 +49,14 @@ const enhanced = withObservables(['channelId'], ({channelId, database}: Props) =
|
|||
switchMap((dm) => of$(checkCustomStatusIsExpired(dm) ? undefined : getUserCustomStatus(dm))),
|
||||
);
|
||||
|
||||
const isCustomStatusEnabled = observeConfigBooleanValue(database, 'EnableCustomUserStatuses');
|
||||
|
||||
return {
|
||||
createdAt,
|
||||
createdBy,
|
||||
customStatus,
|
||||
header,
|
||||
isCustomStatusEnabled,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
91
app/screens/user_profile/custom_status.tsx
Normal file
91
app/screens/user_profile/custom_status.tsx
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import moment from 'moment-timezone';
|
||||
import React from 'react';
|
||||
import {View} from 'react-native';
|
||||
|
||||
import CustomStatusEmoji from '@components/custom_status/custom_status_emoji';
|
||||
import CustomStatusExpiry from '@components/custom_status/custom_status_expiry';
|
||||
import CustomStatusText from '@components/custom_status/custom_status_text';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
||||
type Props = {
|
||||
customStatus: UserCustomStatus;
|
||||
};
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
container: {
|
||||
marginVertical: 8,
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
description: {
|
||||
color: theme.centerChannelColor,
|
||||
...typography('Body', 200),
|
||||
},
|
||||
title: {
|
||||
color: changeOpacity(theme.centerChannelColor, 0.56),
|
||||
marginBottom: 2,
|
||||
...typography('Body', 50, 'SemiBold'),
|
||||
},
|
||||
expiry: {
|
||||
color: changeOpacity(theme.centerChannelColor, 0.56),
|
||||
marginLeft: 3,
|
||||
marginBottom: 2,
|
||||
textTransform: 'lowercase',
|
||||
...typography('Body', 50, 'SemiBold'),
|
||||
},
|
||||
emoji: {
|
||||
marginRight: 8,
|
||||
},
|
||||
}));
|
||||
|
||||
const UserProfileCustomStatus = ({customStatus}: Props) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.row}>
|
||||
<FormattedText
|
||||
id='user_profile.custom_status'
|
||||
defaultMessage='Custom Status'
|
||||
style={styles.title}
|
||||
testID={'user_profile.custom_status.title'}
|
||||
/>
|
||||
{Boolean(customStatus?.duration) &&
|
||||
<CustomStatusExpiry
|
||||
time={moment(customStatus.expires_at)}
|
||||
theme={theme}
|
||||
textStyles={styles.expiry}
|
||||
withinBrackets={true}
|
||||
showPrefix={true}
|
||||
testID={`user_profile.${customStatus.duration}.custom_status_expiry`}
|
||||
/>
|
||||
}
|
||||
</View>
|
||||
<View style={styles.row}>
|
||||
{Boolean(customStatus.emoji) &&
|
||||
<CustomStatusEmoji
|
||||
customStatus={customStatus}
|
||||
emojiSize={24}
|
||||
testID={'user_profile.custom_status_emoji'}
|
||||
style={styles.emoji}
|
||||
/>
|
||||
}
|
||||
<CustomStatusText
|
||||
text={customStatus.text}
|
||||
theme={theme}
|
||||
textStyle={styles.description}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserProfileCustomStatus;
|
||||
|
|
@ -40,12 +40,14 @@ const enhanced = withObservables([], ({channelId, database, userId}: EnhancedPro
|
|||
const preferences = queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_DISPLAY_SETTINGS).
|
||||
observeWithColumns(['value']);
|
||||
const isMilitaryTime = preferences.pipe(map((prefs) => getPreferenceAsBool(prefs, Preferences.CATEGORY_DISPLAY_SETTINGS, 'use_military_time', false)));
|
||||
const isCustomStatusEnabled = observeConfigBooleanValue(database, 'EnableCustomUserStatuses');
|
||||
|
||||
return {
|
||||
currentUserId,
|
||||
enablePostIconOverride,
|
||||
enablePostUsernameOverride,
|
||||
isChannelAdmin,
|
||||
isCustomStatusEnabled,
|
||||
isDirectMessage,
|
||||
isMilitaryTime,
|
||||
isSystemAdmin: systemAdmin,
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ import {Screens} from '@constants';
|
|||
import {useServerUrl} from '@context/server';
|
||||
import {getLocaleFromLanguage} from '@i18n';
|
||||
import BottomSheet from '@screens/bottom_sheet';
|
||||
import {getUserTimezone} from '@utils/user';
|
||||
import {getUserCustomStatus, getUserTimezone, isCustomStatusExpired} from '@utils/user';
|
||||
|
||||
import UserProfileCustomStatus from './custom_status';
|
||||
import UserProfileLabel from './label';
|
||||
import UserProfileOptions, {OptionsType} from './options';
|
||||
import UserProfileTitle from './title';
|
||||
|
|
@ -27,6 +28,7 @@ type Props = {
|
|||
enablePostIconOverride: boolean;
|
||||
enablePostUsernameOverride: boolean;
|
||||
isChannelAdmin: boolean;
|
||||
isCustomStatusEnabled: boolean;
|
||||
isDirectMessage: boolean;
|
||||
isMilitaryTime: boolean;
|
||||
isSystemAdmin: boolean;
|
||||
|
|
@ -47,7 +49,7 @@ const EXTRA_HEIGHT = 60;
|
|||
|
||||
const UserProfile = ({
|
||||
channelId, closeButtonId, currentUserId, enablePostIconOverride, enablePostUsernameOverride,
|
||||
isChannelAdmin, isDirectMessage, isMilitaryTime, isSystemAdmin, isTeamAdmin,
|
||||
isChannelAdmin, isCustomStatusEnabled, isDirectMessage, isMilitaryTime, isSystemAdmin, isTeamAdmin,
|
||||
location, teamId, teammateDisplayName,
|
||||
user, userIconOverride, usernameOverride,
|
||||
}: Props) => {
|
||||
|
|
@ -58,6 +60,8 @@ const UserProfile = ({
|
|||
const showOptions: OptionsType = channelContext && !user.isBot ? 'all' : 'message';
|
||||
const override = Boolean(userIconOverride || usernameOverride);
|
||||
const timezone = getUserTimezone(user);
|
||||
const customStatus = getUserCustomStatus(user);
|
||||
const showCustomStatus = isCustomStatusEnabled && Boolean(customStatus) && !user.isBot && !isCustomStatusExpired(user);
|
||||
let localTime: string|undefined;
|
||||
if (timezone) {
|
||||
moment.locale(getLocaleFromLanguage(locale).toLowerCase());
|
||||
|
|
@ -77,6 +81,10 @@ const UserProfile = ({
|
|||
|
||||
let labels = 0;
|
||||
if (!override && !user.isBot) {
|
||||
if (showCustomStatus) {
|
||||
labels += 1;
|
||||
}
|
||||
|
||||
if (user.nickname) {
|
||||
labels += 1;
|
||||
}
|
||||
|
|
@ -125,6 +133,7 @@ const UserProfile = ({
|
|||
userId={user.id}
|
||||
/>
|
||||
}
|
||||
{showCustomStatus && <UserProfileCustomStatus customStatus={customStatus!}/>}
|
||||
{Boolean(user.nickname) && !override && !user.isBot &&
|
||||
<UserProfileLabel
|
||||
description={user.nickname}
|
||||
|
|
|
|||
|
|
@ -701,9 +701,9 @@
|
|||
"post_info.guest": "Guest",
|
||||
"post_info.system": "System",
|
||||
"post_message_view.edited": "(edited)",
|
||||
"post.options.title": "Options",
|
||||
"post_priority.label.important": "IMPORTANT",
|
||||
"post_priority.label.urgent": "URGENT",
|
||||
"post.options.title": "Options",
|
||||
"post.reactions.title": "Reactions",
|
||||
"posts_view.newMsg": "New Messages",
|
||||
"public_link_copied": "Link copied to clipboard",
|
||||
|
|
@ -832,6 +832,7 @@
|
|||
"unreads.empty.paragraph": "Turn off the unread filter to show all your channels.",
|
||||
"unreads.empty.show_all": "Show all",
|
||||
"unreads.empty.title": "No more unreads",
|
||||
"user_profile.custom_status": "Custom Status",
|
||||
"user.edit_profile.email.auth_service": "Login occurs through {service}. Email cannot be updated. Email address used for notifications is {email}.",
|
||||
"user.edit_profile.email.web_client": "Email must be updated using a web client or desktop application.",
|
||||
"user.settings.general.email": "Email",
|
||||
|
|
|
|||
Loading…
Reference in a new issue