149 lines
3.3 KiB
TypeScript

import type { OnePassword } from "opvault.js"
import styled from "@emotion/styled"
import React, { useCallback, useEffect, useState } from "react"
import { IoMdArrowRoundBack } from "react-icons/io"
import { FaUnlock } from "react-icons/fa"
import { useTranslate } from "../../i18n"
const Container = styled.div`
padding: 20px;
transform: translate(-50%, -50%);
position: absolute;
top: 50%;
left: 50%;
width: 500px;
`
const BackButton = styled.button`
&& {
background: transparent;
}
border: none;
box-shadow: none;
font-size: 2em;
cursor: pointer;
padding: 0;
&:hover {
svg path {
fill: var(--selected-background);
transition: 0.2s;
}
}
`
const Input = styled.input`
box-shadow: inset 0 2px 2px rgb(0 0 0 / 8%);
font-size: 1.5em;
width: calc(95.5% - 60px);
&& {
border-radius: 10px;
border-width: 1px;
padding: 15px 20px;
padding-right: 60px;
}
`
const Select = styled.select`
float: right;
`
const Submit = styled.button`
font-size: 1.8em;
&& {
background: transparent;
border: none;
box-shadow: none;
}
svg path {
fill: var(--color);
}
&:hover {
transition: 0.2s;
}
text-align: center;
position: absolute;
top: 8px;
right: 5px;
`
const VaultPath = styled.div`
margin-top: 15px;
opacity: 0.7;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`
export const Unlock: React.FC<{
instance: OnePassword
vaultPath: string
onUnlock(profile: string, password: string): void
onReturn(): void
}> = ({ onUnlock, onReturn, instance, vaultPath }) => {
const t = useTranslate()
const [profiles, setProfiles] = useState<string[]>(() => [])
const [profile, setProfile] = useState<string>()
const [password, setPassword] = useState("")
const unlock = useCallback(
(e?: React.FormEvent) => {
e?.preventDefault()
if (!profile) return
onUnlock(profile, password)
setPassword("")
},
[onUnlock, profile, password]
)
const onKeyUp = useCallback(
(e: React.KeyboardEvent) => {
if (e.key === "Enter") {
unlock()
}
},
[unlock]
)
useEffect(() => {
instance.getProfileNames().then(profiles => {
setProfiles(profiles)
setProfile(profiles[0])
})
}, [instance])
return (
<Container>
<div style={{ marginBottom: 10 }}>
<BackButton onClick={onReturn} title={t.action.go_back}>
<IoMdArrowRoundBack />
</BackButton>
<Select
title={t.noun.vault}
value={profile}
onChange={e => setProfile(e.currentTarget.value)}
>
{profiles.map(p => (
<option key={p} value={p}>
{t.noun.vault}: {p}
</option>
))}
</Select>
</div>
<div style={{ margin: "10px 0", position: "relative" }}>
<Input
type="password"
value={password}
onChange={e => setPassword(e.currentTarget.value)}
placeholder={t.label.password_placeholder}
onKeyUp={onKeyUp}
/>
<Submit
type="submit"
disabled={!profile || !password}
onClick={unlock}
title={t.action.unlock}
>
<FaUnlock />
</Submit>
</div>
<VaultPath>{vaultPath}</VaultPath>
</Container>
)
}