Skip to content

Commit b50b320

Browse files
authored
[NEB-189] Nebula: Minor UI tweaks (#6831)
1 parent 4c33936 commit b50b320

File tree

5 files changed

+112
-50
lines changed

5 files changed

+112
-50
lines changed

apps/dashboard/src/app/nebula-app/(app)/components/ChatBar.tsx

Lines changed: 67 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@ import {
2929
AccountBlobbie,
3030
AccountName,
3131
AccountProvider,
32+
WalletName,
33+
WalletProvider,
3234
} from "thirdweb/react";
3335
import { shortenAddress } from "thirdweb/utils";
36+
import type { Wallet } from "thirdweb/wallets";
3437
import type { NebulaContext } from "../api/chat";
3538

3639
export type WalletMeta = {
37-
type: "user" | "smart";
40+
walletId: Wallet["id"];
3841
address: string;
3942
};
4043

@@ -95,7 +98,7 @@ export function ChatBar(props: {
9598
hideTestnets
9699
disableChainId
97100
selectedChainIds={selectedChainIds}
98-
popoverContentClassName="!w-[calc(100vw-80px)] lg:!w-[360px]"
101+
popoverContentClassName="!w-[calc(100vw-80px)] lg:!w-[320px]"
99102
align="start"
100103
side="top"
101104
showSelectedValuesInModal={true}
@@ -257,8 +260,22 @@ function WalletSelector(props: {
257260
aria-expanded={open}
258261
className="flex h-auto items-center gap-1 rounded-full px-2 py-1.5 text-xs"
259262
>
260-
{shortenAddress(props.activeAccountAddress)}
261-
<ChevronDown className="ml-1 size-3 text-muted-foreground/70" />
263+
<AccountProvider
264+
address={props.activeAccountAddress}
265+
client={props.client}
266+
>
267+
<AccountAvatar
268+
className="size-4 rounded-full"
269+
loadingComponent={
270+
<Skeleton className="size-3 rounded-full border" />
271+
}
272+
fallbackComponent={
273+
<AccountBlobbie className="size-3 rounded-full" />
274+
}
275+
/>
276+
{shortenAddress(props.activeAccountAddress)}
277+
<ChevronDown className="size-3 text-muted-foreground/70" />
278+
</AccountProvider>
262279
</Button>
263280
</PopoverTrigger>
264281

@@ -288,48 +305,58 @@ function WalletSelector(props: {
288305
>
289306
<div className="flex items-center gap-2">
290307
<AccountProvider address={wallet.address} client={props.client}>
291-
<div className="flex items-center gap-2">
292-
<AccountAvatar
293-
className="size-8 rounded-full"
294-
loadingComponent={
295-
<Skeleton className="size-8 rounded-full border" />
296-
}
297-
fallbackComponent={
298-
<AccountBlobbie className="size-8 rounded-full" />
299-
}
300-
/>
308+
<WalletProvider id={wallet.walletId}>
309+
<div className="flex items-center gap-2">
310+
<AccountAvatar
311+
className="size-8 rounded-full"
312+
loadingComponent={
313+
<Skeleton className="size-8 rounded-full border" />
314+
}
315+
fallbackComponent={
316+
<AccountBlobbie className="size-8 rounded-full" />
317+
}
318+
/>
301319

302-
<div>
303-
<div className="flex items-center gap-1">
304-
<AccountName
305-
className="text-sm"
306-
loadingComponent={
307-
<span className="font-mono text-sm">
308-
{shortenAddress(wallet.address)}
309-
</span>
310-
}
311-
fallbackComponent={
312-
<span className="font-mono text-sm">
313-
{shortenAddress(wallet.address)}
314-
</span>
315-
}
316-
/>
320+
<div>
321+
<div className="flex items-center gap-1">
322+
<AccountName
323+
className="text-sm"
324+
loadingComponent={
325+
<span className="font-mono text-sm">
326+
{shortenAddress(wallet.address)}
327+
</span>
328+
}
329+
fallbackComponent={
330+
<span className="font-mono text-sm">
331+
{shortenAddress(wallet.address)}
332+
</span>
333+
}
334+
/>
317335

318-
<CopyButton address={wallet.address} />
336+
<CopyButton address={wallet.address} />
319337

320-
{wallet.type === "smart" && (
321-
<Badge variant="outline" className="bg-card px-2">
322-
Gasless
323-
</Badge>
324-
)}
325-
</div>
338+
{wallet.walletId === "smart" && (
339+
<Badge variant="outline" className="bg-card px-2">
340+
Gasless
341+
</Badge>
342+
)}
343+
</div>
326344

327-
<div className="text-muted-foreground text-xs">
328-
{wallet.type === "user" && "Your Account"}
329-
{wallet.type === "smart" && "Smart Account"}
345+
<div className="text-muted-foreground text-xs">
346+
{wallet.walletId === "smart" ? (
347+
"Smart Account"
348+
) : (
349+
<WalletName
350+
fallbackComponent={<span> Your Account </span>}
351+
loadingComponent={
352+
<Skeleton className="h-3.5 w-40" />
353+
}
354+
/>
355+
)}
356+
</div>
330357
</div>
331358
</div>
332-
</div>
359+
</WalletProvider>
333360
</AccountProvider>
334361
</div>
335362

apps/dashboard/src/app/nebula-app/(app)/components/ChatPageContent.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ export function ChatPageContent(props: {
312312

313313
const connectedWalletsMeta: WalletMeta[] = connectedWallets.map((x) => ({
314314
address: x.getAccount()?.address || "",
315-
type: x.id === "smart" ? "smart" : "user",
315+
walletId: x.id,
316316
}));
317317

318318
const handleUpdateContextFilters = async (
@@ -491,6 +491,8 @@ export async function handleNebulaPrompt(params: {
491491
} = params;
492492
let requestIdForMessage = "";
493493

494+
let hasReceivedResponse = false;
495+
494496
await promptNebula({
495497
abortController,
496498
message,
@@ -506,6 +508,12 @@ export async function handleNebulaPrompt(params: {
506508
}
507509

508510
if (res.event === "delta") {
511+
// ignore empty string delta
512+
if (!res.data.v) {
513+
return;
514+
}
515+
516+
hasReceivedResponse = true;
509517
setMessages((prev) => {
510518
const lastMessage = prev[prev.length - 1];
511519
// if last message is presence, overwrite it
@@ -561,6 +569,7 @@ export async function handleNebulaPrompt(params: {
561569

562570
if (res.event === "action") {
563571
if (res.type === "sign_transaction") {
572+
hasReceivedResponse = true;
564573
setMessages((prev) => {
565574
let prevMessages = prev;
566575
// if last message is presence, remove it
@@ -588,6 +597,24 @@ export async function handleNebulaPrompt(params: {
588597
},
589598
context: contextFilters,
590599
});
600+
601+
// if the stream ends without any delta or tx events - we have nothing to show
602+
// show an error message in that case
603+
if (!hasReceivedResponse) {
604+
setMessages((prev) => {
605+
const newMessages = prev.slice(
606+
0,
607+
prev[prev.length - 1]?.type === "presence" ? -1 : undefined,
608+
);
609+
610+
newMessages.push({
611+
text: "No response received, please try again",
612+
type: "error",
613+
});
614+
615+
return newMessages;
616+
});
617+
}
591618
}
592619

593620
export function handleNebulaPromptError(params: {

apps/dashboard/src/app/nebula-app/(app)/components/ChatSidebar.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,23 @@ export function ChatSidebar(props: {
4040
<div className="flex h-full flex-col">
4141
<div className="flex items-center justify-start gap-3 p-4 lg:justify-between">
4242
<Link href="/" className="flex items-center gap-2">
43-
<NebulaIcon className="size-8 text-foreground" aria-label="Nebula" />
43+
<NebulaIcon className="size-6 text-foreground" aria-label="Nebula" />
4444
<span className="font-semibold text-lg tracking-tight">Nebula</span>
4545
</Link>
4646

4747
<Badge variant="secondary" className="gap-1 py-1">
48-
Beta
48+
Alpha
4949
</Badge>
5050
</div>
5151

5252
<div className="h-1" />
5353

5454
<div className="flex flex-col gap-2 px-4">
55-
<Button asChild variant="outline" className="w-full gap-2 rounded-lg">
55+
<Button
56+
asChild
57+
variant="outline"
58+
className="w-full gap-2 rounded-lg bg-muted/50"
59+
>
5660
<Link href={newChatPage}>
5761
<PlusIcon className="size-4" />
5862
New Chat

apps/dashboard/src/app/nebula-app/(app)/components/Chatbar.stories.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function Story() {
7777
showContextSelector={true}
7878
connectedWallets={[
7979
{
80-
type: "user",
80+
walletId: "io.metamask",
8181
address: userWalletAddress,
8282
},
8383
]}
@@ -94,11 +94,11 @@ function Story() {
9494
showContextSelector={true}
9595
connectedWallets={[
9696
{
97-
type: "user",
97+
walletId: "io.metamask",
9898
address: userWalletAddress,
9999
},
100100
{
101-
type: "smart",
101+
walletId: "smart",
102102
address: smartWalletAddress,
103103
},
104104
]}

apps/dashboard/src/app/nebula-app/(app)/components/FloatingChat/FloatingChatContent.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import Link from "next/link";
55
import { usePathname } from "next/navigation";
66
import { useCallback, useState } from "react";
77
import type { ThirdwebClient } from "thirdweb";
8-
import { useActiveWalletConnectionStatus } from "thirdweb/react";
8+
import {
9+
useActiveWallet,
10+
useActiveWalletConnectionStatus,
11+
} from "thirdweb/react";
912
import type { NebulaContext } from "../../api/chat";
1013
import { createSession } from "../../api/session";
1114
import type { ExamplePrompt } from "../../data/examplePrompts";
@@ -69,6 +72,7 @@ function FloatingChatContentLoggedIn(props: {
6972
const [isChatStreaming, setIsChatStreaming] = useState(false);
7073
const [enableAutoScroll, setEnableAutoScroll] = useState(false);
7174
const connectionStatus = useActiveWalletConnectionStatus();
75+
const activeWallet = useActiveWallet();
7276

7377
const [contextFilters, setContextFilters] = useState<
7478
NebulaContext | undefined
@@ -194,11 +198,11 @@ function FloatingChatContentLoggedIn(props: {
194198
setContext={setContextFilters}
195199
showContextSelector={false}
196200
connectedWallets={
197-
props.nebulaParams?.wallet
201+
props.nebulaParams?.wallet && activeWallet
198202
? [
199203
{
200204
address: props.nebulaParams.wallet,
201-
type: "user",
205+
walletId: activeWallet.id,
202206
},
203207
]
204208
: []

0 commit comments

Comments
 (0)