a tool for shared writing and social publishing
1import { useEntitySetContext } from "components/EntitySetProvider";
2import { generateKeyBetween } from "fractional-indexing";
3import { useState } from "react";
4import { useEntity, useReplicache } from "src/replicache";
5import { useUIState } from "src/useUIState";
6import { BlockProps } from "../Block";
7import { v7 } from "uuid";
8import { useSmoker } from "components/Toast";
9import { Separator } from "components/Layout";
10import { Input } from "components/Input";
11import { isUrl } from "src/utils/isURL";
12import { addBlueskyPostBlock } from "src/utils/addLinkBlock";
13import { BlockBlueskySmall } from "components/Icons/BlockBlueskySmall";
14import { CheckTiny } from "components/Icons/CheckTiny";
15
16export const BlueskyPostEmpty = (props: BlockProps) => {
17 let { rep } = useReplicache();
18 let isSelected = useUIState((s) =>
19 s.selectedBlocks.find((b) => b.value === props.entityID),
20 );
21 let isLocked = useEntity(props.entityID, "block/is-locked")?.data.value;
22
23 let entity_set = useEntitySetContext();
24 let [urlValue, setUrlValue] = useState("");
25
26 let submit = async () => {
27 if (!rep) return;
28 let entity = props.entityID;
29
30 let blueskyPostBlock = await addBlueskyPostBlock(urlValue, entity, rep);
31 if (blueskyPostBlock === false) {
32 let rect = document
33 .getElementById("bluesky-post-block-submit")
34 ?.getBoundingClientRect();
35 smoker({
36 error: true,
37 text: "post not found!",
38 position: {
39 x: (rect && rect.left + 12) || 0,
40 y: (rect && rect.top) || 0,
41 },
42 });
43 }
44 };
45 let smoker = useSmoker();
46 function errorSmokers(x: number, y: number) {
47 if (!urlValue || urlValue === "") {
48 smoker({
49 error: true,
50 text: "no url!",
51 position: {
52 x: x,
53 y: y,
54 },
55 });
56 return;
57 }
58 if (!isUrl(urlValue) || !urlValue.includes("bsky.app")) {
59 smoker({
60 error: true,
61 text: "invalid bluesky url!",
62 position: {
63 x: x,
64 y: y,
65 },
66 });
67 return;
68 }
69 }
70
71 return (
72 <form
73 onSubmit={(e) => {
74 e.preventDefault();
75 let rect = document
76 .getElementById("bluesky-post-block-submit")
77 ?.getBoundingClientRect();
78
79 rect && errorSmokers(rect.left + 12, rect.top);
80 submit();
81 }}
82 >
83 <div className={`max-w-sm flex gap-2 rounded-md text-secondary`}>
84 {/* TODO: bsky icon? */}
85 <BlockBlueskySmall
86 className={`shrink-0 ${isSelected ? "text-tertiary" : "text-border"} `}
87 />
88 <Separator />
89 <Input
90 type="text"
91 className="w-full grow border-none outline-hidden bg-transparent "
92 placeholder="bsky.app/post-url"
93 value={urlValue}
94 disabled={isLocked}
95 onChange={(e) => setUrlValue(e.target.value)}
96 onKeyDown={(e) => {
97 if (e.key === "Enter") {
98 submit();
99 }
100 if (
101 e.key === "Backspace" &&
102 !e.currentTarget.value &&
103 urlValue !== ""
104 ) {
105 e.preventDefault();
106 }
107 }}
108 />
109 <button
110 type="submit"
111 id="bluesky-post-block-submit"
112 className={`p-1 ${isSelected && !isLocked ? "text-accent-contrast" : "text-border"}`}
113 onMouseDown={(e) => {
114 e.preventDefault();
115 errorSmokers(e.clientX + 12, e.clientY);
116 submit();
117 }}
118 >
119 <CheckTiny />
120 </button>
121 </div>
122 </form>
123 );
124};