A decentralized music tracking and discovery platform built on AT Protocol 🎵

add link to Rocksky's tangled repo

+210 -203
+210 -203
apps/web/src/layouts/Main.tsx
··· 51 51 `; 52 52 53 53 export type MainProps = { 54 - children: React.ReactNode; 55 - withRightPane?: boolean; 54 + children: React.ReactNode; 55 + withRightPane?: boolean; 56 56 }; 57 57 58 58 function Main(props: MainProps) { 59 - const { children } = props; 60 - const withRightPane = props.withRightPane ?? true; 61 - const [handle, setHandle] = useState(""); 62 - const jwt = localStorage.getItem("token"); 63 - const profile = useAtomValue(profileAtom); 64 - const [token, setToken] = useState<string | null>(null); 65 - const { did, cli } = useSearch({ strict: false }); 59 + const { children } = props; 60 + const withRightPane = props.withRightPane ?? true; 61 + const [handle, setHandle] = useState(""); 62 + const jwt = localStorage.getItem("token"); 63 + const profile = useAtomValue(profileAtom); 64 + const [token, setToken] = useState<string | null>(null); 65 + const { did, cli } = useSearch({ strict: false }); 66 66 67 - useEffect(() => { 68 - if (did && did !== "null") { 69 - localStorage.setItem("did", did); 67 + useEffect(() => { 68 + if (did && did !== "null") { 69 + localStorage.setItem("did", did); 70 70 71 - const fetchToken = async () => { 72 - try { 73 - const response = await fetch(`${API_URL}/token`, { 74 - method: "GET", 75 - headers: { 76 - "session-did": did, 77 - }, 78 - }); 79 - const data = await response.json(); 80 - localStorage.setItem("token", data.token); 81 - setToken(data.token); 71 + const fetchToken = async () => { 72 + try { 73 + const response = await fetch(`${API_URL}/token`, { 74 + method: "GET", 75 + headers: { 76 + "session-did": did, 77 + }, 78 + }); 79 + const data = await response.json(); 80 + localStorage.setItem("token", data.token); 81 + setToken(data.token); 82 82 83 - if (cli) { 84 - await fetch("http://localhost:6996/token", { 85 - method: "POST", 86 - headers: { 87 - "Content-Type": "application/json", 88 - }, 89 - body: JSON.stringify({ token: data.token }), 90 - }); 91 - } 83 + if (cli) { 84 + await fetch("http://localhost:6996/token", { 85 + method: "POST", 86 + headers: { 87 + "Content-Type": "application/json", 88 + }, 89 + body: JSON.stringify({ token: data.token }), 90 + }); 91 + } 92 92 93 - if (!jwt && data.token) { 94 - window.location.href = "/"; 95 - } 96 - } catch (e) { 97 - console.error(e); 98 - } 99 - }; 100 - fetchToken(); 101 - } 102 - // eslint-disable-next-line react-hooks/exhaustive-deps 103 - }, []); 93 + if (!jwt && data.token) { 94 + window.location.href = "/"; 95 + } 96 + } catch (e) { 97 + console.error(e); 98 + } 99 + }; 100 + fetchToken(); 101 + } 102 + // eslint-disable-next-line react-hooks/exhaustive-deps 103 + }, []); 104 104 105 - useProfile(token || localStorage.getItem("token")); 105 + useProfile(token || localStorage.getItem("token")); 106 106 107 - const onLogin = async () => { 108 - if (!handle.trim()) { 109 - return; 110 - } 107 + const onLogin = async () => { 108 + if (!handle.trim()) { 109 + return; 110 + } 111 111 112 - if (API_URL.includes("localhost")) { 113 - window.location.href = `${API_URL}/login?handle=${handle}`; 114 - return; 115 - } 112 + if (API_URL.includes("localhost")) { 113 + window.location.href = `${API_URL}/login?handle=${handle}`; 114 + return; 115 + } 116 116 117 - window.location.href = `https://rocksky.pages.dev/loading?handle=${handle}`; 118 - }; 117 + window.location.href = `https://rocksky.pages.dev/loading?handle=${handle}`; 118 + }; 119 119 120 - return ( 121 - <Container className="bg-[var(--color-background)] text-[var(--color-text)]"> 122 - <ToasterContainer 123 - placement={PLACEMENT.top} 124 - overrides={{ 125 - ToastBody: { 126 - style: { 127 - zIndex: 2, 128 - boxShadow: "none", 129 - }, 130 - }, 131 - }} 132 - /> 133 - <Flex style={{ width: withRightPane ? "770px" : "1090px" }}> 134 - <Navbar /> 135 - <div 136 - style={{ 137 - position: "relative", 138 - }} 139 - > 140 - {children} 141 - </div> 142 - </Flex> 143 - {withRightPane && ( 144 - <RightPane className="relative w-[300px]"> 145 - <div className="fixed top-[100px] w-[300px] bg-white p-[20px]"> 146 - <div className="mb-[30px]"> 147 - <Search /> 148 - </div> 149 - {jwt && profile && !profile.spotifyConnected && <SpotifyLogin />} 150 - {jwt && profile && <CloudDrive />} 151 - {!jwt && ( 152 - <div className="mt-[40px]"> 153 - <div className="mb-[20px]"> 154 - <div className="mb-[15px]"> 155 - <LabelMedium className="!text-[var(--color-text)]"> 156 - Bluesky handle 157 - </LabelMedium> 158 - </div> 159 - <Input 160 - name="handle" 161 - startEnhancer={ 162 - <div className="text-[var(--color-text-muted)] bg-[var(--color-input-background)]"> 163 - @ 164 - </div> 165 - } 166 - placeholder="<username>.bsky.social" 167 - value={handle} 168 - onChange={(e) => setHandle(e.target.value)} 169 - overrides={{ 170 - Root: { 171 - style: { 172 - backgroundColor: "var(--color-input-background)", 173 - borderColor: "var(--color-input-background)", 174 - }, 175 - }, 176 - StartEnhancer: { 177 - style: { 178 - backgroundColor: "var(--color-input-background)", 179 - }, 180 - }, 181 - InputContainer: { 182 - style: { 183 - backgroundColor: "var(--color-input-background)", 184 - }, 185 - }, 186 - Input: { 187 - style: { 188 - color: "var(--color-text)", 189 - caretColor: "var(--color-text)", 190 - }, 191 - }, 192 - }} 193 - /> 194 - </div> 195 - <Button 196 - onClick={onLogin} 197 - overrides={{ 198 - BaseButton: { 199 - style: { 200 - width: "100%", 201 - backgroundColor: "var(--color-primary)", 202 - ":hover": { 203 - backgroundColor: "var(--color-primary)", 204 - }, 205 - ":focus": { 206 - backgroundColor: "var(--color-primary)", 207 - }, 208 - }, 209 - }, 210 - }} 211 - > 212 - Sign In 213 - </Button> 214 - <LabelMedium className="text-center mt-[20px] !text-[var(--color-text-muted)]"> 215 - Don't have an account? 216 - </LabelMedium> 217 - <div className="text-center text-[var(--color-text-muted)] "> 218 - <a 219 - href="https://bsky.app" 220 - className="no-underline cursor-pointer !text-[var(--color-primary)]" 221 - target="_blank" 222 - > 223 - Sign up for Bluesky 224 - </a>{" "} 225 - to create one now! 226 - </div> 227 - </div> 228 - )} 120 + return ( 121 + <Container className="bg-[var(--color-background)] text-[var(--color-text)]"> 122 + <ToasterContainer 123 + placement={PLACEMENT.top} 124 + overrides={{ 125 + ToastBody: { 126 + style: { 127 + zIndex: 2, 128 + boxShadow: "none", 129 + }, 130 + }, 131 + }} 132 + /> 133 + <Flex style={{ width: withRightPane ? "770px" : "1090px" }}> 134 + <Navbar /> 135 + <div 136 + style={{ 137 + position: "relative", 138 + }} 139 + > 140 + {children} 141 + </div> 142 + </Flex> 143 + {withRightPane && ( 144 + <RightPane className="relative w-[300px]"> 145 + <div className="fixed top-[100px] w-[300px] bg-white p-[20px]"> 146 + <div className="mb-[30px]"> 147 + <Search /> 148 + </div> 149 + {jwt && profile && !profile.spotifyConnected && <SpotifyLogin />} 150 + {jwt && profile && <CloudDrive />} 151 + {!jwt && ( 152 + <div className="mt-[40px]"> 153 + <div className="mb-[20px]"> 154 + <div className="mb-[15px]"> 155 + <LabelMedium className="!text-[var(--color-text)]"> 156 + Bluesky handle 157 + </LabelMedium> 158 + </div> 159 + <Input 160 + name="handle" 161 + startEnhancer={ 162 + <div className="text-[var(--color-text-muted)] bg-[var(--color-input-background)]"> 163 + @ 164 + </div> 165 + } 166 + placeholder="<username>.bsky.social" 167 + value={handle} 168 + onChange={(e) => setHandle(e.target.value)} 169 + overrides={{ 170 + Root: { 171 + style: { 172 + backgroundColor: "var(--color-input-background)", 173 + borderColor: "var(--color-input-background)", 174 + }, 175 + }, 176 + StartEnhancer: { 177 + style: { 178 + backgroundColor: "var(--color-input-background)", 179 + }, 180 + }, 181 + InputContainer: { 182 + style: { 183 + backgroundColor: "var(--color-input-background)", 184 + }, 185 + }, 186 + Input: { 187 + style: { 188 + color: "var(--color-text)", 189 + caretColor: "var(--color-text)", 190 + }, 191 + }, 192 + }} 193 + /> 194 + </div> 195 + <Button 196 + onClick={onLogin} 197 + overrides={{ 198 + BaseButton: { 199 + style: { 200 + width: "100%", 201 + backgroundColor: "var(--color-primary)", 202 + ":hover": { 203 + backgroundColor: "var(--color-primary)", 204 + }, 205 + ":focus": { 206 + backgroundColor: "var(--color-primary)", 207 + }, 208 + }, 209 + }, 210 + }} 211 + > 212 + Sign In 213 + </Button> 214 + <LabelMedium className="text-center mt-[20px] !text-[var(--color-text-muted)]"> 215 + Don't have an account? 216 + </LabelMedium> 217 + <div className="text-center text-[var(--color-text-muted)] "> 218 + <a 219 + href="https://bsky.app" 220 + className="no-underline cursor-pointer !text-[var(--color-primary)]" 221 + target="_blank" 222 + > 223 + Sign up for Bluesky 224 + </a>{" "} 225 + to create one now! 226 + </div> 227 + </div> 228 + )} 229 229 230 - <div className="mt-[40px]"> 231 - <ScrobblesAreaChart /> 232 - </div> 233 - <ExternalLinks /> 234 - <div className="inline-flex mt-[40px]"> 235 - <Link 236 - href="https://docs.rocksky.app/introduction-918639m0" 237 - target="_blank" 238 - className="mr-[10px] text-[var(--color-primary)]" 239 - > 240 - About 241 - </Link> 242 - <Link 243 - href="https://docs.rocksky.app/faq-918661m0" 244 - target="_blank" 245 - className="mr-[10px] text-[var(--color-primary)]" 246 - > 247 - FAQ 248 - </Link> 249 - <Link 250 - href="https://doc.rocksky.app/" 251 - target="_blank" 252 - className="mr-[10px] text-[var(--color-primary)]" 253 - > 254 - API Docs 255 - </Link> 230 + <div className="mt-[40px]"> 231 + <ScrobblesAreaChart /> 232 + </div> 233 + <ExternalLinks /> 234 + <div className="inline-flex mt-[40px]"> 235 + <Link 236 + href="https://docs.rocksky.app/introduction-918639m0" 237 + target="_blank" 238 + className="mr-[10px] text-[var(--color-primary)]" 239 + > 240 + About 241 + </Link> 242 + <Link 243 + href="https://docs.rocksky.app/faq-918661m0" 244 + target="_blank" 245 + className="mr-[10px] text-[var(--color-primary)]" 246 + > 247 + FAQ 248 + </Link> 249 + <Link 250 + href="https://doc.rocksky.app/" 251 + target="_blank" 252 + className="mr-[10px] text-[var(--color-primary)]" 253 + > 254 + API Docs 255 + </Link> 256 256 257 - <Link 258 - href="https://discord.gg/EVcBy2fVa3" 259 - target="_blank" 260 - className="text-[var(--color-primary)]" 261 - > 262 - Discord 263 - </Link> 264 - </div> 265 - </div> 266 - </RightPane> 267 - )} 268 - <StickyPlayer /> 269 - </Container> 270 - ); 257 + <Link 258 + href="https://discord.gg/EVcBy2fVa3" 259 + target="_blank" 260 + className="text-[var(--color-primary)]" 261 + > 262 + Discord 263 + </Link> 264 + <Link 265 + href="https://tangled.org/@rocksky.app/rocksky" 266 + target="_blank" 267 + className="text-[var(--color-primary)]" 268 + > 269 + Source 270 + </Link> 271 + </div> 272 + </div> 273 + </RightPane> 274 + )} 275 + <StickyPlayer /> 276 + </Container> 277 + ); 271 278 } 272 279 273 280 export default Main;