+3
src/components/create.tsx
+3
src/components/create.tsx
···
10
10
import { TextInput } from "./text-input.jsx";
11
11
import { Modal } from "./modal.jsx";
12
12
import { Button } from "./button.jsx";
13
+
import { setNotif } from "../layout.jsx";
13
14
14
15
export const RecordEditor = (props: { create: boolean; record?: any; refetch?: any }) => {
15
16
const navigate = useNavigate();
···
66
67
return;
67
68
}
68
69
setOpenDialog(false);
70
+
setNotif({ show: true, icon: "lucide--file-check", text: "Record created" });
69
71
navigate(`/${res.data.uri}`);
70
72
};
71
73
···
119
121
}
120
122
}
121
123
setOpenDialog(false);
124
+
setNotif({ show: true, icon: "lucide--file-check", text: "Record edited" });
122
125
props.refetch();
123
126
} catch (err: any) {
124
127
setNotice(err.message);
+18
-5
src/layout.tsx
+18
-5
src/layout.tsx
···
1
-
import { createEffect, ErrorBoundary, Show, Suspense } from "solid-js";
1
+
import { createEffect, createSignal, ErrorBoundary, Show, Suspense } from "solid-js";
2
2
import { A, RouteSectionProps, useLocation, useNavigate, useParams } from "@solidjs/router";
3
3
import { agent } from "./components/login.jsx";
4
4
import { RecordEditor } from "./components/create.jsx";
···
10
10
import { Meta, MetaProvider } from "@solidjs/meta";
11
11
import { Settings } from "./components/settings.jsx";
12
12
import { Handle } from "@atcute/lexicons";
13
-
import { copyNotice } from "./utils/copy.js";
13
+
14
+
export const [notif, setNotif] = createSignal<{
15
+
show: boolean;
16
+
icon?: string;
17
+
text?: string;
18
+
}>({ show: false });
14
19
15
20
const Layout = (props: RouteSectionProps<unknown>) => {
16
21
const params = useParams();
17
22
const location = useLocation();
18
23
const navigate = useNavigate();
24
+
let timeout: number;
19
25
20
26
createEffect(async () => {
21
27
if (params.repo && !params.repo.startsWith("did:")) {
22
28
const did = await resolveHandle(params.repo as Handle);
23
29
navigate(location.pathname.replace(params.repo, did));
30
+
}
31
+
});
32
+
33
+
createEffect(() => {
34
+
if (notif().show) {
35
+
clearTimeout(timeout);
36
+
timeout = setTimeout(() => setNotif({ show: false }), 3000);
24
37
}
25
38
});
26
39
···
80
93
</ErrorBoundary>
81
94
</Show>
82
95
</div>
83
-
<Show when={copyNotice()}>
96
+
<Show when={notif().show}>
84
97
<div class="dark:shadow-dark-900/80 dark:bg-dark-100/70 fixed bottom-10 z-50 flex items-center rounded-lg border-[0.5px] border-neutral-300 bg-neutral-100/70 p-2 shadow-md backdrop-blur-xs dark:border-neutral-700">
85
-
<span class="iconify lucide--clipboard-check mr-1"></span>
86
-
Copied to clipboard
98
+
<span class={`iconify ${notif().icon} mr-1`}></span>
99
+
{notif().text}
87
100
</div>
88
101
</Show>
89
102
</div>
+2
-8
src/utils/copy.ts
+2
-8
src/utils/copy.ts
···
1
-
import { createSignal } from "solid-js";
2
-
3
-
export const [copyNotice, setCopyNotice] = createSignal(false);
4
-
5
-
let timeout: number;
1
+
import { setNotif } from "../layout";
6
2
7
3
export const addToClipboard = (text: string) => {
8
4
navigator.clipboard.writeText(text);
9
-
setCopyNotice(true);
10
-
clearTimeout(timeout);
11
-
timeout = setTimeout(() => setCopyNotice(false), 3000);
5
+
setNotif({ show: true, icon: "lucide--clipboard-check", text: "Copied to clipboard" });
12
6
};
+10
-9
src/views/collection.tsx
+10
-9
src/views/collection.tsx
···
12
12
import { ComAtprotoRepoApplyWrites, ComAtprotoRepoGetRecord } from "@atcute/atproto";
13
13
import { TextInput } from "../components/text-input.jsx";
14
14
import { Button } from "../components/button.jsx";
15
+
import { setNotif } from "../layout.jsx";
15
16
16
17
interface AtprotoRecord {
17
18
rkey: string;
···
106
107
const [response, { refetch }] = createResource(fetchRecords);
107
108
108
109
const deleteRecords = async () => {
109
-
const writes = records
110
-
.filter((record) => record.toDelete)
111
-
.map((record): $type.enforce<ComAtprotoRepoApplyWrites.Delete> => {
112
-
return {
113
-
$type: "com.atproto.repo.applyWrites#delete",
114
-
collection: params.collection as `${string}.${string}.${string}`,
115
-
rkey: record.rkey,
116
-
};
117
-
});
110
+
const recsToDel = records.filter((record) => record.toDelete);
111
+
const writes = recsToDel.map((record): $type.enforce<ComAtprotoRepoApplyWrites.Delete> => {
112
+
return {
113
+
$type: "com.atproto.repo.applyWrites#delete",
114
+
collection: params.collection as `${string}.${string}.${string}`,
115
+
rkey: record.rkey,
116
+
};
117
+
});
118
118
119
119
const BATCHSIZE = 200;
120
120
rpc = new Client({ handler: agent()! });
···
126
126
},
127
127
});
128
128
}
129
+
setNotif({ show: true, icon: "lucide--trash-2", text: `${recsToDel.length} records deleted` });
129
130
setBatchDelete(false);
130
131
setRecords([]);
131
132
setCursor(undefined);
+2
src/views/record.tsx
+2
src/views/record.tsx
···
19
19
import Tooltip from "../components/tooltip.jsx";
20
20
import { Modal } from "../components/modal.jsx";
21
21
import { Button } from "../components/button.jsx";
22
+
import { setNotif } from "../layout.jsx";
22
23
23
24
export const RecordView = () => {
24
25
const navigate = useNavigate();
···
98
99
rkey: params.rkey,
99
100
},
100
101
});
102
+
setNotif({ show: true, icon: "lucide--trash-2", text: "Record deleted" });
101
103
navigate(`/at://${params.repo}/${params.collection}`);
102
104
};
103
105