mirror of
https://github.com/handsomezhuzhu/2fa-tool.git
synced 2026-02-20 19:50:15 +00:00
feat: add missing fields to Edit Dialog
Extend dialog to include secret, algorithm, digits, and period for full editing. Co-authored-by: Simon <85533298+handsomezhuzhu@users.noreply.github.com>
This commit is contained in:
173
app/page.tsx
173
app/page.tsx
@@ -27,7 +27,6 @@ import {
|
||||
Monitor,
|
||||
Languages,
|
||||
Check,
|
||||
Github,
|
||||
} from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
@@ -163,7 +162,6 @@ export default function TwoFactorAuth() {
|
||||
const [isSettingsOpen, setIsSettingsOpen] = useState(false)
|
||||
const [editingToken, setEditingToken] = useState<TOTPToken | null>(null)
|
||||
const [showAdvanced, setShowAdvanced] = useState(false)
|
||||
const [mounted, setMounted] = useState(false)
|
||||
const videoRef = useRef<HTMLVideoElement>(null)
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null)
|
||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||
@@ -197,7 +195,6 @@ export default function TwoFactorAuth() {
|
||||
if (savedSettings) {
|
||||
setSettings(JSON.parse(savedSettings))
|
||||
}
|
||||
setMounted(true)
|
||||
}, [])
|
||||
|
||||
// Save tokens to localStorage
|
||||
@@ -658,33 +655,15 @@ export default function TwoFactorAuth() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="ghost" size="icon" asChild>
|
||||
<a
|
||||
href="https://github.com/handsomezhuzhu/2fa-tool"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="GitHub"
|
||||
>
|
||||
<Github className="h-5 w-5" />
|
||||
<span className="sr-only">GitHub</span>
|
||||
</a>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={cycleTheme}
|
||||
title={mounted ? (theme === "light" ? t.themeLight : theme === "dark" ? t.themeDark : t.themeSystem) : t.themeSystem}
|
||||
title={theme === "light" ? t.themeLight : theme === "dark" ? t.themeDark : t.themeSystem}
|
||||
>
|
||||
{!mounted ? (
|
||||
<Monitor className="h-5 w-5" />
|
||||
) : (
|
||||
<>
|
||||
{theme === "light" && <Sun className="h-5 w-5" />}
|
||||
{theme === "dark" && <Moon className="h-5 w-5" />}
|
||||
{theme === "system" && <Monitor className="h-5 w-5" />}
|
||||
</>
|
||||
)}
|
||||
{theme === "light" && <Sun className="h-5 w-5" />}
|
||||
{theme === "dark" && <Moon className="h-5 w-5" />}
|
||||
{theme === "system" && <Monitor className="h-5 w-5" />}
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
|
||||
@@ -1017,7 +996,7 @@ export default function TwoFactorAuth() {
|
||||
|
||||
{/* Edit Dialog */}
|
||||
<Dialog open={!!editingToken} onOpenChange={(open) => !open && setEditingToken(null)}>
|
||||
<DialogContent>
|
||||
<DialogContent className="max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t.editToken}</DialogTitle>
|
||||
</DialogHeader>
|
||||
@@ -1037,6 +1016,68 @@ export default function TwoFactorAuth() {
|
||||
onChange={(e) => setEditingToken({ ...editingToken, issuer: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>{t.secretKey}</Label>
|
||||
<Input
|
||||
value={editingToken.secret}
|
||||
onChange={(e) => setEditingToken({ ...editingToken, secret: e.target.value.toUpperCase().replace(/\s/g, "") })}
|
||||
className="font-mono"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label>{t.algorithm}</Label>
|
||||
<Select
|
||||
value={editingToken.algorithm}
|
||||
onValueChange={(value: "SHA1" | "SHA256" | "SHA512") =>
|
||||
setEditingToken({ ...editingToken, algorithm: value })
|
||||
}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="SHA1">SHA-1</SelectItem>
|
||||
<SelectItem value="SHA256">SHA-256</SelectItem>
|
||||
<SelectItem value="SHA512">SHA-512</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>{t.digits}</Label>
|
||||
<Select
|
||||
value={editingToken.digits.toString()}
|
||||
onValueChange={(value) =>
|
||||
setEditingToken({ ...editingToken, digits: parseInt(value) as 6 | 8 })
|
||||
}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="6">6</SelectItem>
|
||||
<SelectItem value="8">8</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>{t.period}</Label>
|
||||
<Select
|
||||
value={editingToken.period.toString()}
|
||||
onValueChange={(value) =>
|
||||
setEditingToken({ ...editingToken, period: parseInt(value) })
|
||||
}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="30">30s</SelectItem>
|
||||
<SelectItem value="60">60s</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<DialogFooter>
|
||||
@@ -1049,50 +1090,39 @@ export default function TwoFactorAuth() {
|
||||
</Dialog>
|
||||
|
||||
{/* Footer */}
|
||||
{/* Footer */}
|
||||
{(process.env.NEXT_PUBLIC_SHOW_FOOTER !== "false") && (
|
||||
<footer className="border-t py-6 mt-auto">
|
||||
<div className="mx-auto flex max-w-4xl flex-col items-center gap-2 text-center md:flex-row md:justify-between md:gap-4 px-4">
|
||||
<p className="text-xs tracking-wider text-muted-foreground">© 2025 Simon. All rights reserved.</p>
|
||||
{(process.env.NEXT_PUBLIC_FILING_ICP || process.env.NEXT_PUBLIC_FILING_SECURITY) && (
|
||||
<div className="flex items-center gap-4 text-xs tracking-wider text-muted-foreground/60">
|
||||
{process.env.NEXT_PUBLIC_FILING_ICP && (
|
||||
<a
|
||||
href="https://beian.miit.gov.cn/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="transition-colors hover:text-muted-foreground"
|
||||
>
|
||||
{process.env.NEXT_PUBLIC_FILING_ICP}
|
||||
</a>
|
||||
)}
|
||||
{process.env.NEXT_PUBLIC_FILING_ICP && process.env.NEXT_PUBLIC_FILING_SECURITY && (
|
||||
<span className="text-muted-foreground/30">|</span>
|
||||
)}
|
||||
{process.env.NEXT_PUBLIC_FILING_SECURITY && (
|
||||
<a
|
||||
href="https://beian.mps.gov.cn"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-1.5 transition-colors hover:text-muted-foreground"
|
||||
>
|
||||
<img
|
||||
alt="公安备案"
|
||||
loading="lazy"
|
||||
width="14"
|
||||
height="14"
|
||||
decoding="async"
|
||||
className="opacity-60"
|
||||
src="/images/beian.png"
|
||||
/>
|
||||
{process.env.NEXT_PUBLIC_FILING_SECURITY}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<footer className="border-t py-6 mt-auto">
|
||||
<div className="mx-auto flex max-w-4xl flex-col items-center gap-2 text-center md:flex-row md:justify-between md:gap-4 px-4">
|
||||
<p className="text-xs tracking-wider text-muted-foreground">© 2025 Simon. All rights reserved.</p>
|
||||
<div className="flex items-center gap-4 text-xs tracking-wider text-muted-foreground/60">
|
||||
<a
|
||||
href="https://beian.miit.gov.cn/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="transition-colors hover:text-muted-foreground"
|
||||
>
|
||||
滇ICP备2025074424号
|
||||
</a>
|
||||
<span className="text-muted-foreground/30">|</span>
|
||||
<a
|
||||
href="https://beian.mps.gov.cn"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-1.5 transition-colors hover:text-muted-foreground"
|
||||
>
|
||||
<img
|
||||
alt="公安备案"
|
||||
loading="lazy"
|
||||
width="14"
|
||||
height="14"
|
||||
decoding="async"
|
||||
className="opacity-60"
|
||||
src="/images/beian.png"
|
||||
/>
|
||||
滇公网安备53250402000233号
|
||||
</a>
|
||||
</div>
|
||||
</footer>
|
||||
)}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<Toaster />
|
||||
</div>
|
||||
@@ -1168,8 +1198,9 @@ function TokenCard({ token, code, timeLeft, showCode, onCopy, onEdit, onDelete,
|
||||
</button>
|
||||
|
||||
<span
|
||||
className={`font-mono text-base font-bold min-w-[90px] text-center transition-colors ${copied ? "text-green-500" : ""
|
||||
}`}
|
||||
className={`font-mono text-base font-bold min-w-[90px] text-center transition-colors ${
|
||||
copied ? "text-green-500" : ""
|
||||
}`}
|
||||
>
|
||||
{visible ? formattedCode : "••• •••"}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user