+3
src/components/create.tsx
+3
src/components/create.tsx
···
10
import { TextInput } from "./text-input.jsx";
11
import { Modal } from "./modal.jsx";
12
import { Button } from "./button.jsx";
13
14
export const RecordEditor = (props: { create: boolean; record?: any; refetch?: any }) => {
15
const navigate = useNavigate();
···
66
return;
67
}
68
setOpenDialog(false);
69
navigate(`/${res.data.uri}`);
70
};
71
···
119
}
120
}
121
setOpenDialog(false);
122
props.refetch();
123
} catch (err: any) {
124
setNotice(err.message);
···
10
import { TextInput } from "./text-input.jsx";
11
import { Modal } from "./modal.jsx";
12
import { Button } from "./button.jsx";
13
+
import { setNotif } from "../layout.jsx";
14
15
export const RecordEditor = (props: { create: boolean; record?: any; refetch?: any }) => {
16
const navigate = useNavigate();
···
67
return;
68
}
69
setOpenDialog(false);
70
+
setNotif({ show: true, icon: "lucide--file-check", text: "Record created" });
71
navigate(`/${res.data.uri}`);
72
};
73
···
121
}
122
}
123
setOpenDialog(false);
124
+
setNotif({ show: true, icon: "lucide--file-check", text: "Record edited" });
125
props.refetch();
126
} catch (err: any) {
127
setNotice(err.message);
+18
-5
src/layout.tsx
+18
-5
src/layout.tsx
···
1
-
import { createEffect, ErrorBoundary, Show, Suspense } from "solid-js";
2
import { A, RouteSectionProps, useLocation, useNavigate, useParams } from "@solidjs/router";
3
import { agent } from "./components/login.jsx";
4
import { RecordEditor } from "./components/create.jsx";
···
10
import { Meta, MetaProvider } from "@solidjs/meta";
11
import { Settings } from "./components/settings.jsx";
12
import { Handle } from "@atcute/lexicons";
13
-
import { copyNotice } from "./utils/copy.js";
14
15
const Layout = (props: RouteSectionProps<unknown>) => {
16
const params = useParams();
17
const location = useLocation();
18
const navigate = useNavigate();
19
20
createEffect(async () => {
21
if (params.repo && !params.repo.startsWith("did:")) {
22
const did = await resolveHandle(params.repo as Handle);
23
navigate(location.pathname.replace(params.repo, did));
24
}
25
});
26
···
80
</ErrorBoundary>
81
</Show>
82
</div>
83
-
<Show when={copyNotice()}>
84
<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
87
</div>
88
</Show>
89
</div>
···
1
+
import { createEffect, createSignal, ErrorBoundary, Show, Suspense } from "solid-js";
2
import { A, RouteSectionProps, useLocation, useNavigate, useParams } from "@solidjs/router";
3
import { agent } from "./components/login.jsx";
4
import { RecordEditor } from "./components/create.jsx";
···
10
import { Meta, MetaProvider } from "@solidjs/meta";
11
import { Settings } from "./components/settings.jsx";
12
import { Handle } from "@atcute/lexicons";
13
+
14
+
export const [notif, setNotif] = createSignal<{
15
+
show: boolean;
16
+
icon?: string;
17
+
text?: string;
18
+
}>({ show: false });
19
20
const Layout = (props: RouteSectionProps<unknown>) => {
21
const params = useParams();
22
const location = useLocation();
23
const navigate = useNavigate();
24
+
let timeout: number;
25
26
createEffect(async () => {
27
if (params.repo && !params.repo.startsWith("did:")) {
28
const did = await resolveHandle(params.repo as Handle);
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);
37
}
38
});
39
···
93
</ErrorBoundary>
94
</Show>
95
</div>
96
+
<Show when={notif().show}>
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">
98
+
<span class={`iconify ${notif().icon} mr-1`}></span>
99
+
{notif().text}
100
</div>
101
</Show>
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;
6
7
export const addToClipboard = (text: string) => {
8
navigator.clipboard.writeText(text);
9
-
setCopyNotice(true);
10
-
clearTimeout(timeout);
11
-
timeout = setTimeout(() => setCopyNotice(false), 3000);
12
};
+10
-9
src/views/collection.tsx
+10
-9
src/views/collection.tsx
···
12
import { ComAtprotoRepoApplyWrites, ComAtprotoRepoGetRecord } from "@atcute/atproto";
13
import { TextInput } from "../components/text-input.jsx";
14
import { Button } from "../components/button.jsx";
15
16
interface AtprotoRecord {
17
rkey: string;
···
106
const [response, { refetch }] = createResource(fetchRecords);
107
108
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
-
});
118
119
const BATCHSIZE = 200;
120
rpc = new Client({ handler: agent()! });
···
126
},
127
});
128
}
129
setBatchDelete(false);
130
setRecords([]);
131
setCursor(undefined);
···
12
import { ComAtprotoRepoApplyWrites, ComAtprotoRepoGetRecord } from "@atcute/atproto";
13
import { TextInput } from "../components/text-input.jsx";
14
import { Button } from "../components/button.jsx";
15
+
import { setNotif } from "../layout.jsx";
16
17
interface AtprotoRecord {
18
rkey: string;
···
107
const [response, { refetch }] = createResource(fetchRecords);
108
109
const deleteRecords = async () => {
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
119
const BATCHSIZE = 200;
120
rpc = new Client({ handler: agent()! });
···
126
},
127
});
128
}
129
+
setNotif({ show: true, icon: "lucide--trash-2", text: `${recsToDel.length} records deleted` });
130
setBatchDelete(false);
131
setRecords([]);
132
setCursor(undefined);
+2
src/views/record.tsx
+2
src/views/record.tsx
···
19
import Tooltip from "../components/tooltip.jsx";
20
import { Modal } from "../components/modal.jsx";
21
import { Button } from "../components/button.jsx";
22
23
export const RecordView = () => {
24
const navigate = useNavigate();
···
98
rkey: params.rkey,
99
},
100
});
101
navigate(`/at://${params.repo}/${params.collection}`);
102
};
103
···
19
import Tooltip from "../components/tooltip.jsx";
20
import { Modal } from "../components/modal.jsx";
21
import { Button } from "../components/button.jsx";
22
+
import { setNotif } from "../layout.jsx";
23
24
export const RecordView = () => {
25
const navigate = useNavigate();
···
99
rkey: params.rkey,
100
},
101
});
102
+
setNotif({ show: true, icon: "lucide--trash-2", text: "Record deleted" });
103
navigate(`/at://${params.repo}/${params.collection}`);
104
};
105