placeholder
This commit is contained in:
@@ -57,6 +57,11 @@ export interface ChangeHandleModal {
|
||||
onChanged: () => void
|
||||
}
|
||||
|
||||
export interface ChangePasswordModal {
|
||||
name: 'change-password'
|
||||
onChanged: () => void
|
||||
}
|
||||
|
||||
export interface WaitlistModal {
|
||||
name: 'waitlist'
|
||||
}
|
||||
@@ -70,18 +75,30 @@ export interface ContentFilteringSettingsModal {
|
||||
}
|
||||
|
||||
export type Modal =
|
||||
| ConfirmModal
|
||||
| EditProfileModal
|
||||
| ServerInputModal
|
||||
| ReportPostModal
|
||||
| ReportAccountModal
|
||||
| CropImageModal
|
||||
| DeleteAccountModal
|
||||
| RepostModal
|
||||
// Account
|
||||
| ChangeHandleModal
|
||||
| ChangePasswordModal
|
||||
| DeleteAccountModal
|
||||
| EditProfileModal
|
||||
|
||||
// Curation
|
||||
| ContentFilteringSettingsModal
|
||||
|
||||
// Reporting
|
||||
| ReportAccountModal
|
||||
| ReportPostModal
|
||||
|
||||
// Posting
|
||||
| CropImageModal
|
||||
| ServerInputModal
|
||||
| RepostModal
|
||||
|
||||
// Bluesky access
|
||||
| WaitlistModal
|
||||
| InviteCodesModal
|
||||
| ContentFilteringSettingsModal
|
||||
|
||||
// Generic
|
||||
| ConfirmModal
|
||||
|
||||
interface LightboxModel {}
|
||||
|
||||
|
||||
@@ -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})
|
||||
}
|
||||
}
|
||||
@@ -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: {},
|
||||
})
|
||||
@@ -14,6 +14,7 @@ import * as RepostModal from './Repost'
|
||||
import * as ReportAccountModal from './ReportAccount'
|
||||
import * as DeleteAccountModal from './DeleteAccount'
|
||||
import * as ChangeHandleModal from './ChangeHandle'
|
||||
import * as ChangePasswordModal from './ChangePassword'
|
||||
import * as WaitlistModal from './Waitlist'
|
||||
import * as InviteCodesModal from './InviteCodes'
|
||||
import * as ContentFilteringSettingsModal from './ContentFilteringSettings'
|
||||
@@ -71,6 +72,8 @@ export const ModalsContainer = observer(function ModalsContainer() {
|
||||
} else if (activeModal?.name === 'change-handle') {
|
||||
snapPoints = ChangeHandleModal.snapPoints
|
||||
element = <ChangeHandleModal.Component {...activeModal} />
|
||||
} else if (activeModal?.name === 'change-password') {
|
||||
element = <ChangePasswordModal.Component {...modal} />
|
||||
} else if (activeModal?.name === 'waitlist') {
|
||||
snapPoints = WaitlistModal.snapPoints
|
||||
element = <WaitlistModal.Component />
|
||||
@@ -96,7 +99,8 @@ export const ModalsContainer = observer(function ModalsContainer() {
|
||||
}
|
||||
handleIndicatorStyle={{backgroundColor: pal.text.color}}
|
||||
handleStyle={[styles.handle, pal.view]}
|
||||
onChange={onBottomSheetChange}>
|
||||
onChange={onBottomSheetChange}
|
||||
onClose={onClose}>
|
||||
{element}
|
||||
</BottomSheet>
|
||||
)
|
||||
|
||||
@@ -15,6 +15,7 @@ import * as DeleteAccountModal from './DeleteAccount'
|
||||
import * as RepostModal from './Repost'
|
||||
import * as CropImageModal from './crop-image/CropImage.web'
|
||||
import * as ChangeHandleModal from './ChangeHandle'
|
||||
import * as ChangePasswordModal from './ChangePassword'
|
||||
import * as WaitlistModal from './Waitlist'
|
||||
import * as InviteCodesModal from './InviteCodes'
|
||||
import * as ContentFilteringSettingsModal from './ContentFilteringSettings'
|
||||
@@ -72,6 +73,8 @@ function Modal({modal}: {modal: ModalIface}) {
|
||||
element = <RepostModal.Component {...modal} />
|
||||
} else if (modal.name === 'change-handle') {
|
||||
element = <ChangeHandleModal.Component {...modal} />
|
||||
} else if (modal.name === 'change-password') {
|
||||
element = <ChangePasswordModal.Component {...modal} />
|
||||
} else if (modal.name === 'waitlist') {
|
||||
element = <WaitlistModal.Component />
|
||||
} else if (modal.name === 'invite-codes') {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, {useCallback, useState} from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
StyleSheet,
|
||||
@@ -34,7 +34,6 @@ import {useCustomPalette} from 'lib/hooks/useCustomPalette'
|
||||
import {AccountData} from 'state/models/session'
|
||||
import {useAnalytics} from 'lib/analytics'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {pluralize} from 'lib/strings/helpers'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'>
|
||||
export const SettingsScreen = withAuthRequired(
|
||||
@@ -43,16 +42,8 @@ export const SettingsScreen = withAuthRequired(
|
||||
const store = useStores()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
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>({
|
||||
light: {backgroundColor: colors.red1},
|
||||
dark: {backgroundColor: colors.red7},
|
||||
@@ -63,13 +54,13 @@ export const SettingsScreen = withAuthRequired(
|
||||
})
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
useCallback(() => {
|
||||
screen('Settings')
|
||||
store.shell.setMinimalShellMode(false)
|
||||
}, [screen, store]),
|
||||
)
|
||||
|
||||
const onPressSwitchAccount = React.useCallback(
|
||||
const onPressSwitchAccount = useCallback(
|
||||
async (acct: AccountData) => {
|
||||
track('Settings:SwitchAccountButtonClicked')
|
||||
setIsSwitching(true)
|
||||
@@ -89,14 +80,14 @@ export const SettingsScreen = withAuthRequired(
|
||||
[track, setIsSwitching, navigation, store],
|
||||
)
|
||||
|
||||
const onPressAddAccount = React.useCallback(() => {
|
||||
const onPressAddAccount = useCallback(() => {
|
||||
track('Settings:AddAccountButtonClicked')
|
||||
navigation.navigate('HomeTab')
|
||||
navigation.dispatch(StackActions.popToTop())
|
||||
store.session.clear()
|
||||
}, [track, navigation, store])
|
||||
|
||||
const onPressChangeHandle = React.useCallback(() => {
|
||||
const onPressChangeHandle = useCallback(() => {
|
||||
track('Settings:ChangeHandleButtonClicked')
|
||||
store.shell.openModal({
|
||||
name: 'change-handle',
|
||||
@@ -119,29 +110,53 @@ export const SettingsScreen = withAuthRequired(
|
||||
})
|
||||
}, [track, store, setIsSwitching])
|
||||
|
||||
const onPressInviteCodes = React.useCallback(() => {
|
||||
track('Settings:InvitecodesButtonClicked')
|
||||
store.shell.openModal({name: 'invite-codes'})
|
||||
}, [track, store])
|
||||
const onPressChangePassword = useCallback(() => {
|
||||
track('Settings:ChangePasswordButtonClicked')
|
||||
store.shell.openModal({
|
||||
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')
|
||||
store.shell.openModal({name: 'content-filtering-settings'})
|
||||
}, [track, store])
|
||||
|
||||
const onPressSignout = React.useCallback(() => {
|
||||
const onPressSignout = useCallback(() => {
|
||||
track('Settings:SignOutButtonClicked')
|
||||
store.session.logout()
|
||||
}, [track, store])
|
||||
|
||||
const onPressDeleteAccount = React.useCallback(() => {
|
||||
const onPressDeleteAccount = useCallback(() => {
|
||||
store.shell.openModal({name: 'delete-account'})
|
||||
}, [store])
|
||||
|
||||
return (
|
||||
<View style={[s.hContentRegion]} testID="settingsScreen">
|
||||
<View testID="settingsScreen">
|
||||
<ViewHeader title="Settings" />
|
||||
<ScrollView style={s.hContentRegion} scrollIndicatorInsets={{right: 1}}>
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.contentContainer}
|
||||
scrollIndicatorInsets={{right: 1}}>
|
||||
<View style={styles.spacer20} />
|
||||
<View style={[s.flexRow, styles.heading]}>
|
||||
<Text type="xl-bold" style={pal.text}>
|
||||
@@ -180,6 +195,7 @@ export const SettingsScreen = withAuthRequired(
|
||||
</View>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{store.session.switchableAccounts.map(account => (
|
||||
<TouchableOpacity
|
||||
testID={`switchToAccountBtn-${account.handle}`}
|
||||
@@ -219,37 +235,6 @@ export const SettingsScreen = withAuthRequired(
|
||||
|
||||
<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]}>
|
||||
Advanced
|
||||
</Text>
|
||||
@@ -278,7 +263,21 @@ export const SettingsScreen = withAuthRequired(
|
||||
/>
|
||||
</View>
|
||||
<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>
|
||||
</TouchableOpacity>
|
||||
|
||||
@@ -308,7 +307,7 @@ export const SettingsScreen = withAuthRequired(
|
||||
Developer tools
|
||||
</Text>
|
||||
<Link
|
||||
style={[pal.view, styles.linkCardNoIcon]}
|
||||
style={[pal.view, styles.linkCard]}
|
||||
href="/sys/log"
|
||||
title="System log">
|
||||
<Text type="lg" style={pal.text}>
|
||||
@@ -316,7 +315,7 @@ export const SettingsScreen = withAuthRequired(
|
||||
</Text>
|
||||
</Link>
|
||||
<Link
|
||||
style={[pal.view, styles.linkCardNoIcon]}
|
||||
style={[pal.view, styles.linkCard]}
|
||||
href="/sys/debug"
|
||||
title="Debug tools">
|
||||
<Text type="lg" style={pal.text}>
|
||||
@@ -354,6 +353,10 @@ function AccountDropdownBtn({handle}: {handle: string}) {
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
contentContainer: {
|
||||
paddingLeft: '18px',
|
||||
paddingRight: '18px',
|
||||
},
|
||||
dimmed: {
|
||||
opacity: 0.5,
|
||||
},
|
||||
@@ -361,7 +364,6 @@ const styles = StyleSheet.create({
|
||||
height: 20,
|
||||
},
|
||||
heading: {
|
||||
paddingHorizontal: 18,
|
||||
paddingBottom: 6,
|
||||
},
|
||||
profile: {
|
||||
@@ -369,20 +371,11 @@ const styles = StyleSheet.create({
|
||||
marginVertical: 6,
|
||||
borderRadius: 4,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 10,
|
||||
},
|
||||
linkCard: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 18,
|
||||
marginBottom: 1,
|
||||
},
|
||||
linkCardNoIcon: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingVertical: 20,
|
||||
paddingHorizontal: 18,
|
||||
marginBottom: 1,
|
||||
},
|
||||
avi: {
|
||||
@@ -398,6 +391,5 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
buildInfo: {
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 18,
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user