Skip to content

Commit 6c680fc

Browse files
committed
实现全部私聊功能
1 parent d3d9c8c commit 6c680fc

9 files changed

Lines changed: 314 additions & 269 deletions

File tree

src/components/ui/alert-dialog.tsx

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
1-
import * as React from "react"
2-
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
1+
import * as React from "react";
2+
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
33

4-
import { cn } from "@/lib/utils"
5-
import { buttonVariants } from "@/components/ui/button"
4+
import { cn } from "@/lib/utils";
5+
import { buttonVariants } from "@/components/ui/button";
66

77
function AlertDialog({
88
...props
99
}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
10-
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
10+
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
1111
}
1212

1313
function AlertDialogTrigger({
1414
...props
1515
}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
1616
return (
1717
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
18-
)
18+
);
1919
}
2020

2121
function AlertDialogPortal({
2222
...props
2323
}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
2424
return (
2525
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
26-
)
26+
);
2727
}
2828

2929
function AlertDialogOverlay({
@@ -35,11 +35,11 @@ function AlertDialogOverlay({
3535
data-slot="alert-dialog-overlay"
3636
className={cn(
3737
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
38-
className
38+
className,
3939
)}
4040
{...props}
4141
/>
42-
)
42+
);
4343
}
4444

4545
function AlertDialogContent({
@@ -53,12 +53,12 @@ function AlertDialogContent({
5353
data-slot="alert-dialog-content"
5454
className={cn(
5555
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
56-
className
56+
className,
5757
)}
5858
{...props}
5959
/>
6060
</AlertDialogPortal>
61-
)
61+
);
6262
}
6363

6464
function AlertDialogHeader({
@@ -71,7 +71,7 @@ function AlertDialogHeader({
7171
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
7272
{...props}
7373
/>
74-
)
74+
);
7575
}
7676

7777
function AlertDialogFooter({
@@ -83,11 +83,11 @@ function AlertDialogFooter({
8383
data-slot="alert-dialog-footer"
8484
className={cn(
8585
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
86-
className
86+
className,
8787
)}
8888
{...props}
8989
/>
90-
)
90+
);
9191
}
9292

9393
function AlertDialogTitle({
@@ -100,7 +100,7 @@ function AlertDialogTitle({
100100
className={cn("text-lg font-semibold", className)}
101101
{...props}
102102
/>
103-
)
103+
);
104104
}
105105

106106
function AlertDialogDescription({
@@ -113,7 +113,7 @@ function AlertDialogDescription({
113113
className={cn("text-muted-foreground text-sm", className)}
114114
{...props}
115115
/>
116-
)
116+
);
117117
}
118118

119119
function AlertDialogAction({
@@ -125,7 +125,7 @@ function AlertDialogAction({
125125
className={cn(buttonVariants(), className)}
126126
{...props}
127127
/>
128-
)
128+
);
129129
}
130130

131131
function AlertDialogCancel({
@@ -137,7 +137,7 @@ function AlertDialogCancel({
137137
className={cn(buttonVariants({ variant: "outline" }), className)}
138138
{...props}
139139
/>
140-
)
140+
);
141141
}
142142

143143
export {
@@ -152,4 +152,4 @@ export {
152152
AlertDialogDescription,
153153
AlertDialogAction,
154154
AlertDialogCancel,
155-
}
155+
};

src/components/ui/dialog.tsx

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
1-
import * as React from "react"
2-
import * as DialogPrimitive from "@radix-ui/react-dialog"
3-
import { XIcon } from "lucide-react"
1+
import * as React from "react";
2+
import * as DialogPrimitive from "@radix-ui/react-dialog";
3+
import { XIcon } from "lucide-react";
44

5-
import { cn } from "@/lib/utils"
5+
import { cn } from "@/lib/utils";
66

77
function Dialog({
88
...props
99
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
10-
return <DialogPrimitive.Root data-slot="dialog" {...props} />
10+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
1111
}
1212

1313
function DialogTrigger({
1414
...props
1515
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
16-
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
16+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
1717
}
1818

1919
function DialogPortal({
2020
...props
2121
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
22-
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
22+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
2323
}
2424

2525
function DialogClose({
2626
...props
2727
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
28-
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
28+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
2929
}
3030

3131
function DialogOverlay({
@@ -37,11 +37,11 @@ function DialogOverlay({
3737
data-slot="dialog-overlay"
3838
className={cn(
3939
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
40-
className
40+
className,
4141
)}
4242
{...props}
4343
/>
44-
)
44+
);
4545
}
4646

4747
function DialogContent({
@@ -50,7 +50,7 @@ function DialogContent({
5050
showCloseButton = true,
5151
...props
5252
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
53-
showCloseButton?: boolean
53+
showCloseButton?: boolean;
5454
}) {
5555
return (
5656
<DialogPortal data-slot="dialog-portal">
@@ -59,7 +59,7 @@ function DialogContent({
5959
data-slot="dialog-content"
6060
className={cn(
6161
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
62-
className
62+
className,
6363
)}
6464
{...props}
6565
>
@@ -75,7 +75,7 @@ function DialogContent({
7575
)}
7676
</DialogPrimitive.Content>
7777
</DialogPortal>
78-
)
78+
);
7979
}
8080

8181
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
@@ -85,7 +85,7 @@ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
8585
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
8686
{...props}
8787
/>
88-
)
88+
);
8989
}
9090

9191
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
@@ -94,11 +94,11 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
9494
data-slot="dialog-footer"
9595
className={cn(
9696
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
97-
className
97+
className,
9898
)}
9999
{...props}
100100
/>
101-
)
101+
);
102102
}
103103

104104
function DialogTitle({
@@ -111,7 +111,7 @@ function DialogTitle({
111111
className={cn("text-lg leading-none font-semibold", className)}
112112
{...props}
113113
/>
114-
)
114+
);
115115
}
116116

117117
function DialogDescription({
@@ -124,7 +124,7 @@ function DialogDescription({
124124
className={cn("text-muted-foreground text-sm", className)}
125125
{...props}
126126
/>
127-
)
127+
);
128128
}
129129

130130
export {
@@ -138,4 +138,4 @@ export {
138138
DialogPortal,
139139
DialogTitle,
140140
DialogTrigger,
141-
}
141+
};
Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
export interface UserInfo {
2-
name: string;
3-
avatar?: Uint8Array;
4-
bio?: string;
5-
}
6-
71
export async function blob_to_data_url(blob: Blob) {
82
return await new Promise<string>((resolve, reject) => {
93
const file_reader = new FileReader();

src/lib/observable_map.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export class ObservableMap<K, V> {
2+
private inner: Map<K, V>;
3+
private set_listeners: Map<K, (value: V) => void>;
4+
private delete_listeners: Map<K, () => void>;
5+
6+
constructor() {
7+
this.inner = new Map();
8+
this.set_listeners = new Map();
9+
this.delete_listeners = new Map();
10+
}
11+
listen_set(key: K, callback: (value: V) => void) {
12+
this.set_listeners.set(key, callback);
13+
}
14+
listen_delete(key: K, callback: () => void) {
15+
this.delete_listeners.set(key, callback);
16+
}
17+
set(key: K, value: V) {
18+
this.inner.set(key, value);
19+
this.set_listeners.get(key)?.(value);
20+
}
21+
get(key: K) {
22+
return this.inner.get(key);
23+
}
24+
delete(key: K) {
25+
this.inner.delete(key);
26+
this.set_listeners.delete(key);
27+
this.delete_listeners.get(key)?.();
28+
this.delete_listeners.delete(key);
29+
}
30+
}

src/lib/user_info.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface UserInfo {
2+
name: string;
3+
avatar?: Uint8Array;
4+
bio?: string;
5+
}

src/routes/app.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,15 @@ import { createStore } from "zustand";
6060
import { combine } from "zustand/middleware";
6161
import { Octokit } from "octokit";
6262
import { open_url } from "@/lib/opener";
63-
import type { UserInfo } from "@/lib/type";
63+
import type { UserInfo } from "@/lib/user_info";
6464
import wasm_url from "@zhangxichang/wasm/wasm_bg.wasm?url";
6565
import wasm_instantiate, { wasm_init } from "@zhangxichang/wasm";
6666

6767
const Store = createStore(
6868
combine(
6969
{
7070
wasm_inited: false,
71+
notification: null as [] | null,
7172
dexie: null as
7273
| (Dexie & {
7374
users: EntityTable<
@@ -117,7 +118,12 @@ export const Route = createFileRoute("/app")({
117118
friends: "&[owner+id],name,avatar,bio",
118119
chat_records: "++id,timestamp,sender,receiver,message",
119120
});
120-
store.set({ dexie: (await dexie.open()) as any });
121+
try {
122+
await dexie.open();
123+
} catch (_) {
124+
await dexie.delete({ disableAutoOpen: false });
125+
}
126+
store.set({ dexie: dexie as any });
121127
}
122128
return {
123129
dexie: store.get().dexie!,

0 commit comments

Comments
 (0)