Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
"orientation": "portrait",
"newArchEnabled": true,
"icon": "./src/assets/images/icon.png",
"assetBundlePatterns": [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expoBundlePatterns is deprecated, please elaborate.

expo/expo#26962

"src/assets/fonts/*"
],
"web": {
"bundler": "metro"
},
Expand Down
33 changes: 33 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
"private": true,
"dependencies": {
"@babel/plugin-proposal-export-namespace-from": "^7.18.9",
"@expo-google-fonts/exo-2": "^0.4.2",
"@expo-google-fonts/inter": "^0.2.3",
"@expo-google-fonts/open-sans": "^0.4.2",
"@expo-google-fonts/roboto": "^0.4.1",
"@expo/vector-icons": "^14.1.0",
"@kolking/react-native-avatar": "^2.1.4",
"@react-native-async-storage/async-storage": "2.1.2",
Expand All @@ -24,6 +27,7 @@
"expo-dev-client": "~5.2.4",
"expo-font": "~13.3.2",
"expo-haptics": "~14.1.4",
"expo-linear-gradient": "^15.0.7",
"expo-linking": "~7.1.7",
"expo-localization": "~16.1.6",
"expo-router": "~5.1.6",
Expand Down
8 changes: 2 additions & 6 deletions src/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import React, { useEffect, useState } from 'react'
import { I18nextProvider } from 'react-i18next'
import { Provider } from 'react-redux'
import { MaintenanceScreen, LoadingScreen, AppUpdatePopup } from '@/components'
// eslint-disable-next-line camelcase
import { useFonts, Inter_400Regular } from '@expo-google-fonts/inter'
import { useCustomFonts } from '@/hooks'
import RootContainer from '@/components/RootContainer'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import * as Sentry from '@sentry/react-native'
Expand Down Expand Up @@ -72,10 +71,7 @@ const RootLayout = () => {

// Specify the type of the state to be either null or an EnhancedStore instance
const [reduxStore, setReduxStore] = useState<EnhancedStore<RootState> | null>(null)
let [fontsLoaded] = useFonts({
// eslint-disable-next-line camelcase
Inter: Inter_400Regular,
})
const { fontsLoaded } = useCustomFonts()

useEffect(() => {
initStore().then((store) => {
Expand Down
7 changes: 4 additions & 3 deletions src/app/welcome/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import RootImageBackground from '@/components/RootImageBackground'
Copy link
Collaborator

@amrmelsayed amrmelsayed Oct 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RootImageBackground has two platform specific implementations, a web version and native version (.tsx, .web.tsx), and they are getting replaced with a single version, was this done on purpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RootImageBackground.web.tsx is there but seems to be not used at all in any place.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ajmaljalal that's a platform specific extension, have a look here https://docs.expo.dev/router/advanced/platform-specific-modules/


import WelcomeRootImageBackground from '@/components/welcome/WelcomRootImageBackground'
import { useAuth } from '@/hooks'
import { Redirect, Slot } from 'expo-router'
import React from 'react'
Expand All @@ -18,11 +19,11 @@ export const WelcomeLayout = () => {
}

return (
<RootImageBackground>
<WelcomeRootImageBackground>
<View className='flex-1'>
<Slot />
</View>
</RootImageBackground>
</WelcomeRootImageBackground>
)
}

Expand Down
210 changes: 142 additions & 68 deletions src/app/welcome/index.tsx
Original file line number Diff line number Diff line change
@@ -1,100 +1,174 @@
import { LogoIcon, LogoTextIcon } from '@/components/svg'
import { LogoIcon } from '@/components/svg'
import ActionButtons from '@/components/ActionButtons'
import StyledText from '@/components/StyledText'
import TermsAndPrivacy from '@/components/TermsAndPrivacy'
import { ENButton, WelcomeFeatureRow, WelcomeFooter } from '@/components'
import { useDirection, useGuest, useScreenInfo } from '@/hooks'
import { RootState } from '@/store'
import { createGeneralThemedStyles } from '@/utils'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, View } from 'react-native'
import { View, Text } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { useSelector } from 'react-redux'
import { useRouter } from 'expo-router'
import { LinearGradient } from 'expo-linear-gradient'

const Welcome: React.FC = () => {
const router = useRouter()
const { t } = useTranslation()
const insets = useSafeAreaInsets()

const { guestLoading, handleGuestLogin } = useGuest()
const { isRTL } = useDirection()
const { isSmallScreen, width } = useScreenInfo()
const theme = useSelector((state: RootState) => state.theme.theme)
const generalStyle = createGeneralThemedStyles(theme, isRTL, isSmallScreen, width)


return (
<View className='flex-1'>
<View className={`flex-1 w-full flex ${isSmallScreen ? 'flex-col' : 'flex-row'} justify-center items-center`}>
<View className={`${isSmallScreen ? 'w-full h-auto' : 'w-[70%] h-full'} justify-between p-6`}>
<View className={`${isSmallScreen ? 'flex-col' : 'flex-row'} items-center ${isSmallScreen ? 'mb-6' : ''}`}>
<LogoIcon fill={theme.iconFill} width={52} height={52} />
<LogoTextIcon
fill={theme.logoColor}
width={81}
className={`${isRTL || isSmallScreen ? '' : 'ml-2'} ${isRTL && !isSmallScreen ? 'mr-2' : ''}`}
/>
<LinearGradient
colors={['rgba(255, 255, 255, 0.8)', 'rgba(255, 255, 255, 1)', 'rgba(255, 255, 255, 1)']}
locations={[0, 0.6, 1]}
style={{ flex: 1 }}
>
<View
className={`absolute w-full px-6 flex ${isRTL ? 'items-start' : 'items-end'} z-50`}
style={{ top: Math.max(insets.top, 24) + 12 }}
>
<ActionButtons isTop={true} />
</View>
<View className='flex-1 w-full flex flex-col justify-center items-center p-6'>
<View className='w-full max-w-[400px] items-center'>
<View className='items-center mb-4'>
<LogoIcon fill={theme.darkGreenColor} width={64} height={64} />
</View>
<View>
<StyledText variant='h1' className='font-normal' color={theme.textColor}>
{t('greeting')}
<View className='items-center mb-6'>
<StyledText
variant='h3'
textAlign='center'
className='uppercase tracking-widest'
style={{ color: theme.darkGreenColor, marginBottom: 6, fontFamily: 'Exo2' }}
>
{t('welcomeHeadingSmall', { defaultValue: t('greeting') })}
</StyledText>
<StyledText variant='h1' className='font-bold' color='yellow'>
{t('ansariChat')}
<StyledText
variant='h1'
textAlign='center'
style={{ color: theme.darkGreenColor, width: 500, fontFamily: 'Exo2-Bold' }}
>
{t('welcomeHeadingMain', { defaultValue: t('ansariChat') })}
</StyledText>
</View>
<View>{!isSmallScreen && <ActionButtons isTop={false} />}</View>
</View>
<View
className={`${isSmallScreen ? 'w-full h-auto' : 'w-[30%] h-full my-auto'} justify-center items-center p-6 ${
isSmallScreen ? 'bg-transparent' : ''
}`}
style={{
backgroundColor: isSmallScreen ? undefined : theme.backgroundColor,
}}
>
<View className='w-full items-center px-[10%]'>
<StyledText variant='h2' className='mb-4'>
{t('getStarted')}
</StyledText>
<Pressable
style={[generalStyle.buttonPrimary, generalStyle.fullWidth]}
onPress={() => router.push('/login')}
>
<StyledText style={generalStyle.buttonPrimaryText}>{t('login')}</StyledText>
</Pressable>
<Pressable
className='border'
style={[
generalStyle.buttonPrimary,
generalStyle.fullWidth,
{
backgroundColor: theme.popupBackgroundColor,
borderColor: theme.buttonSecondaryBorderColor,
},
]}
onPress={() => router.push('/register')}
>
<StyledText style={generalStyle.buttonSecondaryText}>{t('register')}</StyledText>
</Pressable>
<Pressable
style={[
generalStyle.buttonSecondary,
generalStyle.fullWidth,
guestLoading && generalStyle.buttonDisabled,
]}
onPress={handleGuestLogin}
disabled={guestLoading}


<View
className='rounded-[16px] p-4 mb-[34px]'
style={{
borderWidth: 1,
borderColor: theme.darkGreenColor,
}}
>
<View
style={{
width: 230,
}}
>
<StyledText style={[generalStyle.buttonSecondaryText, guestLoading && generalStyle.buttonTextDisabled]}>
{guestLoading ? t('login:submitting') : t('login:guestLogin')}
</StyledText>
</Pressable>
<Text
className='text-[16px] leading-[24px] text-center'
style={{
color: '#000000',
fontStyle: 'italic',
fontFamily: 'Exo2-Bold-Italic',
}}
>
{t('welcomeBlurb', {
defaultValue:
'Built by Muslims, trained with care - designed to guide with sources, not guesses.',
})}
</Text>
</View>
</View>

<View className='w-full mb-8'>
<View className={`flex-col ${isRTL ? 'items-end' : 'items-start'} gap-3`}>
<WelcomeFeatureRow
iconName="information"
text={t('welcomeFeatureSourceBased', { defaultValue: 'Get Source-Based Guidance Anytime' })}
/>
<WelcomeFeatureRow
iconName="chat"
text={t('welcomeFeatureSaveChats', {
defaultValue: 'Save your chats and pick up where you left off.',
})}
/>
<WelcomeFeatureRow
iconName="check"
text={t('welcomeFeatureQuickEasy', { defaultValue: 'Quick and easy registration' })}
/>
<WelcomeFeatureRow
iconName="logo"
text={t('welcomeFeatureJoinToday', { defaultValue: 'Join Ansari today!' })}
/>
</View>
</View>
<View className='w-full items-center'>
<ENButton
text={t('createAccount', { defaultValue: 'Create an account' })}
onClick={() => router.push('/register')}
isSubmitting={false}
buttonStyle={{
marginBottom: 12,
borderRadius: 16,
width: '100%',
paddingVertical: 20,
backgroundColor: theme.darkGreenColor,
alignItems: 'center',
}}
buttonTextStyle={{
fontSize: 20,
color: '#FFFFFF',
}}
/>
<ENButton
text={t('logInCta', { defaultValue: 'Log-in' })}
onClick={() => router.push('/login')}
isSubmitting={false}
buttonStyle={{
...generalStyle.buttonSecondary,
marginBottom: 12,
borderRadius: 16,
width: '100%',
paddingVertical: 20,
backgroundColor: 'rgba(22,160,133, 0.4)',
alignItems: 'center',
borderWidth: 0,

}}
buttonTextStyle={{
color: '#000000',
fontSize: 20,
}}
/>
<ENButton
text={t('continueAsGuestLimited', { defaultValue: 'Continue as guest (limited access)' })}
submittingText={t('login:submitting')}
onClick={handleGuestLogin}
isSubmitting={guestLoading}
buttonStyle={{
backgroundColor: 'transparent',
marginTop: 4,
}}
buttonTextStyle={{
color: '#000000',
fontSize: 14,
textAlign: 'center',
}}
/>
</View>
</View>
<View className='absolute bottom-6'>
<TermsAndPrivacy marginLeft={0} />
</View>
</View>
</View>
<WelcomeFooter />
</LinearGradient>
)
}

Expand Down
Empty file added src/assets/fonts/.keep
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this file/folder?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed, not needed for now. we can add when we need it, does not have to be before hand.

Empty file.
Binary file added src/assets/images/welcome-background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading