-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: enable account switch/disconnect wallet
- Loading branch information
Showing
10 changed files
with
187 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,172 @@ | ||
import { User } from 'lucide-react' | ||
import { Button } from "@/components/ui/button" | ||
import { User } from "lucide-react"; | ||
import { Button } from "@/components/ui/button"; | ||
import { | ||
DropdownMenu, | ||
DropdownMenuContent, | ||
DropdownMenuItem, | ||
DropdownMenuSeparator, | ||
DropdownMenuTrigger, | ||
} from "@/components/ui/dropdown-menu" | ||
import { useGlobalState } from '@/app/GlobalStateContext'; | ||
import { useEffect, useState } from 'react'; | ||
import { getUserProfile } from '@/lib/atoma'; | ||
import { LOCAL_STORAGE_MAX_EPOCH, LOCAL_STORAGE_RANDOMNESS, LOCAL_STORAGE_SECRET_KEY, LOCAL_STORAGE_ZKP } from '@/lib/zklogin'; | ||
} from "@/components/ui/dropdown-menu"; | ||
import { useGlobalState } from "@/app/GlobalStateContext"; | ||
import { useEffect, useState } from "react"; | ||
import { getUserProfile } from "@/lib/atoma"; | ||
import { | ||
ConnectModal, | ||
useCurrentAccount, | ||
useCurrentWallet, | ||
useDisconnectWallet, | ||
useSwitchAccount, | ||
} from "@mysten/dapp-kit"; | ||
import { LOCAL_STORAGE_ACCESS_TOKEN } from "@/lib/local_storage_consts"; | ||
import Image from "next/image"; | ||
|
||
export function UserProfileIcon() { | ||
const { setLogState } = useGlobalState(); | ||
const [username, setUsername] = useState<string | null>(null); | ||
const account = useCurrentAccount(); | ||
const [address, setAddress] = useState<string | null>(null); | ||
const [isCopied, setIsCopied] = useState(false); | ||
const { isConnected } = useCurrentWallet(); | ||
const { currentWallet } = useCurrentWallet(); | ||
const { mutateAsync: switchAccount } = useSwitchAccount(); | ||
const { mutateAsync: walletDisconnect } = useDisconnectWallet(); | ||
const { zkLogin } = useGlobalState(); | ||
|
||
useEffect(() => { | ||
getUserProfile().then((profile) => { | ||
setUsername(profile.username); | ||
}); | ||
},[]) | ||
}, []); | ||
|
||
const handleLogOut = () => { | ||
setLogState('loggedOut'); | ||
window.localStorage.removeItem("access_token"); | ||
window.localStorage.removeItem("id_token"); | ||
localStorage.removeItem(LOCAL_STORAGE_SECRET_KEY); | ||
localStorage.removeItem(LOCAL_STORAGE_RANDOMNESS); | ||
localStorage.removeItem(LOCAL_STORAGE_MAX_EPOCH); | ||
localStorage.removeItem(LOCAL_STORAGE_ZKP); | ||
} | ||
setLogState("loggedOut"); | ||
window.localStorage.removeItem(LOCAL_STORAGE_ACCESS_TOKEN); | ||
zkLogin?.disconnect(); | ||
setAddress(null); | ||
}; | ||
|
||
const handleWalletDisconnect = () => { | ||
if (zkLogin?.zkLoginUserAddressValue) { | ||
zkLogin.disconnect(); | ||
if (isConnected) { | ||
walletDisconnect().catch((error) => { | ||
console.error("Error disconnecting wallet", error); | ||
}); | ||
} | ||
} else { | ||
walletDisconnect().catch((error) => { | ||
console.error("Error disconnecting wallet", error); | ||
}); | ||
} | ||
setAddress(null); | ||
}; | ||
|
||
const truncateAddress = (address: string) => { | ||
if (!address) return ""; | ||
return `${address.slice(0, 6)}..${address.slice(-4)}`; | ||
}; | ||
|
||
useEffect(() => { | ||
if (zkLogin?.zkLoginUserAddressValue) { | ||
setAddress(zkLogin?.zkLoginUserAddressValue); | ||
} else if (account?.address) { | ||
setAddress(account?.address); | ||
} else { | ||
setAddress(null); | ||
} | ||
}, [account, zkLogin?.zkLoginUserAddressValue]); | ||
|
||
return ( | ||
<DropdownMenu> | ||
<DropdownMenuTrigger asChild> | ||
<Button | ||
variant="ghost" | ||
className="relative h-8 w-8 rounded-full hover:bg-purple-100 dark:hover:bg-purple-900" | ||
<Button | ||
variant="ghost" | ||
className="relative h-8 w-8 rounded-full hover:bg-purple-100 dark:hover:bg-purple-900 transition-colors" | ||
> | ||
<User className="h-5 w-5 text-purple-600 dark:text-purple-300" /> | ||
</Button> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent | ||
className="w-64 bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-800 text-gray-900 dark:text-white" | ||
align="end" | ||
<DropdownMenuContent | ||
className="w-72 bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-800 shadow-lg animate-in fade-in-0 zoom-in-95" | ||
align="end" | ||
sideOffset={8} | ||
forceMount | ||
> | ||
<div className="px-4 py-3 border-b border-gray-200 dark:border-gray-800"> | ||
<p className="text-sm text-gray-600 dark:text-gray-400">{username}</p> | ||
{/* Email Section */} | ||
<div className="px-4 py-3"> | ||
<p className="text-sm font-medium text-gray-900 dark:text-white">{username}</p> | ||
</div> | ||
<div className="py-2"> | ||
<DropdownMenuItem className="px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer" onClick={handleLogOut}> | ||
Log out | ||
|
||
<DropdownMenuSeparator className="bg-gray-200 dark:bg-gray-800 my-2" /> | ||
|
||
{/* Wallet Section */} | ||
{address && ( | ||
<div className="px-4 py-3"> | ||
<div className="flex items-center justify-between"> | ||
<p className="text-sm font-medium text-gray-900 dark:text-white">SuiAccount</p> | ||
<DropdownMenu> | ||
<div className="flex flex-row gap-2"> | ||
<DropdownMenuTrigger asChild> | ||
<p className="text-sm font-medium text-gray-900 dark:text-white font-mono cursor-pointer"> | ||
{truncateAddress(address)} | ||
</p> | ||
</DropdownMenuTrigger> | ||
<Image | ||
src={isCopied ? "/copy-done.svg" : "/copy.svg"} | ||
className="cursor-pointer dark:invert" | ||
alt="copy" | ||
title="Copy to clipboard" | ||
width={14} | ||
height={14} | ||
onClick={() => { | ||
navigator.clipboard.writeText(address); | ||
setIsCopied(true); | ||
setTimeout(() => setIsCopied(false), 1000); | ||
}} | ||
/> | ||
</div> | ||
<DropdownMenuContent> | ||
{currentWallet?.accounts.map((acc) => ( | ||
<DropdownMenuItem | ||
key={acc.address} | ||
onClick={() => switchAccount({ account: acc })} | ||
className="w-full px-4 py-3 text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer transition-colors rounded-md" | ||
title={acc.address} | ||
> | ||
{acc.label || truncateAddress(acc.address)} | ||
</DropdownMenuItem> | ||
))} | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
</div> | ||
</div> | ||
)} | ||
|
||
{/* Actions Section */} | ||
{address ? ( | ||
<DropdownMenuItem | ||
className="w-full px-4 py-3 text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer transition-colors rounded-md" | ||
onClick={handleWalletDisconnect} | ||
> | ||
Disconnect Wallet | ||
</DropdownMenuItem> | ||
</div> | ||
) : ( | ||
<ConnectModal | ||
trigger={ | ||
<span className="relative flex select-none items-center gap-2 outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 w-full px-4 py-3 text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer transition-colors rounded-md"> | ||
Connect sui wallet | ||
</span> | ||
} | ||
/> | ||
)} | ||
<DropdownMenuSeparator className="bg-gray-200 dark:bg-gray-800 my-2" /> | ||
<DropdownMenuItem | ||
className="w-full px-4 py-3 text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer transition-colors rounded-md" | ||
onClick={handleLogOut} | ||
> | ||
Log out | ||
</DropdownMenuItem> | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
) | ||
); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.