mirror of
https://github.com/hoornet/vega.git
synced 2026-05-07 12:49:13 -07:00
Bump to v0.2.0 — Phase 2: Engagement & Reach
Four features shipped in this release: - Feed reply context: replies show "↩ replying to @name" above the note content; clicking fetches and opens the parent thread - NIP-65 outbox model: fetchUserRelayList + publishRelayList + fetchUserNotesNIP65 in client.ts; profile notes fetched via the author's write relays; "Publish relay list to Nostr" button in Settings (kind 10002) - Notifications: new store (notifications.ts) + NotificationsView; 🔔 sidebar nav item with unread badge; DM nav item also shows unread conversation count; badges clear on open/select - Keyboard shortcuts: useKeyboardShortcuts hook + HelpModal; n=compose, /=search, j/k=feed nav with ring highlight, Esc=back, ?=help overlay Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
42
src/hooks/useKeyboardShortcuts.ts
Normal file
42
src/hooks/useKeyboardShortcuts.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { useEffect } from "react";
|
||||
import { useUIStore } from "../stores/ui";
|
||||
import { useFeedStore } from "../stores/feed";
|
||||
|
||||
export function useKeyboardShortcuts() {
|
||||
const { currentView, setView, goBack, toggleHelp } = useUIStore();
|
||||
const { focusedNoteIndex, setFocusedNoteIndex, notes } = useFeedStore();
|
||||
|
||||
useEffect(() => {
|
||||
const handler = (e: KeyboardEvent) => {
|
||||
const tag = (e.target as HTMLElement).tagName;
|
||||
if (tag === "INPUT" || tag === "TEXTAREA" || (e.target as HTMLElement).isContentEditable) return;
|
||||
switch (e.key) {
|
||||
case "n":
|
||||
setView("feed");
|
||||
setTimeout(() => (document.querySelector("[data-compose]") as HTMLTextAreaElement)?.focus(), 50);
|
||||
break;
|
||||
case "/":
|
||||
e.preventDefault();
|
||||
setView("search");
|
||||
setTimeout(() => (document.querySelector("[data-search-input]") as HTMLInputElement)?.focus(), 50);
|
||||
break;
|
||||
case "Escape":
|
||||
goBack();
|
||||
break;
|
||||
case "?":
|
||||
toggleHelp();
|
||||
break;
|
||||
case "j":
|
||||
if (currentView === "feed")
|
||||
setFocusedNoteIndex(Math.min(focusedNoteIndex + 1, notes.length - 1));
|
||||
break;
|
||||
case "k":
|
||||
if (currentView === "feed")
|
||||
setFocusedNoteIndex(Math.max(focusedNoteIndex - 1, 0));
|
||||
break;
|
||||
}
|
||||
};
|
||||
window.addEventListener("keydown", handler);
|
||||
return () => window.removeEventListener("keydown", handler);
|
||||
}, [currentView, focusedNoteIndex, notes.length]);
|
||||
}
|
||||
Reference in New Issue
Block a user