diff --git a/app/components/emails/create-dialog.tsx b/app/components/emails/create-dialog.tsx
index 8e678fa..2e87943 100644
--- a/app/components/emails/create-dialog.tsx
+++ b/app/components/emails/create-dialog.tsx
@@ -4,13 +4,14 @@ import { useEffect, useState } from "react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
-import { Plus, RefreshCw } from "lucide-react"
+import { Copy, Plus, RefreshCw } from "lucide-react"
import { useToast } from "@/components/ui/use-toast"
import { nanoid } from "nanoid"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { EXPIRY_OPTIONS } from "@/types/email"
+import { useCopy } from "@/hooks/use-copy"
interface CreateDialogProps {
onEmailCreated: () => void
@@ -28,9 +29,14 @@ export function CreateDialog({ onEmailCreated }: CreateDialogProps) {
const [currentDomain, setCurrentDomain] = useState("")
const [expiryTime, setExpiryTime] = useState(EXPIRY_OPTIONS[1].value.toString())
const { toast } = useToast()
+ const { copyToClipboard } = useCopy()
const generateRandomName = () => setEmailName(nanoid(8))
+ const copyEmailAddress = () => {
+ copyToClipboard(`${emailName}@${currentDomain}`)
+ }
+
const createEmail = async () => {
if (!emailName.trim()) {
toast({
@@ -152,8 +158,21 @@ export function CreateDialog({ onEmailCreated }: CreateDialogProps) {
-
- 完整邮箱地址将为: {emailName ? `${emailName}@${currentDomain}` : "..."}
+
+
完整邮箱地址将为:
+ {emailName ? (
+
+
{`${emailName}@${currentDomain}`}
+
+
+
+
+ ) : (
+
...
+ )}
diff --git a/app/components/emails/three-column-layout.tsx b/app/components/emails/three-column-layout.tsx
index fc5b32a..eb2a54e 100644
--- a/app/components/emails/three-column-layout.tsx
+++ b/app/components/emails/three-column-layout.tsx
@@ -5,6 +5,8 @@ import { EmailList } from "./email-list"
import { MessageList } from "./message-list"
import { MessageView } from "./message-view"
import { cn } from "@/lib/utils"
+import { useCopy } from "@/hooks/use-copy"
+import { Copy } from "lucide-react"
interface Email {
id: string
@@ -14,10 +16,11 @@ interface Email {
export function ThreeColumnLayout() {
const [selectedEmail, setSelectedEmail] = useState
(null)
const [selectedMessageId, setSelectedMessageId] = useState(null)
+ const { copyToClipboard } = useCopy()
const columnClass = "border-2 border-primary/20 bg-background rounded-lg overflow-hidden flex flex-col"
const headerClass = "p-2 border-b-2 border-primary/20 flex items-center justify-between shrink-0"
- const titleClass = "text-sm font-bold px-2"
+ const titleClass = "text-sm font-bold px-2 w-full overflow-hidden"
// 移动端视图逻辑
const getMobileView = () => {
@@ -28,6 +31,10 @@ export function ThreeColumnLayout() {
const mobileView = getMobileView()
+ const copyEmailAddress = () => {
+ copyToClipboard(selectedEmail?.address || "")
+ }
+
return (
{/* 桌面端三栏布局 */}
@@ -37,7 +44,7 @@ export function ThreeColumnLayout() {
我的邮箱
-
@@ -48,7 +55,12 @@ export function ThreeColumnLayout() {
{selectedEmail ? (
- {selectedEmail.address}
+
+
{selectedEmail.address}
+
+
+
+
) : (
"选择邮箱查看消息"
)}
@@ -92,7 +104,7 @@ export function ThreeColumnLayout() {
我的邮箱
- {
setSelectedEmail(email)
}}
@@ -101,21 +113,24 @@ export function ThreeColumnLayout() {
>
)}
-
+
{mobileView === "emails" && selectedEmail && (
-
+
-
- {selectedEmail.address}
-
+
+
{selectedEmail.address}
+
+
+
+
)}
-
+
{mobileView === "message" && selectedEmail && selectedMessageId && (
diff --git a/app/hooks/use-copy.ts b/app/hooks/use-copy.ts
new file mode 100644
index 0000000..aff50b5
--- /dev/null
+++ b/app/hooks/use-copy.ts
@@ -0,0 +1,39 @@
+"use client"
+
+import { useCallback } from "react"
+import { useToast } from "@/components/ui/use-toast"
+
+interface UseCopyOptions {
+ successMessage?: string
+ errorMessage?: string
+}
+
+export function useCopy(options: UseCopyOptions = {}) {
+ const { toast } = useToast()
+ const {
+ successMessage = "已复制到剪贴板",
+ errorMessage = "复制失败"
+ } = options
+
+ const copyToClipboard = useCallback(async (text: string) => {
+ try {
+ await navigator.clipboard.writeText(text)
+ toast({
+ title: "成功",
+ description: successMessage
+ })
+ return true
+ } catch {
+ toast({
+ title: "错误",
+ description: errorMessage,
+ variant: "destructive"
+ })
+ return false
+ }
+ }, [successMessage, errorMessage, toast])
+
+ return {
+ copyToClipboard
+ }
+}
\ No newline at end of file