Remove duplicate intro components

This commit is contained in:
Elias Nahum 2022-03-22 23:34:08 -03:00
parent 3e94958ab0
commit 71d442b693
No known key found for this signature in database
GPG key ID: E038DB71E0B61702
17 changed files with 0 additions and 1647 deletions

View file

@ -1,152 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useEffect, useMemo} from 'react';
import {Text, View} from 'react-native';
import {fetchProfilesInChannel} from '@actions/remote/user';
import FormattedText from '@components/formatted_text';
import {BotTag} from '@components/tag';
import {General} from '@constants';
import {useServerUrl} from '@context/server';
import {makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
import IntroOptions from '../options';
import Group from './group';
import Member from './member';
import type ChannelModel from '@typings/database/models/servers/channel';
import type ChannelMembershipModel from '@typings/database/models/servers/channel_membership';
type Props = {
channel: ChannelModel;
currentUserId: string;
isBot: boolean;
members?: ChannelMembershipModel[];
theme: Theme;
}
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
botContainer: {
alignSelf: 'flex-end',
bottom: 7.5,
height: 20,
marginBottom: 0,
marginLeft: 4,
paddingVertical: 0,
},
botText: {
fontSize: 14,
lineHeight: 20,
},
container: {
alignItems: 'center',
},
message: {
color: theme.centerChannelColor,
marginTop: 16,
textAlign: 'center',
...typography('Body', 200, 'Regular'),
},
profilesContainer: {
justifyContent: 'center',
alignItems: 'center',
},
title: {
color: theme.centerChannelColor,
marginTop: 16,
textAlign: 'center',
...typography('Heading', 700, 'SemiBold'),
},
titleGroup: {
...typography('Heading', 600, 'SemiBold'),
},
}));
const DirectChannel = ({channel, currentUserId, isBot, members, theme}: Props) => {
const serverUrl = useServerUrl();
const styles = getStyleSheet(theme);
useEffect(() => {
const channelMembers = members?.filter((m) => m.userId !== currentUserId);
if (!channelMembers?.length) {
fetchProfilesInChannel(serverUrl, channel.id, currentUserId, false);
}
}, []);
const message = useMemo(() => {
if (channel.type === General.DM_CHANNEL) {
return (
<FormattedText
defaultMessage={'This is the start of your conversation with {teammate}. Messages and files shared here are not shown to anyone else.'}
id='intro.direct_message'
style={styles.message}
values={{teammate: channel.displayName}}
/>
);
}
return (
<FormattedText
defaultMessage={'This is the start of your conversation with this group. Messages and files shared here are not shown to anyone else outside of the group.'}
id='intro.group_message'
style={styles.message}
/>
);
}, [channel.displayName, theme]);
const profiles = useMemo(() => {
const channelMembers = members?.filter((m) => m.userId !== currentUserId);
if (!channelMembers?.length) {
return null;
}
if (channel.type === General.DM_CHANNEL) {
return (
<Member
containerStyle={{height: 96}}
member={channelMembers[0]}
size={96}
theme={theme}
/>
);
}
return (
<Group
theme={theme}
userIds={channelMembers.map((cm) => cm.userId)}
/>
);
}, [members, theme]);
return (
<View style={styles.container}>
<View style={styles.profilesContainer}>
{profiles}
</View>
<View style={{flexDirection: 'row'}}>
<Text style={[styles.title, channel.type === General.GM_CHANNEL ? styles.titleGroup : undefined]}>
{channel.displayName}
</Text>
{isBot &&
<BotTag
style={styles.botContainer}
textStyle={styles.botText}
/>
}
</View>
{message}
<IntroOptions
channelId={channel.id}
header={true}
favorite={true}
people={false}
theme={theme}
/>
</View>
);
};
export default DirectChannel;

View file

