Skip to content

Commit

Permalink
[TOOL-2815] Nebula - handle disconnected wallet state, use connected …
Browse files Browse the repository at this point in the history
…account address in execute config (#5821)

## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
This PR primarily focuses on refining the chat functionality and user experience in the `ChatBar` and `ChatPageContent` components. It enhances wallet connection handling, streamlines message sending, and introduces a dialog for when the wallet is disconnected.

### Detailed summary
- Added `e.preventDefault()` in `ChatBar` to prevent default behavior on Enter key.
- Removed unused wallet address fetching in several components.
- Updated `config` type to allow `null` in `Chat` API.
- Introduced `WalletDisconnectedDialog` in `ChatPageContent`.
- Enhanced state management for showing different login pages.
- Improved context filter updates based on wallet address and active chain.
- Added conditional rendering for wallet connection prompts.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
  • Loading branch information
MananTank committed Dec 23, 2024
1 parent 1b103d7 commit 1e27491
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 56 deletions.
7 changes: 5 additions & 2 deletions apps/dashboard/src/app/nebula-app/(app)/api/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export type ContextFilters = {
export async function promptNebula(params: {
message: string;
sessionId: string;
config: ExecuteConfig;
config: ExecuteConfig | null;
authToken: string;
handleStream: (res: ChatStreamedResponse) => void;
abortController: AbortController;
Expand All @@ -24,7 +24,6 @@ export async function promptNebula(params: {
user_id: "default-user",
session_id: params.sessionId,
stream: true,
execute_config: params.config,
};

if (params.contextFilters) {
Expand All @@ -34,6 +33,10 @@ export async function promptNebula(params: {
};
}

if (params.config) {
body.execute_config = params.config;
}

const events = await stream(`${NEXT_PUBLIC_NEBULA_URL}/chat`, {
method: "POST",
headers: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { redirect } from "next/navigation";
import { getValidAccount } from "../../../../account/settings/getAccount";
import {
getAuthToken,
getAuthTokenWalletAddress,
} from "../../../../api/lib/getAuthToken";
import { getAuthToken } from "../../../../api/lib/getAuthToken";
import { loginRedirect } from "../../../../login/loginRedirect";
import { getSessionById } from "../../api/session";
import { ChatPageContent } from "../../components/ChatPageContent";
Expand All @@ -22,12 +19,6 @@ export default async function Page(props: {
loginRedirect(pagePath);
}

const accountAddress = await getAuthTokenWalletAddress();

if (!accountAddress) {
loginRedirect(pagePath);
}

const session = await getSessionById({
authToken,
sessionId: params.session_id,
Expand All @@ -39,7 +30,6 @@ export default async function Page(props: {

return (
<ChatPageContent
accountAddress={accountAddress}
authToken={authToken}
session={session}
type="new-chat"
Expand Down
12 changes: 1 addition & 11 deletions apps/dashboard/src/app/nebula-app/(app)/chat/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { getValidAccount } from "../../../account/settings/getAccount";
import {
getAuthToken,
getAuthTokenWalletAddress,
} from "../../../api/lib/getAuthToken";
import { getAuthToken } from "../../../api/lib/getAuthToken";
import { loginRedirect } from "../../../login/loginRedirect";
import { ChatPageContent } from "../components/ChatPageContent";

Expand All @@ -14,15 +11,8 @@ export default async function Page() {
loginRedirect();
}

const accountAddress = await getAuthTokenWalletAddress();

if (!accountAddress) {
loginRedirect();
}

return (
<ChatPageContent
accountAddress={accountAddress}
authToken={authToken}
session={undefined}
type="new-chat"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function Chatbar(props: {
return;
}
if (e.key === "Enter" && !props.isChatStreaming) {
e.preventDefault();
setMessage("");
props.sendMessage(message);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
"use client";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { useThirdwebClient } from "@/constants/thirdweb.client";
import type { Account } from "@3rdweb-sdk/react/hooks/useApi";
import { ArrowRightIcon } from "lucide-react";
import Link from "next/link";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useActiveAccount, useActiveWalletChain } from "thirdweb/react";
import { type ContextFilters, promptNebula } from "../api/chat";
Expand All @@ -15,7 +26,6 @@ import { EmptyStateChatPageContent } from "./EmptyStateChatPageContent";
export function ChatPageContent(props: {
session: SessionInfo | undefined;
authToken: string;
accountAddress: string;
type: "landing" | "new-chat";
account: Account;
initialPrompt: string | undefined;
Expand Down Expand Up @@ -95,12 +105,7 @@ export function ChatPageContent(props: {
// update the context filters to the current user's wallet address and chain id
// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
if (
!isNewSession ||
hasUserUpdatedContextFilters ||
!address ||
!activeChain
) {
if (!isNewSession || hasUserUpdatedContextFilters) {
return;
}

Expand All @@ -109,19 +114,23 @@ export function ChatPageContent(props: {
? { ..._contextFilters }
: {};

updatedContextFilters.walletAddresses = [address];
updatedContextFilters.chainIds = [activeChain.id.toString()];
updatedContextFilters.walletAddresses = address ? [address] : [];
updatedContextFilters.chainIds = activeChain
? [activeChain.id.toString()]
: [];

return updatedContextFilters;
});
}, [address, isNewSession, hasUserUpdatedContextFilters, activeChain]);

const config: ExecuteConfig = useMemo(() => {
return {
mode: "client",
signer_wallet_address: props.accountAddress,
};
}, [props.accountAddress]);
const config: ExecuteConfig | null = useMemo(() => {
return address
? {
mode: "client",
signer_wallet_address: address,
}
: null;
}, [address]);

const [sessionId, _setSessionId] = useState<string | undefined>(
props.session?.id,
Expand Down Expand Up @@ -150,6 +159,7 @@ export function ChatPageContent(props: {

const [isChatStreaming, setIsChatStreaming] = useState(false);
const [enableAutoScroll, setEnableAutoScroll] = useState(false);
const [showConnectModal, setShowConnectModal] = useState(false);

const initSession = useCallback(async () => {
const session = await createSession({
Expand All @@ -163,6 +173,10 @@ export function ChatPageContent(props: {

const handleSendMessage = useCallback(
async (message: string) => {
if (!address) {
setShowConnectModal(true);
return;
}
setUserHasSubmittedMessage(true);
setMessages((prev) => [
...prev,
Expand Down Expand Up @@ -329,6 +343,7 @@ export function ChatPageContent(props: {
props.authToken,
messages.length,
initSession,
address,
],
);

Expand All @@ -350,6 +365,10 @@ export function ChatPageContent(props: {

return (
<div className="flex grow flex-col overflow-hidden">
<WalletDisconnectedDialog
open={showConnectModal}
onOpenChange={setShowConnectModal}
/>
<header className="flex justify-start border-b bg-background p-4">
<ContextFiltersButton
contextFilters={contextFilters}
Expand Down Expand Up @@ -411,3 +430,35 @@ export function ChatPageContent(props: {
</div>
);
}

function WalletDisconnectedDialog(props: {
open: boolean;
onOpenChange: (value: boolean) => void;
}) {
return (
<Dialog open={props.open} onOpenChange={props.onOpenChange}>
<DialogContent className="p-0">
<div className="p-6">
<DialogHeader>
<DialogTitle> Wallet Disconnected </DialogTitle>
<DialogDescription>
Connect your wallet to continue
</DialogDescription>
</DialogHeader>
</div>

<div className="flex justify-end gap-3 border-t bg-muted/50 p-6">
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button asChild>
<Link href="/login" className="gap-2">
Connect Wallet
<ArrowRightIcon className="size-4" />
</Link>
</Button>
</div>
</DialogContent>
</Dialog>
);
}
11 changes: 1 addition & 10 deletions apps/dashboard/src/app/nebula-app/(app)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { getValidAccount } from "../../account/settings/getAccount";
import {
getAuthToken,
getAuthTokenWalletAddress,
} from "../../api/lib/getAuthToken";
import { getAuthToken } from "../../api/lib/getAuthToken";
import { loginRedirect } from "../../login/loginRedirect";
import { ChatPageContent } from "./components/ChatPageContent";

Expand All @@ -20,16 +17,10 @@ export default async function Page(props: {
loginRedirect();
}

const accountAddress = await getAuthTokenWalletAddress();
const account = await getValidAccount();

if (!accountAddress) {
loginRedirect();
}

return (
<ChatPageContent
accountAddress={accountAddress}
authToken={authToken}
session={undefined}
type="landing"
Expand Down
18 changes: 11 additions & 7 deletions apps/dashboard/src/app/nebula-app/login/NebulaLoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ export function NebulaLoginPage(props: {
account: Account | undefined;
}) {
const [message, setMessage] = useState<string | undefined>(undefined);
const [showLoginPage, setShowLoginPage] = useState<boolean>(false);

const [showPage, setShowPage] = useState<"connect" | "welcome">(
props.account ? "connect" : "welcome",
);
return (
<div className="relative flex min-h-screen flex-col overflow-hidden bg-background">
{/* nav */}
<header className="border-b">
<div className="container flex items-center justify-between p-4">
<NebulaIcon className="size-8 shrink-0 text-foreground" />
Expand All @@ -37,28 +39,30 @@ export function NebulaLoginPage(props: {
Docs
</Link>

{!showLoginPage && (
<Button size="sm" onClick={() => setShowLoginPage(true)}>
{showPage === "welcome" && (
<Button size="sm" onClick={() => setShowPage("connect")}>
Sign in
</Button>
)}
</div>
</div>
</header>

{showLoginPage ? (
{showPage === "connect" && (
<LoginAndOnboardingPageContent
account={props.account}
redirectPath={
message ? `/?prompt=${encodeURIComponent(message)}` : "/"
}
/>
) : (
)}

{showPage === "welcome" && (
<div className="container relative flex max-w-[800px] grow flex-col justify-center overflow-hidden rounded-lg pb-6">
<EmptyStateChatPageContent
sendMessage={(msg) => {
setMessage(msg);
setShowLoginPage(true);
setShowPage("connect");
}}
/>
</div>
Expand Down

0 comments on commit 1e27491

Please sign in to comment.