A locally focused bluesky appview
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;