placeholder

This commit is contained in:
renahlee
2023-04-17 21:35:41 -07:00
parent 04e0ebe8fc
commit bca9136915
6 changed files with 199 additions and 79 deletions
+26 -9
View File
@@ -57,6 +57,11 @@ export interface ChangeHandleModal {
onChanged: () => void onChanged: () => void
} }
export interface ChangePasswordModal {
name: 'change-password'
onChanged: () => void
}
export interface WaitlistModal { export interface WaitlistModal {
name: 'waitlist' name: 'waitlist'
} }
@@ -70,18 +75,30 @@ export interface ContentFilteringSettingsModal {
} }
export type Modal = export type Modal =
| ConfirmModal // Account
| EditProfileModal
| ServerInputModal
| ReportPostModal
| ReportAccountModal
| CropImageModal
| DeleteAccountModal
| RepostModal
| ChangeHandleModal | ChangeHandleModal
| ChangePasswordModal
| DeleteAccountModal
| EditProfileModal
// Curation
| ContentFilteringSettingsModal
// Reporting
| ReportAccountModal
| ReportPostModal
// Posting
| CropImageModal
| ServerInputModal
| RepostModal
// Bluesky access
| WaitlistModal | WaitlistModal
| InviteCodesModal | InviteCodesModal
| ContentFilteringSettingsModal
// Generic
| ConfirmModal
interface LightboxModel {} interface LightboxModel {}
+20
View File
@@ -0,0 +1,20 @@
import {BskyAgent} from '@atproto/api'
import {makeAutoObservable} from 'mobx'
import {RootStoreModel} from '../root-store'
export class AccountModel {
serviceUrl = ''
constructor(public rootStore: RootStoreModel) {
makeAutoObservable(
this,
{},
{
autoBind: true,
},
)
}
updatePassword() {
const agent = new BskyAgent({service: this.serviceUrl})
}
}
+84
View File
@@ -0,0 +1,84 @@
import React, {useCallback} from 'react'
import {StyleSheet, TouchableOpacity, View} from 'react-native'
import {Text} from '../util/text/Text'
import {useStores} from 'state/index'
import {s} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette'
export const snapPoints = ['100%']
interface Props {
onChanged: () => void
}
export function Component({onChanged}: Props) {
const pal = usePalette('default')
const store = useStores()
const onCancel = useCallback(() => {
store.shell.closeModal()
}, [store.shell])
return (
<View style={[s.flex1, pal.view]}>
<View style={[styles.title, pal.border]}>
<View style={styles.titleLeft}>
<TouchableOpacity onPress={onCancel}>
<Text type="lg" style={pal.textLight}>
Cancel
</Text>
</TouchableOpacity>
</View>
<Text type="2xl-bold" style={[styles.titleMiddle, pal.text]}>
Change password
</Text>
<View style={styles.titleRight}>
{/* {isProcessing ? (
<ActivityIndicator />
) : error && !serviceDescription ? (
<TouchableOpacity
testID="retryConnectButton"
onPress={onPressRetryConnect}>
<Text type="xl-bold" style={[pal.link, s.pr5]}>
Retry
</Text>
</TouchableOpacity>
) : canSave ? ( */}
<TouchableOpacity
// onPress={onPressSave}
>
<Text type="lg-bold" style={pal.link}>
Save
</Text>
</TouchableOpacity>
{/* ) : undefined} */}
</View>
</View>
<Text type="lg" style={[pal.text, styles.instructions]}>
Enter the email you used to create your account. We'll send you a "reset
code" so you can set a new password.
</Text>
</View>
)
}
const styles = StyleSheet.create({
instructions: {
paddingHorizontal: 18,
paddingVertical: 16,
},
title: {
flexDirection: 'row',
alignItems: 'baseline',
justifyContent: 'space-between',
paddingTop: 25,
paddingHorizontal: 20,
paddingBottom: 15,
borderBottomWidth: 1,
},
titleLeft: {},
titleMiddle: {
fontSize: 21,
},
titleRight: {},
})
+5 -1
View File
@@ -14,6 +14,7 @@ import * as RepostModal from './Repost'
import * as ReportAccountModal from './ReportAccount' import * as ReportAccountModal from './ReportAccount'
import * as DeleteAccountModal from './DeleteAccount' import * as DeleteAccountModal from './DeleteAccount'
import * as ChangeHandleModal from './ChangeHandle' import * as ChangeHandleModal from './ChangeHandle'
import * as ChangePasswordModal from './ChangePassword'
import * as WaitlistModal from './Waitlist' import * as WaitlistModal from './Waitlist'
import * as InviteCodesModal from './InviteCodes' import * as InviteCodesModal from './InviteCodes'
import * as ContentFilteringSettingsModal from './ContentFilteringSettings' import * as ContentFilteringSettingsModal from './ContentFilteringSettings'
@@ -71,6 +72,8 @@ export const ModalsContainer = observer(function ModalsContainer() {
} else if (activeModal?.name === 'change-handle') { } else if (activeModal?.name === 'change-handle') {
snapPoints = ChangeHandleModal.snapPoints snapPoints = ChangeHandleModal.snapPoints
element = <ChangeHandleModal.Component {...activeModal} /> element = <ChangeHandleModal.Component {...activeModal} />
} else if (activeModal?.name === 'change-password') {
element = <ChangePasswordModal.Component {...modal} />
} else if (activeModal?.name === 'waitlist') { } else if (activeModal?.name === 'waitlist') {
snapPoints = WaitlistModal.snapPoints snapPoints = WaitlistModal.snapPoints
element = <WaitlistModal.Component /> element = <WaitlistModal.Component />
@@ -96,7 +99,8 @@ export const ModalsContainer = observer(function ModalsContainer() {
} }
handleIndicatorStyle={{backgroundColor: pal.text.color}} handleIndicatorStyle={{backgroundColor: pal.text.color}}
handleStyle={[styles.handle, pal.view]} handleStyle={[styles.handle, pal.view]}
onChange={onBottomSheetChange}> onChange={onBottomSheetChange}
onClose={onClose}>
{element} {element}
</BottomSheet> </BottomSheet>
) )
+3
View File
@@ -15,6 +15,7 @@ import * as DeleteAccountModal from './DeleteAccount'
import * as RepostModal from './Repost' import * as RepostModal from './Repost'
import * as CropImageModal from './crop-image/CropImage.web' import * as CropImageModal from './crop-image/CropImage.web'
import * as ChangeHandleModal from './ChangeHandle' import * as ChangeHandleModal from './ChangeHandle'
import * as ChangePasswordModal from './ChangePassword'
import * as WaitlistModal from './Waitlist' import * as WaitlistModal from './Waitlist'
import * as InviteCodesModal from './InviteCodes' import * as InviteCodesModal from './InviteCodes'
import * as ContentFilteringSettingsModal from './ContentFilteringSettings' import * as ContentFilteringSettingsModal from './ContentFilteringSettings'
@@ -72,6 +73,8 @@ function Modal({modal}: {modal: ModalIface}) {
element = <RepostModal.Component {...modal} /> element = <RepostModal.Component {...modal} />
} else if (modal.name === 'change-handle') { } else if (modal.name === 'change-handle') {
element = <ChangeHandleModal.Component {...modal} /> element = <ChangeHandleModal.Component {...modal} />
} else if (modal.name === 'change-password') {
element = <ChangePasswordModal.Component {...modal} />
} else if (modal.name === 'waitlist') { } else if (modal.name === 'waitlist') {
element = <WaitlistModal.Component /> element = <WaitlistModal.Component />
} else if (modal.name === 'invite-codes') { } else if (modal.name === 'invite-codes') {
+61 -69
View File
@@ -1,4 +1,4 @@
import React from 'react' import React, {useCallback, useState} from 'react'
import { import {
ActivityIndicator, ActivityIndicator,
StyleSheet, StyleSheet,
@@ -34,7 +34,6 @@ import {useCustomPalette} from 'lib/hooks/useCustomPalette'
import {AccountData} from 'state/models/session' import {AccountData} from 'state/models/session'
import {useAnalytics} from 'lib/analytics' import {useAnalytics} from 'lib/analytics'
import {NavigationProp} from 'lib/routes/types' import {NavigationProp} from 'lib/routes/types'
import {pluralize} from 'lib/strings/helpers'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'> type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'>
export const SettingsScreen = withAuthRequired( export const SettingsScreen = withAuthRequired(
@@ -43,16 +42,8 @@ export const SettingsScreen = withAuthRequired(
const store = useStores() const store = useStores()
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const {screen, track} = useAnalytics() const {screen, track} = useAnalytics()
const [isSwitching, setIsSwitching] = React.useState(false) const [isSwitching, setIsSwitching] = useState(false)
const primaryBg = useCustomPalette<ViewStyle>({
light: {backgroundColor: colors.blue0},
dark: {backgroundColor: colors.blue6},
})
const primaryText = useCustomPalette<TextStyle>({
light: {color: colors.blue3},
dark: {color: colors.blue2},
})
const dangerBg = useCustomPalette<ViewStyle>({ const dangerBg = useCustomPalette<ViewStyle>({
light: {backgroundColor: colors.red1}, light: {backgroundColor: colors.red1},
dark: {backgroundColor: colors.red7}, dark: {backgroundColor: colors.red7},
@@ -63,13 +54,13 @@ export const SettingsScreen = withAuthRequired(
}) })
useFocusEffect( useFocusEffect(
React.useCallback(() => { useCallback(() => {
screen('Settings') screen('Settings')
store.shell.setMinimalShellMode(false) store.shell.setMinimalShellMode(false)
}, [screen, store]), }, [screen, store]),
) )
const onPressSwitchAccount = React.useCallback( const onPressSwitchAccount = useCallback(
async (acct: AccountData) => { async (acct: AccountData) => {
track('Settings:SwitchAccountButtonClicked') track('Settings:SwitchAccountButtonClicked')
setIsSwitching(true) setIsSwitching(true)
@@ -89,14 +80,14 @@ export const SettingsScreen = withAuthRequired(
[track, setIsSwitching, navigation, store], [track, setIsSwitching, navigation, store],
) )
const onPressAddAccount = React.useCallback(() => { const onPressAddAccount = useCallback(() => {
track('Settings:AddAccountButtonClicked') track('Settings:AddAccountButtonClicked')
navigation.navigate('HomeTab') navigation.navigate('HomeTab')
navigation.dispatch(StackActions.popToTop()) navigation.dispatch(StackActions.popToTop())
store.session.clear() store.session.clear()
}, [track, navigation, store]) }, [track, navigation, store])
const onPressChangeHandle = React.useCallback(() => { const onPressChangeHandle = useCallback(() => {
track('Settings:ChangeHandleButtonClicked') track('Settings:ChangeHandleButtonClicked')
store.shell.openModal({ store.shell.openModal({
name: 'change-handle', name: 'change-handle',
@@ -119,29 +110,53 @@ export const SettingsScreen = withAuthRequired(
}) })
}, [track, store, setIsSwitching]) }, [track, store, setIsSwitching])
const onPressInviteCodes = React.useCallback(() => { const onPressChangePassword = useCallback(() => {
track('Settings:InvitecodesButtonClicked') track('Settings:ChangePasswordButtonClicked')
store.shell.openModal({name: 'invite-codes'}) store.shell.openModal({
}, [track, store]) name: 'change-password',
onChanged() {
setIsSwitching(true)
store.session.reloadFromServer().then(
() => {
setIsSwitching(false)
Toast.show('Your password has been updated')
},
err => {
store.log.error(
'Failed to reload from server after handle update',
{err},
)
setIsSwitching(false)
},
)
},
})
}, [track, store, setIsSwitching])
const onPressContentFiltering = React.useCallback(() => { React.useEffect(() => {
onPressChangePassword()
}, [onPressChangePassword])
const onPressContentFiltering = useCallback(() => {
track('Settings:ContentfilteringButtonClicked') track('Settings:ContentfilteringButtonClicked')
store.shell.openModal({name: 'content-filtering-settings'}) store.shell.openModal({name: 'content-filtering-settings'})
}, [track, store]) }, [track, store])
const onPressSignout = React.useCallback(() => { const onPressSignout = useCallback(() => {
track('Settings:SignOutButtonClicked') track('Settings:SignOutButtonClicked')
store.session.logout() store.session.logout()
}, [track, store]) }, [track, store])
const onPressDeleteAccount = React.useCallback(() => { const onPressDeleteAccount = useCallback(() => {
store.shell.openModal({name: 'delete-account'}) store.shell.openModal({name: 'delete-account'})
}, [store]) }, [store])
return ( return (
<View style={[s.hContentRegion]} testID="settingsScreen"> <View testID="settingsScreen">
<ViewHeader title="Settings" /> <ViewHeader title="Settings" />
<ScrollView style={s.hContentRegion} scrollIndicatorInsets={{right: 1}}> <ScrollView
contentContainerStyle={styles.contentContainer}
scrollIndicatorInsets={{right: 1}}>
<View style={styles.spacer20} /> <View style={styles.spacer20} />
<View style={[s.flexRow, styles.heading]}> <View style={[s.flexRow, styles.heading]}>
<Text type="xl-bold" style={pal.text}> <Text type="xl-bold" style={pal.text}>
@@ -180,6 +195,7 @@ export const SettingsScreen = withAuthRequired(
</View> </View>
</Link> </Link>
)} )}
{store.session.switchableAccounts.map(account => ( {store.session.switchableAccounts.map(account => (
<TouchableOpacity <TouchableOpacity
testID={`switchToAccountBtn-${account.handle}`} testID={`switchToAccountBtn-${account.handle}`}
@@ -219,37 +235,6 @@ export const SettingsScreen = withAuthRequired(
<View style={styles.spacer20} /> <View style={styles.spacer20} />
<Text type="xl-bold" style={[pal.text, styles.heading]}>
Invite a friend
</Text>
<TouchableOpacity
testID="inviteFriendBtn"
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
onPress={isSwitching ? undefined : onPressInviteCodes}>
<View
style={[
styles.iconContainer,
store.me.invitesAvailable > 0 ? primaryBg : pal.btn,
]}>
<FontAwesomeIcon
icon="ticket"
style={
(store.me.invitesAvailable > 0
? primaryText
: pal.text) as FontAwesomeIconStyle
}
/>
</View>
<Text
type="lg"
style={store.me.invitesAvailable > 0 ? pal.link : pal.text}>
{store.me.invitesAvailable} invite{' '}
{pluralize(store.me.invitesAvailable, 'code')} available
</Text>
</TouchableOpacity>
<View style={styles.spacer20} />
<Text type="xl-bold" style={[pal.text, styles.heading]}> <Text type="xl-bold" style={[pal.text, styles.heading]}>
Advanced Advanced
</Text> </Text>
@@ -278,7 +263,21 @@ export const SettingsScreen = withAuthRequired(
/> />
</View> </View>
<Text type="lg" style={pal.text}> <Text type="lg" style={pal.text}>
Change my handle Change handle
</Text>
</TouchableOpacity>
<TouchableOpacity
testID="changePasswordBtn"
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
onPress={isSwitching ? undefined : onPressChangePassword}>
<View style={[styles.iconContainer, pal.btn]}>
<FontAwesomeIcon
icon="lock"
style={pal.text as FontAwesomeIconStyle}
/>
</View>
<Text type="lg" style={pal.text}>
Change password
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
@@ -308,7 +307,7 @@ export const SettingsScreen = withAuthRequired(
Developer tools Developer tools
</Text> </Text>
<Link <Link
style={[pal.view, styles.linkCardNoIcon]} style={[pal.view, styles.linkCard]}
href="/sys/log" href="/sys/log"
title="System log"> title="System log">
<Text type="lg" style={pal.text}> <Text type="lg" style={pal.text}>
@@ -316,7 +315,7 @@ export const SettingsScreen = withAuthRequired(
</Text> </Text>
</Link> </Link>
<Link <Link
style={[pal.view, styles.linkCardNoIcon]} style={[pal.view, styles.linkCard]}
href="/sys/debug" href="/sys/debug"
title="Debug tools"> title="Debug tools">
<Text type="lg" style={pal.text}> <Text type="lg" style={pal.text}>
@@ -354,6 +353,10 @@ function AccountDropdownBtn({handle}: {handle: string}) {
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
contentContainer: {
paddingLeft: '18px',
paddingRight: '18px',
},
dimmed: { dimmed: {
opacity: 0.5, opacity: 0.5,
}, },
@@ -361,7 +364,6 @@ const styles = StyleSheet.create({
height: 20, height: 20,
}, },
heading: { heading: {
paddingHorizontal: 18,
paddingBottom: 6, paddingBottom: 6,
}, },
profile: { profile: {
@@ -369,20 +371,11 @@ const styles = StyleSheet.create({
marginVertical: 6, marginVertical: 6,
borderRadius: 4, borderRadius: 4,
paddingVertical: 10, paddingVertical: 10,
paddingHorizontal: 10,
}, },
linkCard: { linkCard: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
paddingVertical: 12, paddingVertical: 12,
paddingHorizontal: 18,
marginBottom: 1,
},
linkCardNoIcon: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 20,
paddingHorizontal: 18,
marginBottom: 1, marginBottom: 1,
}, },
avi: { avi: {
@@ -398,6 +391,5 @@ const styles = StyleSheet.create({
}, },
buildInfo: { buildInfo: {
paddingVertical: 8, paddingVertical: 8,
paddingHorizontal: 18,
}, },
}) })