@ -1,78 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {chunk} from 'lodash';
import React from 'react';
import {View} from 'react-native';
import FastImage from 'react-native-fast-image';
import {useServerUrl} from '@context/server';
import NetworkManager from '@init/network_manager';
import {makeStyleSheetFromTheme} from '@utils/theme';
import type {Client} from '@client/rest';
import type UserModel from '@typings/database/models/servers/user';
type Props = {
theme: Theme;
users: UserModel[];
}
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
container: {
alignItems: 'center',
flexDirection: 'row',
marginBottom: 12,
},
profile: {
borderColor: theme.centerChannelBg,
borderRadius: 36,
borderWidth: 2,
height: 72,
width: 72,
},
}));
const Group = ({theme, users}: Props) => {
const serverUrl = useServerUrl();
const styles = getStyleSheet(theme);
let client: Client | undefined;
try {
client = NetworkManager.getClient(serverUrl);
} catch {
return null;
}
const rows = chunk(users, 5);
const groups = rows.map((c, k) => {
const group = c.map((u, i) => {
const pictureUrl = client!.getProfilePictureUrl(u.id, u.lastPictureUpdate);
return (
<FastImage
key={pictureUrl + i.toString()}
style={[styles.profile, {transform: [{translateX: -(i * 24)}]}]}
source={{uri: `${serverUrl}${pictureUrl}`}}
/>
);
});
return (
<View
key={'group_avatar' + k.toString()}
style={[styles.container, {left: (c.length - 1) * 12}]}
>
{group}
</View>
);
});
return (
<>
{groups}
</>
);
};
export default Group;

View file

@ -1,21 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Q} from '@nozbe/watermelondb';
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {MM_TABLES} from '@constants/database';
import Group from './group';
import type {WithDatabaseArgs} from '@typings/database/database';
import type UserModel from '@typings/database/models/servers/user';
const {SERVER: {USER}} = MM_TABLES;
const enhanced = withObservables([], ({userIds, database}: {userIds: string[]} & WithDatabaseArgs) => ({
users: database.get<UserModel>(USER).query(Q.where('id', Q.oneOf(userIds))).observeWithColumns(['last_picture_update']),
}));
export default withDatabase(enhanced(Group));

View file

@ -1,45 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {of as of$} from 'rxjs';
import {catchError, switchMap} from 'rxjs/operators';
import {General} from '@constants';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {getUserIdFromChannelName} from '@utils/user';
import DirectChannel from './direct_channel';
import type {WithDatabaseArgs} from '@typings/database/database';
import type ChannelModel from '@typings/database/models/servers/channel';
import type SystemModel from '@typings/database/models/servers/system';
import type UserModel from '@typings/database/models/servers/user';
const enhanced = withObservables([], ({channel, database}: {channel: ChannelModel} & WithDatabaseArgs) => {
const currentUserId = database.get<SystemModel>(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(switchMap(({value}) => of$(value)));
const members = channel.members.observe();
let isBot = of$(false);
if (channel.type === General.DM_CHANNEL) {
isBot = currentUserId.pipe(
switchMap((userId: string) => {
const otherUserId = getUserIdFromChannelName(userId, channel.name);
return database.get<UserModel>(MM_TABLES.SERVER.USER).findAndObserve(otherUserId).pipe(
// eslint-disable-next-line max-nested-callbacks
switchMap((user) => of$(user.isBot)), // eslint-disable-next-line max-nested-callbacks
catchError(() => of$(false)),
);
}),
);
}
return {
currentUserId,
isBot,
members,
};
});
export default withDatabase(enhanced(DirectChannel));

View file

@ -1,15 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import Member from './member';
import type ChannelMembershipModel from '@typings/database/models/servers/channel_membership';
const enhanced = withObservables([], ({member}: {member: ChannelMembershipModel}) => ({
user: member.memberUser.observe(),
}));
export default withDatabase(enhanced(Member));

View file

@ -1,74 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback} from 'react';
import {useIntl} from 'react-intl';
import {StyleProp, StyleSheet, ViewStyle} from 'react-native';
import CompassIcon from '@components/compass_icon';
import ProfilePicture from '@components/profile_picture';
import TouchableWithFeedback from '@components/touchable_with_feedback';
import {Screens} from '@constants';
import {showModal} from '@screens/navigation';
import type UserModel from '@typings/database/models/servers/user';
type Props = {
containerStyle?: StyleProp<ViewStyle>;
size?: number;
showStatus?: boolean;
theme: Theme;
user: UserModel;
}
const styles = StyleSheet.create({
profile: {
height: 67,
marginBottom: 12,
marginRight: 12,
},
});
const Member = ({containerStyle, size = 72, showStatus = true, theme, user}: Props) => {
const intl = useIntl();
const onPress = useCallback(() => {
const screen = Screens.USER_PROFILE;
const title = intl.formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'});
const passProps = {
userId: user.id,
};
const closeButton = CompassIcon.getImageSourceSync('close', 24, theme.sidebarHeaderTextColor);
const options = {
topBar: {
leftButtons: [{
id: 'close-user-profile',
icon: closeButton,
testID: 'close.settings.button',
}],
},
};
showModal(screen, title, passProps, options);
}, [theme]);
return (
<TouchableWithFeedback
onPress={onPress}
style={[styles.profile, containerStyle]}
type='opacity'
>
<ProfilePicture
author={user}
size={size}
iconSize={48}
showStatus={showStatus}
statusSize={24}
testID='channel_intro.profile_picture'
/>
</TouchableWithFeedback>
);
};
export default Member;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,43 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Q} from '@nozbe/watermelondb';
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {combineLatest} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import Intro from './intro';
import type {WithDatabaseArgs} from '@typings/database/database';
import type ChannelModel from '@typings/database/models/servers/channel';
import type MyChannelModel from '@typings/database/models/servers/my_channel';
import type RoleModel from '@typings/database/models/servers/role';
import type SystemModel from '@typings/database/models/servers/system';
import type UserModel from '@typings/database/models/servers/user';
const {SERVER: {CHANNEL, MY_CHANNEL, ROLE, SYSTEM, USER}} = MM_TABLES;
const enhanced = withObservables(['channelId'], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => {
const channel = database.get<ChannelModel>(CHANNEL).findAndObserve(channelId);
const myChannel = database.get<MyChannelModel>(MY_CHANNEL).findAndObserve(channelId);
const me = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
switchMap(({value}) => database.get<UserModel>(USER).findAndObserve(value)),
);
const roles = combineLatest([me, myChannel]).pipe(
switchMap(([{roles: userRoles}, {roles: memberRoles}]) => {
const combinedRoles = userRoles.split(' ').concat(memberRoles.split(' '));
return database.get<RoleModel>(ROLE).query(Q.where('name', Q.oneOf(combinedRoles))).observe();
}),
);
return {
channel,
roles,
};
});
export default withDatabase(enhanced(Intro));

