From bca91369153b8da50f3e128803085d8dc23c9541 Mon Sep 17 00:00:00 2001 From: renahlee Date: Mon, 17 Apr 2023 21:35:41 -0700 Subject: [PATCH] placeholder --- src/state/models/ui/shell.ts | 35 +++++-- src/state/models/ui/update-account.ts | 20 ++++ src/view/com/modals/ChangePassword.tsx | 84 ++++++++++++++++ src/view/com/modals/Modal.tsx | 6 +- src/view/com/modals/Modal.web.tsx | 3 + src/view/screens/Settings.tsx | 130 ++++++++++++------------- 6 files changed, 199 insertions(+), 79 deletions(-) create mode 100644 src/state/models/ui/update-account.ts create mode 100644 src/view/com/modals/ChangePassword.tsx diff --git a/src/state/models/ui/shell.ts b/src/state/models/ui/shell.ts index 47cc0aa825..5eb7177972 100644 --- a/src/state/models/ui/shell.ts +++ b/src/state/models/ui/shell.ts @@ -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 {} diff --git a/src/state/models/ui/update-account.ts b/src/state/models/ui/update-account.ts new file mode 100644 index 0000000000..1fe531717c --- /dev/null +++ b/src/state/models/ui/update-account.ts @@ -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}) + } +} diff --git a/src/view/com/modals/ChangePassword.tsx b/src/view/com/modals/ChangePassword.tsx new file mode 100644 index 0000000000..f8660dd1e8 --- /dev/null +++ b/src/view/com/modals/ChangePassword.tsx @@ -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 ( + + + + + + Cancel + + + + + Change password + + + {/* {isProcessing ? ( + + ) : error && !serviceDescription ? ( + + + Retry + + + ) : canSave ? ( */} + + + Save + + + {/* ) : undefined} */} + + + + Enter the email you used to create your account. We'll send you a "reset + code" so you can set a new password. + + + ) +} + +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: {}, +}) diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx index 3f10ec8365..8101f4dba2 100644 --- a/src/view/com/modals/Modal.tsx +++ b/src/view/com/modals/Modal.tsx @@ -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 = + } else if (activeModal?.name === 'change-password') { + element = } else if (activeModal?.name === 'waitlist') { snapPoints = WaitlistModal.snapPoints element = @@ -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} ) diff --git a/src/view/com/modals/Modal.web.tsx b/src/view/com/modals/Modal.web.tsx index 25fed69a49..74a79b1f78 100644 --- a/src/view/com/modals/Modal.web.tsx +++ b/src/view/com/modals/Modal.web.tsx @@ -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 = } else if (modal.name === 'change-handle') { element = + } else if (modal.name === 'change-password') { + element = } else if (modal.name === 'waitlist') { element = } else if (modal.name === 'invite-codes') { diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx index 76a3efa602..e13e3ca71b 100644 --- a/src/view/screens/Settings.tsx +++ b/src/view/screens/Settings.tsx @@ -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 export const SettingsScreen = withAuthRequired( @@ -43,16 +42,8 @@ export const SettingsScreen = withAuthRequired( const store = useStores() const navigation = useNavigation() const {screen, track} = useAnalytics() - const [isSwitching, setIsSwitching] = React.useState(false) + const [isSwitching, setIsSwitching] = useState(false) - const primaryBg = useCustomPalette({ - light: {backgroundColor: colors.blue0}, - dark: {backgroundColor: colors.blue6}, - }) - const primaryText = useCustomPalette({ - light: {color: colors.blue3}, - dark: {color: colors.blue2}, - }) const dangerBg = useCustomPalette({ 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 ( - + - + @@ -180,6 +195,7 @@ export const SettingsScreen = withAuthRequired( )} + {store.session.switchableAccounts.map(account => ( - - Invite a friend - - - 0 ? primaryBg : pal.btn, - ]}> - 0 - ? primaryText - : pal.text) as FontAwesomeIconStyle - } - /> - - 0 ? pal.link : pal.text}> - {store.me.invitesAvailable} invite{' '} - {pluralize(store.me.invitesAvailable, 'code')} available - - - - - Advanced @@ -278,7 +263,21 @@ export const SettingsScreen = withAuthRequired( /> - Change my handle + Change handle + + + + + + + + Change password @@ -308,7 +307,7 @@ export const SettingsScreen = withAuthRequired( Developer tools @@ -316,7 +315,7 @@ export const SettingsScreen = withAuthRequired( @@ -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, }, })