mirror of
https://github.com/mosip/inji-wallet.git
synced 2026-01-09 05:27:57 -05:00
[INJIMOB-3193]add preauth and credential offer support (#1949)
[INJIMOB-3058]temp commit2 [INJIMOB-3058]temp commit2 [INJIMOB-3058] add support for pre-auth flow by credential-offer [INJIMOB-3187] animo working chcekpoint Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
This commit is contained in:
@@ -11,13 +11,17 @@ export const PinInput: React.FC<PinInputProps> = props => {
|
||||
const [focusedIndex, setFocusedIndex] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.onDone && values.filter(Boolean).length === inputRefs.length) {
|
||||
props.onDone(values.join(''));
|
||||
const current = values.join('');
|
||||
props.onChange?.(current);
|
||||
|
||||
if (props.autosubmit && props.onDone && values.filter(Boolean).length === inputRefs.length) {
|
||||
props.onDone(current);
|
||||
}
|
||||
}, [state]);
|
||||
}, [values]);
|
||||
|
||||
|
||||
return (
|
||||
<Row width="100%" testID={props.testID} removeClippedSubviews={true}>
|
||||
<Row width={`${(100 / 6) * props.length}%`} testID={props.testID} removeClippedSubviews={true}>
|
||||
{inputRefs.map((input, index) => (
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
@@ -53,4 +57,6 @@ interface PinInputProps {
|
||||
testID?: string;
|
||||
length: number;
|
||||
onDone?: (value: string) => void;
|
||||
onChange?: (value: string) => void;
|
||||
autosubmit?: boolean;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ export const VCCardView: React.FC<VCItemProps> = ({
|
||||
credentialConfigurationId,
|
||||
vcMetadata: { format },
|
||||
} = verifiableCredentialData;
|
||||
if (vcMetadata.issuerHost) {
|
||||
if (vcMetadata) {
|
||||
getCredentialIssuersWellKnownConfig(
|
||||
issuer,
|
||||
CARD_VIEW_DEFAULT_FIELDS,
|
||||
|
||||
@@ -50,7 +50,7 @@ export const VCDetailView: React.FC<VCItemDetailsProps> = (
|
||||
} else if (
|
||||
props.verifiableCredentialData.vcMetadata.format === VCFormat.mso_mdoc
|
||||
) {
|
||||
const namespaces = verifiableCredential['issuerSigned']['nameSpaces'];
|
||||
const namespaces = verifiableCredential['issuerSigned']?.['nameSpaces'] ?? verifiableCredential['nameSpaces']??{};
|
||||
Object.keys(namespaces).forEach(namespace => {
|
||||
(namespaces[namespace] as Array<Object>).forEach(element => {
|
||||
availableFieldNames.push(
|
||||
@@ -119,7 +119,8 @@ export const VCDetailView: React.FC<VCItemDetailsProps> = (
|
||||
margin={'0 0 0 24'}
|
||||
style={{flex: 1}}>
|
||||
{fieldItemIterator(
|
||||
props.fields,
|
||||
props.fields,
|
||||
props.wellknownFieldsFlag,
|
||||
verifiableCredential,
|
||||
props.wellknown,
|
||||
wellknownDisplayProperty,
|
||||
@@ -141,6 +142,7 @@ export const VCDetailView: React.FC<VCItemDetailsProps> = (
|
||||
{shouldShowHrLine(verifiableCredential) &&
|
||||
fieldItemIterator(
|
||||
DETAIL_VIEW_BOTTOM_SECTION_FIELDS,
|
||||
props.wellknownFieldsFlag,
|
||||
verifiableCredential,
|
||||
props.wellknown,
|
||||
wellknownDisplayProperty,
|
||||
@@ -240,6 +242,7 @@ export const VCDetailView: React.FC<VCItemDetailsProps> = (
|
||||
export interface VCItemDetailsProps {
|
||||
fields: any[];
|
||||
wellknown: any;
|
||||
wellknownFieldsFlag: boolean;
|
||||
credential: VerifiableCredential | Credential;
|
||||
verifiableCredentialData: VerifiableCredentialData;
|
||||
walletBindingResponse?: WalletBindingResponse;
|
||||
|
||||
@@ -154,7 +154,7 @@ export const getFieldName = (
|
||||
}
|
||||
}
|
||||
}
|
||||
return i18n.t(`VcDetails:${field}`);
|
||||
return field;
|
||||
};
|
||||
|
||||
export function getAddressFields() {
|
||||
@@ -181,17 +181,72 @@ function getFullAddress(credential: CredentialSubject) {
|
||||
.filter(Boolean)
|
||||
.join(', ');
|
||||
}
|
||||
const renderFieldRecursively = (
|
||||
key: string,
|
||||
value: any,
|
||||
fieldNameColor: string,
|
||||
fieldValueColor: string,
|
||||
parentKey = '',
|
||||
depth = 0
|
||||
): JSX.Element[] => {
|
||||
const fullKey = parentKey ? `${parentKey}.${key}` : key;
|
||||
|
||||
if (value === null || value === undefined) return [];
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return value.flatMap((item, index) =>
|
||||
renderFieldRecursively(`${key}[${index}]`, item, fieldNameColor,fieldValueColor,parentKey, depth + 1)
|
||||
);
|
||||
} else if (typeof value === 'object') {
|
||||
return Object.entries(value).flatMap(([childKey, childValue]) =>
|
||||
renderFieldRecursively(childKey, childValue, fieldNameColor,fieldValueColor,fullKey, depth + 1)
|
||||
);
|
||||
} else {
|
||||
let displayValue = String(value);
|
||||
// Truncate base64 if it's an image data URI or very long string
|
||||
if (displayValue.startsWith('data:image') || displayValue.length > 100) {
|
||||
displayValue = displayValue.slice(0, 60) + '...';
|
||||
}
|
||||
|
||||
return [
|
||||
<Row
|
||||
key={`extra-${fullKey}`}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
flex: 1,
|
||||
paddingLeft: depth * 12, // Indent nested levels
|
||||
}}
|
||||
align="space-between"
|
||||
margin="0 8 15 0"
|
||||
>
|
||||
<VCItemField
|
||||
key={`extra-${fullKey}`}
|
||||
fieldName={fullKey}
|
||||
fieldValue={displayValue}
|
||||
fieldNameColor={fieldNameColor}
|
||||
fieldValueColor={fieldValueColor}
|
||||
testID={`extra-${fullKey}`}
|
||||
/>
|
||||
</Row>,
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export const fieldItemIterator = (
|
||||
fields: any[],
|
||||
wellknownFieldsFlag: boolean,
|
||||
verifiableCredential: VerifiableCredential | Credential,
|
||||
wellknown: any,
|
||||
display: Display,
|
||||
props: VCItemDetailsProps,
|
||||
) => {
|
||||
): JSX.Element[] => {
|
||||
const fieldNameColor = display.getTextColor(Theme.Colors.DetailsLabel);
|
||||
const fieldValueColor = display.getTextColor(Theme.Colors.Details);
|
||||
return fields.map(field => {
|
||||
|
||||
const renderedFields = new Set<string>();
|
||||
|
||||
const renderedMainFields = fields.map(field => {
|
||||
const fieldName = getFieldName(
|
||||
field,
|
||||
wellknown,
|
||||
@@ -205,16 +260,20 @@ export const fieldItemIterator = (
|
||||
display,
|
||||
props.verifiableCredentialData.vcMetadata.format,
|
||||
);
|
||||
renderedFields.add(field);
|
||||
|
||||
if (
|
||||
(field === 'credentialRegistry' &&
|
||||
CREDENTIAL_REGISTRY_EDIT === 'false') ||
|
||||
!fieldValue
|
||||
)
|
||||
return;
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Row
|
||||
key={field}
|
||||
style={{flexDirection: 'row', flex: 1}}
|
||||
style={{ flexDirection: 'row', flex: 1 }}
|
||||
align="space-between"
|
||||
margin="0 8 15 0">
|
||||
<VCItemField
|
||||
@@ -228,13 +287,83 @@ export const fieldItemIterator = (
|
||||
</Row>
|
||||
);
|
||||
});
|
||||
|
||||
let renderedExtraFields: JSX.Element[] = [];
|
||||
|
||||
if (!wellknownFieldsFlag) {
|
||||
const renderedAll: JSX.Element[] = [];
|
||||
|
||||
// Extra fields from credentialSubject
|
||||
const credentialSubjectFields =
|
||||
(verifiableCredential.credentialSubject as Record<string, any>) || {};
|
||||
|
||||
const renderedSubjectFields = Object.entries(credentialSubjectFields)
|
||||
.filter(([key]) => !renderedFields.has(key))
|
||||
.flatMap(([key, value]) =>
|
||||
renderFieldRecursively(key, value, fieldNameColor, fieldValueColor)
|
||||
);
|
||||
|
||||
renderedAll.push(...renderedSubjectFields);
|
||||
|
||||
// Render fields from nameSpaces (mso_mdoc)
|
||||
const nameSpaces: Record<string, any> =
|
||||
verifiableCredential.nameSpaces ??
|
||||
verifiableCredential.issuerSigned?.nameSpaces ??
|
||||
verifiableCredential.issuerAuth?.nameSpaces ??
|
||||
{};
|
||||
|
||||
const renderedNamespaceFields = Object.entries(nameSpaces).flatMap(
|
||||
([namespace, entries]) => {
|
||||
if (!Array.isArray(entries)) return [];
|
||||
|
||||
return [
|
||||
|
||||
<VCItemField
|
||||
key={`ns-title-${namespace}`}
|
||||
fieldName={(namespace)}
|
||||
fieldValue=""
|
||||
fieldNameColor={fieldNameColor}
|
||||
fieldValueColor={fieldValueColor}
|
||||
testID={`ns-title-${namespace}`}
|
||||
/>,
|
||||
...entries.flatMap((entry, index) => [
|
||||
<VCItemField
|
||||
key={`entry-heading-${namespace}-${index}`}
|
||||
fieldName={"--"}
|
||||
fieldValue=""
|
||||
fieldNameColor={fieldNameColor}
|
||||
fieldValueColor={fieldValueColor}
|
||||
testID={`entry-heading-${namespace}-${index}`}
|
||||
/>,
|
||||
...Object.entries(entry).flatMap(([key, value]) =>
|
||||
renderFieldRecursively(
|
||||
key,
|
||||
value,
|
||||
fieldNameColor,
|
||||
fieldValueColor,
|
||||
`${namespace}[${index}]`,
|
||||
1
|
||||
)
|
||||
),
|
||||
]),
|
||||
];
|
||||
}
|
||||
);
|
||||
|
||||
renderedAll.push(...renderedNamespaceFields);
|
||||
renderedExtraFields = renderedAll;
|
||||
}
|
||||
|
||||
return [...renderedMainFields, ...renderedExtraFields];
|
||||
};
|
||||
|
||||
|
||||
|
||||
export const isVCLoaded = (
|
||||
verifiableCredential: Credential | null,
|
||||
fields: string[],
|
||||
) => {
|
||||
return verifiableCredential != null && fields.length > 0;
|
||||
return verifiableCredential != null
|
||||
};
|
||||
|
||||
export const getMosipLogo = () => {
|
||||
@@ -365,4 +494,4 @@ const ProtectedCurve = {
|
||||
|
||||
const PROOF_TYPE_ALGORITHM_MAP = {
|
||||
[-7]: 'ES256',
|
||||
};
|
||||
};
|
||||
@@ -1,36 +1,39 @@
|
||||
import React from 'react';
|
||||
import {Pressable, View} from 'react-native';
|
||||
import {Theme} from '../ui/styleUtils';
|
||||
import { Pressable, View } from 'react-native';
|
||||
import { Theme } from '../ui/styleUtils';
|
||||
import testIDProps from '../../shared/commonUtil';
|
||||
import {Text} from '../ui';
|
||||
import {displayType} from '../../machines/Issuers/IssuersMachine';
|
||||
import {SvgImage} from '../ui/svg';
|
||||
import { Text } from '../ui';
|
||||
import { displayType } from '../../machines/Issuers/IssuersMachine';
|
||||
import { SvgImage } from '../ui/svg';
|
||||
|
||||
export const Issuer: React.FC<IssuerProps> = (props: IssuerProps) => {
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
accessible={false}
|
||||
{...testIDProps(`issuer-${props.testID}`)}
|
||||
onPress={props.onPress}
|
||||
style={({pressed}) =>
|
||||
style={({ pressed }) =>
|
||||
pressed
|
||||
? [
|
||||
Theme.IssuersScreenStyles.issuerBoxContainerPressed,
|
||||
Theme.Styles.boxShadow,
|
||||
]
|
||||
Theme.IssuersScreenStyles.issuerBoxContainerPressed,
|
||||
Theme.Styles.boxShadow,
|
||||
]
|
||||
: [
|
||||
Theme.IssuersScreenStyles.issuerBoxContainer,
|
||||
Theme.Styles.boxShadow,
|
||||
]
|
||||
Theme.IssuersScreenStyles.issuerBoxContainer,
|
||||
Theme.Styles.boxShadow,
|
||||
]
|
||||
}>
|
||||
<View style={Theme.IssuersScreenStyles.issuerBoxIconContainer}>
|
||||
{SvgImage.IssuerIcon(props)}
|
||||
{props.displayDetails.logo
|
||||
? SvgImage.IssuerIcon(props)
|
||||
: SvgImage.defaultIssuerLogo(props.defaultLogo)}
|
||||
</View>
|
||||
<View style={Theme.IssuersScreenStyles.issuerBoxContent}>
|
||||
<Text
|
||||
testID={`issuerHeading-${props.testID}`}
|
||||
style={Theme.IssuersScreenStyles.issuerHeading}>
|
||||
{props.displayDetails.title}
|
||||
{props.displayDetails.title ?? props.displayDetails.name}
|
||||
</Text>
|
||||
<Text
|
||||
testID={`issuerDescription-${props.testID}`}
|
||||
@@ -46,4 +49,5 @@ export interface IssuerProps {
|
||||
displayDetails: displayType;
|
||||
onPress: () => void;
|
||||
testID: string;
|
||||
defaultLogo?: any;
|
||||
}
|
||||
|
||||
@@ -21,10 +21,12 @@ export const Text: React.FC<TextProps> = (props: TextProps) => {
|
||||
{...testIDProps(props.testID)}
|
||||
style={textStyles}
|
||||
numberOfLines={props.numLines}
|
||||
onTextLayout={props.onTextLayout}
|
||||
ellipsizeMode={props.ellipsizeMode}
|
||||
accessible={props.accessible}
|
||||
onPress={props.onPress}>
|
||||
{props.children}
|
||||
|
||||
</RNText>
|
||||
);
|
||||
};
|
||||
@@ -43,4 +45,5 @@ interface TextProps {
|
||||
style?: StyleProp<TextStyle>;
|
||||
accessible?: boolean | true;
|
||||
onPress?: () => void;
|
||||
onTextLayout?: (e: any) => void;
|
||||
}
|
||||
|
||||
@@ -98,6 +98,11 @@ export class SvgImage {
|
||||
);
|
||||
}
|
||||
|
||||
static defaultIssuerLogo(defaultLogo: any) {
|
||||
const DefaultLogo=defaultLogo
|
||||
return <DefaultLogo/>
|
||||
}
|
||||
|
||||
static starIcon() {
|
||||
return (
|
||||
<StarIcon
|
||||
@@ -593,7 +598,7 @@ export class SvgImage {
|
||||
}
|
||||
|
||||
function getIssuerLogo(props: displayType) {
|
||||
return {uri: props.logo.url};
|
||||
return {uri: props.logo.url || props.logo.uri};
|
||||
}
|
||||
|
||||
interface LogoProps {
|
||||
|
||||
@@ -864,7 +864,7 @@ export const DefaultTheme = {
|
||||
flex: 1,
|
||||
fontSize: 33,
|
||||
fontFamily: 'Inter_600SemiBold',
|
||||
height: 40,
|
||||
height: 50,
|
||||
lineHeight: 28,
|
||||
margin: 8,
|
||||
textAlign: 'center',
|
||||
@@ -876,7 +876,7 @@ export const DefaultTheme = {
|
||||
flex: 1,
|
||||
fontFamily: 'Inter_700Bold',
|
||||
fontSize: 29,
|
||||
height: 40,
|
||||
height: 50,
|
||||
margin: 8,
|
||||
textAlign: 'center',
|
||||
},
|
||||
@@ -1940,6 +1940,120 @@ export const DefaultTheme = {
|
||||
},
|
||||
}),
|
||||
|
||||
TransactionCodeScreenStyle: StyleSheet.create({
|
||||
showMoreButton: {
|
||||
alignItems: 'flex-end',
|
||||
marginTop: 6,
|
||||
marginBottom: 10,
|
||||
marginRight: -Dimensions.get('window').width + 150,
|
||||
fontSize: 12,
|
||||
fontWeight: '600',
|
||||
color: Colors.Grey,
|
||||
},
|
||||
errorView: {
|
||||
backgroundColor: '#FAEFEF',
|
||||
padding: 8,
|
||||
borderRadius: 10,
|
||||
marginBottom: 10,
|
||||
marginTop: 10,
|
||||
width: '80%',
|
||||
},
|
||||
inputStyle: {
|
||||
fontSize: 20,
|
||||
fontWeight: '500',
|
||||
textAlign: 'center',
|
||||
},
|
||||
confirmationModalView: {
|
||||
flex: 1,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.4)',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 40,
|
||||
},
|
||||
confirmationModalContentHeading: {
|
||||
fontSize: 18,
|
||||
fontWeight: '600',
|
||||
textAlign: 'center',
|
||||
marginBottom: 5,
|
||||
},
|
||||
confirmationModalContentSubHeading: {
|
||||
fontSize: 14,
|
||||
color: '#888',
|
||||
marginTop: 12,
|
||||
textAlign: 'center',
|
||||
lineHeight: 20,
|
||||
marginBottom: 20,
|
||||
},
|
||||
confirmationModalInnerView: {
|
||||
backgroundColor: 'white',
|
||||
borderRadius: 20,
|
||||
paddingVertical: 35,
|
||||
paddingHorizontal: 24,
|
||||
alignItems: 'center',
|
||||
},
|
||||
}),
|
||||
|
||||
TrustIssuerScreenStyle: StyleSheet.create({
|
||||
modalOverlay: {
|
||||
flex: 1,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: 20,
|
||||
},
|
||||
modalContainer: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: 20,
|
||||
width: '100%',
|
||||
padding: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
issuerHeader: {
|
||||
padding: 10,
|
||||
alignItems: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
issuerLogo: {
|
||||
width: 60,
|
||||
height: 60,
|
||||
resizeMode: 'contain',
|
||||
},
|
||||
issuerName: {
|
||||
marginTop: 8,
|
||||
fontWeight: 'bold',
|
||||
fontSize: 16,
|
||||
},
|
||||
description: {
|
||||
fontSize: 14,
|
||||
color: '#666',
|
||||
textAlign: 'center',
|
||||
lineHeight: 20,
|
||||
marginBottom: 24,
|
||||
},
|
||||
}),
|
||||
|
||||
AuthWebViewScreenStyle: StyleSheet.create({
|
||||
header: {
|
||||
height: 56,
|
||||
paddingHorizontal: 16,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: '#F5F5F5',
|
||||
borderBottomWidth: 1,
|
||||
borderColor: '#E0E0E0',
|
||||
},
|
||||
headerText: {
|
||||
fontSize: 18,
|
||||
fontWeight: '500',
|
||||
},
|
||||
loader: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
}),
|
||||
|
||||
ICON_SMALL_SIZE: 16,
|
||||
ICON_MID_SIZE: 22,
|
||||
ICON_LARGE_SIZE: 33,
|
||||
|
||||
@@ -1943,6 +1943,118 @@ export const PurpleTheme = {
|
||||
paddingTop: 10,
|
||||
},
|
||||
}),
|
||||
TransactionCodeScreenStyle: StyleSheet.create({
|
||||
showMoreButton: {
|
||||
alignItems: 'flex-end',
|
||||
marginTop: 6,
|
||||
marginBottom: 10,
|
||||
marginRight: -Dimensions.get('window').width + 150,
|
||||
fontSize: 12,
|
||||
fontWeight: '600',
|
||||
color: Colors.Grey,
|
||||
},
|
||||
errorView: {
|
||||
backgroundColor: '#FAEFEF',
|
||||
padding: 8,
|
||||
borderRadius: 10,
|
||||
marginBottom: 10,
|
||||
marginTop: 10,
|
||||
width: '80%',
|
||||
},
|
||||
inputStyle: {
|
||||
fontSize: 20,
|
||||
fontWeight: '500',
|
||||
textAlign: 'center',
|
||||
},
|
||||
confirmationModalView: {
|
||||
flex: 1,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.4)',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 40,
|
||||
},
|
||||
confirmationModalContentHeading: {
|
||||
fontSize: 18,
|
||||
fontWeight: '600',
|
||||
textAlign: 'center',
|
||||
marginBottom: 5,
|
||||
},
|
||||
confirmationModalContentSubHeading: {
|
||||
fontSize: 14,
|
||||
color: '#888',
|
||||
marginTop: 12,
|
||||
textAlign: 'center',
|
||||
lineHeight: 20,
|
||||
marginBottom: 20,
|
||||
},
|
||||
confirmationModalInnerView: {
|
||||
backgroundColor: 'white',
|
||||
borderRadius: 20,
|
||||
paddingVertical: 35,
|
||||
paddingHorizontal: 24,
|
||||
alignItems: 'center',
|
||||
},
|
||||
}),
|
||||
TrustIssuerScreenStyle: StyleSheet.create({
|
||||
modalOverlay: {
|
||||
flex: 1,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: 20,
|
||||
},
|
||||
modalContainer: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: 20,
|
||||
width: '100%',
|
||||
padding: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
issuerHeader: {
|
||||
padding: 10,
|
||||
alignItems: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
issuerLogo: {
|
||||
width: 60,
|
||||
height: 60,
|
||||
resizeMode: 'contain',
|
||||
},
|
||||
issuerName: {
|
||||
marginTop: 8,
|
||||
fontWeight: 'bold',
|
||||
fontSize: 16,
|
||||
},
|
||||
description: {
|
||||
fontSize: 14,
|
||||
color: '#666',
|
||||
textAlign: 'center',
|
||||
lineHeight: 20,
|
||||
marginBottom: 24,
|
||||
},
|
||||
}),
|
||||
|
||||
AuthWebViewScreenStyle: StyleSheet.create({
|
||||
header: {
|
||||
height: 56,
|
||||
paddingHorizontal: 16,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: '#F5F5F5',
|
||||
borderBottomWidth: 1,
|
||||
borderColor: '#E0E0E0',
|
||||
},
|
||||
headerText: {
|
||||
fontSize: 18,
|
||||
fontWeight: '500',
|
||||
},
|
||||
loader: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
}),
|
||||
|
||||
ICON_SMALL_SIZE: 16,
|
||||
ICON_MID_SIZE: 22,
|
||||
|
||||
Reference in New Issue
Block a user