View file

@ -1,86 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useMemo} from 'react';
import {ActivityIndicator, Platform, StyleSheet, View} from 'react-native';
import {General} from '@constants';
import {useTheme} from '@context/theme';
import DirectChannel from './direct_channel';
import PublicOrPrivateChannel from './public_or_private_channel';
import TownSquare from './townsquare';
import type ChannelModel from '@typings/database/models/servers/channel';
import type RoleModel from '@typings/database/models/servers/role';
type Props = {
channel: ChannelModel;
loading?: boolean;
roles: RoleModel[];
}
const styles = StyleSheet.create({
container: {
marginVertical: 12,
overflow: 'hidden',
...Platform.select({
android: {
scaleY: -1,
},
}),
},
});
const Intro = ({channel, loading = false, roles}: Props) => {
const theme = useTheme();
const element = useMemo(() => {
if (channel.type === General.OPEN_CHANNEL && channel.name === General.DEFAULT_CHANNEL) {
return (
<TownSquare
channelId={channel.id}
displayName={channel.displayName}
roles={roles}
theme={theme}
/>
);
}
switch (channel.type) {
case General.OPEN_CHANNEL:
case General.PRIVATE_CHANNEL:
return (
<PublicOrPrivateChannel
channel={channel}
roles={roles}
theme={theme}
/>
);
default:
return (
<DirectChannel
channel={channel}
theme={theme}
/>
);
}
}, [channel, roles, theme]);
if (loading) {
return (
<ActivityIndicator
size='small'
color={theme.centerChannelColor}
style={styles.container}
/>
);
}
return (
<View style={styles.container}>
{element}
</View>
);
};
export default Intro;

View file

@ -1,38 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback} from 'react';
import {useIntl} from 'react-intl';
import {saveFavoriteChannel} from '@actions/remote/preference';
import {useServerUrl} from '@context/server';
import OptionItem from '../item';
type Props = {
channelId: string;
isFavorite: boolean;
theme: Theme;
}
const IntroFavorite = ({channelId, isFavorite, theme}: Props) => {
const {formatMessage} = useIntl();
const serverUrl = useServerUrl();
const toggleFavorite = useCallback(() => {
saveFavoriteChannel(serverUrl, channelId, !isFavorite);
}, [channelId, isFavorite]);
return (
<OptionItem
applyMargin={true}
color={isFavorite ? theme.buttonBg : undefined}
iconName={isFavorite ? 'star' : 'star-outline'}
label={formatMessage({id: 'intro.favorite', defaultMessage: 'Favorite'})}
onPress={toggleFavorite}
theme={theme}
/>
);
};
export default IntroFavorite;

