Skip to content

Commit

Permalink
MM-36721 [GEKIDOU] Porting Channel Nav Bar (#5550)
Browse files Browse the repository at this point in the history
* MM_36721 : Added testscript for AppVersion component + Corrected imported Type definition

* Added CompassIcon component

* Adding TextProps to FormattedText component

* Added status bar component

* Added User status component

* Added ProfilePicture, did_update hook and sorted imports

* Added ChannelIcon component

* Added ChannelTitle component

* Added Channel Nav Bar component

* Added channel screen

* Added withSafeAreaInsets HOC and Added font compassIcon to Xcode

* Fix Android crashes as it is looking for MainSidebar and SettingsSidebar

* Revert "Fix Android crashes as it is looking for MainSidebar and SettingsSidebar"

This reverts commit 62ea11a.

* Channel Icon clean up

* Updated assets/compass-icons files

* Updated channel title component

* ProfilePicture - Code clean up

* UserStatus component - cleaned

* Channel screen fix

* Fix TS issue

* Update index.tsx

* Removed ProfilePicture component

To be added when needed

* Removed UserStatus component

* Added IS_LANDSCAPE constant

* Code review correction

* Fix ts issue

* Added channel.displayName to reinforce security for findAndObserve on potential null teammate profile

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>

* Fix observation on array vs single element

* Refactored ChannelTitle component

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>

* Refactored ChannelGuestLabel

* Refactored ChannelDisplayName

* ChannelTitle cleaned up

* Fix roles check

* Removing unused user utils

* Minor clean up

* Fix TS issue

* Code Refactored.

* Fix render bug in channel_display_name

* Added logout button

* refactored code

Co-authored-by: Avinash Lingaloo <>
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
  • Loading branch information
avinashlng1080 and enahum authored Jul 22, 2021
1 parent 324dbbd commit 64c1158
Show file tree
Hide file tree
Showing 27 changed files with 988 additions and 100 deletions.
Binary file modified android/app/src/main/assets/fonts/compass-icons.ttf
Binary file not shown.
7 changes: 4 additions & 3 deletions app/actions/local/timezone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {getTimeZone} from 'react-native-localize';
import DatabaseManager from '@database/manager';
import {queryUserById} from '@queries/servers/user';
import {updateMe} from '@actions/remote/user';
import User from '@typings/database/models/servers/user';

import type UserModel from '@typings/database/models/servers/user';

export const isTimezoneEnabled = (config: Partial<ClientConfig>) => {
return config?.ExperimentalTimezone === 'true';
Expand All @@ -33,13 +34,13 @@ export const autoUpdateTimezone = async (serverUrl: string, {deviceTimezone, use

if (currentTimezone.useAutomaticTimezone && newTimezoneExists) {
const timezone = {useAutomaticTimezone: 'true', automaticTimezone: deviceTimezone, manualTimezone: currentTimezone.manualTimezone};
const updatedUser = {...currentUser, timezone} as User;
const updatedUser = {...currentUser, timezone} as UserModel;
await updateMe(serverUrl, updatedUser);
}
return null;
};

export const getUserTimezone = (currentUser: User) => {
export const getUserTimezone = (currentUser: UserModel) => {
if (currentUser?.timezone) {
return {
...currentUser?.timezone,
Expand Down
26 changes: 26 additions & 0 deletions app/components/app_version/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`@components/app_version should match snapshot 1`] = `
<View
pointerEvents="none"
>
<View
style={
Object {
"alignItems": "center",
"justifyContent": "flex-end",
}
}
>
<Text
style={
Object {
"fontSize": 12,
}
}
>
App Version: 0.0.0 (Build 0)
</Text>
</View>
</View>
`;
15 changes: 15 additions & 0 deletions app/components/app_version/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React from 'react';

import {renderWithIntl} from '@test/intl-test-helper';

import AppVersion from './index';

describe('@components/app_version', () => {
it('should match snapshot', () => {
const wrapper = renderWithIntl(<AppVersion/>);
expect(wrapper.toJSON()).toMatchSnapshot();
});
});
186 changes: 186 additions & 0 deletions app/components/channel_icon/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React from 'react';
import {StyleProp, Text, View, ViewStyle} from 'react-native';

import CompassIcon from '@components/compass_icon';
import General from '@constants/general';
import {useTheme} from '@context/theme';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';

type ChannelIconProps = {
hasDraft?: boolean;
isActive?: boolean;
isArchived?: boolean;
isInfo?: boolean;
isUnread?: boolean;
membersCount?: number;
shared: boolean;
size?: number;
style?: StyleProp<ViewStyle>;
testID?: string;
type: string;
};

const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
return {
container: {
alignItems: 'center',
justifyContent: 'center',
},
icon: {
color: changeOpacity(theme.sidebarText, 0.4),
},
iconActive: {
color: theme.sidebarTextActiveColor,
},
iconUnread: {
color: theme.sidebarUnreadText,
},
iconInfo: {
color: theme.centerChannelColor,
},
groupBox: {
alignItems: 'center',
backgroundColor: changeOpacity(theme.sidebarText, 0.16),
borderRadius: 4,
justifyContent: 'center',
},
groupBoxActive: {
backgroundColor: changeOpacity(theme.sidebarTextActiveColor, 0.3),
},
groupBoxUnread: {
backgroundColor: changeOpacity(theme.sidebarUnreadText, 0.3),
},
groupBoxInfo: {
backgroundColor: changeOpacity(theme.centerChannelColor, 0.3),
},
group: {
color: theme.sidebarText,
fontSize: 10,
fontWeight: '600',
},
groupActive: {
color: theme.sidebarTextActiveColor,
},
groupUnread: {
color: theme.sidebarUnreadText,
},
groupInfo: {
color: theme.centerChannelColor,
},
};
});

const ChannelIcon = ({
hasDraft = false,
isActive = false,
isArchived = false,
isInfo = false,
isUnread = false,
membersCount = 0,
shared,
size = 12,
style,
testID,
type,
}: ChannelIconProps) => {
const theme = useTheme();
const styles = getStyleSheet(theme);

let activeIcon;
let unreadIcon;
let activeGroupBox;
let unreadGroupBox;
let activeGroup;
let unreadGroup;

if (isUnread) {
unreadIcon = styles.iconUnread;
unreadGroupBox = styles.groupBoxUnread;
unreadGroup = styles.groupUnread;
}

if (isActive) {
activeIcon = styles.iconActive;
activeGroupBox = styles.groupBoxActive;
activeGroup = styles.groupActive;
}

if (isInfo) {
activeIcon = styles.iconInfo;
activeGroupBox = styles.groupBoxInfo;
activeGroup = styles.groupInfo;
}

let icon;
if (isArchived) {
icon = (
<CompassIcon
name='archive-outline'
style={[styles.icon, unreadIcon, activeIcon, {fontSize: size, left: 1}]}
testID={`${testID}.archive`}
/>
);
} else if (hasDraft) {
icon = (
<CompassIcon
name='pencil-outline'
style={[styles.icon, unreadIcon, activeIcon, {fontSize: size, left: 2}]}
testID={`${testID}.draft`}
/>
);
} else if (shared) {
const iconName = type === General.PRIVATE_CHANNEL ? 'circle-multiple-outline-lock' : 'circle-multiple-outline';
const sharedTestID = type === General.PRIVATE_CHANNEL ? 'channel_icon.shared_private' : 'channel_icon.shared_open';
icon = (
<CompassIcon
name={iconName}
style={[styles.icon, unreadIcon, activeIcon, {fontSize: size, left: 0.5}]}
testID={sharedTestID}
/>
);
} else if (type === General.OPEN_CHANNEL) {
icon = (
<CompassIcon
name='globe'
style={[styles.icon, unreadIcon, activeIcon, {fontSize: size, left: 1}]}
testID={`${testID}.public`}
/>
);
} else if (type === General.PRIVATE_CHANNEL) {
icon = (
<CompassIcon
name='lock-outline'
style={[styles.icon, unreadIcon, activeIcon, {fontSize: size, left: 0.5}]}
testID={`${testID}.private`}
/>
);
} else if (type === General.GM_CHANNEL) {
const fontSize = size - 12;
const boxSize = size - 4;
icon = (
<View
style={[styles.groupBox, unreadGroupBox, activeGroupBox, {width: boxSize, height: boxSize}]}
>
<Text
style={[styles.group, unreadGroup, activeGroup, {fontSize}]}
testID={`${testID}.gm_member_count`}
>
{membersCount}
</Text>
</View>
);
} else if (type === General.DM_CHANNEL) {
//todo: Implement ProfilePicture component
}

return (
<View style={[styles.container, {width: size, height: size}, style]}>
{icon}
</View>
);
};

export default ChannelIcon;
8 changes: 8 additions & 0 deletions app/components/compass_icon/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import {createIconSetFromFontello} from 'react-native-vector-icons';

import fontelloConfig from '@assets/compass-icons.json';

export default createIconSetFromFontello(fontelloConfig, 'compass-icons', 'compass-icons.ttf');
1 change: 1 addition & 0 deletions app/components/error_text/error_text.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import React from 'react';
import {render} from '@testing-library/react-native';

import {Preferences} from '@constants';

import ErrorText from './index';
Expand Down
4 changes: 2 additions & 2 deletions app/components/formatted_text/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// See LICENSE.txt for license information.

import {createElement, isValidElement} from 'react';
import {StyleProp, Text, TextStyle, ViewStyle} from 'react-native';
import {StyleProp, Text, TextProps, TextStyle, ViewStyle} from 'react-native';
import {useIntl} from 'react-intl';

type FormattedTextProps = {
type FormattedTextProps = TextProps & {
id: string;
defaultMessage: string;
values?: Record<string, any>;
Expand Down
23 changes: 23 additions & 0 deletions app/components/status_bar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React from 'react';
import {Platform, StatusBar as NativeStatusBar, StatusBarStyle} from 'react-native';
import tinyColor from 'tinycolor2';

type StatusBarProps = {
theme: Theme;
headerColor?: string;
};

const StatusBar = ({theme, headerColor}: StatusBarProps) => {
const headerBarStyle = tinyColor(headerColor ?? theme.sidebarHeaderBg);
let barStyle: StatusBarStyle = 'light-content';
if (headerBarStyle.isLight() && Platform.OS === 'ios') {
barStyle = 'dark-content';
}

return <NativeStatusBar barStyle={barStyle}/>;
};

export default StatusBar;
9 changes: 6 additions & 3 deletions app/constants/device.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import {Platform} from 'react-native';
import {FileSystem} from 'react-native-unimodules';
import DeviceInfo from 'react-native-device-info';

import keyMirror from '@utils/key_mirror';

const device = keyMirror({
Expand All @@ -17,10 +19,11 @@ export default {
...device,
DOCUMENTS_PATH: `${FileSystem.cacheDirectory}/Documents`,
IMAGES_PATH: `${FileSystem.cacheDirectory}/Images`,
IS_IPHONE_WITH_INSETS: Platform.OS === 'ios' && DeviceInfo.hasNotch(),
IS_TABLET: DeviceInfo.isTablet(),
VIDEOS_PATH: `${FileSystem.cacheDirectory}/Videos`,
PERMANENT_SIDEBAR_SETTINGS: '@PERMANENT_SIDEBAR_SETTINGS',
TABLET_WIDTH: 250,
PUSH_NOTIFY_APPLE_REACT_NATIVE: 'apple_rn',
PUSH_NOTIFY_ANDROID_REACT_NATIVE: 'android_rn',
PUSH_NOTIFY_APPLE_REACT_NATIVE: 'apple_rn',
TABLET_WIDTH: 250,
VIDEOS_PATH: `${FileSystem.cacheDirectory}/Videos`,
};
3 changes: 3 additions & 0 deletions app/constants/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ const ViewTypes = keyMirror({
LANDSCAPE: null,

INDICATOR_BAR_VISIBLE: null,

CHANNEL_NAV_BAR_CHANGED: null,

});

const RequiredServer = {
Expand Down
18 changes: 18 additions & 0 deletions app/hooks/did_update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import {useRef, useEffect, EffectCallback, DependencyList} from 'react';

function useDidUpdate(callback: EffectCallback, deps?: DependencyList) {
const hasMount = useRef(false);

useEffect(() => {
if (hasMount.current) {
callback();
} else {
hasMount.current = true;
}
}, deps);
}

export default useDidUpdate;
Loading

0 comments on commit 64c1158

Please sign in to comment.