Write on the margins of the internet. Powered by the AT Protocol.
margin.at
extension
web
atproto
comments
1import React, { useState } from "react";
2import { useNavigate, useSearchParams, Link } from "react-router-dom";
3import { useStore } from "@nanostores/react";
4import { $user } from "../../store/auth";
5import Composer from "../../components/feed/Composer";
6import type { Selector } from "../../types";
7
8export default function NewAnnotationPage() {
9 const user = useStore($user);
10 const navigate = useNavigate();
11 const [searchParams] = useSearchParams();
12
13 const initialUrl = searchParams.get("url") || "";
14
15 let initialSelector: Selector | null = null;
16 const selectorParam = searchParams.get("selector");
17 if (selectorParam) {
18 try {
19 initialSelector = JSON.parse(selectorParam);
20 } catch (e) {
21 console.error("Failed to parse selector:", e);
22 }
23 }
24
25 const legacyQuote = searchParams.get("quote") || "";
26 if (legacyQuote && !initialSelector) {
27 initialSelector = {
28 type: "TextQuoteSelector",
29 exact: legacyQuote,
30 };
31 }
32
33 const [url, setUrl] = useState(initialUrl);
34
35 if (!user) {
36 return (
37 <div className="max-w-sm mx-auto py-16 px-4">
38 <div className="bg-white dark:bg-surface-900 rounded-xl ring-1 ring-black/5 dark:ring-white/5 p-6 text-center">
39 <h2 className="text-xl font-bold text-surface-900 dark:text-white mb-2">
40 Sign in to create
41 </h2>
42 <p className="text-surface-500 dark:text-surface-400 text-sm mb-5">
43 You need a Bluesky account
44 </p>
45 <Link
46 to="/login"
47 className="block w-full py-2.5 px-4 bg-primary-600 hover:bg-primary-700 text-white font-medium rounded-lg transition-colors"
48 >
49 Sign in with Bluesky
50 </Link>
51 </div>
52 </div>
53 );
54 }
55
56 const handleSuccess = () => {
57 navigate("/home");
58 };
59
60 return (
61 <div className="max-w-2xl mx-auto pb-20">
62 <div className="mb-6 text-center sm:text-left">
63 <h1 className="text-2xl font-display font-bold text-surface-900 dark:text-white mb-1">
64 New Annotation
65 </h1>
66 <p className="text-surface-500 dark:text-surface-400">
67 Write in the margins of the web
68 </p>
69 </div>
70
71 {!initialUrl && (
72 <div className="mb-4">
73 <label
74 htmlFor="url-input"
75 className="block text-sm font-medium text-surface-700 dark:text-surface-300 mb-1.5"
76 >
77 URL to annotate
78 </label>
79 <input
80 id="url-input"
81 type="url"
82 value={url}
83 onChange={(e) => setUrl(e.target.value)}
84 placeholder="https://example.com/article"
85 className="w-full p-3 bg-white dark:bg-surface-900 border border-surface-200 dark:border-surface-700 rounded-lg text-surface-900 dark:text-white placeholder:text-surface-400 dark:placeholder:text-surface-500 focus:ring-2 focus:ring-primary-500/20 focus:border-primary-500 dark:focus:border-primary-400 outline-none transition-all"
86 required
87 />
88 </div>
89 )}
90
91 <div className="bg-white dark:bg-surface-900 rounded-xl ring-1 ring-black/5 dark:ring-white/5 p-5">
92 <Composer
93 url={
94 (url || initialUrl) && !/^(?:f|ht)tps?:\/\//.test(url || initialUrl)
95 ? `https://${url || initialUrl}`
96 : url || initialUrl
97 }
98 selector={initialSelector}
99 onSuccess={handleSuccess}
100 onCancel={() => navigate(-1)}
101 />
102 </div>
103 </div>
104 );
105}