Skip to content

Commit

Permalink
add a loading state for adding, removing and reseting sync
Browse files Browse the repository at this point in the history
  • Loading branch information
cezaraugusto committed Jan 2, 2019
1 parent 7731052 commit bd48127
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 41 deletions.
1 change: 1 addition & 0 deletions components/brave_sync/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import("//brave/components/common/typescript.gni")
transpile_web_ui("ui") {
inputs = [
"actions/sync_actions.ts",
"components/commonDialogs/areYouSure.tsx",
"components/modals/deviceType.tsx",
"components/modals/enterSyncCode.tsx",
"components/modals/removeDevice.tsx",
Expand Down
35 changes: 35 additions & 0 deletions components/brave_sync/ui/components/commonDialogs/areYouSure.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

import * as React from 'react'

// Components
import { AlertBox } from 'brave-ui'

// Feature-specific components
import { Title } from 'brave-ui/features/sync'

// Utils
import { getLocale } from '../../../../common/locale'

interface Props {
onClickOk: () => void
onClickCancel: () => void
}

export default class AreYouSure extends React.PureComponent<Props, {}> {
render () {
const { onClickOk, onClickCancel } = this.props
return (
<AlertBox
okString={getLocale('ok')}
onClickOk={onClickOk}
cancelString={getLocale('cancel')}
onClickCancel={onClickCancel}
>
<Title level={1}>{getLocale('areYouSure')}</Title>
</AlertBox>
)
}
}
11 changes: 8 additions & 3 deletions components/brave_sync/ui/components/enabledContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,14 @@ export default class SyncEnabledContent extends React.PureComponent<Props, State
this.setState({
deviceToRemoveName: target.dataset.name,
deviceToRemoveId: target.dataset.id,
removeDevice: !this.state.removeDevice
removeDevice: true
})
}

onClickCancelRemoveDeviceButton = () => {
this.setState({ removeDevice: !this.state.removeDevice })
}

onUserNoticedError = () => {
this.props.actions.resetSyncSetupError()
}
Expand Down Expand Up @@ -199,10 +203,11 @@ export default class SyncEnabledContent extends React.PureComponent<Props, State
removeDevice
? (
<RemoveDeviceModal
syncData={syncData}
deviceName={deviceToRemoveName}
deviceId={Number(deviceToRemoveId)}
deviceId={deviceToRemoveId}
actions={actions}
onClose={this.onClickRemoveDeviceButton}
onClose={this.onClickCancelRemoveDeviceButton}
/>
)
: null
Expand Down
44 changes: 40 additions & 4 deletions components/brave_sync/ui/components/modals/enterSyncCode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import {
SubTitle
} from 'brave-ui/features/sync'

// Icons
import { LoaderIcon } from 'brave-ui/components/icons'

// Utils
import { getLocale } from '../../../../common/locale'

Expand All @@ -29,13 +32,33 @@ interface Props {
}
interface State {
passphrase: string
willCreateNewSyncChainFromCode: boolean
}

export default class EnterSyncCodeModal extends React.PureComponent<Props, State> {
constructor (props: Props) {
super(props)
this.state = {
passphrase: ''
passphrase: '',
willCreateNewSyncChainFromCode: false
}
}

componentDidUpdate (prevProps: Props) {
// when component updates with a different config, disable the
// loading state and unfreeze the modal. at this point the component
// auto refresh and lead the user to the enabledContent view
if (
this.props.syncData.error !== undefined ||
(
this.state.willCreateNewSyncChainFromCode &&
prevProps.syncData.isSyncConfigured !==
this.props.syncData.isSyncConfigured &&
this.props.syncData.devices.length > 1
)
) {
this.setState({ willCreateNewSyncChainFromCode: false })
this.props.onClose()
}
}

Expand All @@ -47,19 +70,26 @@ export default class EnterSyncCodeModal extends React.PureComponent<Props, State
this.setState({ passphrase: event.target.value })
}

onDismissModal = () => {
this.props.onClose()
}

onClickConfirmSyncCode = () => {
const { error, thisDeviceName } = this.props.syncData
if (thisDeviceName !== '' || error) {
return
}
const { passphrase } = this.state
this.setState({ willCreateNewSyncChainFromCode: true })
this.props.actions.onSetupSyncHaveCode(passphrase, '')
}

render () {
const { onClose, syncData } = this.props
const { syncData } = this.props
const { willCreateNewSyncChainFromCode } = this.state

return (
<Modal id='enterSyncCodeModal' onClose={onClose} size='small'>
<Modal id='enterSyncCodeModal' displayCloseButton={false} size='small'>
{
syncData.error === 'ERR_SYNC_WRONG_WORDS'
? <AlertBox okString={getLocale('ok')} onClickOk={this.onUserNoticedError}>
Expand Down Expand Up @@ -110,7 +140,8 @@ export default class EnterSyncCodeModal extends React.PureComponent<Props, State
level='secondary'
type='accent'
size='medium'
onClick={onClose}
disabled={willCreateNewSyncChainFromCode}
onClick={this.onDismissModal}
text={getLocale('cancel')}
/>
</OneColumnButtonGrid>
Expand All @@ -120,6 +151,11 @@ export default class EnterSyncCodeModal extends React.PureComponent<Props, State
size='medium'
onClick={this.onClickConfirmSyncCode}
text={getLocale('confirmCode')}
disabled={willCreateNewSyncChainFromCode}
icon={{
position: 'after',
image: willCreateNewSyncChainFromCode && <LoaderIcon />
}}
/>
</TwoColumnButtonGrid>
</Modal>
Expand Down
63 changes: 52 additions & 11 deletions components/brave_sync/ui/components/modals/removeDevice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,70 @@ import {
OneColumnButtonGrid
} from 'brave-ui/features/sync'

// Icons
import { LoaderIcon } from 'brave-ui/components/icons'

// Utils
import { getLocale } from '../../../../common/locale'

interface Props {
syncData: Sync.State
onClose: (event?: React.MouseEvent<HTMLButtonElement>) => void
actions: any
deviceName: string | undefined
deviceId: number | undefined
deviceId: string | undefined
}

interface State {
willRemoveDevice: boolean
}

export default class RemoveMainDeviceModal extends React.PureComponent<Props, {}> {
export default class RemoveMainDeviceModal extends React.PureComponent<Props, State> {
constructor (props: Props) {
super(props)
this.state = { willRemoveDevice: false }
}

componentDidUpdate (prevProps: Props) {
// if devices lengh is different it means that sync
// computed the device removal. in this case, cancel
// the loading state and close the modal
if (
prevProps.syncData.devices.length !==
this.props.syncData.devices.length
) {
this.setState({ willRemoveDevice: false })
this.props.onClose()
}
}

onDismissModal = () => {
this.props.onClose()
}

onClickConfirmRemoveDeviceButton = () => {
const { deviceName, deviceId } = this.props
const { syncData, deviceName, deviceId } = this.props
// if there aren't enough devices, reset sync
if (syncData.devices.length < 2) {
this.props.actions.onSyncReset()
return
}
this.props.actions.onRemoveDevice(Number(deviceId), deviceName)
this.props.onClose()
this.setState({ willRemoveDevice: true })
}

render () {
const { onClose, deviceName, deviceId } = this.props
const { syncData, deviceName, deviceId } = this.props
const { willRemoveDevice } = this.state

return (
<Modal id='removeMainDeviceModal' onClose={onClose} size='small'>
<Modal id='removeMainDeviceModal' displayCloseButton={false} size='small'>
<ModalHeader>
<ModalTitle level={1}>{getLocale('remove')}{deviceName}{getLocale('thisSyncChain')}?</ModalTitle>
</ModalHeader>
<ModalContent>
{
// zero is always the this device
deviceId === 0
deviceId === syncData.thisDeviceId
? <div>
<Paragraph>{getLocale('thisDeviceRemovalDescription')}</Paragraph>
<Paragraph>{getLocale('joinSyncChain')}</Paragraph>
Expand All @@ -57,18 +92,24 @@ export default class RemoveMainDeviceModal extends React.PureComponent<Props, {}
<OneColumnButtonGrid>
<Button
level='secondary'
type='accent'
type='subtle'
size='medium'
onClick={onClose}
onClick={this.onDismissModal}
disabled={willRemoveDevice}
text={getLocale('cancel')}
/>
</OneColumnButtonGrid>
<Button
level='primary'
type='accent'
type='warn'
size='medium'
onClick={this.onClickConfirmRemoveDeviceButton}
text={getLocale('remove')}
disabled={willRemoveDevice}
icon={{
position: 'after',
image: willRemoveDevice && <LoaderIcon />
}}
/>
</TwoColumnButtonGrid>
</Modal>
Expand Down
Loading

0 comments on commit bd48127

Please sign in to comment.