Remove duplicate intro components
This commit is contained in:
parent
3e94958ab0
commit
71d442b693
17 changed files with 0 additions and 1647 deletions
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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));
|
||||
|
|
@ -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));
|
||||
|
|
@ -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));
|
||||
|
|
@ -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
|
|
@ -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));
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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));
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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));
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
Loading…
Reference in a new issue