mirror of
https://github.com/dergigi/boris.git
synced 2026-01-31 12:44:37 +01:00
feat: display user public key after successful login
- Add userPublicKey state to App component - Pass public key from Login to App to Bookmarks - Display formatted public key in bookmarks header - Show 'Logged in as: abc12345...xyz67890' format - Update header layout to accommodate user info - Add styling for user info display - Improve login success feedback for users
This commit is contained in:
2095
dist/assets/index-4FXhSRz4.js
vendored
2095
dist/assets/index-4FXhSRz4.js
vendored
File diff suppressed because one or more lines are too long
1
dist/assets/index-FV8IYC7S.css
vendored
1
dist/assets/index-FV8IYC7S.css
vendored
@@ -1 +0,0 @@
|
||||
:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}body{margin:0;min-width:320px;min-height:100vh}#root{max-width:1280px;margin:0 auto;padding:2rem}.app{text-align:center}.app header{margin-bottom:2rem}.app header h1{font-size:2.5rem;margin:0;color:#646cff}.app header p{margin:.5rem 0 0;color:#888}.login-container{display:flex;justify-content:center;align-items:center;min-height:50vh}.login-card{background:#1a1a1a;padding:2rem;border-radius:8px;border:1px solid #333;max-width:400px;width:100%}.login-card h2{margin:0 0 1rem;color:#fff}.login-card p{margin:0 0 1.5rem;color:#ccc}.login-button{background:#646cff;color:#fff;border:none;padding:.75rem 1.5rem;border-radius:4px;font-size:1rem;cursor:pointer;transition:background-color .2s}.login-button:hover:not(:disabled){background:#535bf2}.login-button:disabled{opacity:.6;cursor:not-allowed}.bookmarks-container{text-align:left}.bookmarks-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:2rem;padding-bottom:1rem;border-bottom:1px solid #333}.bookmarks-header h2{margin:0;color:#fff}.logout-button{background:#dc3545;color:#fff;border:none;padding:.5rem 1rem;border-radius:4px;cursor:pointer;transition:background-color .2s}.logout-button:hover{background:#c82333}.loading{text-align:center;padding:2rem;color:#ccc}.empty-state{text-align:center;padding:3rem;color:#888}.empty-state p{margin:.5rem 0}.bookmarks-list{display:grid;gap:1rem}.bookmark-item{background:#1a1a1a;padding:1.5rem;border-radius:8px;border:1px solid #333;transition:border-color .2s}.bookmark-item:hover{border-color:#646cff}.bookmark-item h3{margin:0 0 .5rem;color:#fff;font-size:1.2rem}.bookmark-url{color:#646cff;text-decoration:none;display:block;margin-bottom:.5rem;word-break:break-all}.bookmark-url:hover{text-decoration:underline}.bookmark-content{color:#ccc;margin:.5rem 0;line-height:1.4}.bookmark-meta{color:#888;font-size:.9rem;margin-top:.5rem}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}.login-card,.bookmark-item{background:#f9f9f9;border-color:#ddd}.bookmarks-header{border-bottom-color:#ddd}.bookmark-item h3{color:#213547}.bookmark-content{color:#666}}
|
||||
5
dist/index.html
vendored
5
dist/index.html
vendored
@@ -5,10 +5,11 @@
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Markr - Nostr Bookmarks</title>
|
||||
<script type="module" crossorigin src="/assets/index-4FXhSRz4.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-FV8IYC7S.css">
|
||||
<script type="module" crossorigin src="/assets/index-Cnm-Nmlg.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-D18sZheu.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
14
src/App.tsx
14
src/App.tsx
@@ -7,6 +7,7 @@ import Bookmarks from './components/Bookmarks'
|
||||
function App() {
|
||||
const [eventStore, setEventStore] = useState<EventStore | null>(null)
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false)
|
||||
const [userPublicKey, setUserPublicKey] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
// Initialize event store
|
||||
@@ -27,9 +28,18 @@ function App() {
|
||||
</header>
|
||||
|
||||
{!isAuthenticated ? (
|
||||
<Login onLogin={() => setIsAuthenticated(true)} />
|
||||
<Login onLogin={(publicKey) => {
|
||||
setIsAuthenticated(true)
|
||||
setUserPublicKey(publicKey)
|
||||
}} />
|
||||
) : (
|
||||
<Bookmarks onLogout={() => setIsAuthenticated(false)} />
|
||||
<Bookmarks
|
||||
userPublicKey={userPublicKey}
|
||||
onLogout={() => {
|
||||
setIsAuthenticated(false)
|
||||
setUserPublicKey(null)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</EventStoreProvider>
|
||||
|
||||
@@ -12,39 +12,34 @@ interface Bookmark {
|
||||
}
|
||||
|
||||
interface BookmarksProps {
|
||||
userPublicKey: string | null
|
||||
onLogout: () => void
|
||||
}
|
||||
|
||||
const Bookmarks: React.FC<BookmarksProps> = ({ onLogout }) => {
|
||||
const Bookmarks: React.FC<BookmarksProps> = ({ userPublicKey, onLogout }) => {
|
||||
const [bookmarks, setBookmarks] = useState<Bookmark[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const eventStore = useContext(EventStoreContext)
|
||||
|
||||
useEffect(() => {
|
||||
if (eventStore) {
|
||||
if (eventStore && userPublicKey) {
|
||||
fetchBookmarks()
|
||||
}
|
||||
}, [eventStore])
|
||||
}, [eventStore, userPublicKey])
|
||||
|
||||
const fetchBookmarks = async () => {
|
||||
if (!eventStore) return
|
||||
if (!eventStore || !userPublicKey) return
|
||||
|
||||
try {
|
||||
setLoading(true)
|
||||
|
||||
// Get public key from nostr extension
|
||||
const publicKey = await window.nostr?.getPublicKey()
|
||||
if (!publicKey) {
|
||||
throw new Error('No public key available')
|
||||
}
|
||||
|
||||
// Fetch bookmarks according to NIP-51
|
||||
// Kind 10003: bookmark lists
|
||||
// Kind 30003: parameterized replaceable events (bookmark lists with d-tag)
|
||||
const events = eventStore.getByFilters([
|
||||
{
|
||||
kinds: [10003, 30003],
|
||||
authors: [publicKey]
|
||||
authors: [userPublicKey]
|
||||
}
|
||||
])
|
||||
|
||||
@@ -109,11 +104,20 @@ const Bookmarks: React.FC<BookmarksProps> = ({ onLogout }) => {
|
||||
return new Date(timestamp * 1000).toLocaleDateString()
|
||||
}
|
||||
|
||||
const formatPublicKey = (publicKey: string) => {
|
||||
return `${publicKey.slice(0, 8)}...${publicKey.slice(-8)}`
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="bookmarks-container">
|
||||
<div className="bookmarks-header">
|
||||
<h2>Your Bookmarks</h2>
|
||||
<div>
|
||||
<h2>Your Bookmarks</h2>
|
||||
{userPublicKey && (
|
||||
<p className="user-info">Logged in as: {formatPublicKey(userPublicKey)}</p>
|
||||
)}
|
||||
</div>
|
||||
<button onClick={onLogout} className="logout-button">
|
||||
Logout
|
||||
</button>
|
||||
@@ -126,7 +130,12 @@ const Bookmarks: React.FC<BookmarksProps> = ({ onLogout }) => {
|
||||
return (
|
||||
<div className="bookmarks-container">
|
||||
<div className="bookmarks-header">
|
||||
<h2>Your Bookmarks ({bookmarks.length})</h2>
|
||||
<div>
|
||||
<h2>Your Bookmarks ({bookmarks.length})</h2>
|
||||
{userPublicKey && (
|
||||
<p className="user-info">Logged in as: {formatPublicKey(userPublicKey)}</p>
|
||||
)}
|
||||
</div>
|
||||
<button onClick={onLogout} className="logout-button">
|
||||
Logout
|
||||
</button>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState } from 'react'
|
||||
|
||||
interface LoginProps {
|
||||
onLogin: () => void
|
||||
onLogin: (publicKey: string) => void
|
||||
}
|
||||
|
||||
const Login: React.FC<LoginProps> = ({ onLogin }) => {
|
||||
@@ -20,7 +20,7 @@ const Login: React.FC<LoginProps> = ({ onLogin }) => {
|
||||
const publicKey = await window.nostr.getPublicKey()
|
||||
|
||||
if (publicKey) {
|
||||
onLogin()
|
||||
onLogin(publicKey)
|
||||
} else {
|
||||
throw new Error('Failed to get public key')
|
||||
}
|
||||
|
||||
@@ -100,17 +100,28 @@ body {
|
||||
.bookmarks-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
|
||||
.bookmarks-header > div {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.bookmarks-header h2 {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
margin: 0.5rem 0 0 0;
|
||||
color: #888;
|
||||
font-size: 0.9rem;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.logout-button {
|
||||
background: #dc3545;
|
||||
color: white;
|
||||
@@ -211,4 +222,8 @@ body {
|
||||
.bookmark-content {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user