Merge pull request #6085 from mattermost/gekidou-fixes
[Gekidou] UI fixes
This commit is contained in:
commit
941aa9d0d0
31 changed files with 108 additions and 1706 deletions
|
|
@ -17,7 +17,7 @@ exports[`components/channel_list should render channels error 1`] = `
|
|||
"maxWidth": "100%",
|
||||
"paddingLeft": 18,
|
||||
"paddingRight": 20,
|
||||
"paddingVertical": 10,
|
||||
"paddingTop": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
|
|
@ -187,7 +187,7 @@ exports[`components/channel_list should render team error 1`] = `
|
|||
"maxWidth": "100%",
|
||||
"paddingLeft": 18,
|
||||
"paddingRight": 20,
|
||||
"paddingVertical": 10,
|
||||
"paddingTop": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ type Props = {
|
|||
isActive: boolean;
|
||||
isOwnDirectMessage: boolean;
|
||||
isMuted: boolean;
|
||||
myChannel: MyChannelModel;
|
||||
myChannel?: MyChannelModel;
|
||||
collapsed: boolean;
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ const ChannelListItem = ({channel, isActive, isOwnDirectMessage, isMuted, myChan
|
|||
const serverUrl = useServerUrl();
|
||||
|
||||
// Make it brighter if it's not muted, and highlighted or has unreads
|
||||
const bright = !isMuted && (isActive || myChannel.isUnread || myChannel.mentionsCount > 0);
|
||||
const bright = !isMuted && (isActive || (myChannel && (myChannel.isUnread || myChannel.mentionsCount > 0)));
|
||||
|
||||
const sharedValue = useSharedValue(collapsed && !bright);
|
||||
|
||||
|
|
@ -92,7 +92,11 @@ const ChannelListItem = ({channel, isActive, isOwnDirectMessage, isMuted, myChan
|
|||
};
|
||||
});
|
||||
|
||||
const switchChannels = () => switchToChannelById(serverUrl, myChannel.id);
|
||||
const switchChannels = () => {
|
||||
if (myChannel) {
|
||||
switchToChannelById(serverUrl, myChannel.id);
|
||||
}
|
||||
};
|
||||
const membersCount = useMemo(() => {
|
||||
if (channel.type === General.GM_CHANNEL) {
|
||||
return channel.displayName?.split(',').length;
|
||||
|
|
@ -112,7 +116,7 @@ const ChannelListItem = ({channel, isActive, isOwnDirectMessage, isMuted, myChan
|
|||
displayName = formatMessage({id: 'channel_header.directchannel.you', defaultMessage: '{displayName} (you)'}, {displayName});
|
||||
}
|
||||
|
||||
if (channel.deleteAt > 0 && !isActive) {
|
||||
if ((channel.deleteAt > 0 && !isActive) || !myChannel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ import {getUserIdFromChannelName} from '@utils/user';
|
|||
import ChannelListItem from './channel_list_item';
|
||||
|
||||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type MyChannelSettingsModel from '@typings/database/models/servers/my_channel_settings';
|
||||
|
||||
const enhance = withObservables(['channelId'], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => {
|
||||
const myChannel = observeMyChannel(database, channelId);
|
||||
|
|
@ -37,16 +35,16 @@ const enhance = withObservables(['channelId'], ({channelId, database}: {channelI
|
|||
return {
|
||||
isOwnDirectMessage,
|
||||
isMuted: settings.pipe(
|
||||
switchMap((s: MyChannelSettingsModel) => of$(s.notifyProps?.mark_unread === 'mention')),
|
||||
switchMap((s) => of$(s?.notifyProps?.mark_unread === 'mention')),
|
||||
),
|
||||
myChannel,
|
||||
channel: channel.pipe(
|
||||
switchMap((c: ChannelModel) => of$({
|
||||
deleteAt: c.deleteAt,
|
||||
displayName: c.displayName,
|
||||
name: c.name,
|
||||
shared: c.shared,
|
||||
type: c.type,
|
||||
switchMap((c) => of$({
|
||||
deleteAt: c?.deleteAt || 0,
|
||||
displayName: c?.displayName || '',
|
||||
name: c?.name || '',
|
||||
shared: c?.shared || false,
|
||||
type: c?.type || '',
|
||||
})),
|
||||
),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useCallback} from 'react';
|
||||
import React, {useCallback, useEffect, useRef} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {FlatList, StyleSheet} from 'react-native';
|
||||
|
||||
|
|
@ -9,12 +9,13 @@ import CategoryBody from './body';
|
|||
import LoadCategoriesError from './error';
|
||||
import CategoryHeader from './header';
|
||||
|
||||
import type {CategoryModel} from '@database/models/server';
|
||||
import type CategoryModel from '@typings/database/models/servers/category';
|
||||
|
||||
type Props = {
|
||||
categories: CategoryModel[];
|
||||
currentChannelId: string;
|
||||
currentUserId: string;
|
||||
currentTeamId: string;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
|
@ -25,8 +26,9 @@ const styles = StyleSheet.create({
|
|||
|
||||
const extractKey = (item: CategoryModel) => item.id;
|
||||
|
||||
const Categories = ({categories, currentChannelId, currentUserId}: Props) => {
|
||||
const Categories = ({categories, currentChannelId, currentUserId, currentTeamId}: Props) => {
|
||||
const intl = useIntl();
|
||||
const listRef = useRef<FlatList>(null);
|
||||
|
||||
const renderCategory = useCallback((data: {item: CategoryModel}) => {
|
||||
return (
|
||||
|
|
@ -42,6 +44,10 @@ const Categories = ({categories, currentChannelId, currentUserId}: Props) => {
|
|||
);
|
||||
}, [categories, currentChannelId, intl.locale]);
|
||||
|
||||
useEffect(() => {
|
||||
listRef.current?.scrollToOffset({animated: false, offset: 0});
|
||||
}, [currentTeamId]);
|
||||
|
||||
// Sort Categories
|
||||
categories.sort((a, b) => a.sortOrder - b.sortOrder);
|
||||
|
||||
|
|
@ -52,6 +58,7 @@ const Categories = ({categories, currentChannelId, currentUserId}: Props) => {
|
|||
return (
|
||||
<FlatList
|
||||
data={categories}
|
||||
ref={listRef}
|
||||
renderItem={renderCategory}
|
||||
style={styles.flex}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
|||
backgroundColor: theme.sidebarBg,
|
||||
paddingLeft: 18,
|
||||
paddingRight: 20,
|
||||
paddingVertical: 10,
|
||||
paddingTop: 10,
|
||||
},
|
||||
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ const PostList = ({
|
|||
<ThreadOverview
|
||||
rootId={rootId!}
|
||||
testID={`${testID}.thread_overview`}
|
||||
style={styles.scale}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -312,11 +313,11 @@ const PostList = ({
|
|||
);
|
||||
}, [currentTimezone, highlightPinnedOrSaved, isTimezoneEnabled, orderedPosts, shouldRenderReplyButton, theme]);
|
||||
|
||||
const scrollToIndex = useCallback((index: number, animated = true) => {
|
||||
const scrollToIndex = useCallback((index: number, animated = true, applyOffset = true) => {
|
||||
listRef.current?.scrollToIndex({
|
||||
animated,
|
||||
index,
|
||||
viewOffset: 0,
|
||||
viewOffset: applyOffset ? Platform.select({ios: -45, default: 0}) : 0,
|
||||
viewPosition: 1, // 0 is at bottom
|
||||
});
|
||||
}, []);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
|
||||
import {ActivityIndicator, DeviceEventEmitter, View, ViewToken} from 'react-native';
|
||||
import {ActivityIndicator, DeviceEventEmitter, Platform, View, ViewToken} from 'react-native';
|
||||
import Animated, {interpolate, useAnimatedStyle, useSharedValue, withSpring} from 'react-native-reanimated';
|
||||
|
||||
import {resetMessageCount} from '@actions/local/channel';
|
||||
|
|
@ -23,14 +23,14 @@ type Props = {
|
|||
posts: Array<string | PostModel>;
|
||||
registerScrollEndIndexListener: (fn: (endIndex: number) => void) => () => void;
|
||||
registerViewableItemsListener: (fn: (viewableItems: ViewToken[]) => void) => () => void;
|
||||
scrollToIndex: (index: number, animated?: boolean) => void;
|
||||
scrollToIndex: (index: number, animated?: boolean, applyOffset?: boolean) => void;
|
||||
unreadCount: number;
|
||||
theme: Theme;
|
||||
testID: string;
|
||||
}
|
||||
|
||||
const HIDDEN_TOP = -60;
|
||||
const SHOWN_TOP = 0;
|
||||
const SHOWN_TOP = Platform.select({ios: 40, default: 0});
|
||||
const MIN_INPUT = 0;
|
||||
const MAX_INPUT = 1;
|
||||
|
||||
|
|
@ -103,6 +103,7 @@ const MoreMessages = ({
|
|||
const serverUrl = useServerUrl();
|
||||
const pressed = useRef(false);
|
||||
const resetting = useRef(false);
|
||||
const initialScroll = useRef(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [remaining, setRemaining] = useState(0);
|
||||
const underlayColor = useMemo(() => `hsl(${hexToHue(theme.buttonBg)}, 50%, 38%)`, [theme]);
|
||||
|
|
@ -149,13 +150,14 @@ const MoreMessages = ({
|
|||
|
||||
const lastViewableIndex = viewableItems.filter((v) => v.isViewable)[viewableItems.length - 1]?.index || 0;
|
||||
const nextViewableIndex = lastViewableIndex + 1;
|
||||
if (viewableItems[0].index === 0 && nextViewableIndex > newMessageLineIndex) {
|
||||
if (viewableItems[0].index === 0 && nextViewableIndex > newMessageLineIndex && !initialScroll.current) {
|
||||
// Auto scroll if the first post is viewable and
|
||||
// * the new message line is viewable OR
|
||||
// * the new message line will be the first next viewable item
|
||||
scrollToIndex(newMessageLineIndex, true);
|
||||
scrollToIndex(newMessageLineIndex, true, false);
|
||||
resetCount();
|
||||
top.value = 0;
|
||||
initialScroll.current = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -212,6 +214,7 @@ const MoreMessages = ({
|
|||
|
||||
useEffect(() => {
|
||||
resetting.current = false;
|
||||
initialScroll.current = false;
|
||||
}, [channelId]);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
|
|||
flexDirection: 'column',
|
||||
},
|
||||
rightColumnPadding: {paddingBottom: 3},
|
||||
touchableContainer: {marginHorizontal: -20, paddingHorizontal: 20},
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -274,6 +275,7 @@ const Post = ({
|
|||
onPress={handlePress}
|
||||
onLongPress={showPostOptions}
|
||||
underlayColor={changeOpacity(theme.centerChannelColor, 0.1)}
|
||||
style={styles.touchableContainer}
|
||||
>
|
||||
<>
|
||||
<PreHeader
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ exports[`ThreadOverview should match snapshot when post is not saved and 0 repli
|
|||
Object {
|
||||
"borderBottomWidth": 0,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
testID="thread-overview"
|
||||
|
|
@ -120,6 +121,7 @@ exports[`ThreadOverview should match snapshot when post is saved and has replies
|
|||
"paddingHorizontal": 20,
|
||||
"paddingVertical": 10,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
testID="thread-overview"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import React, {useCallback, useMemo} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {Keyboard, Platform, View} from 'react-native';
|
||||
import {Keyboard, Platform, StyleProp, View, ViewStyle} from 'react-native';
|
||||
import {TouchableOpacity} from 'react-native-gesture-handler';
|
||||
|
||||
import {deleteSavedPost, savePostPreference} from '@actions/remote/preference';
|
||||
|
|
@ -25,6 +25,7 @@ type Props = {
|
|||
repliesCount: number;
|
||||
rootPost?: PostModel;
|
||||
testID: string;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
};
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
|
||||
|
|
@ -55,7 +56,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
|
|||
};
|
||||
});
|
||||
|
||||
const ThreadOverview = ({isSaved, repliesCount, rootPost, testID}: Props) => {
|
||||
const ThreadOverview = ({isSaved, repliesCount, rootPost, style, testID}: Props) => {
|
||||
const theme = useTheme();
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
|
|
@ -85,14 +86,15 @@ const ThreadOverview = ({isSaved, repliesCount, rootPost, testID}: Props) => {
|
|||
}), [rootPost]);
|
||||
|
||||
const containerStyle = useMemo(() => {
|
||||
const style = [styles.container];
|
||||
const container = [styles.container];
|
||||
if (repliesCount === 0) {
|
||||
style.push({
|
||||
container.push({
|
||||
borderBottomWidth: 0,
|
||||
});
|
||||
}
|
||||
return style;
|
||||
}, [repliesCount]);
|
||||
container.push(style);
|
||||
return container;
|
||||
}, [repliesCount, style]);
|
||||
|
||||
return (
|
||||
<View
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ const PostHandler = (superclass: any) => class extends superclass {
|
|||
|
||||
const emojis: CustomEmoji[] = [];
|
||||
const files: FileInfo[] = [];
|
||||
const metadatas: Metadata[] = [];
|
||||
const postsReactions: ReactionsPerPost[] = [];
|
||||
const pendingPostsToDelete: Post[] = [];
|
||||
const postsInThread: Record<string, Post[]> = {};
|
||||
|
|
@ -193,12 +192,6 @@ const PostHandler = (superclass: any) => class extends superclass {
|
|||
batch.push(...postFiles);
|
||||
}
|
||||
|
||||
if (metadatas.length) {
|
||||
// calls handler for postMetadata ( embeds and images )
|
||||
const postMetadata = await this.handlePostMetadata({metadatas, prepareRecordsOnly: true});
|
||||
batch.push(...postMetadata);
|
||||
}
|
||||
|
||||
if (emojis.length) {
|
||||
const postEmojis = await this.handleCustomEmojis({emojis, prepareRecordsOnly: true});
|
||||
batch.push(...postEmojis);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export const transformChannelRecord = ({action, database, value}: TransformerArg
|
|||
const rawMembers = raw.display_name.split(',').length;
|
||||
const recordMembers = record?.displayName.split(',').length || rawMembers;
|
||||
|
||||
if (recordMembers < rawMembers) {
|
||||
if (recordMembers < rawMembers && record.displayName) {
|
||||
displayName = record.displayName;
|
||||
} else {
|
||||
displayName = raw.display_name;
|
||||
|
|
|
|||
|
|
@ -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,17 +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 {queryUsersById} from '@queries/servers/user';
|
||||
|
||||
import Group from './group';
|
||||
|
||||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
|
||||
const enhanced = withObservables([], ({userIds, database}: {userIds: string[]} & WithDatabaseArgs) => ({
|
||||
users: queryUsersById(database, 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 {switchMap} from 'rxjs/operators';
|
||||
|
||||
import {General} from '@constants';
|
||||
import {observeCurrentUserId} from '@queries/servers/system';
|
||||
import {observeUser} from '@queries/servers/user';
|
||||
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 UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
const observeIsBot = (user: UserModel | undefined) => of$(Boolean(user?.isBot));
|
||||
|
||||
const enhanced = withObservables([], ({channel, database}: {channel: ChannelModel} & WithDatabaseArgs) => {
|
||||
const currentUserId = observeCurrentUserId(database);
|
||||
const members = channel.members.observe();
|
||||
let isBot = of$(false);
|
||||
|
||||
if (channel.type === General.DM_CHANNEL) {
|
||||
isBot = currentUserId.pipe(
|
||||
switchMap((userId) => {
|
||||
const otherUserId = getUserIdFromChannelName(userId, channel.name);
|
||||
return observeUser(database, otherUserId).pipe(
|
||||
switchMap(observeIsBot),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
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 {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
||||
import withObservables from '@nozbe/with-observables';
|
||||
import {combineLatest} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
|
||||
import {observeChannel, observeMyChannel} from '@queries/servers/channel';
|
||||
import {queryRolesByNames} from '@queries/servers/role';
|
||||
import {observeCurrentUser} from '@queries/servers/user';
|
||||
|
||||
import Intro from './intro';
|
||||
|
||||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
|
||||
const enhanced = withObservables(['channelId'], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => {
|
||||
const channel = observeChannel(database, channelId);
|
||||
const myChannel = observeMyChannel(database, channelId);
|
||||
const me = observeCurrentUser(database);
|
||||
|
||||
const roles = combineLatest([me, myChannel]).pipe(
|
||||
switchMap(([user, member]) => {
|
||||
const userRoles = user?.roles.split(' ');
|
||||
const memberRoles = member?.roles.split(' ');
|
||||
const combinedRoles = [];
|
||||
if (userRoles) {
|
||||
combinedRoles.push(...userRoles);
|
||||
}
|
||||
if (memberRoles) {
|
||||
combinedRoles.push(...memberRoles);
|
||||
}
|
||||
return queryRolesByNames(database, 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,24 +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 {switchMap} from 'rxjs/operators';
|
||||
|
||||
import {Preferences} from '@constants';
|
||||
import {queryPreferencesByCategoryAndName} from '@queries/servers/preference';
|
||||
|
||||
import FavoriteItem from './favorite';
|
||||
|
||||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
|
||||
const enhanced = withObservables([], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => ({
|
||||
isFavorite: queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_FAVORITE_CHANNEL, 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,46 +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 {combineLatest, of as of$} from 'rxjs';
|
||||
import {map} from 'rxjs/operators';
|
||||
|
||||
import {Preferences} from '@constants';
|
||||
import {getTeammateNameDisplaySetting} from '@helpers/api/preference';
|
||||
import {queryPreferencesByCategoryAndName} from '@queries/servers/preference';
|
||||
import {observeConfig, observeLicense} from '@queries/servers/system';
|
||||
import {observeCurrentUser} from '@queries/servers/user';
|
||||
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 UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
const enhanced = withObservables([], ({channel, database}: {channel: ChannelModel} & WithDatabaseArgs) => {
|
||||
let creator;
|
||||
if (channel.creatorId) {
|
||||
const config = observeConfig(database);
|
||||
const license = observeLicense(database);
|
||||
const preferences = queryPreferencesByCategoryAndName(database, Preferences.CATEGORY_DISPLAY_SETTINGS).observe();
|
||||
const me = observeCurrentUser(database);
|
||||
|
||||
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;
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useMemo} from 'react';
|
||||
import {StyleSheet} from 'react-native';
|
||||
import {StyleSheet, View} from 'react-native';
|
||||
import {Edge, SafeAreaView} from 'react-native-safe-area-context';
|
||||
|
||||
import PostList from '@components/post_list';
|
||||
|
|
@ -25,8 +25,9 @@ type Props = {
|
|||
const edges: Edge[] = ['bottom'];
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {marginTop: 20},
|
||||
container: {marginTop: 10},
|
||||
flex: {flex: 1},
|
||||
footer: {height: 20},
|
||||
});
|
||||
|
||||
const ThreadPostList = ({
|
||||
|
|
@ -54,6 +55,7 @@ const ThreadPostList = ({
|
|||
shouldShowJoinLeaveMessages={false}
|
||||
showMoreMessages={false}
|
||||
showNewMessageLine={false}
|
||||
footer={<View style={styles.footer}/>}
|
||||
testID='thread.post_list'
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
83
package-lock.json
generated
83
package-lock.json
generated
|
|
@ -5,7 +5,6 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mattermost-mobile",
|
||||
"version": "2.0.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache 2.0",
|
||||
|
|
@ -4262,7 +4261,7 @@
|
|||
"integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
|
||||
"dependencies": {
|
||||
"@jest/types": "^26.6.2",
|
||||
"ansi-regex": "^5.0.1",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"ansi-styles": "^4.0.0",
|
||||
"react-is": "^17.0.1"
|
||||
},
|
||||
|
|
@ -4304,7 +4303,7 @@
|
|||
"chalk": "^4.1.2",
|
||||
"lodash": "^4.17.15",
|
||||
"mime": "^2.4.1",
|
||||
"node-fetch": "^2.6.7",
|
||||
"node-fetch": "^2.6.0",
|
||||
"open": "^6.2.0",
|
||||
"semver": "^6.3.0",
|
||||
"shell-quote": "1.6.1"
|
||||
|
|
@ -4606,7 +4605,7 @@
|
|||
"integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
|
||||
"dependencies": {
|
||||
"@jest/types": "^26.6.2",
|
||||
"ansi-regex": "^5.0.1",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"ansi-styles": "^4.0.0",
|
||||
"react-is": "^17.0.1"
|
||||
},
|
||||
|
|
@ -4883,6 +4882,7 @@
|
|||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/masked-view/-/masked-view-0.1.11.tgz",
|
||||
"integrity": "sha512-rQfMIGSR/1r/SyN87+VD8xHHzDYeHaJq6elOSCAD+0iLagXkSI2pfA0LmSXP21uw5i3em7GkkRjfJ8wpqWXZNw==",
|
||||
"deprecated": "Repository was moved to @react-native-masked-view/masked-view",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.0",
|
||||
"react-native": ">=0.57"
|
||||
|
|
@ -5037,7 +5037,7 @@
|
|||
"dependencies": {
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"mkdirp": "^0.5.5",
|
||||
"node-fetch": "^2.6.7",
|
||||
"node-fetch": "^2.6.0",
|
||||
"npmlog": "^4.1.2",
|
||||
"progress": "^2.0.3",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
|
|
@ -8644,7 +8644,6 @@
|
|||
"node_modules/commonmark-react-renderer": {
|
||||
"version": "4.3.5",
|
||||
"resolved": "git+ssh://git@github.com/mattermost/commonmark-react-renderer.git#4e52e1725c0ef5b1e2ecfe9883220ec36c2eb67d",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash.assign": "^4.2.0",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
|
|
@ -8833,7 +8832,7 @@
|
|||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
|
||||
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=",
|
||||
"deprecated": "core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js."
|
||||
"deprecated": "core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js."
|
||||
},
|
||||
"node_modules/core-js-compat": {
|
||||
"version": "3.20.3",
|
||||
|
|
@ -13444,7 +13443,7 @@
|
|||
"integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.7",
|
||||
"node-fetch": "^2.6.1",
|
||||
"whatwg-fetch": "^3.4.1"
|
||||
}
|
||||
},
|
||||
|
|
@ -16560,7 +16559,7 @@
|
|||
"integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
|
||||
"dependencies": {
|
||||
"@jest/types": "^26.6.2",
|
||||
"ansi-regex": "^5.0.1",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"ansi-styles": "^4.0.0",
|
||||
"react-is": "^17.0.1"
|
||||
},
|
||||
|
|
@ -17599,9 +17598,8 @@
|
|||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz"
|
||||
},
|
||||
"node_modules/mississippi": {
|
||||
"version": "3.0.0",
|
||||
|
|
@ -17667,11 +17665,13 @@
|
|||
"node_modules/mmjstool/node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/mmjstool/node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
|
|
@ -17680,6 +17680,7 @@
|
|||
"node_modules/mmjstool/node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
|
|
@ -17693,6 +17694,7 @@
|
|||
"node_modules/mmjstool/node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
|
|
@ -17701,6 +17703,7 @@
|
|||
"node_modules/mmjstool/node_modules/yargs": {
|
||||
"version": "17.3.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz",
|
||||
"integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cliui": "^7.0.2",
|
||||
|
|
@ -17718,6 +17721,7 @@
|
|||
"node_modules/mmjstool/node_modules/yargs-parser": {
|
||||
"version": "21.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
|
||||
"integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
|
|
@ -18204,11 +18208,20 @@
|
|||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch/node_modules/tr46": {
|
||||
|
|
@ -19129,9 +19142,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/plist": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz",
|
||||
"integrity": "sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg==",
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz",
|
||||
"integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.5.1",
|
||||
"xmlbuilder": "^9.0.7"
|
||||
|
|
@ -20233,7 +20246,7 @@
|
|||
"integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
|
||||
"dependencies": {
|
||||
"@jest/types": "^26.6.2",
|
||||
"ansi-regex": "^5.0.1",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"ansi-styles": "^4.0.0",
|
||||
"react-is": "^17.0.1"
|
||||
},
|
||||
|
|
@ -21666,6 +21679,7 @@
|
|||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
|
||||
"integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
|
||||
"deprecated": "See https://github.com/lydell/source-map-resolve#deprecated",
|
||||
"dependencies": {
|
||||
"atob": "^2.1.2",
|
||||
"decode-uri-component": "^0.2.0",
|
||||
|
|
@ -21694,7 +21708,8 @@
|
|||
"node_modules/source-map-url": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
|
||||
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw=="
|
||||
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
|
||||
"deprecated": "See https://github.com/lydell/source-map-url#deprecated"
|
||||
},
|
||||
"node_modules/split-on-first": {
|
||||
"version": "1.1.0",
|
||||
|
|
@ -23503,7 +23518,7 @@
|
|||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
|
||||
"integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
|
||||
"deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.",
|
||||
"deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
|
|
@ -27223,7 +27238,7 @@
|
|||
"integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
|
||||
"requires": {
|
||||
"@jest/types": "^26.6.2",
|
||||
"ansi-regex": "^5.0.1",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"ansi-styles": "^4.0.0",
|
||||
"react-is": "^17.0.1"
|
||||
}
|
||||
|
|
@ -27658,7 +27673,7 @@
|
|||
"integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
|
||||
"requires": {
|
||||
"@jest/types": "^26.6.2",
|
||||
"ansi-regex": "^5.0.1",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"ansi-styles": "^4.0.0",
|
||||
"react-is": "^17.0.1"
|
||||
}
|
||||
|
|
@ -27696,7 +27711,7 @@
|
|||
"chalk": "^4.1.2",
|
||||
"lodash": "^4.17.15",
|
||||
"mime": "^2.4.1",
|
||||
"node-fetch": "^2.6.7",
|
||||
"node-fetch": "^2.6.0",
|
||||
"open": "^6.2.0",
|
||||
"semver": "^6.3.0",
|
||||
"shell-quote": "1.6.1"
|
||||
|
|
@ -28055,7 +28070,7 @@
|
|||
"requires": {
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"mkdirp": "^0.5.5",
|
||||
"node-fetch": "^2.6.7",
|
||||
"node-fetch": "^2.6.0",
|
||||
"npmlog": "^4.1.2",
|
||||
"progress": "^2.0.3",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
|
|
@ -34584,7 +34599,7 @@
|
|||
"integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"node-fetch": "^2.6.7",
|
||||
"node-fetch": "^2.6.1",
|
||||
"whatwg-fetch": "^3.4.1"
|
||||
}
|
||||
},
|
||||
|
|
@ -37326,7 +37341,7 @@
|
|||
"integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
|
||||
"requires": {
|
||||
"@jest/types": "^26.6.2",
|
||||
"ansi-regex": "^5.0.1",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"ansi-styles": "^4.0.0",
|
||||
"react-is": "^17.0.1"
|
||||
}
|
||||
|
|
@ -37887,9 +37902,8 @@
|
|||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz"
|
||||
},
|
||||
"mississippi": {
|
||||
"version": "3.0.0",
|
||||
|
|
@ -37943,16 +37957,19 @@
|
|||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
|
|
@ -37963,11 +37980,13 @@
|
|||
"y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "17.3.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz",
|
||||
"integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cliui": "^7.0.2",
|
||||
|
|
@ -37982,6 +38001,7 @@
|
|||
"yargs-parser": {
|
||||
"version": "21.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
|
||||
"integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
|
@ -38361,6 +38381,7 @@
|
|||
"node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
|
|
@ -39076,9 +39097,9 @@
|
|||
}
|
||||
},
|
||||
"plist": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz",
|
||||
"integrity": "sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg==",
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz",
|
||||
"integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==",
|
||||
"requires": {
|
||||
"base64-js": "^1.5.1",
|
||||
"xmlbuilder": "^9.0.7"
|
||||
|
|
@ -39551,7 +39572,7 @@
|
|||
"integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
|
||||
"requires": {
|
||||
"@jest/types": "^26.6.2",
|
||||
"ansi-regex": "^5.0.1",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"ansi-styles": "^4.0.0",
|
||||
"react-is": "^17.0.1"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue