Skip to content

Commit 145144d

Browse files
brendan-kellammsukkari
authored andcommitted
Move logout button & profile picture into settings dropdown (#172)
1 parent fde51e3 commit 145144d

File tree

5 files changed

+65
-67
lines changed

5 files changed

+65
-67
lines changed

packages/web/src/app/components/navigationMenu.tsx

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import { Separator } from "@/components/ui/separator";
55
import Image from "next/image";
66
import logoDark from "../../../public/sb_logo_dark_small.png";
77
import logoLight from "../../../public/sb_logo_light_small.png";
8-
import { ProfilePicture } from "./profilePicture";
9-
import { signOut } from "@/auth";
108
import { SettingsDropdown } from "./settingsDropdown";
119
import { GitHubLogoIcon, DiscordLogoIcon } from "@radix-ui/react-icons";
1210
import { redirect } from "next/navigation";
@@ -88,21 +86,6 @@ export const NavigationMenu = async () => {
8886
</Button>
8987
</form>
9088
<SettingsDropdown />
91-
<form
92-
action={async () => {
93-
"use server";
94-
await signOut();
95-
}}
96-
>
97-
<Button
98-
type="submit"
99-
variant="outline"
100-
size="default"
101-
>
102-
Logout
103-
</Button>
104-
</form>
105-
<ProfilePicture />
10689
</div>
10790
</div>
10891
<Separator />

packages/web/src/app/components/profilePicture.tsx

Lines changed: 0 additions & 20 deletions
This file was deleted.

packages/web/src/app/components/settingsDropdown.tsx

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import {
44
CodeIcon,
55
Laptop,
6+
LogOut,
67
Moon,
78
Settings,
89
Sun
@@ -12,7 +13,7 @@ import {
1213
DropdownMenu,
1314
DropdownMenuContent,
1415
DropdownMenuGroup,
15-
DropdownMenuLabel,
16+
DropdownMenuItem,
1617
DropdownMenuPortal,
1718
DropdownMenuRadioGroup,
1819
DropdownMenuRadioItem,
@@ -28,6 +29,10 @@ import { KeymapType } from "@/lib/types"
2829
import { cn } from "@/lib/utils"
2930
import { useKeymapType } from "@/hooks/useKeymapType"
3031
import { NEXT_PUBLIC_SOURCEBOT_VERSION } from "@/lib/environment.client";
32+
import { useSession } from "next-auth/react";
33+
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
34+
import { signOut } from "next-auth/react"
35+
3136

3237
interface SettingsDropdownProps {
3338
menuButtonClassName?: string;
@@ -38,7 +43,8 @@ export const SettingsDropdown = ({
3843
}: SettingsDropdownProps) => {
3944

4045
const { theme: _theme, setTheme } = useTheme();
41-
const [ keymapType, setKeymapType ] = useKeymapType();
46+
const [keymapType, setKeymapType] = useKeymapType();
47+
const { data: session } = useSession();
4248

4349
const theme = useMemo(() => {
4450
return _theme ?? "light";
@@ -64,9 +70,31 @@ export const SettingsDropdown = ({
6470
<Settings className="h-4 w-4" />
6571
</Button>
6672
</DropdownMenuTrigger>
67-
<DropdownMenuContent className="w-56">
68-
<DropdownMenuLabel>Settings</DropdownMenuLabel>
69-
<DropdownMenuSeparator />
73+
<DropdownMenuContent className="w-64">
74+
{session?.user && (
75+
<DropdownMenuGroup>
76+
<div className="flex flex-row items-center gap-1 p-2">
77+
<Avatar>
78+
<AvatarImage
79+
src={session.user.image ?? ""}
80+
/>
81+
<AvatarFallback>
82+
{session.user.name && session.user.name.length > 0 ? session.user.name[0] : 'U'}
83+
</AvatarFallback>
84+
</Avatar>
85+
<p className="text-sm font-medium text-ellipsis">{session.user.email ?? "User"}</p>
86+
</div>
87+
<DropdownMenuItem
88+
onClick={() => {
89+
signOut();
90+
}}
91+
>
92+
<LogOut className="mr-2 h-4 w-4" />
93+
<span>Log out</span>
94+
</DropdownMenuItem>
95+
<DropdownMenuSeparator />
96+
</DropdownMenuGroup>
97+
)}
7098
<DropdownMenuGroup>
7199
<DropdownMenuSub>
72100
<DropdownMenuSubTrigger>
@@ -107,11 +135,11 @@ export const SettingsDropdown = ({
107135
</DropdownMenuSubContent>
108136
</DropdownMenuPortal>
109137
</DropdownMenuSub>
110-
<DropdownMenuSeparator />
111-
<div className="px-2 py-1 text-sm text-muted-foreground">
112-
version: {NEXT_PUBLIC_SOURCEBOT_VERSION}
113-
</div>
114138
</DropdownMenuGroup>
139+
<DropdownMenuSeparator />
140+
<div className="px-2 py-1 text-sm text-muted-foreground">
141+
version: {NEXT_PUBLIC_SOURCEBOT_VERSION}
142+
</div>
115143
</DropdownMenuContent>
116144
</DropdownMenu>
117145
)

packages/web/src/app/layout.tsx

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import type { Metadata } from "next";
22
import "./globals.css";
33
import { ThemeProvider } from "next-themes";
4-
import { Suspense } from "react";
54
import { QueryClientProvider } from "./queryClientProvider";
65
import { PHProvider } from "./posthogProvider";
76
import { Toaster } from "@/components/ui/toaster";
87
import { TooltipProvider } from "@/components/ui/tooltip";
8+
import { SessionProvider } from "next-auth/react";
99

1010
export const metadata: Metadata = {
1111
title: "Sourcebot",
@@ -25,26 +25,22 @@ export default function RootLayout({
2525
>
2626
<body>
2727
<Toaster />
28-
<PHProvider>
29-
<ThemeProvider
30-
attribute="class"
31-
defaultTheme="system"
32-
enableSystem
33-
disableTransitionOnChange
34-
>
35-
<QueryClientProvider>
36-
<TooltipProvider>
37-
{/*
38-
@todo : ideally we don't wrap everything in a suspense boundary.
39-
@see : https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
40-
*/}
41-
<Suspense>
28+
<SessionProvider>
29+
<PHProvider>
30+
<ThemeProvider
31+
attribute="class"
32+
defaultTheme="system"
33+
enableSystem
34+
disableTransitionOnChange
35+
>
36+
<QueryClientProvider>
37+
<TooltipProvider>
4238
{children}
43-
</Suspense>
44-
</TooltipProvider>
45-
</QueryClientProvider>
46-
</ThemeProvider>
47-
</PHProvider>
39+
</TooltipProvider>
40+
</QueryClientProvider>
41+
</ThemeProvider>
42+
</PHProvider>
43+
</SessionProvider>
4844
</body>
4945
</html>
5046
);

packages/web/src/app/search/page.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { createPathWithQueryParams } from "@/lib/utils";
1414
import { SymbolIcon } from "@radix-ui/react-icons";
1515
import { useQuery } from "@tanstack/react-query";
1616
import { useRouter } from "next/navigation";
17-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
17+
import { Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react";
1818
import { ImperativePanelHandle } from "react-resizable-panels";
1919
import { getRepos, search } from "../api/(client)/client";
2020
import { TopBar } from "../components/topBar";
@@ -25,6 +25,17 @@ import { SearchResultsPanel } from "./components/searchResultsPanel";
2525
const DEFAULT_MAX_MATCH_DISPLAY_COUNT = 10000;
2626

2727
export default function SearchPage() {
28+
// We need a suspense boundary here since we are accessing query params
29+
// in the top level page.
30+
// @see : https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
31+
return (
32+
<Suspense>
33+
<SearchPageInternal />
34+
</Suspense>
35+
)
36+
}
37+
38+
const SearchPageInternal = () => {
2839
const router = useRouter();
2940
const searchQuery = useNonEmptyQueryParam(SearchQueryParams.query) ?? "";
3041
const _maxMatchDisplayCount = parseInt(useNonEmptyQueryParam(SearchQueryParams.maxMatchDisplayCount) ?? `${DEFAULT_MAX_MATCH_DISPLAY_COUNT}`);

0 commit comments

Comments
 (0)