diff --git a/desktop/src/features/forum/ui/ForumComposer.tsx b/desktop/src/features/forum/ui/ForumComposer.tsx index 6c1e95bab0..064d38e926 100644 --- a/desktop/src/features/forum/ui/ForumComposer.tsx +++ b/desktop/src/features/forum/ui/ForumComposer.tsx @@ -35,6 +35,7 @@ type ForumComposerProps = { className?: string; placeholder: string; disabled?: boolean; + header?: React.ReactNode; isSending?: boolean; onCancel?: () => void; onSubmit: ( @@ -53,6 +54,7 @@ export function ForumComposer({ className, placeholder, disabled, + header, isSending, onCancel, onSubmit, @@ -355,6 +357,7 @@ export function ForumComposer({ onSubmit={handleSubmit} > {media.isDragOver && } + {header ?
{header}
: null} -
- +
+
+ {isAgent ? ( ) : null}
-
-
- +
+
+ {displayName} {isAgent ? ( @@ -67,7 +71,7 @@ export function NoteCard({ {profile.nip05Handle} ) : null} - + {formatRelativeTime(note.createdAt)} {!isOwnNote ? ( @@ -97,8 +101,8 @@ export function NoteCard({ ) : null}
-
- +
+
{!isOwnNote ? ( diff --git a/desktop/src/features/pulse/ui/PulseView.tsx b/desktop/src/features/pulse/ui/PulseView.tsx index 313430657c..7ed34c4df0 100644 --- a/desktop/src/features/pulse/ui/PulseView.tsx +++ b/desktop/src/features/pulse/ui/PulseView.tsx @@ -1,4 +1,4 @@ -import { Check, Filter, RefreshCw } from "lucide-react"; +import { Check, Filter, Search } from "lucide-react"; import * as React from "react"; import { useRelayAgentsQuery } from "@/features/agents/hooks"; @@ -28,14 +28,15 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from "@/shared/ui/dropdown-menu"; +import { Input } from "@/shared/ui/input"; import { Skeleton } from "@/shared/ui/skeleton"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/shared/ui/tabs"; import { UserAvatar } from "@/shared/ui/UserAvatar"; -type PulseTab = "foryou" | "people" | "agents" | "mine"; +type PulseTab = "search" | "foryou" | "people" | "agents" | "mine"; const tabTriggerClassName = - "h-6 rounded-full px-3 py-0 text-[11px] font-semibold shadow-none transition-colors text-muted-foreground hover:text-foreground data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm"; + "h-6 rounded-full px-3 py-0 text-[11px] font-semibold shadow-none transition-colors !text-muted-foreground hover:!text-foreground data-[state=active]:bg-background data-[state=active]:!text-foreground data-[state=active]:shadow-sm dark:!text-white/35 dark:hover:!text-white/70 dark:data-[state=active]:!text-white"; type PulseViewProps = { currentPubkey?: string; @@ -136,6 +137,7 @@ function AgentFilter({ export function PulseView({ currentPubkey }: PulseViewProps) { const [activeTab, setActiveTab] = React.useState("foryou"); const [agentFilter, setAgentFilter] = React.useState(null); + const [searchQuery, setSearchQuery] = React.useState(""); // ── Contact list & follow state ──────────────────────────────────────── const contactListQuery = useContactListQuery(currentPubkey); @@ -274,11 +276,6 @@ export function PulseView({ currentPubkey }: PulseViewProps) { ? agentTimelineQuery : myNotesQuery; const isLoading = activeQuery.isLoading; - const isRefetching = activeQuery.isRefetching; - - function handleRefresh() { - void activeQuery.refetch(); - } function handleFollow(pubkey: string) { followMutation.mutate(pubkey); @@ -290,6 +287,7 @@ export function PulseView({ currentPubkey }: PulseViewProps) { // ── Render ───────────────────────────────────────────────────────────── const emptyMessages: Record = { + search: "Search Pulse notes by author or text.", foryou: "No notes yet. Follow people and agents to build your personalized feed.", people: "No notes yet. Follow people to see their updates here.", @@ -346,25 +344,34 @@ export function PulseView({ currentPubkey }: PulseViewProps) { {/* Tab bar */}
- - - Everyone - - - Following - - - Agents - {relayAgents.length > 0 ? ( - - {relayAgents.length} - - ) : null} - - - Mine - - +
+ + + + + + Everyone + + + Following + + + Agents + {relayAgents.length > 0 ? ( + + {relayAgents.length} + + ) : null} + + + Mine + + +
{activeTab === "agents" && relayAgents.length > 1 ? ( @@ -375,17 +382,6 @@ export function PulseView({ currentPubkey }: PulseViewProps) { selectedPubkey={agentFilter} /> ) : null} -
@@ -397,47 +393,77 @@ export function PulseView({ currentPubkey }: PulseViewProps) { className="mt-0 min-h-0 flex-1 overflow-y-auto" >
- {activeTab !== "agents" ? ( -
-
- +
+
+ Sprout -
-
-
- - {currentDisplayName} - -
- {publishMutation.isError && ( -
- {publishMutation.error instanceof Error - ? publishMutation.error.message - : "Failed to publish note"} +
+
+
+ + setSearchQuery(event.target.value)} + placeholder="What would you like to know?" + type="search" + value={searchQuery} + /> +
- )} - - publishMutation.mutateAsync({ - content, - mentionPubkeys, - mediaTags, - }) - } - profiles={mentionProfiles} - /> +
+ ) : activeTab !== "agents" ? ( +
+ {publishMutation.isError && ( +
+ {publishMutation.error instanceof Error + ? publishMutation.error.message + : "Failed to publish note"} +
+ )} + + +
+ } + members={pulseMentionMembers} + placeholder="What's on your mind?" + isSending={publishMutation.isPending} + onSubmit={(content, mentionPubkeys, mediaTags) => + publishMutation.mutateAsync({ + content, + mentionPubkeys, + mediaTags, + }) + } + profiles={mentionProfiles} + /> +
) : null} -
{renderTimeline()}
+ {activeTab !== "search" ? ( +
{renderTimeline()}
+ ) : null}
diff --git a/desktop/src/shared/styles/globals.css b/desktop/src/shared/styles/globals.css index 9a7ba1cd92..e15eeded49 100644 --- a/desktop/src/shared/styles/globals.css +++ b/desktop/src/shared/styles/globals.css @@ -22,6 +22,20 @@ height: 0; } +.pulse-composer + .rich-text-composer + .tiptap + p.is-editor-empty:first-child::before { + color: hsl(var(--muted-foreground) / 0.65); +} + +.pulse-composer:focus-within + .rich-text-composer + .tiptap + p.is-editor-empty:first-child::before { + color: hsl(var(--foreground)); +} + .rich-text-composer .tiptap strong { font-weight: 600; }