MM-55010 - Calls: more messages bar adjustments (#7620)

* refactor; tried to clarify more_messages; new design

* adjust more_messages text spacing

* small fix for height with incoming call on current channel

* move calls-specific code in the calls product behind a hook
This commit is contained in:
Christopher Poile 2023-11-03 17:51:32 -04:00 committed by GitHub
parent a0b1367fd3
commit 332aab134e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 45 deletions

View file

@ -7,16 +7,15 @@ import Animated, {interpolate, useAnimatedStyle, useSharedValue, withSpring} fro
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {resetMessageCount} from '@actions/local/channel';
import {useCallsAdjustment} from '@app/products/calls/hooks';
import CompassIcon from '@components/compass_icon';
import FormattedText from '@components/formatted_text';
import TouchableWithFeedback from '@components/touchable_with_feedback';
import {Events} from '@constants';
import {CURRENT_CALL_BAR_HEIGHT, JOIN_CALL_BAR_HEIGHT} from '@constants/view';
import {useServerUrl} from '@context/server';
import {useIsTablet} from '@hooks/device';
import useDidUpdate from '@hooks/did_update';
import EphemeralStore from '@store/ephemeral_store';
import {makeStyleSheetFromTheme, hexToHue} from '@utils/theme';
import {makeStyleSheetFromTheme, hexToHue, changeOpacity} from '@utils/theme';
import {typography} from '@utils/typography';
import type {PostList} from '@typings/components/post_list';
@ -34,8 +33,6 @@ type Props = {
unreadCount: number;
theme: Theme;
testID: string;
currentCallBarVisible: boolean;
joinCallBannerVisible: boolean;
}
const HIDDEN_TOP = -60;
@ -60,9 +57,13 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
flexDirection: 'row',
justifyContent: 'space-evenly',
alignItems: 'center',
paddingLeft: 12,
width: '100%',
height: 42,
height: 40,
borderRadius: 8,
paddingTop: 4,
paddingRight: 4,
paddingBottom: 4,
paddingLeft: 8,
shadowColor: theme.centerChannelColor,
shadowOffset: {
width: 0,
@ -70,29 +71,30 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
},
shadowOpacity: 0.12,
shadowRadius: 4,
elevation: 4,
},
roundBorder: {
borderRadius: 8,
iconContainer: {
top: 1,
width: 32,
},
icon: {
fontSize: 18,
color: theme.buttonColor,
alignSelf: 'center',
},
iconContainer: {
top: 2,
width: 22,
closeIcon: {
color: changeOpacity(theme.buttonColor, 0.56),
},
pressContainer: {
flex: 1,
flexDirection: 'row',
},
textContainer: {
paddingLeft: 4,
marginLeft: 8,
},
text: {
color: theme.buttonColor,
...typography('Body', 200, 'SemiBold'),
...typography('Body', 100, 'SemiBold'),
},
};
});
@ -110,11 +112,8 @@ const MoreMessages = ({
unreadCount,
testID,
theme,
currentCallBarVisible,
joinCallBannerVisible,
}: Props) => {
const serverUrl = useServerUrl();
const isTablet = useIsTablet();
const insets = useSafeAreaInsets();
const pressed = useRef(false);
const resetting = useRef(false);
@ -122,12 +121,14 @@ const MoreMessages = ({
const [loading, setLoading] = useState(EphemeralStore.isLoadingMessagesForChannel(serverUrl, channelId));
const [remaining, setRemaining] = useState(0);
const underlayColor = useMemo(() => `hsl(${hexToHue(theme.buttonBg)}, 50%, 38%)`, [theme]);
const top = useSharedValue(0);
const adjustedShownTop = SHOWN_TOP + (currentCallBarVisible ? CURRENT_CALL_BAR_HEIGHT : 0) + (joinCallBannerVisible ? JOIN_CALL_BAR_HEIGHT : 0);
const adjustTop = isTablet || (isCRTEnabled && rootId);
const shownTop = adjustTop ? SHOWN_TOP : adjustedShownTop;
const BARS_FACTOR = Math.abs((1) / (HIDDEN_TOP - SHOWN_TOP));
const styles = getStyleSheet(theme);
const top = useSharedValue(0);
const callsAdjustment = useCallsAdjustment(serverUrl, channelId);
// The final top:
const adjustedTop = insets.top + callsAdjustment;
const BARS_FACTOR = Math.abs((1) / (HIDDEN_TOP - SHOWN_TOP));
const animatedStyle = useAnimatedStyle(() => ({
transform: [{
@ -142,13 +143,13 @@ const MoreMessages = ({
[
HIDDEN_TOP,
HIDDEN_TOP,
shownTop + (adjustTop ? 0 : insets.top),
shownTop + (adjustTop ? 0 : insets.top),
adjustedTop,
adjustedTop,
],
'clamp',
), {damping: 15}),
}],
}), [shownTop, insets.top, adjustTop]);
}), [adjustedTop]);
// Due to the implementation differences "unreadCount" gets updated for a channel on reset but not for a thread.
// So we maintain a localUnreadCount to hide the indicator when the count is reset.
@ -254,7 +255,7 @@ const MoreMessages = ({
return (
<Animated.View style={[styles.animatedContainer, animatedStyle]}>
<View style={[styles.container, styles.roundBorder]}>
<View style={[styles.container]}>
<TouchableWithFeedback
type={'opacity'}
onPress={onPress}
@ -295,7 +296,7 @@ const MoreMessages = ({
<View style={styles.cancelContainer}>
<CompassIcon
name='close'
style={styles.icon}
style={[styles.icon, styles.closeIcon]}
/>
</View>
</TouchableWithFeedback>

View file

@ -52,7 +52,6 @@ type Props = {
header?: ReactElement;
testID: string;
currentCallBarVisible?: boolean;
joinCallBannerVisible?: boolean;
savedPostIds: Set<string>;
}
@ -111,8 +110,6 @@ const PostList = ({
showMoreMessages,
showNewMessageLine = true,
testID,
currentCallBarVisible,
joinCallBannerVisible,
savedPostIds,
}: Props) => {
const listRef = useRef<FlatList<string | PostModel>>(null);
@ -377,8 +374,6 @@ const PostList = ({
scrollToIndex={scrollToIndex}
theme={theme}
testID={`${testID}.more_messages_button`}
currentCallBarVisible={Boolean(currentCallBarVisible)}
joinCallBannerVisible={Boolean(joinCallBannerVisible)}
/>
}
</>

View file

@ -8,12 +8,10 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context';
import CurrentCallBar from '@calls/components/current_call_bar';
import {IncomingCallsContainer} from '@calls/components/incoming_calls_container';
import JoinCallBanner from '@calls/components/join_call_banner';
import {DEFAULT_HEADER_HEIGHT} from '@constants/view';
import {DEFAULT_HEADER_HEIGHT, TABLET_HEADER_HEIGHT} from '@constants/view';
import {useServerUrl} from '@context/server';
import {useIsTablet} from '@hooks/device';
const topBarHeight = DEFAULT_HEADER_HEIGHT;
const style = StyleSheet.create({
wrapper: {
position: 'absolute',
@ -36,9 +34,10 @@ const FloatingCallContainer = ({channelId, showJoinCallBanner, showIncomingCalls
const insets = useSafeAreaInsets();
const isTablet = useIsTablet();
const topBarIsIncludedAlready = Boolean(isTablet || threadScreen);
const topBarForTablet = (isTablet && !threadScreen) ? TABLET_HEADER_HEIGHT : 0;
const topBarChannel = (!isTablet && !threadScreen) ? DEFAULT_HEADER_HEIGHT : 0;
const wrapperTop = {
top: insets.top + (topBarIsIncludedAlready ? 0 : topBarHeight),
top: insets.top + topBarForTablet + topBarChannel,
};
return (

View file

@ -8,8 +8,9 @@ import {useIntl} from 'react-intl';
import {Alert, Platform} from 'react-native';
import Permissions from 'react-native-permissions';
import {CALL_ERROR_BAR_HEIGHT, CALL_NOTIFICATION_BAR_HEIGHT, CURRENT_CALL_BAR_HEIGHT, JOIN_CALL_BAR_HEIGHT} from '@app/constants/view';
import {initializeVoiceTrack} from '@calls/actions/calls';
import {setMicPermissionsGranted} from '@calls/state';
import {setMicPermissionsGranted, useCallsState, useChannelsWithCalls, useCurrentCall, useGlobalCallsState, useIncomingCalls} from '@calls/state';
import {errorAlert} from '@calls/utils';
import {useServerUrl} from '@context/server';
import {useAppState} from '@hooks/device';
@ -108,3 +109,27 @@ export const usePermissionsChecker = (micPermissionsGranted: boolean) => {
}
}, [appState]);
};
export const useCallsAdjustment = (serverUrl: string, channelId: string) => {
const incomingCalls = useIncomingCalls().incomingCalls;
const channelsWithCalls = useChannelsWithCalls(serverUrl);
const callsState = useCallsState(serverUrl);
const globalCallsState = useGlobalCallsState();
const currentCall = useCurrentCall();
const dismissed = Boolean(callsState.calls[channelId]?.dismissed[callsState.myUserId]);
const inCurrentCall = currentCall?.id === channelId;
const joinCallBannerVisible = Boolean(channelsWithCalls[channelId]) && !dismissed && !inCurrentCall;
// Do we have calls banners?
const currentCallBarVisible = Boolean(currentCall);
const micPermissionsError = !globalCallsState.micPermissionsGranted && (currentCall && !currentCall.micPermissionsErrorDismissed);
const callQualityAlert = Boolean(currentCall?.callQualityAlert);
const incomingCallsShowing = incomingCalls.filter((ic) => ic.channelID !== channelId);
const callsIncomingAdjustment = (incomingCallsShowing.length * CALL_NOTIFICATION_BAR_HEIGHT) + (incomingCallsShowing.length * 8);
const callsAdjustment = (currentCallBarVisible ? CURRENT_CALL_BAR_HEIGHT + 8 : 0) +
(micPermissionsError ? CALL_ERROR_BAR_HEIGHT + 8 : 0) +
(callQualityAlert ? CALL_ERROR_BAR_HEIGHT + 8 : 0) +
(joinCallBannerVisible ? JOIN_CALL_BAR_HEIGHT + 8 : 0) +
callsIncomingAdjustment;
return callsAdjustment;
};

View file

@ -131,8 +131,6 @@ const Channel = ({
<ChannelPostList
channelId={channelId}
nativeID={channelId}
currentCallBarVisible={isInACall}
joinCallBannerVisible={showJoinCallBanner}
/>
</View>
<PostDraft

View file

@ -29,8 +29,6 @@ type Props = {
nativeID: string;
posts: PostModel[];
shouldShowJoinLeaveMessages: boolean;
currentCallBarVisible: boolean;
joinCallBannerVisible: boolean;
}
const edges: Edge[] = ['bottom'];
@ -42,7 +40,6 @@ const styles = StyleSheet.create({
const ChannelPostList = ({
channelId, contentContainerStyle, isCRTEnabled,
lastViewedAt, nativeID, posts, shouldShowJoinLeaveMessages,
currentCallBarVisible, joinCallBannerVisible,
}: Props) => {
const appState = useAppState();
const isTablet = useIsTablet();
@ -110,8 +107,6 @@ const ChannelPostList = ({
shouldShowJoinLeaveMessages={shouldShowJoinLeaveMessages}
showMoreMessages={true}
testID='channel.post_list'
currentCallBarVisible={currentCallBarVisible}
joinCallBannerVisible={joinCallBannerVisible}
/>
);