feat(base/native): Fixes around UI (#14820)

feat(base/native): Fixes around 
notifications, polls, local participant video menu, breakout room and participants UI
pull/14827/head jitsi-meet_9568
Calinteodor 12 months ago committed by GitHub
parent 8ee6d179d5
commit b2ae72249d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 31
      react/features/breakout-rooms/components/native/BreakoutRooms.tsx
  2. 24
      react/features/notifications/components/native/styles.ts
  3. 15
      react/features/participants-pane/components/native/ParticipantsPane.tsx
  4. 20
      react/features/polls/components/native/PollAnswer.tsx
  5. 57
      react/features/polls/components/native/PollCreate.tsx
  6. 4
      react/features/polls/components/native/PollItem.tsx
  7. 8
      react/features/polls/components/native/PollResults.tsx
  8. 6
      react/features/polls/components/native/PollsList.tsx
  9. 8
      react/features/polls/components/native/PollsPane.tsx
  10. 29
      react/features/polls/components/native/styles.ts
  11. 8
      react/features/video-menu/components/native/ConnectionStatusButton.ts
  12. 7
      react/features/video-menu/components/native/LocalVideoMenu.tsx

@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import React, { useCallback, useMemo } from 'react';
import { FlatList } from 'react-native';
import { useSelector } from 'react-redux';
@ -33,6 +33,19 @@ const BreakoutRooms = () => {
.sort((p1, p2) => (p1?.name || '').localeCompare(p2?.name || ''));
const showAddBreakoutRoom = useSelector(isAddBreakoutRoomButtonVisible);
const showAutoAssign = useSelector(isAutoAssignParticipantsVisible);
const renderListHeaderComponent = useMemo(() => (
<>
{ showAutoAssign && <AutoAssignButton /> }
{ inBreakoutRoom && <LeaveBreakoutRoomButton /> }
{
isBreakoutRoomsSupported
&& rooms.map(room => (<CollapsibleRoom
key = { room.id }
room = { room }
roomId = { room.id } />))
}
</>
), [ showAutoAssign, inBreakoutRoom, isBreakoutRoomsSupported, rooms ]);
return (
<JitsiScreen
@ -42,21 +55,7 @@ const BreakoutRooms = () => {
{ /* Fixes warning regarding nested lists */ }
<FlatList
/* eslint-disable react/jsx-no-bind */
ListHeaderComponent = { () => (
<>
{ showAutoAssign && <AutoAssignButton /> }
{ inBreakoutRoom && <LeaveBreakoutRoomButton /> }
{
isBreakoutRoomsSupported
&& rooms.map(room => (<CollapsibleRoom
key = { room.id }
room = { room }
roomId = { room.id } />))
}
</>
) }
ListHeaderComponent = { renderListHeaderComponent }
data = { [] as ReadonlyArray<undefined> }
keyExtractor = { keyExtractor }
renderItem = { null }

@ -3,7 +3,7 @@ import BaseTheme from '../../../base/ui/components/BaseTheme.native';
const contentColumn = {
flex: 1,
flexDirection: 'column',
marginLeft: BaseTheme.spacing[2]
paddingLeft: BaseTheme.spacing[2]
};
const notification = {
@ -14,9 +14,9 @@ const notification = {
display: 'flex',
flexDirection: 'row',
height: 'auto',
marginBottom: BaseTheme.spacing[2],
marginHorizontal: BaseTheme.spacing[2],
maxWidth: 400,
paddingBottom: BaseTheme.spacing[2],
paddingHorizontal: BaseTheme.spacing[2],
maxWidth: 432,
width: 'auto'
};
@ -42,20 +42,20 @@ export default {
*/
contentContainer: {
marginHorizontal: BaseTheme.spacing[2]
paddingHorizontal: BaseTheme.spacing[2]
},
contentText: {
color: BaseTheme.palette.text04,
marginLeft: BaseTheme.spacing[4],
marginTop: BaseTheme.spacing[1]
paddingLeft: BaseTheme.spacing[5],
paddingTop: BaseTheme.spacing[1]
},
contentTextTitle: {
color: BaseTheme.palette.text04,
fontWeight: 'bold',
marginLeft: BaseTheme.spacing[4],
marginTop: BaseTheme.spacing[2]
paddingLeft: BaseTheme.spacing[5],
paddingTop: BaseTheme.spacing[2]
},
/**
@ -90,17 +90,19 @@ export default {
iconContainer: {
position: 'absolute',
left: BaseTheme.spacing[2],
top: 12
},
btn: {
marginLeft: BaseTheme.spacing[4]
paddingLeft: BaseTheme.spacing[3]
},
btnContainer: {
display: 'flex',
flexDirection: 'row',
marginLeft: BaseTheme.spacing[3]
paddingLeft: BaseTheme.spacing[4],
paddingTop: BaseTheme.spacing[1]
},
withToolbox: {

@ -21,6 +21,13 @@ const ParticipantsPane = () => {
const isLocalModerator = useSelector(isLocalParticipantModerator);
const keyExtractor
= useCallback((e: undefined, i: number) => i.toString(), []);
const renderListHeaderComponent = () => (
<>
<VisitorsList />
<LobbyParticipantList />
<MeetingParticipantList />
</>
);
return (
<JitsiScreen
@ -31,13 +38,7 @@ const ParticipantsPane = () => {
<FlatList
// eslint-disable-next-line react/jsx-no-bind
ListHeaderComponent = { () => (
<>
<VisitorsList />
<LobbyParticipantList />
<MeetingParticipantList />
</>
) }
ListHeaderComponent = { renderListHeaderComponent }
data = { [] as ReadonlyArray<undefined> }
keyExtractor = { keyExtractor }
renderItem = { null }

@ -12,7 +12,7 @@ import { editPoll } from '../../actions';
import { isSubmitAnswerDisabled } from '../../functions';
import AbstractPollAnswer, { AbstractProps } from '../AbstractPollAnswer';
import { chatStyles, dialogStyles } from './styles';
import { dialogStyles, pollsStyles } from './styles';
const PollAnswer = (props: AbstractProps) => {
const {
@ -39,17 +39,17 @@ const PollAnswer = (props: AbstractProps) => {
t('polls.by', { name: localParticipant?.name })
}
</Text>
<View style = { chatStyles.answerContent as ViewStyle }>
<View style = { pollsStyles.answerContent as ViewStyle }>
{
poll.answers.map((answer, index: number) => (
<View
key = { index }
style = { chatStyles.switchRow as ViewStyle } >
style = { pollsStyles.switchRow as ViewStyle } >
<Switch
checked = { checkBoxStates[index] }
disabled = { poll.saved }
onChange = { state => setCheckbox(index, state) } />
<Text style = { chatStyles.switchLabel as TextStyle }>
<Text style = { pollsStyles.switchLabel as TextStyle }>
{ answer.name }
</Text>
</View>
@ -58,7 +58,7 @@ const PollAnswer = (props: AbstractProps) => {
</View>
{
pollSaved
? <View style = { chatStyles.buttonRow as ViewStyle }>
? <View style = { pollsStyles.buttonRow as ViewStyle }>
<Button
accessibilityLabel = 'polls.answer.edit'
labelKey = 'polls.answer.edit'
@ -66,28 +66,28 @@ const PollAnswer = (props: AbstractProps) => {
setCreateMode(true);
dispatch(editPoll(pollId, true));
} }
style = { chatStyles.pollCreateButton }
style = { pollsStyles.pollCreateButton }
type = { SECONDARY } />
<Button
accessibilityLabel = 'polls.answer.send'
labelKey = 'polls.answer.send'
onClick = { sendPoll }
style = { chatStyles.pollCreateButton }
style = { pollsStyles.pollCreateButton }
type = { PRIMARY } />
</View>
: <View style = { chatStyles.buttonRow as ViewStyle }>
: <View style = { pollsStyles.buttonRow as ViewStyle }>
<Button
accessibilityLabel = 'polls.answer.skip'
labelKey = 'polls.answer.skip'
onClick = { changingVote ? skipChangeVote : skipAnswer }
style = { chatStyles.pollCreateButton }
style = { pollsStyles.pollCreateButton }
type = { SECONDARY } />
<Button
accessibilityLabel = 'polls.answer.submit'
disabled = { isSubmitAnswerDisabled(checkBoxStates) }
labelKey = 'polls.answer.submit'
onClick = { submitAnswer }
style = { chatStyles.pollCreateButton }
style = { pollsStyles.pollCreateButton }
type = { PRIMARY } />
</View>
}

@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { FlatList, Platform, View, ViewStyle } from 'react-native';
import { TextInput } from 'react-native-gesture-handler';
import { Divider } from 'react-native-paper';
@ -7,13 +7,11 @@ import { useDispatch } from 'react-redux';
import Button from '../../../base/ui/components/native/Button';
import Input from '../../../base/ui/components/native/Input';
import { BUTTON_TYPES } from '../../../base/ui/constants.native';
import styles
from '../../../settings/components/native/styles';
import { editPoll } from '../../actions';
import { ANSWERS_LIMIT, CHAR_LIMIT } from '../../constants';
import AbstractPollCreate, { AbstractProps } from '../AbstractPollCreate';
import { chatStyles, dialogStyles } from './styles';
import { dialogStyles, pollsStyles } from './styles';
const PollCreate = (props: AbstractProps) => {
const {
@ -98,7 +96,7 @@ const PollCreate = (props: AbstractProps) => {
);
const pollCreateButtonsContainerStyles = Platform.OS === 'android'
? chatStyles.pollCreateButtonsContainerAndroid : chatStyles.pollCreateButtonsContainerIos;
? pollsStyles.pollCreateButtonsContainerAndroid : pollsStyles.pollCreateButtonsContainerIos;
/* eslint-disable react/jsx-no-bind */
const renderListItem = ({ index }: { index: number; }) => {
@ -119,7 +117,6 @@ const PollCreate = (props: AbstractProps) => {
id = { `polls-answer-input-${index}` }
label = { t('polls.create.pollOption', { index: index + 1 }) }
maxLength = { CHAR_LIMIT }
multiline = { true }
onChange = { name => setAnswer(index,
{
name,
@ -140,26 +137,30 @@ const PollCreate = (props: AbstractProps) => {
);
};
return (
<View style = { chatStyles.pollCreateContainer as ViewStyle }>
<View style = { chatStyles.pollCreateSubContainer as ViewStyle }>
<Input
autoFocus = { true }
blurOnSubmit = { false }
customStyles = {{ container: dialogStyles.customContainer }}
label = { t('polls.create.pollQuestion') }
maxLength = { CHAR_LIMIT }
multiline = { true }
onChange = { setQuestion }
onSubmitEditing = { onQuestionKeyDown }
placeholder = { t('polls.create.questionPlaceholder') }
const renderListHeaderComponent = useMemo(() => (
<>
<Input
autoFocus = { true }
blurOnSubmit = { false }
customStyles = {{ container: dialogStyles.customContainer }}
label = { t('polls.create.pollQuestion') }
maxLength = { CHAR_LIMIT }
onChange = { setQuestion }
onSubmitEditing = { onQuestionKeyDown }
placeholder = { t('polls.create.questionPlaceholder') }
// This is set to help the touch event not be propagated to any subviews.
pointerEvents = { 'auto' }
value = { question } />
<Divider style = { pollsStyles.fieldSeparator as ViewStyle } />
</>
), [ question ]);
// This is set to help the touch event not be propagated to any subviews.
pointerEvents = { 'auto' }
value = { question } />
{/* @ts-ignore */}
<Divider style = { styles.fieldSeparator } />
return (
<View style = { pollsStyles.pollCreateContainer as ViewStyle }>
<View style = { pollsStyles.pollCreateSubContainer as ViewStyle }>
<FlatList
ListHeaderComponent = { renderListHeaderComponent }
data = { answers }
extraData = { answers }
keyExtractor = { (item, index) => index.toString() }
@ -175,10 +176,10 @@ const PollCreate = (props: AbstractProps) => {
addAnswer();
requestFocus(answers.length);
} }
style = { chatStyles.pollCreateAddButton }
style = { pollsStyles.pollCreateAddButton }
type = { SECONDARY } />
<View
style = { chatStyles.buttonRow as ViewStyle }>
style = { pollsStyles.buttonRow as ViewStyle }>
<Button
accessibilityLabel = 'polls.create.cancel'
labelKey = 'polls.create.cancel'
@ -188,14 +189,14 @@ const PollCreate = (props: AbstractProps) => {
&& editingPoll?.editing
&& dispatch(editPoll(editingPollId, false));
} }
style = { chatStyles.pollCreateButton }
style = { pollsStyles.pollCreateButton }
type = { SECONDARY } />
<Button
accessibilityLabel = 'polls.create.save'
disabled = { isSubmitDisabled }
labelKey = 'polls.create.save'
onClick = { onSubmit }
style = { chatStyles.pollCreateButton }
style = { pollsStyles.pollCreateButton }
type = { PRIMARY } />
</View>
</View>

@ -6,7 +6,7 @@ import { shouldShowResults } from '../../functions';
import PollAnswer from './PollAnswer';
import PollResults from './PollResults';
import { chatStyles } from './styles';
import { pollsStyles } from './styles';
interface IProps {
@ -27,7 +27,7 @@ const PollItem = ({ pollId, setCreateMode }: IProps) => {
return (
<View
style = { chatStyles.pollItemContainer as ViewStyle }>
style = { pollsStyles.pollItemContainer as ViewStyle }>
{ showResults
? <PollResults
key = { pollId }

@ -6,7 +6,7 @@ import { BUTTON_TYPES } from '../../../base/ui/constants.native';
import AbstractPollResults from '../AbstractPollResults';
import type { AbstractProps, AnswerInfo } from '../AbstractPollResults';
import { chatStyles, dialogStyles, resultsStyles } from './styles';
import { dialogStyles, pollsStyles, resultsStyles } from './styles';
/**
* Component that renders the poll results.
@ -100,14 +100,14 @@ const PollResults = (props: AbstractProps) => {
data = { answers }
keyExtractor = { (item, index) => index.toString() }
renderItem = { answer => renderRow(answer.item) } />
<View style = { chatStyles.bottomLinks as ViewStyle }>
<View style = { pollsStyles.bottomLinks as ViewStyle }>
<Button
labelKey = {
showDetails
? 'polls.results.hideDetailedResults'
: 'polls.results.showDetailedResults'
}
labelStyle = { chatStyles.toggleText }
labelStyle = { pollsStyles.toggleText }
onClick = { toggleIsDetailed }
type = { BUTTON_TYPES.TERTIARY } />
<Button
@ -116,7 +116,7 @@ const PollResults = (props: AbstractProps) => {
? 'polls.results.changeVote'
: 'polls.results.vote'
}
labelStyle = { chatStyles.toggleText }
labelStyle = { pollsStyles.toggleText }
onClick = { changeVote }
type = { BUTTON_TYPES.TERTIARY } />
</View>

@ -10,7 +10,7 @@ import { IconMessage } from '../../../base/icons/svg';
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
import PollItem from './PollItem';
import { chatStyles } from './styles';
import { pollsStyles } from './styles';
interface IPollListProps {
setCreateMode: (mode: boolean) => void;
@ -42,12 +42,12 @@ const PollsList = ({ setCreateMode }: IPollListProps) => {
<>
{
listPolls.length === 0
&& <View style = { chatStyles.noPollContent as ViewStyle }>
&& <View style = { pollsStyles.noPollContent as ViewStyle }>
<Icon
color = { BaseTheme.palette.icon03 }
size = { 160 }
src = { IconMessage } />
<Text style = { chatStyles.noPollText as TextStyle } >
<Text style = { pollsStyles.noPollText as TextStyle } >
{
t('polls.results.empty')
}

@ -17,7 +17,7 @@ import type { AbstractProps } from '../AbstractPollsPane';
import PollCreate from './PollCreate';
import PollsList from './PollsList';
import { chatStyles } from './styles';
import { pollsStyles } from './styles';
const PollsPane = (props: AbstractProps) => {
const { createMode, onCreate, setCreateMode, t } = props;
@ -42,14 +42,14 @@ const PollsPane = (props: AbstractProps) => {
}, [ isPollsTabFocused, nbUnreadPolls ]);
const createPollButtonStyles = Platform.OS === 'android'
? chatStyles.createPollButtonAndroid : chatStyles.createPollButtonIos;
? pollsStyles.createPollButtonAndroid : pollsStyles.createPollButtonIos;
return (
<JitsiScreen
contentContainerStyle = { chatStyles.pollPane as StyleType }
contentContainerStyle = { pollsStyles.pollPane as StyleType }
disableForcedKeyboardDismiss = { true }
hasExtraHeaderHeight = { true }
style = { chatStyles.pollPaneContainer as StyleType }>
style = { pollsStyles.pollPaneContainer as StyleType }>
{
createMode
? <PollCreate setCreateMode = { setCreateMode } />

@ -30,7 +30,6 @@ export const dialogStyles = createStyleSheet({
},
optionRemoveButton: {
marginTop: BaseTheme.spacing[2],
width: 128
},
@ -110,7 +109,7 @@ export const resultsStyles = createStyleSheet({
}
});
export const chatStyles = createStyleSheet({
export const pollsStyles = createStyleSheet({
noPollContent: {
alignItems: 'center',
@ -195,7 +194,6 @@ export const chatStyles = createStyleSheet({
pollCreateButton: {
marginHorizontal: BaseTheme.spacing[1],
maxWidth: 160,
flex: 1
},
@ -229,26 +227,9 @@ export const chatStyles = createStyleSheet({
marginHorizontal: BaseTheme.spacing[1]
},
unreadPollsCounterContainer: {
display: 'flex',
flexDirection: 'row'
},
unreadPollsCounterDescription: {
color: BaseTheme.palette.text01
},
unreadPollsCounterCircle: {
backgroundColor: BaseTheme.palette.warning01,
borderRadius: BaseTheme.spacing[3] / 2,
height: BaseTheme.spacing[3],
justifyContent: 'center',
marginLeft: BaseTheme.spacing[2],
width: BaseTheme.spacing[3]
},
unreadPollsCounter: {
alignSelf: 'center',
color: BaseTheme.palette.text04
fieldSeparator: {
borderBottomWidth: 1,
borderColor: BaseTheme.palette.ui05,
marginTop: BaseTheme.spacing[3]
}
});

@ -1,11 +1,9 @@
import { connect } from 'react-redux';
import { openSheet } from '../../../base/dialog/actions';
import { translate } from '../../../base/i18n/functions';
import { IconInfoCircle } from '../../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import ConnectionStatusComponent from './ConnectionStatusComponent';
import { showConnectionStatus } from '../../../participants-pane/actions.native';
export interface IProps extends AbstractButtonProps {
@ -31,9 +29,7 @@ class ConnectionStatusButton extends AbstractButton<IProps> {
_handleClick() {
const { dispatch, participantID } = this.props;
dispatch(openSheet(ConnectionStatusComponent, {
participantID
}));
dispatch(showConnectionStatus(participantID));
}
}

@ -83,13 +83,18 @@ class LocalVideoMenu extends PureComponent<IProps> {
styles: bottomSheetStyles.buttons
};
const connectionStatusButtonProps = {
...buttonProps,
afterClick: undefined
};
return (
<BottomSheet
renderHeader = { this._renderMenuHeader }
showSlidingView = { true }>
<ToggleSelfViewButton { ...buttonProps } />
{ _showDemote && <DemoteToVisitorButton { ...buttonProps } /> }
<ConnectionStatusButton { ...buttonProps } />
<ConnectionStatusButton { ...connectionStatusButtonProps } />
</BottomSheet>
);
}

Loading…
Cancel
Save