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:
parent
a0b1367fd3
commit
332aab134e
6 changed files with 58 additions and 45 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)}
|
||||
/>
|
||||
}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -131,8 +131,6 @@ const Channel = ({
|
|||
<ChannelPostList
|
||||
channelId={channelId}
|
||||
nativeID={channelId}
|
||||
currentCallBarVisible={isInACall}
|
||||
joinCallBannerVisible={showJoinCallBanner}
|
||||
/>
|
||||
</View>
|
||||
<PostDraft
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue