Skip to content

Commit

Permalink
feat: add permission request popup
Browse files Browse the repository at this point in the history
  • Loading branch information
SunriseFox authored and Jack-Works committed Sep 18, 2019
1 parent 22f1155 commit 6880103
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 73 deletions.
10 changes: 8 additions & 2 deletions src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,14 @@
"welcome_1b_qr_3": {
"message": "3. click \"Setup for Mobile\""
},
"welcome_1b_qr_confirm": {
"message": "Confirm"
"welcome_1b_hint_identity": {
"message": "This backup file contains the following accounts:"
},
"welcome_1b_hint_network": {
"message": "And we're going to request permissions for these sites:"
},
"welcome_1b_confirm": {
"message": "Restore the backup"
},
"welcome_1b_qr_rescan": {
"message": "Rescan"
Expand Down
10 changes: 8 additions & 2 deletions src/_locales/zh/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,14 @@
"welcome_1b_qr_3": {
"message": "3. 點擊「設定移動版」"
},
"welcome_1b_qr_confirm": {
"message": "確認"
"welcome_1b_hint_identity": {
"message": "備份文件中包含了以下身份:"
},
"welcome_1b_hint_network": {
"message": "爲此,將要請求以下網站的權限:"
},
"welcome_1b_confirm": {
"message": "恢復備份"
},
"welcome_1b_qr_rescan": {
"message": "重試"
Expand Down
92 changes: 76 additions & 16 deletions src/components/Welcomes/1b1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,31 @@ import * as React from 'react'

import { useDragAndDrop } from '../../utils/hooks/useDragAndDrop'
import { geti18nString } from '../../utils/i18n'
import { makeStyles, Button, Typography, Tabs, Tab, Theme } from '@material-ui/core'
import { makeStyles, Button, Typography, Tabs, Tab, Theme, Card, CardContent, CardActions } from '@material-ui/core'
import { styled } from '@material-ui/styles'
import FolderOpen from '@material-ui/icons/FolderOpen'
import Camera from '@material-ui/icons/CameraAlt'
import Text from '@material-ui/icons/TextFormat'
import Avatar from '@material-ui/core/Avatar'
import List from '@material-ui/core/List'
import ListItem from '@material-ui/core/ListItem'
import ListItemAvatar from '@material-ui/core/ListItemAvatar'
import ListItemText from '@material-ui/core/ListItemText'
import DialogTitle from '@material-ui/core/DialogTitle'
import Dialog from '@material-ui/core/Dialog'
import PersonIcon from '@material-ui/icons/Person'
import CheckIcon from '@material-ui/icons/Check'
import LanguageIcon from '@material-ui/icons/Language'
import WelcomeContainer from './WelcomeContainer'
import Navigation from './Navigation/Navigation'
import QRScanner from './QRScanner'
import { isWKWebkit, iOSHost } from '../../utils/iOS-RPC'
import { useAsync } from '../../utils/components/AsyncComponent'
import {
BackupJSONFileVersion1,
UpgradeBackupJSONFile,
BackupJSONFileLatest,
} from '../../utils/type-transform/BackupFile'

const RestoreBox = styled('div')(({ theme }: { theme: Theme }) => ({
color: theme.palette.text.hint,
Expand All @@ -32,7 +47,7 @@ interface Props {
back(): void
// ? We cannot send out File | string. Because Firefox will reject the permission request
// ? because read the file is a async procedure.
restore(file: string): void
restore(json: BackupJSONFileLatest): void
}
const videoHeight = 360
const useStyles = makeStyles<Theme>(theme => ({
Expand Down Expand Up @@ -76,23 +91,37 @@ const useStyles = makeStyles<Theme>(theme => ({
width: '100%',
height: 200,
},
cardAction: {
marginRight: 0,
marginLeft: 'auto',
},
}))
export default function Welcome({ back, restore }: Props) {
export default function Welcome({ back, restore: originalRestore }: Props) {
const classes = useStyles()
const ref = React.useRef<HTMLInputElement>(null)
const textAreaRef = React.useRef<HTMLTextAreaElement>(null)
const [fileContent, setFileContent] = React.useState('')
const restore = (str: string) => {
const json = JSON.parse(str)
const upgraded = UpgradeBackupJSONFile(json)
setJson(upgraded)
}
const { dragEvents, fileReceiver, fileRef, dragStatus } = useDragAndDrop(file => {
const fr = new FileReader()
fr.readAsText(file)
fr.addEventListener('loadend', async () => {
setFileContent(fr.result as string)
restore(fr.result as string)
})
})

const [tab, setTab] = React.useState(0)
const [qrError, setError] = React.useState<boolean>(false)

const [json, setJson] = React.useState<null | BackupJSONFileVersion1>(null)
const clearJson = () => {
setJson(null)
if (ref && ref.current) ref.current.value = ''
}

return (
<WelcomeContainer {...dragEvents}>
<Navigation back={back} />
Expand All @@ -104,29 +133,60 @@ export default function Welcome({ back, restore }: Props) {
textColor="primary"
aria-label="icon tabs example">
<Tab icon={<FolderOpen />} aria-label={geti18nString('welcome_1b_tabs_backup')} />
{/* TODO: add support for Firefox */}
<Tab
disabled={!('BarcodeDetector' in window || isWKWebkit)}
icon={<Camera />}
aria-label={geti18nString('welcome_1b_tabs_qr')}
/>
<Tab icon={<Text />} aria-label={geti18nString('welcome_1b_tabs_text')} />
</Tabs>
{json && (
<Dialog onClose={clearJson} aria-labelledby="restore-dialog" open={json !== null}>
<Card>
<CardContent>
<DialogTitle>{geti18nString('welcome_1b_hint_identity')}</DialogTitle>
<List>
{json!.whoami.map(identity => (
<ListItem button onClick={() => void 0} key={identity.userId}>
<ListItemAvatar>
<Avatar className={classes.avatar}>
{true ? <PersonIcon /> : <CheckIcon />}
</Avatar>
</ListItemAvatar>
<ListItemText primary={identity.nickname || identity.userId} />
</ListItem>
))}
</List>
<DialogTitle>{geti18nString('welcome_1b_hint_network')}</DialogTitle>
<List>
{json!.grantedHostPermissions.map(host => (
<ListItem button onClick={() => void 0} key={host}>
<ListItemAvatar>
<Avatar className={classes.avatar}>
<LanguageIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary={host} />
</ListItem>
))}
</List>
</CardContent>
<CardActions>
<Button
onClick={() => originalRestore(json)}
color="primary"
className={`${classes.button} ${classes.cardAction}`}>
{geti18nString('welcome_1b_confirm')}
</Button>
</CardActions>
</Card>
</Dialog>
)}
<main className={classes.main}>
{tab === 0 ? FileUI() : null}
{tab === 1 ? isWKWebkit ? <WKWebkitQR onScan={restore} onQuit={() => setTab(0)} /> : QR() : null}
{tab === 2 ? TextArea() : null}

{tab === 0 ? (
<Button
onClick={() => restore(fileContent)}
disabled={!fileRef.current}
variant="contained"
color="primary"
className={classes.button}>
{geti18nString('restore')}
</Button>
) : null}
{tab === 2 ? (
<Button
onClick={() => restore(textAreaRef.current!.value)}
Expand Down
46 changes: 2 additions & 44 deletions src/components/Welcomes/QRScanner/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
/// <reference path="./ShapeDetectionPolyfill.ts" />
import * as React from 'react'
import { useRef, useState } from 'react'
import { useRef } from 'react'
import { useQRCodeScan } from '../../../utils/hooks/useQRCodeScan'
import { geti18nString } from '../../../utils/i18n'
import { Button } from '@material-ui/core'
import RefreshIcon from '@material-ui/icons/Refresh'
import CheckIcon from '@material-ui/icons/Check'

interface Props {
scanning: boolean
Expand All @@ -21,48 +17,10 @@ export default function QRScanner(
const { scanning, onResult, onError, ...videoProps } = props
const video = useRef<HTMLVideoElement | null>(null)

const [result, setResult] = useState('')

function onQRResult(file: string) {
if (video.current) {
video.current.pause()
}
setResult(file)
}

function onRescanClicked() {
setResult('')
video.current!.play()
}

useQRCodeScan(video, scanning, onQRResult, onError)
useQRCodeScan(video, scanning, onResult, onError)
return (
<div style={{ position: 'relative' }}>
<video ref={video} aria-label="QR Code scanner" {...videoProps} />
{result && (
<div
style={{
background: 'rgba(255,255,255,0.3)',
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
color: 'white',
}}>
<Button disableFocusRipple disableRipple onClick={() => onResult(result)}>
<CheckIcon />
{geti18nString('welcome_1b_qr_confirm')}
</Button>
<Button disableFocusRipple disableRipple onClick={onRescanClicked}>
<RefreshIcon />
{geti18nString('welcome_1b_qr_rescan')}
</Button>
</div>
)}
</div>
)
}
14 changes: 5 additions & 9 deletions src/extension/options-page/Welcome/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import { useValueRef } from '../../../utils/hooks/useValueRef'
import { Person } from '../../../database'
import { getCurrentNetworkWorkerService } from '../../background-script/WorkerService'
import getCurrentNetworkWorker from '../../../social-network/utils/getCurrentNetworkWorker'
import { UpgradeBackupJSONFile } from '../../../utils/type-transform/BackupFile'
import { geti18nString } from '../../../utils/i18n'
import { BackupJSONFileLatest } from '../../../utils/type-transform/BackupFile'

enum WelcomeState {
// Step 0
Expand All @@ -42,13 +41,10 @@ const WelcomeActions = {
* @param file The backup file
* @param id Who am I?
*/
restoreFromFile(file: string, id: PersonIdentifier): Promise<void> {
const json = JSON.parse(file)
const upgraded = UpgradeBackupJSONFile(json)
if (!upgraded) throw new TypeError(geti18nString('service_invalid_backup_file'))
restoreFromFile(json: BackupJSONFileLatest, id: PersonIdentifier): Promise<void> {
// This request MUST BE sync or Firefox will reject this request
return browser.permissions
.request({ origins: upgraded.grantedHostPermissions })
.request({ origins: json.grantedHostPermissions })
.then(() => Services.People.restoreBackup(json, id))
},
autoVerifyBio(network: PersonIdentifier, provePost: string) {
Expand Down Expand Up @@ -168,8 +164,8 @@ function Welcome(props: Welcome) {
return (
<Welcome1b1
back={() => onStepChange(WelcomeState.Start)}
restore={url => {
sideEffects.restoreFromFile(url, props.whoAmI.identifier).then(
restore={json => {
sideEffects.restoreFromFile(json, props.whoAmI.identifier).then(
() => onStepChange(WelcomeState.End),
// TODO: use a better UI
error => alert(error),
Expand Down

0 comments on commit 6880103

Please sign in to comment.