mirror of
https://github.com/selfxyz/self.git
synced 2026-01-09 14:48:06 -05:00
App polish for 2.9 rd1 (#1359)
* add useSafeBottomPadding * add bottom padding to dev screen * use safe bottom padding * skip uploading if building android bundle locally * fix tests * cache fix script * clean up country picker, fix font color * sort package jsons, add watcher for mobile sdk * formatting * only bump versions for successfull builds * move all css * cleaner script * kill watchers before starting new one
This commit is contained in:
@@ -110,10 +110,10 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build": "yarn build:android && yarn build:ios && tsup && yarn postbuild",
|
||||
"build:ts-only": "tsup && yarn postbuild",
|
||||
"postbuild": "node ./scripts/postBuild.mjs",
|
||||
"build:android": "sh ./scripts/build-android.sh",
|
||||
"build:ios": "sh ./scripts/build-ios.sh",
|
||||
"postbuild": "node ./scripts/postBuild.mjs",
|
||||
"build:ts-only": "tsup && yarn postbuild",
|
||||
"fmt": "prettier --check .",
|
||||
"fmt:fix": "prettier --write .",
|
||||
"format": "sh -c 'if [ -z \"$SKIP_BUILD_DEPS\" ]; then yarn nice; else yarn fmt:fix; fi'",
|
||||
@@ -127,7 +127,8 @@
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit",
|
||||
"types": "tsc -p tsconfig.json --noEmit",
|
||||
"validate:exports": "node ./scripts/validate-exports.mjs",
|
||||
"validate:pkg": "node ./scripts/verify-conditions.mjs"
|
||||
"validate:pkg": "node ./scripts/verify-conditions.mjs",
|
||||
"watch": "pkill -f 'tsup.*--watch' 2>/dev/null || true && tsup && yarn postbuild && tsup --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.28.3",
|
||||
|
||||
@@ -45,9 +45,9 @@ export function useCountries() {
|
||||
|
||||
if (result.status === 'success') {
|
||||
setCountryData(result.data);
|
||||
if (__DEV__) {
|
||||
console.log('Set country data:', result.data);
|
||||
}
|
||||
// if (__DEV__) {
|
||||
// console.log('Set country data:', result.data);
|
||||
// }
|
||||
} else {
|
||||
console.error('API returned non-success status:', result.status);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { Dimensions, StyleSheet } from 'react-native';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import type { DocumentCategory } from '@selfxyz/common/utils/types';
|
||||
|
||||
@@ -17,6 +17,7 @@ import { black, white } from '../../constants/colors';
|
||||
import { useSelfClient } from '../../context';
|
||||
import { loadSelectedDocument } from '../../documents/utils';
|
||||
import { notificationSuccess } from '../../haptic';
|
||||
import { useSafeBottomPadding } from '../../hooks/useSafeBottomPadding';
|
||||
import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout';
|
||||
import { SdkEvents } from '../../types/events';
|
||||
import type { SelfClient } from '../../types/public';
|
||||
@@ -38,17 +39,7 @@ export const ConfirmIdentificationScreen = ({ onBeforeConfirm }: { onBeforeConfi
|
||||
await onConfirm(selfClient);
|
||||
}, [onBeforeConfirm, selfClient]);
|
||||
|
||||
// Calculate total bottom padding: base padding + fallback for smaller screens
|
||||
const paddingBottom = useMemo(() => {
|
||||
const basePadding = 20;
|
||||
|
||||
// Estimate for smaller screens to account for safe areas
|
||||
const windowHeight = Dimensions.get('window').height;
|
||||
const isSmallScreen = windowHeight < 900;
|
||||
const fallbackPadding = isSmallScreen ? 50 : 0;
|
||||
|
||||
return basePadding + fallbackPadding;
|
||||
}, []);
|
||||
const paddingBottom = useSafeBottomPadding(20);
|
||||
|
||||
return (
|
||||
<ExpandableBottomLayout.Layout backgroundColor={black}>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { memo, useCallback } from 'react';
|
||||
import { ActivityIndicator, FlatList, TouchableOpacity, View } from 'react-native';
|
||||
import { ActivityIndicator, FlatList, StyleSheet, TouchableOpacity, View } from 'react-native';
|
||||
|
||||
import { commonNames } from '@selfxyz/common/constants/countries';
|
||||
|
||||
@@ -32,15 +32,10 @@ const CountryItem = memo<{
|
||||
if (!countryName) return null;
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={() => onSelect(countryCode)}
|
||||
style={{
|
||||
paddingVertical: 13,
|
||||
}}
|
||||
>
|
||||
<XStack alignItems="center" gap={16}>
|
||||
<TouchableOpacity onPress={() => onSelect(countryCode)} style={styles.countryItemContainer}>
|
||||
<XStack style={styles.countryItemContent}>
|
||||
<RoundFlag countryCode={countryCode} size={FLAG_SIZE} />
|
||||
<BodyText style={{ fontSize: 16, color: black, flex: 1 }}>{countryName}</BodyText>
|
||||
<BodyText style={styles.countryItemText}>{countryName}</BodyText>
|
||||
</XStack>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
@@ -49,7 +44,7 @@ const CountryItem = memo<{
|
||||
CountryItem.displayName = 'CountryItem';
|
||||
|
||||
const Loading = () => (
|
||||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
||||
<View style={styles.loadingContainer}>
|
||||
<ActivityIndicator size="small" />
|
||||
</View>
|
||||
);
|
||||
@@ -63,11 +58,11 @@ const CountryPickerScreen: React.FC = () => {
|
||||
const onPressCountry = useCallback(
|
||||
(countryCode: string) => {
|
||||
buttonTap();
|
||||
if (__DEV__) {
|
||||
console.log('Selected country code:', countryCode);
|
||||
console.log('Current countryData:', countryData);
|
||||
console.log('Available country codes:', Object.keys(countryData));
|
||||
}
|
||||
// if (__DEV__) {
|
||||
// console.log('Selected country code:', countryCode);
|
||||
// console.log('Current countryData:', countryData);
|
||||
// console.log('Available country codes:', Object.keys(countryData));
|
||||
// }
|
||||
const documentTypes = countryData[countryCode];
|
||||
if (__DEV__) {
|
||||
console.log('documentTypes for', countryCode, ':', documentTypes);
|
||||
@@ -111,8 +106,8 @@ const CountryPickerScreen: React.FC = () => {
|
||||
return (
|
||||
<YStack flex={1} paddingTop="$4" paddingHorizontal="$4" backgroundColor={slate100}>
|
||||
<YStack marginTop="$4" marginBottom="$6">
|
||||
<BodyText style={{ fontSize: 29, fontFamily: advercase }}>Select the country that issued your ID</BodyText>
|
||||
<BodyText style={{ fontSize: 16, color: slate500, marginTop: 20 }}>
|
||||
<BodyText style={styles.titleText}>Select the country that issued your ID</BodyText>
|
||||
<BodyText style={styles.subtitleText}>
|
||||
Self has support for over 300 ID types. You can select the type of ID in the next step
|
||||
</BodyText>
|
||||
</YStack>
|
||||
@@ -122,32 +117,12 @@ const CountryPickerScreen: React.FC = () => {
|
||||
<YStack flex={1}>
|
||||
{showSuggestion && (
|
||||
<YStack marginBottom="$2">
|
||||
<BodyText
|
||||
style={{
|
||||
fontSize: 16,
|
||||
color: black,
|
||||
fontFamily: dinot,
|
||||
letterSpacing: 0.8,
|
||||
marginBottom: 8,
|
||||
}}
|
||||
>
|
||||
SUGGESTION
|
||||
</BodyText>
|
||||
<BodyText style={styles.sectionLabel}>SUGGESTION</BodyText>
|
||||
<CountryItem
|
||||
countryCode={userCountryCode as string /*safe due to showSuggestion*/}
|
||||
onSelect={onPressCountry}
|
||||
/>
|
||||
<BodyText
|
||||
style={{
|
||||
fontSize: 16,
|
||||
color: black,
|
||||
fontFamily: dinot,
|
||||
letterSpacing: 0.8,
|
||||
marginTop: 20,
|
||||
}}
|
||||
>
|
||||
SELECT AN ISSUING COUNTRY
|
||||
</BodyText>
|
||||
<BodyText style={styles.sectionLabelBottom}>SELECT AN ISSUING COUNTRY</BodyText>
|
||||
</YStack>
|
||||
)}
|
||||
<FlatList
|
||||
@@ -169,4 +144,48 @@ const CountryPickerScreen: React.FC = () => {
|
||||
};
|
||||
CountryPickerScreen.displayName = 'CountryPickerScreen';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
countryItemContainer: {
|
||||
paddingVertical: 13,
|
||||
},
|
||||
countryItemContent: {
|
||||
alignItems: 'center',
|
||||
gap: 16,
|
||||
},
|
||||
countryItemText: {
|
||||
fontSize: 16,
|
||||
color: black,
|
||||
flex: 1,
|
||||
},
|
||||
loadingContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
titleText: {
|
||||
fontSize: 29,
|
||||
fontFamily: advercase,
|
||||
color: black,
|
||||
},
|
||||
subtitleText: {
|
||||
fontSize: 16,
|
||||
color: slate500,
|
||||
marginTop: 20,
|
||||
},
|
||||
sectionLabel: {
|
||||
fontSize: 16,
|
||||
color: black,
|
||||
fontFamily: dinot,
|
||||
letterSpacing: 0.8,
|
||||
marginBottom: 8,
|
||||
},
|
||||
sectionLabelBottom: {
|
||||
fontSize: 16,
|
||||
color: black,
|
||||
fontFamily: dinot,
|
||||
letterSpacing: 0.8,
|
||||
marginTop: 20,
|
||||
},
|
||||
});
|
||||
|
||||
export default CountryPickerScreen;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import type React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import AadhaarLogo from '../../../svgs/icons/aadhaar.svg';
|
||||
import EPassportLogoRounded from '../../../svgs/icons/epassport_rounded.svg';
|
||||
@@ -105,16 +106,7 @@ const IDSelectionScreen: React.FC<IDSelectionScreenProps> = props => {
|
||||
<SelfLogo width={24} height={24} />
|
||||
</YStack>
|
||||
</XStack>
|
||||
<BodyText
|
||||
style={{
|
||||
marginTop: 48,
|
||||
fontSize: 29,
|
||||
fontFamily: advercase,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
Select an ID type
|
||||
</BodyText>
|
||||
<BodyText style={styles.titleText}>Select an ID type</BodyText>
|
||||
</YStack>
|
||||
<YStack gap="$3">
|
||||
{documentTypes.map((docType: string) => (
|
||||
@@ -135,35 +127,42 @@ const IDSelectionScreen: React.FC<IDSelectionScreenProps> = props => {
|
||||
<XStack alignItems="center" gap={'$3'} flex={1}>
|
||||
{getDocumentLogo(docType)}
|
||||
<YStack gap={'$1'}>
|
||||
<BodyText style={{ fontSize: 24, fontFamily: dinot, color: black }}>
|
||||
{getDocumentName(docType)}
|
||||
</BodyText>
|
||||
<BodyText
|
||||
style={{
|
||||
fontSize: 14,
|
||||
fontFamily: dinot,
|
||||
color: slate400,
|
||||
}}
|
||||
>
|
||||
{getDocumentDescription(docType)}
|
||||
</BodyText>
|
||||
<BodyText style={styles.documentNameText}>{getDocumentName(docType)}</BodyText>
|
||||
<BodyText style={styles.documentDescriptionText}>{getDocumentDescription(docType)}</BodyText>
|
||||
</YStack>
|
||||
</XStack>
|
||||
</XStack>
|
||||
))}
|
||||
<BodyText
|
||||
style={{
|
||||
fontSize: 18,
|
||||
fontFamily: dinot,
|
||||
color: slate400,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
Be sure your document is ready to scan
|
||||
</BodyText>
|
||||
<BodyText style={styles.footerText}>Be sure your document is ready to scan</BodyText>
|
||||
</YStack>
|
||||
</YStack>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
titleText: {
|
||||
marginTop: 48,
|
||||
fontSize: 29,
|
||||
fontFamily: advercase,
|
||||
textAlign: 'center',
|
||||
color: black,
|
||||
},
|
||||
documentNameText: {
|
||||
fontSize: 24,
|
||||
fontFamily: dinot,
|
||||
color: black,
|
||||
},
|
||||
documentDescriptionText: {
|
||||
fontSize: 14,
|
||||
fontFamily: dinot,
|
||||
color: slate400,
|
||||
},
|
||||
footerText: {
|
||||
fontSize: 18,
|
||||
fontFamily: dinot,
|
||||
color: slate400,
|
||||
textAlign: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
export default IDSelectionScreen;
|
||||
|
||||
5
packages/mobile-sdk-alpha/src/hooks/index.ts
Normal file
5
packages/mobile-sdk-alpha/src/hooks/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
export { useSafeBottomPadding } from './useSafeBottomPadding';
|
||||
33
packages/mobile-sdk-alpha/src/hooks/useSafeBottomPadding.ts
Normal file
33
packages/mobile-sdk-alpha/src/hooks/useSafeBottomPadding.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { Dimensions } from 'react-native';
|
||||
|
||||
/**
|
||||
* Custom hook to calculate bottom padding that prevents UI elements from bleeding
|
||||
* into the system navigation area on smaller screens.
|
||||
*
|
||||
* This hook uses screen height detection to add extra padding for smaller screens
|
||||
* (< 900px height) to account for system navigation bars and safe areas.
|
||||
*
|
||||
* @param basePadding - Base padding to add (default: 20)
|
||||
* @returns Total bottom padding value
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* // For use with ExpandableBottomLayout.BottomSection
|
||||
* const bottomPadding = useSafeBottomPadding(20);
|
||||
* <ExpandableBottomLayout.BottomSection paddingBottom={bottomPadding} />
|
||||
* ```
|
||||
*/
|
||||
export const useSafeBottomPadding = (basePadding: number = 20): number => {
|
||||
const { height: windowHeight } = Dimensions.get('window');
|
||||
|
||||
return useMemo(() => {
|
||||
const isSmallScreen = windowHeight < 900;
|
||||
const fallbackPadding = isSmallScreen ? 50 : 0;
|
||||
return basePadding + fallbackPadding;
|
||||
}, [windowHeight, basePadding]);
|
||||
};
|
||||
@@ -40,6 +40,8 @@ const entry = {
|
||||
'constants/analytics': 'src/constants/analytics.ts',
|
||||
'constants/colors': 'src/constants/colors.ts',
|
||||
'components/index': 'src/components/index.ts',
|
||||
'hooks/index': 'src/hooks/index.ts',
|
||||
'hooks/useSafeBottomPadding': 'src/hooks/useSafeBottomPadding.ts',
|
||||
stores: 'src/stores/index.ts',
|
||||
...flowEntries,
|
||||
};
|
||||
|
||||
22
packages/mobile-sdk-demo/ios/scripts/pod-install-with-cache-fix.sh
Executable file
22
packages/mobile-sdk-demo/ios/scripts/pod-install-with-cache-fix.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Pod install with hermes-engine cache fix for React Native upgrades
|
||||
# This script handles CocoaPods cache mismatches that occur after React Native version upgrades
|
||||
|
||||
set -e # Exit on any error
|
||||
|
||||
echo "🧹 Clearing CocoaPods cache to prevent hermes-engine version conflicts..."
|
||||
pod cache clean --all > /dev/null 2>&1 || true
|
||||
rm -rf ~/Library/Caches/CocoaPods > /dev/null 2>&1 || true
|
||||
|
||||
echo "📦 Attempting pod install..."
|
||||
if pod install; then
|
||||
echo "✅ Pods installed successfully"
|
||||
else
|
||||
echo "⚠️ Pod install failed, likely due to hermes-engine cache mismatch after React Native upgrade"
|
||||
echo "🔧 Running targeted fix: pod update hermes-engine..."
|
||||
pod update hermes-engine --no-repo-update
|
||||
echo "🔄 Retrying pod install..."
|
||||
pod install
|
||||
echo "✅ Pods installed successfully after cache fix"
|
||||
fi
|
||||
@@ -23,9 +23,9 @@
|
||||
"reinstall": "yarn clean && yarn install && yarn prebuild && cd ios && pod install && cd ..",
|
||||
"start": "react-native start",
|
||||
"test": "vitest run",
|
||||
"test:e2e:android": "bash scripts/e2e-android-ci.sh",
|
||||
"test:watch": "vitest",
|
||||
"types": "yarn prebuild && tsc --noEmit",
|
||||
"test:e2e:android": "bash scripts/e2e-android-ci.sh"
|
||||
"types": "yarn prebuild && tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.28.3",
|
||||
|
||||
Reference in New Issue
Block a user