-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
10 changed files
with
311 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import React, {useEffect, useState} from 'react'; | ||
import {ScrollView} from 'react-native'; | ||
import {TextInput} from 'react-native-gesture-handler'; | ||
import {View, Text, Colors} from 'react-native-ui-lib'; | ||
import {observer} from 'mobx-react'; | ||
import {NavioScreen} from 'rn-navio'; | ||
|
||
import {useStores} from '@app/stores'; | ||
import {useServices} from '@app/services'; | ||
import {useAppearance} from '@app/utils/hooks'; | ||
import {BButton} from '@app/components/button'; | ||
|
||
export type Props = { | ||
type?: 'push'; | ||
}; | ||
|
||
export const AuthLogin: NavioScreen<Props> = observer(({type = 'push'}) => { | ||
useAppearance(); // for Dark Mode | ||
const {t, navio, api} = useServices(); | ||
const {auth} = useStores(); | ||
|
||
// State | ||
const [loading, setLoading] = useState(false); | ||
const [password, setPassword] = useState(''); | ||
|
||
// Start | ||
useEffect(() => { | ||
configureUI(); | ||
}, []); | ||
|
||
// API Methods | ||
const login = async () => { | ||
setLoading(true); | ||
|
||
try { | ||
const {status} = await api.auth.login(); // fake login | ||
|
||
if (status === 'success') { | ||
// marking that we are logged in | ||
auth.set('state', 'logged-in'); | ||
|
||
// navigating to main app | ||
navio.setRoot('tabs', 'AppTabs'); | ||
} | ||
} catch (e) { | ||
// handle error | ||
} finally { | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
// Methods | ||
const configureUI = () => {}; | ||
|
||
const setEmail = (v: string) => auth.set('email', v); | ||
|
||
return ( | ||
<View flex bg-bgColor> | ||
<ScrollView contentInsetAdjustmentBehavior="always"> | ||
<View> | ||
<View flex centerH marginT-30> | ||
<Text text50>Login</Text> | ||
|
||
<Text grey30 marginT-4> | ||
just fill in any credentials | ||
</Text> | ||
</View> | ||
|
||
<View marginT-s6 centerH> | ||
<View | ||
paddingH-s4 | ||
marginV-s10 | ||
style={{width: 300, borderWidth: 1, borderColor: Colors.grey50, borderRadius: 12}} | ||
> | ||
<View paddingH-s3 paddingV-s2 marginV-s4> | ||
<TextInput | ||
placeholder={'Email'} | ||
value={auth.email} | ||
onChangeText={setEmail} | ||
keyboardType="email-address" | ||
inputMode="email" | ||
/> | ||
</View> | ||
|
||
<View centerH> | ||
<View height={1} bg-grey50 style={{width: '100%'}} /> | ||
</View> | ||
|
||
<View paddingH-s3 paddingV-s2 marginV-s4> | ||
<TextInput | ||
placeholder={'Password'} | ||
value={password} | ||
onChangeText={setPassword} | ||
keyboardType="visible-password" | ||
secureTextEntry | ||
/> | ||
</View> | ||
</View> | ||
|
||
<BButton label={loading ? 'Logging in ...' : 'Login'} onPress={login} /> | ||
</View> | ||
</View> | ||
</ScrollView> | ||
</View> | ||
); | ||
}); | ||
AuthLogin.options = props => ({ | ||
title: `Auth flow`, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,120 @@ | ||
import React, {useMemo} from 'react'; | ||
import {Image} from 'expo-image'; | ||
import {Text, View} from 'react-native-ui-lib'; | ||
import {FlashList} from '@shopify/flash-list'; | ||
import {observer} from 'mobx-react'; | ||
import {ScrollView} from 'react-native-gesture-handler'; | ||
import {Bounceable} from 'rn-bounceable'; | ||
import {If} from '@kanzitelli/if-component'; | ||
|
||
import {useStores} from '@app/stores'; | ||
import {useServices} from '@app/services'; | ||
import {useAppearance} from '@app/utils/hooks'; | ||
import {randomStr} from '@app/utils/help'; | ||
import {Row} from '@app/components/row'; | ||
import {Icon} from '@app/components/icon'; | ||
import {Section} from '@app/components/section'; | ||
|
||
const blurhash = | ||
'|rF?hV%2WCj[ayj[a|j[az_NaeWBj@ayfRayfQfQM{M|azj[azf6fQfQfQIpWXofj[ayj[j[fQayWCoeoeaya}j[ayfQa{oLj?j[WVj[ayayj[fQoff7azayj[ayj[j[ayofayayayj[fQj[ayayj[ayfjj[j[ayjuayj['; | ||
type SectionData = { | ||
content: { | ||
title: string; | ||
subtitle?: string; | ||
icon: string; | ||
onPress: PureFunc; | ||
}[]; | ||
}; | ||
|
||
export const Playground: React.FC = observer(() => { | ||
useAppearance(); | ||
// const {t} = useServices(); | ||
// const {ui} = useStores(); | ||
|
||
const DATA = useMemo( | ||
() => | ||
Array.from({length: 1000}).map((v, ndx) => ({ | ||
title: `Item ${ndx}`, | ||
image: `https://picsum.photos/200?image=${ndx + 1}`, | ||
description: randomStr(300), | ||
})), | ||
[], | ||
); | ||
|
||
// State | ||
const {navio} = useServices(); | ||
const {auth} = useStores(); | ||
|
||
// Methods | ||
// UI Methods | ||
const showAuthFlow = () => { | ||
// logging out from previous session | ||
if (auth.state === 'logged-in') { | ||
auth.logout(); | ||
} else { | ||
// we can move `navio.setRoot` inside `auth.logout` | ||
// but is left here for more clarity and simplicity | ||
navio.setRoot('stacks', 'AuthFlow'); | ||
} | ||
}; | ||
|
||
return ( | ||
<View flex bg-bgColor> | ||
<FlashList | ||
contentInsetAdjustmentBehavior="always" | ||
data={DATA} | ||
renderItem={({item}) => <ListItem item={item} />} | ||
ListHeaderComponent={ListHeader} | ||
estimatedItemSize={300} | ||
/> | ||
</View> | ||
); | ||
}); | ||
// Memos | ||
const SectionsData: Record<string, SectionData> = useMemo(() => { | ||
return { | ||
Libraries: { | ||
content: [ | ||
{ | ||
title: 'Flash List', | ||
subtitle: 'by Shopify', | ||
icon: 'list-outline', | ||
onPress: () => navio.push('PlaygroundFlashList'), | ||
}, | ||
{ | ||
title: 'Expo Image', | ||
subtitle: 'by Expo', | ||
icon: 'image-outline', | ||
onPress: () => navio.push('PlaygroundExpoImage'), | ||
}, | ||
], | ||
}, | ||
Navio: { | ||
content: [ | ||
{ | ||
title: 'Auth flow', | ||
icon: 'lock-closed-outline', | ||
subtitle: auth.stateStr, | ||
onPress: showAuthFlow, | ||
}, | ||
], | ||
}, | ||
}; | ||
}, [auth.state]); | ||
|
||
const ListItem = ({item}: any) => { | ||
useAppearance(); | ||
|
||
return ( | ||
<View padding-s2 bg-bgColor> | ||
<Image | ||
style={{width: 120, height: 120, borderRadius: 20}} | ||
source={item.image} | ||
placeholder={blurhash} | ||
contentFit="cover" | ||
resizeMode="contain" | ||
transition={100} | ||
/> | ||
// UI Methods | ||
const Sections = useMemo(() => { | ||
const keys = Object.keys(SectionsData) as (keyof typeof SectionsData)[]; | ||
return keys.map(k => { | ||
const s = SectionsData[k]; | ||
return ( | ||
<Section key={k} title={k}> | ||
{s.content.map(content => { | ||
return ( | ||
<View key={content.title} marginV-s1> | ||
<Bounceable onPress={content.onPress}> | ||
<View bg-bg2Color padding-s3 br30> | ||
<Row> | ||
<Icon name={content.icon} size={34} /> | ||
|
||
<Text textColor text50R> | ||
{item.title} | ||
</Text> | ||
<View flex marginH-s3> | ||
<Text text60R textColor> | ||
{content.title} | ||
</Text> | ||
|
||
<Text textColor text70R> | ||
{item.description} | ||
</Text> | ||
</View> | ||
); | ||
}; | ||
{If({ | ||
_: !!content.subtitle, | ||
_then: ( | ||
<Text text70 grey20> | ||
{content.subtitle} | ||
</Text> | ||
), | ||
})} | ||
</View> | ||
|
||
const ListHeader = () => { | ||
useAppearance(); | ||
<Icon name="chevron-forward" /> | ||
</Row> | ||
</View> | ||
</Bounceable> | ||
</View> | ||
); | ||
})} | ||
</Section> | ||
); | ||
}); | ||
}, [SectionsData]); | ||
|
||
return ( | ||
<View padding-s2 bg-bgColor> | ||
<Text text50M textColor> | ||
FlashList by Shopify | ||
</Text> | ||
<View flex bg-bgColor> | ||
<ScrollView contentInsetAdjustmentBehavior="always">{Sections}</ScrollView> | ||
</View> | ||
); | ||
}; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import {sleep} from '@app/utils/help'; | ||
import {Auth$Login$Response} from '@app/utils/types/api'; | ||
|
||
export class AuthApi { | ||
login = async (): Promise<Auth$Login$Response> => { | ||
// faking request | ||
await sleep(1000); // sleeping for 1s | ||
|
||
return { | ||
status: 'success', | ||
data: { | ||
'some-session-info?': {}, | ||
}, | ||
}; | ||
}; | ||
} |
Oops, something went wrong.