View file

@ -1,29 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Q} from '@nozbe/watermelondb';
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {of as of$} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import {Preferences} from '@constants';
import {MM_TABLES} from '@constants/database';
import FavoriteItem from './favorite';
import type {WithDatabaseArgs} from '@typings/database/database';
import type PreferenceModel from '@typings/database/models/servers/preference';
const enhanced = withObservables([], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => ({
isFavorite: database.get<PreferenceModel>(MM_TABLES.SERVER.PREFERENCE).query(
Q.where('category', Preferences.CATEGORY_FAVORITE_CHANNEL),
Q.where('name', channelId),
).observeWithColumns(['value']).pipe(
switchMap((prefs) => {
return prefs.length ? of$(prefs[0].value === 'true') : of$(false);
}),
),
}));
export default withDatabase(enhanced(FavoriteItem));

View file

@ -1,86 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback} from 'react';
import {useIntl} from 'react-intl';
import {StyleSheet, View} from 'react-native';
import {Screens} from '@constants';
import {showModal} from '@screens/navigation';
import IntroFavorite from './favorite';
import OptionItem from './item';
type Props = {
channelId: string;
header?: boolean;
favorite?: boolean;
people?: boolean;
theme: Theme;
}
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
flexDirection: 'row',
marginBottom: 8,
marginTop: 28,
width: '100%',
},
});
const IntroOptions = ({channelId, header, favorite, people, theme}: Props) => {
const {formatMessage} = useIntl();
const onAddPeople = useCallback(() => {
const title = formatMessage({id: 'intro.add_people', defaultMessage: 'Add People'});
showModal(Screens.CHANNEL_ADD_PEOPLE, title, {channelId});
}, []);
const onSetHeader = useCallback(() => {
const title = formatMessage({id: 'screens.channel_edit', defaultMessage: 'Edit Channel'});
showModal(Screens.CHANNEL_EDIT, title, {channelId});
}, []);
const onDetails = useCallback(() => {
const title = formatMessage({id: 'screens.channel_details', defaultMessage: 'Channel Details'});
showModal(Screens.CHANNEL_DETAILS, title, {channelId});
}, []);
return (
<View style={styles.container}>
{people &&
<OptionItem
applyMargin={true}
iconName='account-plus-outline'
label={formatMessage({id: 'intro.add_people', defaultMessage: 'Add People'})}
onPress={onAddPeople}
theme={theme}
/>
}
{header &&
<OptionItem
applyMargin={true}
iconName='pencil-outline'
label={formatMessage({id: 'intro.set_header', defaultMessage: 'Set Header'})}
onPress={onSetHeader}
theme={theme}
/>
}
{favorite &&
<IntroFavorite
channelId={channelId}
theme={theme}
/>
}
<OptionItem
iconName='information-outline'
label={formatMessage({id: 'intro.channel_details', defaultMessage: 'Details'})}
onPress={onDetails}
theme={theme}
/>
</View>
);
};
export default IntroOptions;

View file

@ -1,88 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback} from 'react';
import {Pressable, PressableStateCallbackType, Text} from 'react-native';
import CompassIcon from '@components/compass_icon';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
type Props = {
applyMargin?: boolean;
color?: string;
iconName: string;
label: string;
onPress: () => void;
theme: Theme;
}
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
container: {
alignItems: 'center',
backgroundColor: changeOpacity(theme.centerChannelColor, 0.04),
borderRadius: 4,
height: 70,
justifyContent: 'center',
paddingHorizontal: 16,
paddingVertical: 12,
width: 112,
},
containerPressed: {
backgroundColor: changeOpacity(theme.buttonBg, 0.08),
},
label: {
marginTop: 6,
...typography('Body', 50, 'SemiBold'),
},
margin: {
marginRight: 8,
},
}));
const IntroItem = ({applyMargin, color, iconName, label, onPress, theme}: Props) => {
const styles = getStyleSheet(theme);
const pressedStyle = useCallback(({pressed}: PressableStateCallbackType) => {
const style = [styles.container];
if (pressed) {
style.push(styles.containerPressed);
}
if (applyMargin) {
style.push(styles.margin);
}
return style;
}, [applyMargin, theme]);
const renderPressableChildren = ({pressed}: PressableStateCallbackType) => {
let pressedColor = color || changeOpacity(theme.centerChannelColor, 0.56);
if (pressed) {
pressedColor = theme.linkColor;
}
return (
<>
<CompassIcon
name={iconName}
color={pressedColor}
size={24}
/>
<Text style={[styles.label, {color: pressedColor}]}>
{label}
</Text>
</>
);
};
return (
<Pressable
onPress={onPress}
style={pressedStyle}
>
{renderPressableChildren}
</Pressable>
);
};
export default IntroItem;

