A locally focused bluesky appview
at master 89 lines 2.7 kB view raw
1import React, { useState, useEffect } from 'react'; 2import { BrowserRouter as Router, Routes, Route, Link, useLocation } from 'react-router-dom'; 3import { FollowingFeed } from './components/FollowingFeed'; 4import { ProfilePage } from './components/ProfilePage'; 5import { PostView } from './components/PostView'; 6import { ThreadView } from './components/ThreadView'; 7import { PostComposer } from './components/PostComposer'; 8import { NotificationsPage } from './components/NotificationsPage'; 9import { ApiClient } from './api'; 10import './App.css'; 11 12function Navigation() { 13 const location = useLocation(); 14 const [myHandle, setMyHandle] = useState<string | null>(null); 15 16 useEffect(() => { 17 ApiClient.getMe().then(data => { 18 setMyHandle(data.handle); 19 }).catch(err => { 20 console.error('Failed to fetch current user:', err); 21 }); 22 }, []); 23 24 return ( 25 <nav className="app-nav"> 26 <div className="nav-container"> 27 <Link to="/" className="nav-brand"> 28 Konbini 29 </Link> 30 <div className="nav-links"> 31 <Link 32 to="/" 33 className={`nav-link ${location.pathname === '/' ? 'active' : ''}`} 34 > 35 Following 36 </Link> 37 <Link 38 to="/notifications" 39 className={`nav-link ${location.pathname === '/notifications' ? 'active' : ''}`} 40 > 41 Notifications 42 </Link> 43 {myHandle && ( 44 <Link 45 to={`/profile/${myHandle}`} 46 className={`nav-link ${location.pathname.includes('/profile/') ? 'active' : ''}`} 47 > 48 Profile 49 </Link> 50 )} 51 </div> 52 </div> 53 </nav> 54 ); 55} 56 57function App() { 58 const [showComposer, setShowComposer] = useState(false); 59 60 return ( 61 <Router> 62 <div className="app"> 63 <Navigation /> 64 <main className="app-main"> 65 <Routes> 66 <Route path="/" element={<FollowingFeed />} /> 67 <Route path="/notifications" element={<NotificationsPage />} /> 68 <Route path="/profile/:account" element={<ProfilePage />} /> 69 <Route path="/profile/:account/post/:rkey" element={<PostView />} /> 70 <Route path="/thread" element={<ThreadView />} /> 71 </Routes> 72 </main> 73 <button className="floating-post-button" onClick={() => setShowComposer(true)}> 74 POST 75 </button> 76 {showComposer && ( 77 <PostComposer 78 onClose={() => setShowComposer(false)} 79 onPostCreated={() => { 80 window.location.reload(); 81 }} 82 /> 83 )} 84 </div> 85 </Router> 86 ); 87} 88 89export default App;