blessing-skin-server/resources/assets/src/components/Captcha.tsx
2020-05-16 21:56:08 +08:00

105 lines
2.4 KiB
TypeScript

/** @jsx jsx */
import * as React from 'react'
import { jsx } from '@emotion/core'
import Reaptcha from 'reaptcha'
import { emit, on } from '@/scripts/event'
import { t } from '@/scripts/i18n'
import * as cssUtils from '@/styles/utils'
const eventId = Symbol()
type State = {
value: string
time: number
sitekey: string
invisible: boolean
}
class Captcha extends React.Component<{}, State> {
state: State
ref: React.MutableRefObject<Reaptcha | null>
constructor(props: {}) {
super(props)
this.state = {
value: '',
time: Date.now(),
sitekey: blessing.extra.recaptcha,
invisible: blessing.extra.invisible,
}
this.ref = React.createRef()
}
execute = async () => {
const recaptcha = this.ref.current
if (recaptcha && this.state.invisible) {
return new Promise<string>((resolve) => {
const off = on(eventId, (value: string) => {
resolve(value)
off()
})
recaptcha.execute()
})
}
return this.state.value
}
reset = () => {
const recaptcha = this.ref.current
if (recaptcha) {
recaptcha.reset()
} else {
this.setState({ time: Date.now() })
}
}
handleValueChange = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ value: event.target.value })
}
handleVerify = (value: string) => {
emit(eventId, value)
this.setState({ value })
}
handleRefresh = () => {
this.setState({ time: Date.now() })
}
render() {
return this.state.sitekey ? (
<div className="mb-2">
<Reaptcha
ref={this.ref}
sitekey={this.state.sitekey}
size={this.state.invisible ? 'invisible' : 'normal'}
onVerify={this.handleVerify}
/>
</div>
) : (
<div className="d-flex">
<div className="form-group mb-3 mr-2">
<input
type="text"
className="form-control"
placeholder={t('auth.captcha')}
required
value={this.state.value}
onChange={this.handleValueChange}
/>
</div>
<img
src={`${blessing.base_url}/auth/captcha?v=${this.state.time}`}
alt={t('auth.captcha')}
css={cssUtils.pointerCursor}
height={34}
title={t('auth.change-captcha')}
onClick={this.handleRefresh}
/>
</div>
)
}
}
export default Captcha