View file

@ -1,51 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Q} from '@nozbe/watermelondb';
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {combineLatest, of as of$} from 'rxjs';
import {map, switchMap} from 'rxjs/operators';
import {Preferences} from '@constants';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {getTeammateNameDisplaySetting} from '@helpers/api/preference';
import {displayUsername} from '@utils/user';
import PublicOrPrivateChannel from './public_or_private_channel';
import type {WithDatabaseArgs} from '@typings/database/database';
import type ChannelModel from '@typings/database/models/servers/channel';
import type PreferenceModel from '@typings/database/models/servers/preference';
import type SystemModel from '@typings/database/models/servers/system';
import type UserModel from '@typings/database/models/servers/user';
const {SERVER: {PREFERENCE, SYSTEM, USER}} = MM_TABLES;
const enhanced = withObservables([], ({channel, database}: {channel: ChannelModel} & WithDatabaseArgs) => {
let creator;
if (channel.creatorId) {
const config = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(switchMap(({value}) => of$(value as ClientConfig)));
const license = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE).pipe(switchMap(({value}) => of$(value as ClientLicense)));
const preferences = database.get<PreferenceModel>(PREFERENCE).query(Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS)).observe();
const me = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
switchMap(({value}) => database.get<UserModel>(USER).findAndObserve(value)),
);
const profile = channel.creator.observe();
const teammateNameDisplay = combineLatest([preferences, config, license]).pipe(
map(([prefs, cfg, lcs]) => getTeammateNameDisplaySetting(prefs, cfg, lcs)),
);
creator = combineLatest([profile, teammateNameDisplay, me]).pipe(
map(([user, displaySetting, currentUser]) => (user ? displayUsername(user as UserModel, currentUser.locale, displaySetting, true) : '')),
);
} else {
creator = of$(undefined);
}
return {
creator,
};
});
export default withDatabase(enhanced(PublicOrPrivateChannel));

View file

