1import * as React from 'react' 2import * as Container from '../util/container' 3import * as Constants from '../constants/settings' 4import * as Tabs from '../constants/tabs' 5import * as SettingsGen from '../actions/settings-gen' 6import * as RouteTreeGen from '../actions/route-tree-gen' 7import * as ConfigGen from '../actions/config-gen' 8import * as Kb from '../common-adapters' 9import * as Styles from '../styles' 10import {appendNewChatBuilder} from '../actions/typed-routes' 11import {SettingsSection} from './account' 12 13const enabledDescription = 'Your phone contacts are being synced on this device.' 14const disabledDescription = 'Import your phone contacts and start encrypted chats with your friends.' 15 16const ManageContacts = () => { 17 const dispatch = Container.useDispatch() 18 19 const status = Container.useSelector(s => s.settings.contacts.permissionStatus) 20 const contactsImported = Container.useSelector(s => s.settings.contacts.importEnabled) 21 const waiting = Container.useAnyWaiting(Constants.importContactsWaitingKey) 22 23 if (contactsImported === null) { 24 dispatch(SettingsGen.createLoadContactImportEnabled()) 25 } 26 27 const onToggle = React.useCallback( 28 () => 29 dispatch( 30 status !== 'granted' 31 ? SettingsGen.createRequestContactPermissions({fromSettings: true, thenToggleImportOn: true}) 32 : SettingsGen.createEditContactImportEnabled({enable: !contactsImported, fromSettings: true}) 33 ), 34 [dispatch, contactsImported, status] 35 ) 36 37 return ( 38 <Kb.Box2 direction="vertical" fullWidth={true} fullHeight={true} style={styles.positionRelative}> 39 <Kb.BoxGrow> 40 <ManageContactsBanner /> 41 <SettingsSection> 42 <Kb.Box2 direction="vertical" gap="xtiny" fullWidth={true}> 43 <Kb.Text type="Header">Phone contacts</Kb.Text> 44 <Kb.Text type="BodySmall"> 45 {contactsImported && status === 'granted' ? enabledDescription : disabledDescription} 46 </Kb.Text> 47 <Kb.ButtonBar align="flex-start" style={styles.buttonBar}> 48 <Kb.Button 49 disabled={status === 'never_ask_again'} 50 mode="Secondary" 51 label={contactsImported && status === 'granted' ? 'Remove contacts' : 'Import phone contacts'} 52 type={contactsImported && status === 'granted' ? 'Danger' : 'Default'} 53 onClick={onToggle} 54 small={true} 55 waiting={waiting} 56 /> 57 </Kb.ButtonBar> 58 </Kb.Box2> 59 </SettingsSection> 60 </Kb.BoxGrow> 61 </Kb.Box2> 62 ) 63} 64 65ManageContacts.navigationOptions = { 66 header: undefined, 67 title: 'Contacts', 68} 69 70const ManageContactsBanner = () => { 71 const dispatch = Container.useDispatch() 72 73 const status = Container.useSelector(s => s.settings.contacts.permissionStatus) 74 const contactsImported = Container.useSelector(s => s.settings.contacts.importEnabled) 75 const importedCount = Container.useSelector(s => s.settings.contacts.importedCount) 76 const error = Container.useSelector(s => s.settings.contacts.importError) 77 78 const onOpenAppSettings = React.useCallback(() => dispatch(ConfigGen.createOpenAppSettings()), [dispatch]) 79 const onStartChat = React.useCallback(() => { 80 dispatch(RouteTreeGen.createSwitchTab({tab: Tabs.chatTab})) 81 dispatch(appendNewChatBuilder()) 82 }, [dispatch]) 83 const onSendFeedback = React.useCallback(() => { 84 dispatch( 85 RouteTreeGen.createNavigateAppend({ 86 path: [{props: {feedback: `Contact import failed\n${error}\n\n`}, selected: Constants.feedbackTab}], 87 }) 88 ) 89 }, [dispatch, error]) 90 91 return ( 92 <> 93 {!!importedCount && ( 94 <Kb.Banner color="green"> 95 <Kb.BannerParagraph bannerColor="green" content={[`You imported ${importedCount} contacts.`]} /> 96 <Kb.BannerParagraph bannerColor="green" content={[{onClick: onStartChat, text: 'Start a chat'}]} /> 97 </Kb.Banner> 98 )} 99 {(status === 'never_ask_again' || (Styles.isAndroid && status !== 'granted' && contactsImported)) && ( 100 <Kb.Banner color="red"> 101 <Kb.BannerParagraph 102 bannerColor="red" 103 content={[ 104 contactsImported 105 ? "Contact importing is paused because Keybase doesn't have permission to access your contacts. " 106 : "Keybase doesn't have permission to access your contacts. ", 107 {onClick: onOpenAppSettings, text: 'Enable in settings'}, 108 '.', 109 ]} 110 /> 111 </Kb.Banner> 112 )} 113 {!!error && ( 114 <Kb.Banner color="red"> 115 <Kb.BannerParagraph bannerColor="red" content="There was an error importing your contacts." /> 116 <Kb.BannerParagraph 117 bannerColor="red" 118 content={[{onClick: onSendFeedback, text: 'Send us feedback.'}]} 119 /> 120 </Kb.Banner> 121 )} 122 </> 123 ) 124} 125 126ManageContacts.navigationOptions = { 127 header: undefined, 128 title: 'Contacts', 129} 130 131const styles = Styles.styleSheetCreate( 132 () => 133 ({ 134 buttonBar: { 135 marginTop: Styles.globalMargins.tiny, 136 minHeight: undefined, 137 width: undefined, 138 }, 139 positionRelative: {position: 'relative'}, 140 } as const) 141) 142 143export default ManageContacts 144