an independent Bluesky client using Constellation, PDS Queries, and other services
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

initial layouting

+390 -83
+1 -1
conven-docs/color.md
··· 1 1 # Conven Color Defs 2 2 3 - [See the CSS definition here](../src/styles/app.css) 3 + [See the CSS definition here](/src/styles/app.css) 4 4 tailwind atoms are defined in app.css 5 5 6 6 ```css
+90
src/routeTree.gen.ts
··· 19 19 import { Route as PathlessLayoutRouteImport } from './routes/_pathlessLayout' 20 20 import { Route as IndexRouteImport } from './routes/index' 21 21 import { Route as CallbackIndexRouteImport } from './routes/callback/index' 22 + import { Route as CDidRouteImport } from './routes/c.$did' 22 23 import { Route as PathlessLayoutNestedLayoutRouteImport } from './routes/_pathlessLayout/_nested-layout' 23 24 import { Route as ProfileDidIndexRouteImport } from './routes/profile.$did/index' 25 + import { Route as CDidIndexRouteImport } from './routes/c.$did/index' 24 26 import { Route as ProfileDidFollowsRouteImport } from './routes/profile.$did/follows' 25 27 import { Route as ProfileDidFollowersRouteImport } from './routes/profile.$did/followers' 26 28 import { Route as PathlessLayoutNestedLayoutRouteBRouteImport } from './routes/_pathlessLayout/_nested-layout/route-b' 27 29 import { Route as PathlessLayoutNestedLayoutRouteARouteImport } from './routes/_pathlessLayout/_nested-layout/route-a' 28 30 import { Route as ProfileDidPostRkeyRouteImport } from './routes/profile.$did/post.$rkey' 29 31 import { Route as ProfileDidFeedRkeyRouteImport } from './routes/profile.$did/feed.$rkey' 32 + import { Route as CDidProfileDidIndexRouteImport } from './routes/c.$did/profile.$did/index' 33 + import { Route as CDidFeedRkeyIndexRouteImport } from './routes/c.$did/feed.$rkey/index' 30 34 import { Route as ProfileDidPostRkeyRepostedByRouteImport } from './routes/profile.$did/post.$rkey.reposted-by' 31 35 import { Route as ProfileDidPostRkeyQuotesRouteImport } from './routes/profile.$did/post.$rkey.quotes' 32 36 import { Route as ProfileDidPostRkeyLikedByRouteImport } from './routes/profile.$did/post.$rkey.liked-by' ··· 81 85 path: '/callback/', 82 86 getParentRoute: () => rootRouteImport, 83 87 } as any) 88 + const CDidRoute = CDidRouteImport.update({ 89 + id: '/c/$did', 90 + path: '/c/$did', 91 + getParentRoute: () => rootRouteImport, 92 + } as any) 84 93 const PathlessLayoutNestedLayoutRoute = 85 94 PathlessLayoutNestedLayoutRouteImport.update({ 86 95 id: '/_nested-layout', ··· 91 100 path: '/profile/$did/', 92 101 getParentRoute: () => rootRouteImport, 93 102 } as any) 103 + const CDidIndexRoute = CDidIndexRouteImport.update({ 104 + id: '/', 105 + path: '/', 106 + getParentRoute: () => CDidRoute, 107 + } as any) 94 108 const ProfileDidFollowsRoute = ProfileDidFollowsRouteImport.update({ 95 109 id: '/profile/$did/follows', 96 110 path: '/profile/$did/follows', ··· 123 137 path: '/profile/$did/feed/$rkey', 124 138 getParentRoute: () => rootRouteImport, 125 139 } as any) 140 + const CDidProfileDidIndexRoute = CDidProfileDidIndexRouteImport.update({ 141 + id: '/profile/$did/', 142 + path: '/profile/$did/', 143 + getParentRoute: () => CDidRoute, 144 + } as any) 145 + const CDidFeedRkeyIndexRoute = CDidFeedRkeyIndexRouteImport.update({ 146 + id: '/feed/$rkey/', 147 + path: '/feed/$rkey/', 148 + getParentRoute: () => CDidRoute, 149 + } as any) 126 150 const ProfileDidPostRkeyRepostedByRoute = 127 151 ProfileDidPostRkeyRepostedByRouteImport.update({ 128 152 id: '/reposted-by', ··· 157 181 '/root-copy': typeof RootCopyRoute 158 182 '/search': typeof SearchRoute 159 183 '/settings': typeof SettingsRoute 184 + '/c/$did': typeof CDidRouteWithChildren 160 185 '/callback': typeof CallbackIndexRoute 161 186 '/route-a': typeof PathlessLayoutNestedLayoutRouteARoute 162 187 '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute 163 188 '/profile/$did/followers': typeof ProfileDidFollowersRoute 164 189 '/profile/$did/follows': typeof ProfileDidFollowsRoute 190 + '/c/$did/': typeof CDidIndexRoute 165 191 '/profile/$did': typeof ProfileDidIndexRoute 166 192 '/profile/$did/feed/$rkey': typeof ProfileDidFeedRkeyRoute 167 193 '/profile/$did/post/$rkey': typeof ProfileDidPostRkeyRouteWithChildren 168 194 '/profile/$did/post/$rkey/liked-by': typeof ProfileDidPostRkeyLikedByRoute 169 195 '/profile/$did/post/$rkey/quotes': typeof ProfileDidPostRkeyQuotesRoute 170 196 '/profile/$did/post/$rkey/reposted-by': typeof ProfileDidPostRkeyRepostedByRoute 197 + '/c/$did/feed/$rkey': typeof CDidFeedRkeyIndexRoute 198 + '/c/$did/profile/$did': typeof CDidProfileDidIndexRoute 171 199 '/profile/$did/post/$rkey/image/$i': typeof ProfileDidPostRkeyImageIRoute 172 200 } 173 201 export interface FileRoutesByTo { ··· 184 212 '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute 185 213 '/profile/$did/followers': typeof ProfileDidFollowersRoute 186 214 '/profile/$did/follows': typeof ProfileDidFollowsRoute 215 + '/c/$did': typeof CDidIndexRoute 187 216 '/profile/$did': typeof ProfileDidIndexRoute 188 217 '/profile/$did/feed/$rkey': typeof ProfileDidFeedRkeyRoute 189 218 '/profile/$did/post/$rkey': typeof ProfileDidPostRkeyRouteWithChildren 190 219 '/profile/$did/post/$rkey/liked-by': typeof ProfileDidPostRkeyLikedByRoute 191 220 '/profile/$did/post/$rkey/quotes': typeof ProfileDidPostRkeyQuotesRoute 192 221 '/profile/$did/post/$rkey/reposted-by': typeof ProfileDidPostRkeyRepostedByRoute 222 + '/c/$did/feed/$rkey': typeof CDidFeedRkeyIndexRoute 223 + '/c/$did/profile/$did': typeof CDidProfileDidIndexRoute 193 224 '/profile/$did/post/$rkey/image/$i': typeof ProfileDidPostRkeyImageIRoute 194 225 } 195 226 export interface FileRoutesById { ··· 204 235 '/search': typeof SearchRoute 205 236 '/settings': typeof SettingsRoute 206 237 '/_pathlessLayout/_nested-layout': typeof PathlessLayoutNestedLayoutRouteWithChildren 238 + '/c/$did': typeof CDidRouteWithChildren 207 239 '/callback/': typeof CallbackIndexRoute 208 240 '/_pathlessLayout/_nested-layout/route-a': typeof PathlessLayoutNestedLayoutRouteARoute 209 241 '/_pathlessLayout/_nested-layout/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute 210 242 '/profile/$did/followers': typeof ProfileDidFollowersRoute 211 243 '/profile/$did/follows': typeof ProfileDidFollowsRoute 244 + '/c/$did/': typeof CDidIndexRoute 212 245 '/profile/$did/': typeof ProfileDidIndexRoute 213 246 '/profile/$did/feed/$rkey': typeof ProfileDidFeedRkeyRoute 214 247 '/profile/$did/post/$rkey': typeof ProfileDidPostRkeyRouteWithChildren 215 248 '/profile/$did/post/$rkey/liked-by': typeof ProfileDidPostRkeyLikedByRoute 216 249 '/profile/$did/post/$rkey/quotes': typeof ProfileDidPostRkeyQuotesRoute 217 250 '/profile/$did/post/$rkey/reposted-by': typeof ProfileDidPostRkeyRepostedByRoute 251 + '/c/$did/feed/$rkey/': typeof CDidFeedRkeyIndexRoute 252 + '/c/$did/profile/$did/': typeof CDidProfileDidIndexRoute 218 253 '/profile/$did/post/$rkey/image/$i': typeof ProfileDidPostRkeyImageIRoute 219 254 } 220 255 export interface FileRouteTypes { ··· 228 263 | '/root-copy' 229 264 | '/search' 230 265 | '/settings' 266 + | '/c/$did' 231 267 | '/callback' 232 268 | '/route-a' 233 269 | '/route-b' 234 270 | '/profile/$did/followers' 235 271 | '/profile/$did/follows' 272 + | '/c/$did/' 236 273 | '/profile/$did' 237 274 | '/profile/$did/feed/$rkey' 238 275 | '/profile/$did/post/$rkey' 239 276 | '/profile/$did/post/$rkey/liked-by' 240 277 | '/profile/$did/post/$rkey/quotes' 241 278 | '/profile/$did/post/$rkey/reposted-by' 279 + | '/c/$did/feed/$rkey' 280 + | '/c/$did/profile/$did' 242 281 | '/profile/$did/post/$rkey/image/$i' 243 282 fileRoutesByTo: FileRoutesByTo 244 283 to: ··· 255 294 | '/route-b' 256 295 | '/profile/$did/followers' 257 296 | '/profile/$did/follows' 297 + | '/c/$did' 258 298 | '/profile/$did' 259 299 | '/profile/$did/feed/$rkey' 260 300 | '/profile/$did/post/$rkey' 261 301 | '/profile/$did/post/$rkey/liked-by' 262 302 | '/profile/$did/post/$rkey/quotes' 263 303 | '/profile/$did/post/$rkey/reposted-by' 304 + | '/c/$did/feed/$rkey' 305 + | '/c/$did/profile/$did' 264 306 | '/profile/$did/post/$rkey/image/$i' 265 307 id: 266 308 | '__root__' ··· 274 316 | '/search' 275 317 | '/settings' 276 318 | '/_pathlessLayout/_nested-layout' 319 + | '/c/$did' 277 320 | '/callback/' 278 321 | '/_pathlessLayout/_nested-layout/route-a' 279 322 | '/_pathlessLayout/_nested-layout/route-b' 280 323 | '/profile/$did/followers' 281 324 | '/profile/$did/follows' 325 + | '/c/$did/' 282 326 | '/profile/$did/' 283 327 | '/profile/$did/feed/$rkey' 284 328 | '/profile/$did/post/$rkey' 285 329 | '/profile/$did/post/$rkey/liked-by' 286 330 | '/profile/$did/post/$rkey/quotes' 287 331 | '/profile/$did/post/$rkey/reposted-by' 332 + | '/c/$did/feed/$rkey/' 333 + | '/c/$did/profile/$did/' 288 334 | '/profile/$did/post/$rkey/image/$i' 289 335 fileRoutesById: FileRoutesById 290 336 } ··· 298 344 RootCopyRoute: typeof RootCopyRoute 299 345 SearchRoute: typeof SearchRoute 300 346 SettingsRoute: typeof SettingsRoute 347 + CDidRoute: typeof CDidRouteWithChildren 301 348 CallbackIndexRoute: typeof CallbackIndexRoute 302 349 ProfileDidFollowersRoute: typeof ProfileDidFollowersRoute 303 350 ProfileDidFollowsRoute: typeof ProfileDidFollowsRoute ··· 378 425 preLoaderRoute: typeof CallbackIndexRouteImport 379 426 parentRoute: typeof rootRouteImport 380 427 } 428 + '/c/$did': { 429 + id: '/c/$did' 430 + path: '/c/$did' 431 + fullPath: '/c/$did' 432 + preLoaderRoute: typeof CDidRouteImport 433 + parentRoute: typeof rootRouteImport 434 + } 381 435 '/_pathlessLayout/_nested-layout': { 382 436 id: '/_pathlessLayout/_nested-layout' 383 437 path: '' ··· 392 446 preLoaderRoute: typeof ProfileDidIndexRouteImport 393 447 parentRoute: typeof rootRouteImport 394 448 } 449 + '/c/$did/': { 450 + id: '/c/$did/' 451 + path: '/' 452 + fullPath: '/c/$did/' 453 + preLoaderRoute: typeof CDidIndexRouteImport 454 + parentRoute: typeof CDidRoute 455 + } 395 456 '/profile/$did/follows': { 396 457 id: '/profile/$did/follows' 397 458 path: '/profile/$did/follows' ··· 434 495 preLoaderRoute: typeof ProfileDidFeedRkeyRouteImport 435 496 parentRoute: typeof rootRouteImport 436 497 } 498 + '/c/$did/profile/$did/': { 499 + id: '/c/$did/profile/$did/' 500 + path: '/profile/$did' 501 + fullPath: '/c/$did/profile/$did' 502 + preLoaderRoute: typeof CDidProfileDidIndexRouteImport 503 + parentRoute: typeof CDidRoute 504 + } 505 + '/c/$did/feed/$rkey/': { 506 + id: '/c/$did/feed/$rkey/' 507 + path: '/feed/$rkey' 508 + fullPath: '/c/$did/feed/$rkey' 509 + preLoaderRoute: typeof CDidFeedRkeyIndexRouteImport 510 + parentRoute: typeof CDidRoute 511 + } 437 512 '/profile/$did/post/$rkey/reposted-by': { 438 513 id: '/profile/$did/post/$rkey/reposted-by' 439 514 path: '/reposted-by' ··· 495 570 PathlessLayoutRouteChildren, 496 571 ) 497 572 573 + interface CDidRouteChildren { 574 + CDidIndexRoute: typeof CDidIndexRoute 575 + CDidFeedRkeyIndexRoute: typeof CDidFeedRkeyIndexRoute 576 + CDidProfileDidIndexRoute: typeof CDidProfileDidIndexRoute 577 + } 578 + 579 + const CDidRouteChildren: CDidRouteChildren = { 580 + CDidIndexRoute: CDidIndexRoute, 581 + CDidFeedRkeyIndexRoute: CDidFeedRkeyIndexRoute, 582 + CDidProfileDidIndexRoute: CDidProfileDidIndexRoute, 583 + } 584 + 585 + const CDidRouteWithChildren = CDidRoute._addFileChildren(CDidRouteChildren) 586 + 498 587 interface ProfileDidPostRkeyRouteChildren { 499 588 ProfileDidPostRkeyLikedByRoute: typeof ProfileDidPostRkeyLikedByRoute 500 589 ProfileDidPostRkeyQuotesRoute: typeof ProfileDidPostRkeyQuotesRoute ··· 522 611 RootCopyRoute: RootCopyRoute, 523 612 SearchRoute: SearchRoute, 524 613 SettingsRoute: SettingsRoute, 614 + CDidRoute: CDidRouteWithChildren, 525 615 CallbackIndexRoute: CallbackIndexRoute, 526 616 ProfileDidFollowersRoute: ProfileDidFollowersRoute, 527 617 ProfileDidFollowsRoute: ProfileDidFollowsRoute,
+107 -82
src/routes/__root.tsx
··· 25 25 import { Composer } from "~/components/Composer"; 26 26 import { DefaultCatchBoundary } from "~/components/DefaultCatchBoundary"; 27 27 import { Import } from "~/components/Import"; 28 + import Login from "~/components/Login"; 28 29 //import Login from "~/components/Login"; 29 30 import Logo from "~/components/LogoSvg"; 30 31 //import { ModerationBatcher } from "~/components/ModerationBatcher"; ··· 93 94 return ( 94 95 <UnifiedAuthProvider> 95 96 {/* <AutoLabelProvider> */} 96 - <LikeMutationQueueProvider> 97 - {/* <PollMutationQueueProvider> 97 + <LikeMutationQueueProvider> 98 + {/* <PollMutationQueueProvider> 98 99 <ModerationInitializer /> 99 100 <ModerationBatcher /> */} 100 - <RootDocument> 101 - <KeepAliveProvider> 102 - <AppToaster /> 103 - <KeepAliveOutlet /> 104 - </KeepAliveProvider> 105 - </RootDocument> 106 - {/* </PollMutationQueueProvider> */} 107 - </LikeMutationQueueProvider> 101 + <RootDocument> 102 + <KeepAliveProvider> 103 + <AppToaster /> 104 + <KeepAliveOutlet /> 105 + </KeepAliveProvider> 106 + </RootDocument> 107 + {/* </PollMutationQueueProvider> */} 108 + </LikeMutationQueueProvider> 108 109 {/* </AutoLabelProvider> */} 109 110 </UnifiedAuthProvider> 110 111 ); ··· 158 159 rounded-md 159 160 px-4 py-3 160 161 shadow-sm 161 - dark:bg-gray-300 dark:text-gray-900 162 - bg-gray-700 text-gray-100 163 - ring-1 dark:ring-gray-200 ring-gray-800 162 + dark:bg-base-300 dark:text-base-900 163 + bg-base-700 text-base-100 164 + ring-1 dark:ring-base-200 ring-base-800 164 165 " 165 166 > 166 167 <div className="flex-1 min-w-0"> 167 168 <p className="text-sm font-medium truncate">{title}</p> 168 169 {description ? ( 169 - <p className="mt-1 text-sm dark:text-gray-600 text-gray-300 truncate"> 170 + <p className="mt-1 text-sm dark:text-base-600 text-base-300 truncate"> 170 171 {description} 171 172 </p> 172 173 ) : null} ··· 178 179 className=" 179 180 text-sm font-medium 180 181 px-3 py-1 rounded-md 181 - bg-gray-200 text-gray-900 182 - hover:bg-gray-300 183 - dark:bg-gray-800 dark:text-gray-100 dark:hover:bg-gray-700 184 - focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-300 dark:focus:ring-gray-700 182 + bg-base-200 text-base-900 183 + hover:bg-base-300 184 + dark:bg-base-800 dark:text-base-100 dark:hover:bg-base-700 185 + focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-base-300 dark:focus:ring-base-700 185 186 " 186 187 onClick={() => { 187 188 button.onClick(); ··· 216 217 } 217 218 218 219 function RootDocument({ children }: { children: React.ReactNode }) { 219 - useAtomCssVar(hueAtom, "--tw-gray-hue"); 220 + // useAtomCssVar(hueBaseAtom, "--system-hue-base"); 221 + // useAtomCssVar(hueAccentAtom, "--system-hue-accent"); 222 + // useAtomCssVar(hueContrastAtom, "--system-hue-contrast"); 223 + // useAtomCssVar(hueMutedAtom, "--system-hue-muted"); 224 + 225 + return ( 226 + <> 227 + <div className="h-14 sticky top-0 z-50 bg-accent-700 flex items-center justify-between px-6"> 228 + hello i am the persistent top bar ! <Login compact /> 229 + </div> 230 + {/* Layout */} 231 + <div className="flex"> 232 + <nav className="w-16 sticky top-14 self-start h-[calc(100vh-3.5rem)] p-2 bg-base-800"> 233 + <span>hello i am the discord-like persistent left sidebar</span> 234 + </nav> 235 + <main className="flex-1 min-h-[200vh]"> 236 + {children} 237 + </main> 238 + </div> 239 + </> 240 + ) 241 + } 242 + 243 + 244 + function OldRootDocument({ children }: { children: React.ReactNode }) { 245 + useAtomCssVar(hueAtom, "--tw-base-hue"); 220 246 const location = useLocation(); 221 247 const navigate = useNavigate(); 222 248 const { agent } = useAuth(); ··· 262 288 <> 263 289 <Composer /> 264 290 265 - <div className="min-h-screen flex justify-center bg-gray-50 dark:bg-gray-950"> 266 - <nav className="hidden lg:flex h-screen w-[250px] xl:ml-[50px] flex-col gap-0 p-4 dark:border-gray-800 sticky top-0 self-start"> 291 + <div className="min-h-screen flex justify-center bg-base-50 dark:bg-base-950"> 292 + <nav className="hidden lg:flex h-screen w-[250px] xl:ml-[50px] flex-col gap-0 p-4 dark:border-base-800 sticky top-0 self-start"> 267 293 <div className="flex items-center gap-3 mb-4 pl-3"> 268 294 <Logo 269 295 className="h-8 w-8" ··· 272 298 "oklch(0.6616 0.2249 calc(25.88 + (var(--safe-hue) - 28))", 273 299 }} 274 300 /> 275 - <span className="font-extrabold text-2xl text-gray-900 dark:text-gray-100"> 301 + <span className="font-extrabold text-2xl text-base-900 dark:text-base-100"> 276 302 {HOST_MAIN_TITLE} 277 - {HOST_SUB_TITLE && (<span className="text-gray-500 dark:text-gray-400 text-sm"> 303 + {HOST_SUB_TITLE && (<span className="text-base-500 dark:text-base-400 text-sm"> 278 304 {HOST_SUB_TITLE} 279 - </span>) } 305 + </span>)} 280 306 </span> 281 307 </div> 282 308 <MaterialNavItem ··· 412 438 )} 413 439 {!agent?.did && ( 414 440 <> 415 - <div className="mt-4 mb-2 w-full h-[1px] bg-gray-200 dark:bg-gray-800" /> 441 + <div className="mt-4 mb-2 w-full h-[1px] bg-base-200 dark:bg-base-800" /> 416 442 {/* <Login /> */} 417 443 <LoginRedirect /> 418 444 </> ··· 420 446 {/* <Link 421 447 to="/" 422 448 className={ 423 - `py-2 px-4 hover:bg-gray-100 dark:hover:bg-gray-900 text-xl flex items-center gap-3 ` + 449 + `py-2 px-4 hover:bg-base-100 dark:hover:bg-base-900 text-xl flex items-center gap-3 ` + 424 450 (isHome ? "font-bold" : "") 425 451 } 426 452 > ··· 434 460 <Link 435 461 to="/notifications" 436 462 className={ 437 - `py-2 px-4 hover:bg-gray-100 dark:hover:bg-gray-900 text-xl flex items-center gap-3 ` + 463 + `py-2 px-4 hover:bg-base-100 dark:hover:bg-base-900 text-xl flex items-center gap-3 ` + 438 464 (isNotifications ? "font-bold" : "") 439 465 } 440 466 > ··· 447 473 </Link> 448 474 <Link 449 475 to="/feeds" 450 - className={`py-2 px-4 hover:bg-gray-100 dark:hover:bg-gray-900 text-xl flex items-center gap-3 ${ 476 + className={`py-2 px-4 hover:bg-base-100 dark:hover:bg-base-900 text-xl flex items-center gap-3 ${ 451 477 location.pathname.startsWith("/feeds") ? "font-bold" : "" 452 478 }`} 453 479 > ··· 461 487 462 488 <Link 463 489 to="/search" 464 - className={`py-2 px-4 hover:bg-gray-100 dark:hover:bg-gray-900 text-xl flex items-center gap-3 ${ 490 + className={`py-2 px-4 hover:bg-base-100 dark:hover:bg-base-900 text-xl flex items-center gap-3 ${ 465 491 location.pathname.startsWith("/search") ? "font-bold" : "" 466 492 }`} 467 493 > ··· 473 499 <span>Search</span> 474 500 </Link> 475 501 <button 476 - className={`py-2 px-4 hover:bg-gray-100 dark:hover:bg-gray-900 text-xl flex items-center gap-3 w-full text-left ${ 477 - isProfile ? "bg-gray-100 dark:bg-gray-900 font-bold" : "" 502 + className={`py-2 px-4 hover:bg-base-100 dark:hover:bg-base-900 text-xl flex items-center gap-3 w-full text-left ${ 503 + isProfile ? "bg-base-100 dark:bg-base-900 font-bold" : "" 478 504 }`} 479 505 onClick={() => { 480 506 if (authed && agent && agent.assertDid) { ··· 496 522 </button> 497 523 <Link 498 524 to="/settings" 499 - className={`py-2 px-4 hover:bg-gray-100 dark:hover:bg-gray-900 text-xl flex items-center gap-3 ${ 525 + className={`py-2 px-4 hover:bg-base-100 dark:hover:bg-base-900 text-xl flex items-center gap-3 ${ 500 526 location.pathname.startsWith("/settings") ? "font-bold" : "" 501 527 }`} 502 528 > ··· 508 534 <span>Settings</span> 509 535 </Link> */} 510 536 {/* <button 511 - className="mt-4 w-full flex items-center justify-center gap-3 py-3 px-0 mb-3 bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 text-gray-900 dark:text-gray-100 text-xl font-bold rounded-full transition-colors shadow" 537 + className="mt-4 w-full flex items-center justify-center gap-3 py-3 px-0 mb-3 bg-base-200 dark:bg-base-800 hover:bg-base-300 dark:hover:bg-base-700 text-base-900 dark:text-base-100 text-xl font-bold rounded-full transition-colors shadow" 512 538 onClick={() => setPostOpen(true)} 513 539 type="button" 514 540 > 515 541 <IconMdiPencilOutline 516 542 width={24} 517 543 height={24} 518 - className="text-gray-600 dark:text-gray-400" 544 + className="text-base-600 dark:text-base-400" 519 545 /> 520 546 <span>Post</span> 521 547 </button> */} 522 548 <div className="flex-1"></div> 523 549 {!!agent?.did && ( 524 550 <div className="flex flex-row items-center lg:mb-1"> 525 - <div className="flex p-2 h-12 flex-1 rounded-full hover:dark:bg-gray-800 hover:bg-gray-200"> 551 + <div className="flex p-2 h-12 flex-1 rounded-full hover:dark:bg-base-800 hover:bg-base-200"> 526 552 <ProfileSmall did={agent.did} /> 527 553 </div> 528 554 <Link 529 555 to="/settings" 530 - className="flex p-3 h-12 w-12 rounded-full hover:dark:bg-gray-800 hover:bg-gray-200 items-center justify-center" 556 + className="flex p-3 h-12 w-12 rounded-full hover:dark:bg-base-800 hover:bg-base-200 items-center justify-center" 531 557 > 532 558 <IconMaterialSymbolsMoreVert /> 533 559 </Link> ··· 538 564 href="https://tangled.sh/@whey.party/red-dwarf" 539 565 target="_blank" 540 566 rel="noopener noreferrer" 541 - className="mt-1 text-xs text-gray-400 dark:text-gray-500 text-center hover:underline" 567 + className="mt-1 text-xs text-base-400 dark:text-base-500 text-center hover:underline" 542 568 > 543 569 git repo 544 570 </a> ··· 546 572 href="https://whey.party/" 547 573 target="_blank" 548 574 rel="noopener noreferrer" 549 - className="mt-1 text-xs text-gray-400 dark:text-gray-500 text-center hover:underline" 575 + className="mt-1 text-xs text-base-400 dark:text-base-500 text-center hover:underline" 550 576 > 551 577 made by @whey.party 552 578 </a> 553 - <div className="mt-2 text-xs text-gray-400 dark:text-gray-500 text-center"> 579 + <div className="mt-2 text-xs text-base-400 dark:text-base-500 text-center"> 554 580 powered by{" "} 555 581 <a 556 582 href="https://microcosm.blue" ··· 564 590 */} 565 591 </nav> 566 592 567 - <nav className="hidden sm:flex items-center lg:hidden h-screen flex-col gap-2 p-4 dark:border-gray-800 sticky top-0 self-start"> 593 + <nav className="hidden sm:flex items-center lg:hidden h-screen flex-col gap-2 p-4 dark:border-base-800 sticky top-0 self-start"> 568 594 <div className="flex items-center gap-3 mb-4"> 569 595 <Logo 570 596 className="h-8 w-8" ··· 719 745 720 746 {agent?.did && ( 721 747 <button 722 - className="lg:hidden fixed bottom-22 right-4 z-50 bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 rounded-2xl w-14 h-14 flex items-center justify-center transition-all" 748 + className="lg:hidden fixed bottom-22 right-4 z-50 bg-base-200 dark:bg-base-800 hover:bg-base-300 dark:hover:bg-base-700 rounded-2xl w-14 h-14 flex items-center justify-center transition-all" 723 749 style={{ boxShadow: "0 4px 24px 0 rgba(0,0,0,0.12)" }} 724 750 onClick={() => setComposerPost({ kind: "root" })} 725 751 type="button" ··· 728 754 <IconMdiPencilOutline 729 755 width={24} 730 756 height={24} 731 - className="text-gray-600 dark:text-gray-400" 757 + className="text-base-600 dark:text-base-400" 732 758 /> 733 759 </button> 734 760 )} 735 761 736 - <main className="w-full max-w-[600px] sm:border-x border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 pb-16 lg:pb-0 overflow-x-clip"> 762 + <main className="w-full max-w-[600px] sm:border-x border-base-200 dark:border-base-800 bg-white dark:bg-base-950 pb-16 lg:pb-0 overflow-x-clip"> 737 763 {children} 738 764 </main> 739 765 ··· 750 776 )} 751 777 {!agent?.did && ( 752 778 <> 753 - <span className=" text-gray-500 dark:text-gray-400 text-sm leading-tight"><span className=" font-bold">{window.location.host}</span> is a hosted Red Dwarf instance that you can use to participate in the Bluesky social network.</span> 779 + <span className=" text-base-500 dark:text-base-400 text-sm leading-tight"><span className=" font-bold">{window.location.host}</span> is a hosted Red Dwarf instance that you can use to participate in the Bluesky social network.</span> 754 780 <img className="rounded-sm" src={HOST_HERO} /> 755 - <span className=" text-gray-500 dark:text-gray-400 text-sm">{HOST_DESCRIPTION}</span> 781 + <span className=" text-base-500 dark:text-base-400 text-sm">{HOST_DESCRIPTION}</span> 756 782 <div className="flex flex-col gap-1 "> 757 - <span className="text-gray-500 dark:text-gray-400 text-sm font-bold">ADMINISTERED BY:</span> 783 + <span className="text-base-500 dark:text-base-400 text-sm font-bold">ADMINISTERED BY:</span> 758 784 <ProfileSmall did={HOST_ADMIN} /> 759 785 </div> 760 786 </> ··· 767 793 </div> 768 794 769 795 {agent?.did ? ( 770 - <nav className="sm:hidden fixed bottom-0 left-0 right-0 bg-gray-50 dark:bg-gray-900 border-0 border-t-1 dark:border-t-0 shadow border-gray-200 dark:border-gray-700 z-40"> 796 + <nav className="sm:hidden fixed bottom-0 left-0 right-0 bg-base-50 dark:bg-base-900 border-0 border-t-1 dark:border-t-0 shadow border-base-200 dark:border-base-700 z-40"> 771 797 <div className="flex justify-around items-center p-2"> 772 798 <MaterialNavItem 773 799 small ··· 788 814 to="/" 789 815 className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${ 790 816 isHome 791 - ? "text-gray-900 dark:text-gray-100" 792 - : "text-gray-600 dark:text-gray-400" 817 + ? "text-base-900 dark:text-base-100" 818 + : "text-base-600 dark:text-base-400" 793 819 }`} 794 820 > 795 821 {!isHome ? ( ··· 816 842 to="/search" 817 843 className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${ 818 844 location.pathname.startsWith("/search") 819 - ? "text-gray-900 dark:text-gray-100" 820 - : "text-gray-600 dark:text-gray-400" 845 + ? "text-base-900 dark:text-base-100" 846 + : "text-base-600 dark:text-base-400" 821 847 }`} 822 848 > 823 849 {!location.pathname.startsWith("/search") ? ( ··· 848 874 to="/notifications" 849 875 className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${ 850 876 isNotifications 851 - ? "text-gray-900 dark:text-gray-100" 852 - : "text-gray-600 dark:text-gray-400" 877 + ? "text-base-900 dark:text-base-100" 878 + : "text-base-600 dark:text-base-400" 853 879 }`} 854 880 > 855 881 {!isNotifications ? ( ··· 885 911 {/* <button 886 912 className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${ 887 913 isProfile 888 - ? "text-gray-900 dark:text-gray-100" 889 - : "text-gray-600 dark:text-gray-400" 914 + ? "text-base-900 dark:text-base-100" 915 + : "text-base-600 dark:text-base-400" 890 916 }`} 891 917 onClick={() => { 892 918 if (authed && agent && agent.assertDid) { ··· 925 951 to="/settings" 926 952 className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${ 927 953 location.pathname.startsWith("/settings") 928 - ? "text-gray-900 dark:text-gray-100" 929 - : "text-gray-600 dark:text-gray-400" 954 + ? "text-base-900 dark:text-base-100" 955 + : "text-base-600 dark:text-base-400" 930 956 }`} 931 957 > 932 958 {!location.pathname.startsWith("/settings") ? ( ··· 939 965 </div> 940 966 </nav> 941 967 ) : ( 942 - <div className="lg:hidden flex items-center fixed bottom-0 left-0 right-0 justify-between px-4 py-3 border-0 border-t-1 dark:border-t-0 shadow border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 z-10"> 968 + <div className="lg:hidden flex items-center fixed bottom-0 left-0 right-0 justify-between px-4 py-3 border-0 border-t-1 dark:border-t-0 shadow border-base-200 dark:border-base-700 bg-base-50 dark:bg-base-900 z-10"> 943 969 <div className="flex items-center gap-2"> 944 970 <Logo 945 971 className="h-6 w-6" ··· 948 974 "oklch(0.6616 0.2249 calc(25.88 + (var(--safe-hue) - 28))", 949 975 }} 950 976 /> 951 - <span className="font-bold text-lg text-gray-900 dark:text-gray-100"> 977 + <span className="font-bold text-lg text-base-900 dark:text-base-100"> 952 978 {HOST_MAIN_TITLE} 953 - {HOST_SUB_TITLE && (<span className="text-gray-500 dark:text-gray-400 text-sm"> 979 + {HOST_SUB_TITLE && (<span className="text-base-500 dark:text-base-400 text-sm"> 954 980 {HOST_SUB_TITLE} 955 - </span>) } 981 + </span>)} 956 982 </span> 957 983 </div> 958 984 <div className="flex items-center gap-2"> 959 985 {/* <Login compact={true} popup={true} /> */} 960 986 <Link 961 987 to="/settings" 962 - className="rounded-full bg-gray-600 text-gray-100 dark:bg-gray-400 dark:text-gray-900 px-4 py-2 text-sm font-medium text-center" 988 + className="rounded-full bg-base-600 text-base-100 dark:bg-base-400 dark:text-base-900 px-4 py-2 text-sm font-medium text-center" 963 989 > 964 990 Log in 965 991 </Link> ··· 995 1021 return ( 996 1022 <button 997 1023 className={`flex flex-col items-center rounded-lg transition-colors ${small} gap-1 ${active 998 - ? "text-gray-900 dark:text-gray-100" 999 - : "text-gray-600 dark:text-gray-400" 1024 + ? "text-base-900 dark:text-base-100" 1025 + : "text-base-600 dark:text-base-400" 1000 1026 }`} 1001 1027 onClick={() => { 1002 1028 onClickCallbback(); 1003 1029 }} 1004 1030 > 1005 1031 <div 1006 - className={`px-4 py-1 rounded-full flex items-center justify-center ${active ? " bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 hover:dark:bg-gray-700" : "hover:bg-gray-50 hover:dark:bg-gray-900"}`} 1032 + className={`px-4 py-1 rounded-full flex items-center justify-center ${active ? " bg-base-100 dark:bg-base-800 hover:bg-base-200 hover:dark:bg-base-700" : "hover:bg-base-50 hover:dark:bg-base-900"}`} 1007 1033 > 1008 1034 {active ? ActiveIcon : InactiveIcon} 1009 1035 </div> ··· 1018 1044 return ( 1019 1045 <button 1020 1046 className={`flex flex-row h-12 min-h-12 max-h-12 px-4 py-0.5 w-full items-center rounded-full transition-colors flex-1 gap-1 ${active 1021 - ? "text-gray-900 dark:text-gray-100 hover:bg-gray-300 dark:bg-gray-800 bg-gray-200 hover:dark:bg-gray-700" 1022 - : "text-gray-600 dark:text-gray-400 hover:bg-gray-100 hover:dark:bg-gray-900" 1047 + ? "text-base-900 dark:text-base-100 hover:bg-base-300 dark:bg-base-800 bg-base-200 hover:dark:bg-base-700" 1048 + : "text-base-600 dark:text-base-400 hover:bg-base-100 hover:dark:bg-base-900" 1023 1049 }`} 1024 1050 onClick={() => { 1025 1051 onClickCallbback(); ··· 1055 1081 const active = false; 1056 1082 return ( 1057 1083 <button 1058 - className={`flex border border-gray-400 dark:border-gray-400 flex-row h-12 min-h-12 max-h-12 ${small ? "p-3 w-12" : "px-4 py-0.5"} items-center rounded-full transition-colors gap-1 ${active 1059 - ? "text-gray-900 dark:text-gray-100 hover:bg-gray-300 dark:bg-gray-700 bg-gray-200 hover:dark:bg-gray-600" 1060 - : "text-gray-600 dark:text-gray-400 hover:bg-gray-100 hover:dark:bg-gray-800" 1084 + className={`flex border border-base-400 dark:border-base-400 flex-row h-12 min-h-12 max-h-12 ${small ? "p-3 w-12" : "px-4 py-0.5"} items-center rounded-full transition-colors gap-1 ${active 1085 + ? "text-base-900 dark:text-base-100 hover:bg-base-300 dark:bg-base-700 bg-base-200 hover:dark:bg-base-600" 1086 + : "text-base-600 dark:text-base-400 hover:bg-base-100 hover:dark:bg-base-800" 1061 1087 }`} 1062 1088 onClick={() => { 1063 1089 onClickCallbback(); ··· 1116 1142 className={`hover:cursor-pointer flex items-center gap-2.5 animate-pulse ${large ? "mb-1" : ""}`} 1117 1143 > 1118 1144 <div 1119 - className={`rounded-full bg-gray-300 dark:bg-gray-700 ${large ? "w-10 h-10" : "w-[30px] h-[30px]"}`} 1145 + className={`rounded-full bg-base-300 dark:bg-base-700 ${large ? "w-10 h-10" : "w-[30px] h-[30px]"}`} 1120 1146 /> 1121 1147 <div className="flex flex-col gap-2"> 1122 1148 <div 1123 - className={`bg-gray-300 dark:bg-gray-700 rounded ${large ? "h-4 w-28" : "h-3 w-20"}`} 1149 + className={`bg-base-300 dark:bg-base-700 rounded ${large ? "h-4 w-28" : "h-3 w-20"}`} 1124 1150 /> 1125 1151 <div 1126 - className={`bg-gray-300 dark:bg-gray-700 rounded ${large ? "h-4 w-20" : "h-3 w-16"}`} 1152 + className={`bg-base-300 dark:bg-base-700 rounded ${large ? "h-4 w-20" : "h-3 w-16"}`} 1127 1153 /> 1128 1154 </div> 1129 1155 </div> ··· 1142 1168 /> 1143 1169 <div className="flex flex-col items-start text-left"> 1144 1170 <div 1145 - className={`font-medium ${large ? "text-gray-800 dark:text-gray-100 text-md" : "text-gray-800 dark:text-gray-100 text-sm"}`} 1171 + className={`font-medium ${large ? "text-base-800 dark:text-base-100 text-md" : "text-base-800 dark:text-base-100 text-sm"}`} 1146 1172 > 1147 1173 {profile?.displayName} 1148 1174 </div> 1149 1175 <div 1150 - className={` ${large ? "text-gray-500 dark:text-gray-400 text-sm" : "text-gray-500 dark:text-gray-400 text-xs"}`} 1176 + className={` ${large ? "text-base-500 dark:text-base-400 text-sm" : "text-base-500 dark:text-base-400 text-xs"}`} 1151 1177 > 1152 1178 @{identity?.handle} 1153 1179 </div> ··· 1155 1181 </div> 1156 1182 ); 1157 1183 }; 1158 - 1159 1184 1160 1185 function FeedListDesktopSidebar() { 1161 1186 const { agent, status } = useAuth(); ··· 1174 1199 const prefs = prefsresultmaybe?.data; 1175 1200 1176 1201 const savedFeeds = React.useMemo(() => { 1177 - const savedFeedsPref = prefs?.preferences?.find( 1178 - (p): p is $Typed<SavedFeedsPrefV2> => 1179 - p?.$type === "app.bsky.actor.defs#savedFeedsPrefV2" 1202 + const savedFeedsPref = prefs?.preferences?.find( 1203 + (p): p is $Typed<SavedFeedsPrefV2> => 1204 + p?.$type === "app.bsky.actor.defs#savedFeedsPrefV2" 1180 1205 ); 1181 1206 1182 1207 return savedFeedsPref?.items || []; ··· 1207 1232 const dontShowLoginButton = location.pathname === "/settings" 1208 1233 return ( 1209 1234 <div className=""> 1210 - <span className="text-gray-500 dark:text-gray-400 text-sm leading-tight"> 1235 + <span className="text-base-500 dark:text-base-400 text-sm leading-tight"> 1211 1236 {HOST_LOGIN_BLURB} 1212 1237 </span> 1213 1238 1214 1239 <div className="flex flex-col gap-2 my-4"> 1215 1240 {!dontShowLoginButton && (<Link 1216 1241 to="/settings" 1217 - className="w-full rounded-full bg-gray-600 text-gray-100 dark:bg-gray-400 dark:text-gray-900 px-4 py-2 text-sm font-medium text-center" 1242 + className="w-full rounded-full bg-base-600 text-base-100 dark:bg-base-400 dark:text-base-900 px-4 py-2 text-sm font-medium text-center" 1218 1243 > 1219 1244 Log in 1220 1245 </Link>)} ··· 1222 1247 {HOST_SIGNUP_PDS && ( 1223 1248 // todo make signup actually work 1224 1249 <button 1225 - className="w-full rounded-sm border border-gray-300 dark:border-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300" 1250 + className="w-full rounded-sm border border-base-300 dark:border-base-700 px-4 py-2 text-sm font-medium text-base-700 dark:text-base-300" 1226 1251 > 1227 1252 Sign up 1228 1253 </button>
+164
src/routes/c.$did.tsx
··· 1 + import { createFileRoute, Outlet, useLocation, useNavigate } from '@tanstack/react-router' 2 + import { useAtom } from 'jotai' 3 + 4 + import { selectedFeedUriAtom } from '~/utils/atoms' 5 + 6 + export const Route = createFileRoute('/c/$did')({ 7 + component: RouteComponent, 8 + }) 9 + 10 + const dummyfeedlist: ConvenFeed[] = [ 11 + { 12 + feeduri: "at://did:plc:mn45tewwnse5btfftvd3powc/app.bsky.feed.generator/aaagnl3s4wdiq", 13 + title: "Deadlock", 14 + imgurl: "https://cdn.bsky.app/img/avatar_thumbnail/plain/did:plc:mn45tewwnse5btfftvd3powc/bafkreihze2xi3f23bnqy2cij3kic4jrbv2limalfq4saiqemtffo5pdysq" 15 + }, 16 + { 17 + feeduri: "at://did:plc:mn45tewwnse5btfftvd3powc/app.bsky.feed.generator/g3NYFrOGYLwukwD", 18 + title: "Deadlock Migration Test2", 19 + imgurl: "https://cdn.bsky.app/img/avatar_thumbnail/plain/did:plc:mn45tewwnse5btfftvd3powc/bafkreic45gyky6yv72xlvey4eykvohs6zx76lcsomy5n7plxtdafgfgvqy" 20 + }, 21 + { 22 + feeduri: "at://did:plc:mn45tewwnse5btfftvd3powc/app.bsky.feed.generator/deadlock-migrat", 23 + title: "Deadlock Migration Test", 24 + imgurl: "https://cdn.bsky.app/img/avatar_thumbnail/plain/did:plc:mn45tewwnse5btfftvd3powc/bafkreic45gyky6yv72xlvey4eykvohs6zx76lcsomy5n7plxtdafgfgvqy" 25 + }, 26 + { 27 + feeduri: "at://did:plc:mn45tewwnse5btfftvd3powc/app.bsky.feed.generator/TRwWxXWPlipeDVW", 28 + title: "Deadlock Migration Test3", 29 + imgurl: "https://cdn.bsky.app/img/avatar_thumbnail/plain/did:plc:mn45tewwnse5btfftvd3powc/bafkreic45gyky6yv72xlvey4eykvohs6zx76lcsomy5n7plxtdafgfgvqy" 30 + } 31 + ] 32 + 33 + function RouteComponent() { 34 + return ( 35 + <> 36 + <div className="h-64 bg-accent-400 flex justify-center"> 37 + <div className="w-full max-w-[calc(600px+16px+16px+224px+300px)] py-8 flex flex-col justify-end"> 38 + <div className="flex items-center justify-between"> 39 + <span className="text-muted-200 text-5xl font-bold"> 40 + hello i am the community header 41 + </span> 42 + <button>Action</button> 43 + </div> 44 + </div> 45 + </div> 46 + <div className="sticky top-14 min-h-[calc(100vh - 3.5rem)] flex justify-center bg-base-50 dark:bg-base-700 gap-4"> 47 + <nav className="min-h-14 top-14 sticky z-10 bg-contrast-700 w-[224px]"> 48 + <span>hello i am the sticky left sidebar !</span> 49 + <ConvenFeedListDesktopSidebar items={dummyfeedlist} /> 50 + </nav> 51 + <main className="w-full min-h-[100vh] max-w-[600px] sm:border-x border-base-200 dark:border-base-800 bg-white dark:bg-base-950 pb-16 lg:pb-0 overflow-x-clip outline-red-500 outline-8"> 52 + <Outlet /> 53 + </main> 54 + <aside className="min-h-14 top-14 sticky z-10 bg-contrast-700 w-[300px]"> 55 + hello i am the sticky right sidebar ! 56 + </aside> 57 + </div> 58 + </> 59 + ) 60 + } 61 + 62 + 63 + 64 + export interface ConvenFeed { 65 + feeduri: string 66 + specialType?: 'trending' | 'new' | 'featured' | 'top' | (string & {}) 67 + title: string 68 + imgurl: string 69 + } 70 + 71 + 72 + function ConvenFeedListDesktopSidebar({ items }: { items: ConvenFeed[] }) { 73 + return ( 74 + <div className="flex flex-col gap-1 items-start "> 75 + {items.map((item: ConvenFeed, idx: number) => { return <ConvenFeedTab key={item.feeduri} item={item} idx={idx} rightDesktopSidebar={true} /> })} 76 + </div> 77 + ) 78 + } 79 + // TODO: Holy shit dont do this, im just lazy and reusing many red dwarf logic here but 80 + // please for conven just move to direct bsky appview queries i dont care 81 + // and also dont use the fake tab system for the root page like this 82 + // just navigate normally i dont care 83 + function ConvenFeedTab({ 84 + item, 85 + idx, 86 + rightDesktopSidebar = false 87 + }: { 88 + item: ConvenFeed, 89 + idx: number, 90 + rightDesktopSidebar?: boolean 91 + }) { 92 + const location = useLocation(); 93 + const navigate = useNavigate(); 94 + const isAtHome = location.pathname == "/" || location.pathname == ""; 95 + const [persistentSelectedFeed, setPersistentSelectedFeed] = useAtom(selectedFeedUriAtom); 96 + const selectedFeed = persistentSelectedFeed 97 + const setSelectedFeed = setPersistentSelectedFeed 98 + const rkey = item.feeduri.split("/").pop() || item.feeduri; 99 + const isActive = selectedFeed === item.feeduri; 100 + return ( 101 + <button 102 + key={item.feeduri || idx} 103 + className={`${rightDesktopSidebar ? "flex flex-row items-center gap-2 pr-4 pl-2.5 py-1.5" : "px-3 py-1 font-medium"} rounded-full whitespace-nowrap transition-colors ${isActive 104 + ? "text-accent-900 dark:text-accent-100 hover:bg-muted-300 dark:bg-muted-700 bg-muted-200 hover:dark:bg-muted-600 font-medium" 105 + : "text-accent-600 dark:text-accent-400 hover:bg-muted-100 hover:dark:bg-muted-800" 106 + // ? "bg-muted-500 text-white" 107 + // : item.pinned 108 + // ? "bg-muted-200 text-accent-700 dark:bg-muted-700 dark:text-accent-200" 109 + // : "bg-muted-100 text-accent-700 dark:bg-muted-800 dark:text-accent-200" 110 + }`} 111 + onClick={() => { 112 + if (rightDesktopSidebar && !isAtHome) { 113 + navigate({ 114 + to: "/" 115 + }) 116 + } 117 + setSelectedFeed(item.feeduri) 118 + }} 119 + title={item.feeduri} 120 + > 121 + {rightDesktopSidebar && ( 122 + <ConvenFeedIcon imgurl={item.imgurl} className="w-5 h-5 rounded-sm object-cover" /> 123 + )} 124 + {item.title} 125 + {/* {!rightDesktopSidebar && item.pinned && ( 126 + <span 127 + className={`ml-1 text-xs ${isActive 128 + ? "text-accent-900 dark:text-accent-100" 129 + : "text-accent-600 dark:text-accent-400" 130 + }`} 131 + > 132 + 133 + </span> 134 + )} */} 135 + </button> 136 + ); 137 + } 138 + 139 + 140 + function ConvenFeedIcon({ imgurl, className = "w-10 h-10 rounded-sm object-cover" }: { imgurl: string, className?: string }) { 141 + 142 + const avatarUrl = imgurl; 143 + if (!avatarUrl) { 144 + return ( 145 + <div 146 + className={className} 147 + > 148 + <IconMaterialSymbolsRssFeed className="text-accent-200 p-0.5 rounded-sm bg-contrast-600" /> 149 + </div> 150 + ) 151 + } 152 + return ( 153 + <img 154 + src={avatarUrl} 155 + alt={/*feed?.displayName || */"Feed avatar"} 156 + className={className} 157 + onError={(e) => { 158 + const target = e.target as HTMLImageElement; 159 + target.onerror = null; 160 + target.src = "/defaultpfp.png"; 161 + }} 162 + /> 163 + ) 164 + }
+9
src/routes/c.$did/feed.$rkey/index.tsx
··· 1 + import { createFileRoute } from '@tanstack/react-router' 2 + 3 + export const Route = createFileRoute('/c/$did/feed/$rkey/')({ 4 + component: RouteComponent, 5 + }) 6 + 7 + function RouteComponent() { 8 + return <div>Hello "/c/$did/feed/$rkey/"!</div> 9 + }
+10
src/routes/c.$did/index.tsx
··· 1 + import { createFileRoute } from '@tanstack/react-router' 2 + 3 + export const Route = createFileRoute('/c/$did/')({ 4 + component: RouteComponent, 5 + }) 6 + 7 + function RouteComponent() { 8 + return <div>default content from the dot index file</div> 9 + } 10 +
+9
src/routes/c.$did/profile.$did/index.tsx
··· 1 + import { createFileRoute } from '@tanstack/react-router' 2 + 3 + export const Route = createFileRoute('/c/$did/profile/$did/')({ 4 + component: RouteComponent, 5 + }) 6 + 7 + function RouteComponent() { 8 + return <div>Hello "/c/$did/profile/$did/"!</div> 9 + }