@ -1,145 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useEffect, useMemo} from 'react';
import {useIntl} from 'react-intl';
import {Text, View} from 'react-native';
import {fetchChannelCreator} from '@actions/remote/channel';
import CompassIcon from '@components/compass_icon';
import {General, Permissions} from '@constants';
import {useServerUrl} from '@context/server';
import {t} from '@i18n';
import {hasPermission} from '@utils/role';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
import PrivateChannel from '../illustration/private';
import PublicChannel from '../illustration/public';
import IntroOptions from '../options';
import type ChannelModel from '@typings/database/models/servers/channel';
import type RoleModel from '@typings/database/models/servers/role';
type Props = {
channel: ChannelModel;
creator?: string;
roles: RoleModel[];
theme: Theme;
}
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
container: {
alignItems: 'center',
},
created: {
color: changeOpacity(theme.centerChannelColor, 0.64),
...typography('Body', 50, 'Regular'),
},
icon: {
marginRight: 5,
},
message: {
color: theme.centerChannelColor,
marginTop: 16,
textAlign: 'center',
...typography('Body', 200, 'Regular'),
},
title: {
color: theme.centerChannelColor,
marginTop: 16,
marginBottom: 8,
...typography('Heading', 700, 'SemiBold'),
},
}));
const PublicOrPrivateChannel = ({channel, creator, roles, theme}: Props) => {
const intl = useIntl();
const serverUrl = useServerUrl();
const styles = getStyleSheet(theme);
const illustration = useMemo(() => {
if (channel.type === General.OPEN_CHANNEL) {
return <PublicChannel theme={theme}/>;
}
return <PrivateChannel theme={theme}/>;
}, [channel.type, theme]);
useEffect(() => {
if (!creator && channel.creatorId) {
fetchChannelCreator(serverUrl, channel.id);
}
}, []);
const canManagePeople = useMemo(() => {
const permission = channel.type === General.OPEN_CHANNEL ? Permissions.MANAGE_PUBLIC_CHANNEL_MEMBERS : Permissions.MANAGE_PRIVATE_CHANNEL_MEMBERS;
return hasPermission(roles, permission, false);
}, [channel.type, roles]);
const canSetHeader = useMemo(() => {
const permission = channel.type === General.OPEN_CHANNEL ? Permissions.MANAGE_PUBLIC_CHANNEL_PROPERTIES : Permissions.MANAGE_PRIVATE_CHANNEL_PROPERTIES;
return hasPermission(roles, permission, false);
}, [channel.type, roles]);
const createdBy = useMemo(() => {
const id = channel.type === General.OPEN_CHANNEL ? t('intro.public_channel') : t('intro.private_channel');
const defaultMessage = channel.type === General.OPEN_CHANNEL ? 'Public Channel' : 'Private Channel';
const channelType = `${intl.formatMessage({id, defaultMessage})} `;
const date = intl.formatDate(channel.createAt, {
year: 'numeric',
month: 'long',
day: 'numeric',
});
const by = intl.formatMessage({id: 'intro.created_by', defaultMessage: 'created by {creator} on {date}.'}, {
creator,
date,
});
return `${channelType} ${by}`;
}, [channel.type, creator, theme]);
const message = useMemo(() => {
const id = channel.type === General.OPEN_CHANNEL ? t('intro.welcome.public') : t('intro.welcome.private');
const msg = channel.type === General.OPEN_CHANNEL ? 'Add some more team members to the channel or start a conversation below.' : 'Only invited members can see messages posted in this private channel.';
const mainMessage = intl.formatMessage({
id: 'intro.welcome',
defaultMessage: 'Welcome to {displayName} channel.',
}, {displayName: channel.displayName});
const suffix = intl.formatMessage({id, defaultMessage: msg});
return `${mainMessage} ${suffix}`;
}, [channel.displayName, channel.type, theme]);
return (
<View style={styles.container}>
{illustration}
<Text style={styles.title}>
{channel.displayName}
</Text>
<View style={{flexDirection: 'row'}}>
<CompassIcon
name={channel.type === General.OPEN_CHANNEL ? 'globe' : 'lock'}
size={14.4}
color={changeOpacity(theme.centerChannelColor, 0.64)}
style={styles.icon}
/>
<Text style={styles.created}>
{createdBy}
</Text>
</View>
<Text style={styles.message}>
{message}
</Text>
<IntroOptions
channelId={channel.id}
header={canSetHeader}
people={canManagePeople}
theme={theme}
/>
</View>
);
};
export default PublicOrPrivateChannel;

View file

@ -1,66 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {Text, View} from 'react-native';
import FormattedText from '@components/formatted_text';
import {Permissions} from '@constants';
import {hasPermission} from '@utils/role';
import {makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
import PublicChannel from '../illustration/public';
import IntroOptions from '../options';
import type RoleModel from '@typings/database/models/servers/role';
type Props = {
channelId: string;
displayName: string;
roles: RoleModel[];
theme: Theme;
}
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
container: {
alignItems: 'center',
},
message: {
color: theme.centerChannelColor,
marginTop: 16,
textAlign: 'center',
...typography('Body', 200, 'Regular'),
width: '100%',
},
title: {
color: theme.centerChannelColor,
marginTop: 16,
...typography('Heading', 700, 'SemiBold'),
},
}));
const TownSquare = ({channelId, displayName, roles, theme}: Props) => {
const styles = getStyleSheet(theme);
return (
<View style={styles.container}>
<PublicChannel theme={theme}/>
<Text style={styles.title}>
{displayName}
</Text>
<FormattedText
defaultMessage='Welcome to {name}. Everyone automatically becomes a member of this channel when they join the team.'
id='intro.townsquare'
style={styles.message}
values={{name: displayName}}
/>
<IntroOptions
channelId={channelId}
header={hasPermission(roles, Permissions.MANAGE_PUBLIC_CHANNEL_PROPERTIES, false)}
theme={theme}
/>
</View>
);
};
export default TownSquare;