mirror of
https://github.com/mosip/inji-wallet.git
synced 2026-01-08 05:03:56 -05:00
fix(#158): tooltip displaced by keyboard
This commit is contained in:
356
lib/react-native-elements/tooltip/Tooltip.tsx
Normal file
356
lib/react-native-elements/tooltip/Tooltip.tsx
Normal file
@@ -0,0 +1,356 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import {
|
||||
TouchableOpacity,
|
||||
Modal,
|
||||
View,
|
||||
StatusBar,
|
||||
I18nManager,
|
||||
ViewStyle,
|
||||
FlexStyle,
|
||||
StyleProp,
|
||||
StyleSheet,
|
||||
ColorValue,
|
||||
Platform,
|
||||
Keyboard,
|
||||
} from 'react-native';
|
||||
import { withTheme } from 'react-native-elements/dist/config';
|
||||
import { ThemeProps } from 'react-native-elements/dist/config';
|
||||
import {
|
||||
ScreenWidth,
|
||||
ScreenHeight,
|
||||
isIOS,
|
||||
} from 'react-native-elements/dist/helpers';
|
||||
import Triangle from './Triangle';
|
||||
import getTooltipCoordinate, {
|
||||
getElementVisibleWidth,
|
||||
} from './getTooltipCoordinate';
|
||||
|
||||
export type TooltipProps = {
|
||||
withPointer?: boolean;
|
||||
popover?: React.ReactElement<{}>;
|
||||
toggleOnPress?: boolean;
|
||||
toggleAction?: string | 'onPress' | 'onLongPress';
|
||||
height?: FlexStyle['height'];
|
||||
width?: FlexStyle['width'];
|
||||
containerStyle?: StyleProp<ViewStyle>;
|
||||
pointerColor?: ColorValue;
|
||||
onClose?(): void;
|
||||
onOpen?(): void;
|
||||
overlayColor?: ColorValue;
|
||||
withOverlay?: boolean;
|
||||
backgroundColor?: ColorValue;
|
||||
highlightColor?: ColorValue;
|
||||
skipAndroidStatusBar?: boolean;
|
||||
ModalComponent?: typeof React.Component;
|
||||
closeOnlyOnBackdropPress?: boolean;
|
||||
} & typeof defaultProps;
|
||||
|
||||
const defaultProps = {
|
||||
withOverlay: true,
|
||||
overlayColor: 'rgba(250, 250, 250, 0.70)',
|
||||
highlightColor: 'transparent',
|
||||
withPointer: true,
|
||||
toggleOnPress: true,
|
||||
toggleAction: 'onPress',
|
||||
height: 40,
|
||||
width: 150,
|
||||
containerStyle: {},
|
||||
backgroundColor: '#617080',
|
||||
onClose: () => {},
|
||||
onOpen: () => {},
|
||||
skipAndroidStatusBar: false,
|
||||
ModalComponent: Modal,
|
||||
closeOnlyOnBackdropPress: false,
|
||||
};
|
||||
|
||||
type TooltipState = {
|
||||
isVisible: boolean;
|
||||
yOffset: number;
|
||||
xOffset: number;
|
||||
elementWidth: number;
|
||||
elementHeight: number;
|
||||
};
|
||||
|
||||
class Tooltip extends React.Component<
|
||||
TooltipProps & Partial<ThemeProps<TooltipProps>>,
|
||||
TooltipState
|
||||
> {
|
||||
static defaultProps = defaultProps;
|
||||
_isMounted: boolean = false;
|
||||
state = {
|
||||
isVisible: false,
|
||||
yOffset: 0,
|
||||
xOffset: 0,
|
||||
elementWidth: 0,
|
||||
elementHeight: 0,
|
||||
};
|
||||
renderedElement?: View | null;
|
||||
|
||||
toggleTooltip = () => {
|
||||
const { onClose } = this.props;
|
||||
Keyboard.dismiss();
|
||||
setTimeout(() => {
|
||||
this.getElementPosition();
|
||||
this._isMounted &&
|
||||
this.setState((prevState) => {
|
||||
if (prevState.isVisible) {
|
||||
onClose && onClose();
|
||||
}
|
||||
return { isVisible: !prevState.isVisible };
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
wrapWithPress = (
|
||||
toggleOnPress: TooltipProps['toggleOnPress'],
|
||||
toggleAction: TooltipProps['toggleAction'],
|
||||
children: React.ReactNode
|
||||
) => {
|
||||
if (toggleOnPress) {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
{...{ [toggleAction]: this.toggleTooltip }}
|
||||
delayLongPress={250}
|
||||
activeOpacity={1}>
|
||||
{children}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
return children;
|
||||
};
|
||||
|
||||
containerStyle = (withOverlay: boolean, overlayColor: string): ViewStyle => {
|
||||
return {
|
||||
backgroundColor: withOverlay ? overlayColor : 'transparent',
|
||||
flex: 1,
|
||||
};
|
||||
};
|
||||
|
||||
getTooltipStyle = () => {
|
||||
const { yOffset, xOffset, elementHeight, elementWidth } = this.state;
|
||||
const { height, backgroundColor, width, withPointer, containerStyle } =
|
||||
this.props;
|
||||
const { x, y } = getTooltipCoordinate(
|
||||
xOffset,
|
||||
yOffset,
|
||||
elementWidth,
|
||||
elementHeight,
|
||||
ScreenWidth,
|
||||
ScreenHeight,
|
||||
width,
|
||||
height,
|
||||
withPointer
|
||||
);
|
||||
|
||||
return StyleSheet.flatten([
|
||||
{
|
||||
position: 'absolute',
|
||||
[I18nManager.isRTL ? 'right' : 'left']: x,
|
||||
top: y,
|
||||
width,
|
||||
height,
|
||||
backgroundColor,
|
||||
// default styles
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flex: 1,
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
},
|
||||
containerStyle,
|
||||
]);
|
||||
};
|
||||
|
||||
renderPointer = (tooltipY: FlexStyle['top']) => {
|
||||
const { yOffset, xOffset, elementHeight, elementWidth } = this.state;
|
||||
const { backgroundColor, pointerColor } = this.props;
|
||||
const pastMiddleLine = yOffset > (tooltipY || 0);
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: pastMiddleLine ? yOffset - 13 : yOffset + elementHeight - 2,
|
||||
[I18nManager.isRTL ? 'right' : 'left']:
|
||||
xOffset +
|
||||
getElementVisibleWidth(elementWidth, xOffset, ScreenWidth) / 2 -
|
||||
7.5,
|
||||
}}>
|
||||
<Triangle
|
||||
style={{ borderBottomColor: pointerColor || backgroundColor }}
|
||||
isDown={pastMiddleLine}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
getTooltipHighlightedButtonStyle = (): ViewStyle => {
|
||||
const { highlightColor } = this.props;
|
||||
const { yOffset, xOffset, elementWidth, elementHeight } = this.state;
|
||||
|
||||
return {
|
||||
position: 'absolute',
|
||||
top: yOffset,
|
||||
[I18nManager.isRTL ? 'right' : 'left']: xOffset,
|
||||
backgroundColor: highlightColor,
|
||||
overflow: 'visible',
|
||||
width: elementWidth,
|
||||
height: elementHeight,
|
||||
};
|
||||
};
|
||||
|
||||
renderTouchableHighlightedButton = () => {
|
||||
const TooltipHighlightedButtonStyle =
|
||||
this.getTooltipHighlightedButtonStyle();
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
testID="tooltipTouchableHighlightedButton"
|
||||
onPress={() => this.toggleTooltip()}
|
||||
style={TooltipHighlightedButtonStyle}>
|
||||
{this.props.children}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
renderStaticHighlightedButton = () => {
|
||||
const TooltipHighlightedButtonStyle =
|
||||
this.getTooltipHighlightedButtonStyle();
|
||||
|
||||
return (
|
||||
<View style={TooltipHighlightedButtonStyle}>{this.props.children}</View>
|
||||
);
|
||||
};
|
||||
|
||||
renderHighlightedButton = () => {
|
||||
const { closeOnlyOnBackdropPress } = this.props;
|
||||
if (closeOnlyOnBackdropPress) {
|
||||
return this.renderTouchableHighlightedButton();
|
||||
} else {
|
||||
return this.renderStaticHighlightedButton();
|
||||
}
|
||||
};
|
||||
|
||||
renderContent = (withTooltip: boolean) => {
|
||||
const { popover, withPointer, toggleOnPress, toggleAction } = this.props;
|
||||
if (!withTooltip) {
|
||||
return this.wrapWithPress(
|
||||
toggleOnPress,
|
||||
toggleAction,
|
||||
this.props.children
|
||||
);
|
||||
}
|
||||
|
||||
const tooltipStyle = this.getTooltipStyle() as ViewStyle;
|
||||
|
||||
return (
|
||||
<View>
|
||||
{this.renderHighlightedButton()}
|
||||
{withPointer && this.renderPointer(tooltipStyle.top)}
|
||||
<View style={tooltipStyle} testID="tooltipPopoverContainer">
|
||||
{popover}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
// wait to compute onLayout values.
|
||||
requestAnimationFrame(this.getElementPosition);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
getElementPosition = () => {
|
||||
const { skipAndroidStatusBar } = this.props;
|
||||
this.renderedElement &&
|
||||
this.renderedElement.measure(
|
||||
(
|
||||
_frameOffsetX,
|
||||
_frameOffsetY,
|
||||
width,
|
||||
height,
|
||||
pageOffsetX,
|
||||
pageOffsetY
|
||||
) => {
|
||||
this._isMounted &&
|
||||
this.setState({
|
||||
xOffset: pageOffsetX,
|
||||
yOffset:
|
||||
isIOS || skipAndroidStatusBar
|
||||
? pageOffsetY
|
||||
: pageOffsetY -
|
||||
Platform.select({
|
||||
android: StatusBar.currentHeight,
|
||||
ios: 20,
|
||||
default: 0,
|
||||
}),
|
||||
elementWidth: width,
|
||||
elementHeight: height,
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
renderStaticModalContent = () => {
|
||||
const { withOverlay, overlayColor } = this.props;
|
||||
return (
|
||||
<Fragment>
|
||||
<TouchableOpacity
|
||||
style={this.containerStyle(withOverlay, overlayColor)}
|
||||
onPress={this.toggleTooltip}
|
||||
activeOpacity={1}
|
||||
/>
|
||||
<View>{this.renderContent(true)}</View>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
renderTogglingModalContent = () => {
|
||||
const { withOverlay, overlayColor } = this.props;
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={this.containerStyle(withOverlay, overlayColor)}
|
||||
onPress={this.toggleTooltip}
|
||||
activeOpacity={1}>
|
||||
{this.renderContent(true)}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
renderModalContent = () => {
|
||||
const { closeOnlyOnBackdropPress } = this.props;
|
||||
if (closeOnlyOnBackdropPress) {
|
||||
return this.renderStaticModalContent();
|
||||
} else {
|
||||
return this.renderTogglingModalContent();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isVisible } = this.state;
|
||||
const { onOpen, ModalComponent } = this.props;
|
||||
return (
|
||||
<View
|
||||
collapsable={false}
|
||||
ref={(e) => {
|
||||
this.renderedElement = e;
|
||||
}}>
|
||||
{this.renderContent(false)}
|
||||
<ModalComponent
|
||||
animationType="fade"
|
||||
visible={isVisible}
|
||||
transparent
|
||||
onShow={onOpen}>
|
||||
{this.renderModalContent()}
|
||||
</ModalComponent>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { Tooltip };
|
||||
export default withTheme(Tooltip, 'Tooltip');
|
||||
40
lib/react-native-elements/tooltip/Triangle.tsx
Normal file
40
lib/react-native-elements/tooltip/Triangle.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
||||
|
||||
type TriangleProps = {
|
||||
style?: StyleProp<ViewStyle>;
|
||||
isDown?: boolean;
|
||||
};
|
||||
|
||||
const Triangle: React.FunctionComponent<TriangleProps> = ({
|
||||
style,
|
||||
isDown,
|
||||
}) => (
|
||||
<View
|
||||
style={StyleSheet.flatten([
|
||||
styles.triangle,
|
||||
style,
|
||||
isDown ? styles.down : {},
|
||||
])}
|
||||
/>
|
||||
);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
down: {
|
||||
transform: [{ rotate: '180deg' }],
|
||||
},
|
||||
triangle: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
backgroundColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderLeftWidth: 8,
|
||||
borderRightWidth: 8,
|
||||
borderBottomWidth: 15,
|
||||
borderLeftColor: 'transparent',
|
||||
borderRightColor: 'transparent',
|
||||
borderBottomColor: 'white',
|
||||
},
|
||||
});
|
||||
|
||||
export default Triangle;
|
||||
142
lib/react-native-elements/tooltip/getTooltipCoordinate.tsx
Normal file
142
lib/react-native-elements/tooltip/getTooltipCoordinate.tsx
Normal file
@@ -0,0 +1,142 @@
|
||||
const getArea = (a: number, b: number) => a * b;
|
||||
|
||||
const getPointDistance = (a: number[], b: number[]) =>
|
||||
Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2));
|
||||
|
||||
export const getElementVisibleWidth = (
|
||||
elementWidth: number,
|
||||
xOffset: number,
|
||||
ScreenWidth: number
|
||||
) => {
|
||||
// Element is fully visible OR scrolled right
|
||||
if (xOffset >= 0) {
|
||||
return xOffset + elementWidth <= ScreenWidth // is element fully visible?
|
||||
? elementWidth // element is fully visible;
|
||||
: ScreenWidth - xOffset; // calculate visible width of scrolled element
|
||||
}
|
||||
// Element is scrolled LEFT
|
||||
return elementWidth - xOffset; // calculate visible width of scrolled element
|
||||
};
|
||||
|
||||
/*
|
||||
type Coord = {
|
||||
x: number,
|
||||
y: number,
|
||||
};
|
||||
|
||||
~Tooltip coordinate system:~
|
||||
The tooltip coordinates are based on the element which it is wrapping.
|
||||
We take the x and y coordinates of the element and find the best position
|
||||
to place the tooltip. To find the best position we look for the side with the
|
||||
most space. In order to find the side with the most space we divide the the
|
||||
surroundings in four quadrants and check for the one with biggest area.
|
||||
Once we know the quandrant with the biggest area it place the tooltip in that
|
||||
direction.
|
||||
|
||||
To find the areas we first get 5 coordinate points. The center and the other 4 extreme points
|
||||
which together make a perfect cross shape.
|
||||
|
||||
Once we know the coordinates we can get the length of the vertices which form each quadrant.
|
||||
Since they are squares we only need two.
|
||||
*/
|
||||
const getTooltipCoordinate = (
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
ScreenWidth: number,
|
||||
ScreenHeight: number,
|
||||
tooltipWidth: number,
|
||||
tooltipHeight: number,
|
||||
withPointer: boolean
|
||||
) => {
|
||||
// The following are point coordinates: [x, y]
|
||||
const center = [
|
||||
x + getElementVisibleWidth(width, x, ScreenWidth) / 2,
|
||||
y + height / 2,
|
||||
];
|
||||
const pOne = [center[0], 0];
|
||||
const pTwo = [ScreenWidth, center[1]];
|
||||
const pThree = [center[0], ScreenHeight];
|
||||
const pFour = [0, center[1]];
|
||||
// vertices
|
||||
const vOne = getPointDistance(center, pOne);
|
||||
const vTwo = getPointDistance(center, pTwo);
|
||||
const vThree = getPointDistance(center, pThree);
|
||||
const vFour = getPointDistance(center, pFour);
|
||||
// Quadrant areas.
|
||||
// type Areas = {
|
||||
// area: number,
|
||||
// id: number,
|
||||
// };
|
||||
const areas = [
|
||||
getArea(vOne, vFour),
|
||||
getArea(vOne, vTwo),
|
||||
getArea(vTwo, vThree),
|
||||
getArea(vThree, vFour),
|
||||
].map((each, index) => ({ area: each, id: index }));
|
||||
const sortedArea = areas.sort((a, b) => b.area - a.area);
|
||||
// deslocated points
|
||||
const dX = 0.001;
|
||||
const dY = height / 2;
|
||||
// Deslocate the coordinates in the direction of the quadrant.
|
||||
const directionCorrection = [
|
||||
[-1, -1],
|
||||
[1, -1],
|
||||
[1, 1],
|
||||
[-1, 1],
|
||||
];
|
||||
const deslocateReferencePoint = [
|
||||
[-tooltipWidth, -tooltipHeight],
|
||||
[0, -tooltipHeight],
|
||||
[0, 0],
|
||||
[-tooltipWidth, 0],
|
||||
];
|
||||
// current quadrant index
|
||||
const qIndex = sortedArea[0].id;
|
||||
const getWithPointerOffsetY = () =>
|
||||
withPointer ? 10 * directionCorrection[qIndex][1] : 0;
|
||||
const getWithPointerOffsetX = () =>
|
||||
withPointer ? center[0] - 18 * directionCorrection[qIndex][0] : center[0];
|
||||
const newX =
|
||||
getWithPointerOffsetX() +
|
||||
(dX * directionCorrection[qIndex][0] + deslocateReferencePoint[qIndex][0]);
|
||||
return {
|
||||
x: constraintX(newX, qIndex, center[0], ScreenWidth, tooltipWidth),
|
||||
y:
|
||||
center[1] +
|
||||
(dY * directionCorrection[qIndex][1] +
|
||||
deslocateReferencePoint[qIndex][1]) +
|
||||
getWithPointerOffsetY(),
|
||||
};
|
||||
};
|
||||
|
||||
const constraintX = (
|
||||
newX: number,
|
||||
qIndex: number,
|
||||
x: number,
|
||||
ScreenWidth: number,
|
||||
tooltipWidth: number
|
||||
) => {
|
||||
switch (qIndex) {
|
||||
// 0 and 3 are the left side quadrants.
|
||||
case 0:
|
||||
case 3: {
|
||||
const maxWidth = newX > ScreenWidth ? ScreenWidth - 10 : newX;
|
||||
return newX < 1 ? 10 : maxWidth;
|
||||
}
|
||||
// 1 and 2 are the right side quadrants
|
||||
case 1:
|
||||
case 2: {
|
||||
const leftOverSpace = ScreenWidth - newX;
|
||||
return leftOverSpace >= tooltipWidth
|
||||
? newX
|
||||
: newX - (tooltipWidth - leftOverSpace + 10);
|
||||
}
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default getTooltipCoordinate;
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Dimensions, I18nManager } from 'react-native';
|
||||
import { Icon, Input, Tooltip } from 'react-native-elements';
|
||||
import { Button, Column, Row, Text } from '../../../components/ui';
|
||||
import { Icon, Input } from 'react-native-elements';
|
||||
import { Button, Centered, Column, Row, Text } from '../../../components/ui';
|
||||
import { Modal } from '../../../components/ui/Modal';
|
||||
import { Theme } from '../../../components/ui/styleUtils';
|
||||
import {
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import { KeyboardAvoidingView, Platform } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { MessageOverlay } from '../../../components/MessageOverlay';
|
||||
import Tooltip from '../../../lib/react-native-elements/tooltip/Tooltip';
|
||||
|
||||
export const GetIdInputModal: React.FC<GetIdInputModalProps> = (props) => {
|
||||
const { t } = useTranslation('GetIdInputModal');
|
||||
@@ -63,25 +64,27 @@ export const GetIdInputModal: React.FC<GetIdInputModalProps> = (props) => {
|
||||
skipAndroidStatusBar={true}
|
||||
onOpen={controller.ACTIVATE_ICON_COLOR}
|
||||
onClose={controller.DEACTIVATE_ICON_COLOR}>
|
||||
{controller.isInvalid ? (
|
||||
<Icon
|
||||
name="error"
|
||||
size={18}
|
||||
color={
|
||||
!controller.iconColor
|
||||
? Theme.Colors.errorMessage
|
||||
: Theme.Colors.Icon
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
name={'help'}
|
||||
size={18}
|
||||
color={
|
||||
!controller.iconColor ? null : Theme.Colors.Icon
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<Centered width={32} fill>
|
||||
{controller.isInvalid ? (
|
||||
<Icon
|
||||
name="error"
|
||||
size={18}
|
||||
color={
|
||||
!controller.iconColor
|
||||
? Theme.Colors.errorMessage
|
||||
: Theme.Colors.Icon
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
name={'help'}
|
||||
size={18}
|
||||
color={
|
||||
!controller.iconColor ? null : Theme.Colors.Icon
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Centered>
|
||||
</Tooltip>
|
||||
}
|
||||
errorStyle={{ color: Theme.Colors.errorMessage }}
|
||||
|
||||
@@ -39,83 +39,82 @@ export const ProfileScreen: React.FC<MainRouteProps> = (props) => {
|
||||
const { t } = useTranslation('ProfileScreen');
|
||||
const controller = useProfileScreen(props);
|
||||
return (
|
||||
<Column
|
||||
fill
|
||||
padding="24 0"
|
||||
backgroundColor={Theme.Colors.lightGreyBackgroundColor}>
|
||||
<MessageOverlay
|
||||
isVisible={controller.alertMsg != ''}
|
||||
onBackdropPress={controller.hideAlert}
|
||||
title={controller.alertMsg}
|
||||
/>
|
||||
<EditableListItem
|
||||
label={t('name')}
|
||||
value={controller.name}
|
||||
onEdit={controller.UPDATE_NAME}
|
||||
/>
|
||||
<EditableListItem
|
||||
label={t('vcLabel')}
|
||||
value={controller.vcLabel.singular}
|
||||
onEdit={controller.UPDATE_VC_LABEL}
|
||||
/>
|
||||
<LanguageSetting />
|
||||
<Revoke label={t('revokeLabel')} />
|
||||
<ListItem bottomDivider disabled={!controller.canUseBiometrics}>
|
||||
<ListItem.Content>
|
||||
<ListItem.Title>
|
||||
<Text color={Theme.Colors.profileLabel}>{t('bioUnlock')}</Text>
|
||||
</ListItem.Title>
|
||||
</ListItem.Content>
|
||||
<Switch
|
||||
value={controller.isBiometricUnlockEnabled}
|
||||
onValueChange={controller.useBiometrics}
|
||||
color={Theme.Colors.profileValue}
|
||||
<Column fill backgroundColor={Theme.Colors.lightGreyBackgroundColor}>
|
||||
<Column scroll padding="24 0">
|
||||
<MessageOverlay
|
||||
isVisible={controller.alertMsg != ''}
|
||||
onBackdropPress={controller.hideAlert}
|
||||
title={controller.alertMsg}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem bottomDivider disabled>
|
||||
<ListItem.Content>
|
||||
<ListItem.Title>
|
||||
<Text color={Theme.Colors.profileAuthFactorUnlock}>
|
||||
{t('authFactorUnlock')}
|
||||
<EditableListItem
|
||||
label={t('name')}
|
||||
value={controller.name}
|
||||
onEdit={controller.UPDATE_NAME}
|
||||
/>
|
||||
<EditableListItem
|
||||
label={t('vcLabel')}
|
||||
value={controller.vcLabel.singular}
|
||||
onEdit={controller.UPDATE_VC_LABEL}
|
||||
/>
|
||||
<LanguageSetting />
|
||||
<Revoke label={t('revokeLabel')} />
|
||||
<ListItem bottomDivider disabled={!controller.canUseBiometrics}>
|
||||
<ListItem.Content>
|
||||
<ListItem.Title>
|
||||
<Text color={Theme.Colors.profileLabel}>{t('bioUnlock')}</Text>
|
||||
</ListItem.Title>
|
||||
</ListItem.Content>
|
||||
<Switch
|
||||
value={controller.isBiometricUnlockEnabled}
|
||||
onValueChange={controller.useBiometrics}
|
||||
color={Theme.Colors.profileValue}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem bottomDivider disabled>
|
||||
<ListItem.Content>
|
||||
<ListItem.Title>
|
||||
<Text color={Theme.Colors.profileAuthFactorUnlock}>
|
||||
{t('authFactorUnlock')}
|
||||
</Text>
|
||||
</ListItem.Title>
|
||||
</ListItem.Content>
|
||||
</ListItem>
|
||||
<Credits label={t('credits')} color={Theme.Colors.profileLabel} />
|
||||
<ListItem bottomDivider onPress={controller.LOGOUT}>
|
||||
<ListItem.Content>
|
||||
<ListItem.Title>
|
||||
<Text color={Theme.Colors.profileLabel}>{t('logout')}</Text>
|
||||
</ListItem.Title>
|
||||
</ListItem.Content>
|
||||
</ListItem>
|
||||
<Text
|
||||
weight="semibold"
|
||||
margin="32 0 0 0"
|
||||
align="center"
|
||||
size="smaller"
|
||||
color={Theme.Colors.profileVersion}>
|
||||
{t('version')}: {getVersion()}
|
||||
</Text>
|
||||
{controller.backendInfo.application.name !== '' ? (
|
||||
<View>
|
||||
<Text
|
||||
weight="semibold"
|
||||
align="center"
|
||||
size="smaller"
|
||||
color={Theme.Colors.profileValue}>
|
||||
{controller.backendInfo.application.name}:{' '}
|
||||
{controller.backendInfo.application.version}
|
||||
</Text>
|
||||
</ListItem.Title>
|
||||
</ListItem.Content>
|
||||
</ListItem>
|
||||
<Credits label={t('credits')} color={Theme.Colors.profileLabel} />
|
||||
<ListItem bottomDivider onPress={controller.LOGOUT}>
|
||||
<ListItem.Content>
|
||||
<ListItem.Title>
|
||||
<Text color={Theme.Colors.profileLabel}>{t('logout')}</Text>
|
||||
</ListItem.Title>
|
||||
</ListItem.Content>
|
||||
</ListItem>
|
||||
<Text
|
||||
weight="semibold"
|
||||
margin="32 0 0 0"
|
||||
align="center"
|
||||
size="smaller"
|
||||
color={Theme.Colors.profileVersion}>
|
||||
{t('version')}: {getVersion()}
|
||||
</Text>
|
||||
{controller.backendInfo.application.name !== '' ? (
|
||||
<View>
|
||||
<Text
|
||||
weight="semibold"
|
||||
align="center"
|
||||
size="smaller"
|
||||
color={Theme.Colors.profileValue}>
|
||||
{controller.backendInfo.application.name}:{' '}
|
||||
{controller.backendInfo.application.version}
|
||||
</Text>
|
||||
<Text
|
||||
weight="semibold"
|
||||
align="center"
|
||||
size="smaller"
|
||||
color={Theme.Colors.profileValue}>
|
||||
MOSIP: {controller.backendInfo.config['mosip.host']}
|
||||
</Text>
|
||||
</View>
|
||||
) : null}
|
||||
<Text
|
||||
weight="semibold"
|
||||
align="center"
|
||||
size="smaller"
|
||||
color={Theme.Colors.profileValue}>
|
||||
MOSIP: {controller.backendInfo.config['mosip.host']}
|
||||
</Text>
|
||||
</View>
|
||||
) : null}
|
||||
</Column>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -160,6 +160,7 @@ export function useScanLayout() {
|
||||
} else if (isOffline) {
|
||||
statusOverlay = {
|
||||
message: t('status.offline'),
|
||||
onBackdropPress: DISMISS,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user