mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 12:25:22 +00:00
Move logout button & profile picture into settings dropdown (#172)
This commit is contained in:
parent
5d253ffa12
commit
a5091fb900
5 changed files with 65 additions and 67 deletions
|
|
@ -5,8 +5,6 @@ import { Separator } from "@/components/ui/separator";
|
|||
import Image from "next/image";
|
||||
import logoDark from "../../../public/sb_logo_dark_small.png";
|
||||
import logoLight from "../../../public/sb_logo_light_small.png";
|
||||
import { ProfilePicture } from "./profilePicture";
|
||||
import { signOut } from "@/auth";
|
||||
import { SettingsDropdown } from "./settingsDropdown";
|
||||
import { GitHubLogoIcon, DiscordLogoIcon } from "@radix-ui/react-icons";
|
||||
import { redirect } from "next/navigation";
|
||||
|
|
@ -88,21 +86,6 @@ export const NavigationMenu = async () => {
|
|||
</Button>
|
||||
</form>
|
||||
<SettingsDropdown />
|
||||
<form
|
||||
action={async () => {
|
||||
"use server";
|
||||
await signOut();
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="outline"
|
||||
size="default"
|
||||
>
|
||||
Logout
|
||||
</Button>
|
||||
</form>
|
||||
<ProfilePicture />
|
||||
</div>
|
||||
</div>
|
||||
<Separator />
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
import { auth } from "@/auth"
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from "@/components/ui/avatar"
|
||||
|
||||
export const ProfilePicture = async () => {
|
||||
const session = await auth()
|
||||
|
||||
return (
|
||||
<Avatar>
|
||||
<AvatarImage
|
||||
src={session?.user?.image ?? ""}
|
||||
alt="@shadcn"
|
||||
/>
|
||||
<AvatarFallback>U</AvatarFallback>
|
||||
</Avatar>
|
||||
)
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
import {
|
||||
CodeIcon,
|
||||
Laptop,
|
||||
LogOut,
|
||||
Moon,
|
||||
Settings,
|
||||
Sun
|
||||
|
|
@ -12,7 +13,7 @@ import {
|
|||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
|
|
@ -28,6 +29,10 @@ import { KeymapType } from "@/lib/types"
|
|||
import { cn } from "@/lib/utils"
|
||||
import { useKeymapType } from "@/hooks/useKeymapType"
|
||||
import { NEXT_PUBLIC_SOURCEBOT_VERSION } from "@/lib/environment.client";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { signOut } from "next-auth/react"
|
||||
|
||||
|
||||
interface SettingsDropdownProps {
|
||||
menuButtonClassName?: string;
|
||||
|
|
@ -38,7 +43,8 @@ export const SettingsDropdown = ({
|
|||
}: SettingsDropdownProps) => {
|
||||
|
||||
const { theme: _theme, setTheme } = useTheme();
|
||||
const [ keymapType, setKeymapType ] = useKeymapType();
|
||||
const [keymapType, setKeymapType] = useKeymapType();
|
||||
const { data: session } = useSession();
|
||||
|
||||
const theme = useMemo(() => {
|
||||
return _theme ?? "light";
|
||||
|
|
@ -64,9 +70,31 @@ export const SettingsDropdown = ({
|
|||
<Settings className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56">
|
||||
<DropdownMenuLabel>Settings</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuContent className="w-64">
|
||||
{session?.user && (
|
||||
<DropdownMenuGroup>
|
||||
<div className="flex flex-row items-center gap-1 p-2">
|
||||
<Avatar>
|
||||
<AvatarImage
|
||||
src={session.user.image ?? ""}
|
||||
/>
|
||||
<AvatarFallback>
|
||||
{session.user.name && session.user.name.length > 0 ? session.user.name[0] : 'U'}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<p className="text-sm font-medium text-ellipsis">{session.user.email ?? "User"}</p>
|
||||
</div>
|
||||
<DropdownMenuItem
|
||||
onClick={() => {
|
||||
signOut();
|
||||
}}
|
||||
>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
<span>Log out</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
</DropdownMenuGroup>
|
||||
)}
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger>
|
||||
|
|
@ -107,11 +135,11 @@ export const SettingsDropdown = ({
|
|||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
<DropdownMenuSeparator />
|
||||
<div className="px-2 py-1 text-sm text-muted-foreground">
|
||||
version: {NEXT_PUBLIC_SOURCEBOT_VERSION}
|
||||
</div>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<div className="px-2 py-1 text-sm text-muted-foreground">
|
||||
version: {NEXT_PUBLIC_SOURCEBOT_VERSION}
|
||||
</div>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import type { Metadata } from "next";
|
||||
import "./globals.css";
|
||||
import { ThemeProvider } from "next-themes";
|
||||
import { Suspense } from "react";
|
||||
import { QueryClientProvider } from "./queryClientProvider";
|
||||
import { PHProvider } from "./posthogProvider";
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import { SessionProvider } from "next-auth/react";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Sourcebot",
|
||||
|
|
@ -25,26 +25,22 @@ export default function RootLayout({
|
|||
>
|
||||
<body>
|
||||
<Toaster />
|
||||
<PHProvider>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="system"
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<QueryClientProvider>
|
||||
<TooltipProvider>
|
||||
{/*
|
||||
@todo : ideally we don't wrap everything in a suspense boundary.
|
||||
@see : https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
|
||||
*/}
|
||||
<Suspense>
|
||||
<SessionProvider>
|
||||
<PHProvider>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="system"
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<QueryClientProvider>
|
||||
<TooltipProvider>
|
||||
{children}
|
||||
</Suspense>
|
||||
</TooltipProvider>
|
||||
</QueryClientProvider>
|
||||
</ThemeProvider>
|
||||
</PHProvider>
|
||||
</TooltipProvider>
|
||||
</QueryClientProvider>
|
||||
</ThemeProvider>
|
||||
</PHProvider>
|
||||
</SessionProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { createPathWithQueryParams } from "@/lib/utils";
|
|||
import { SymbolIcon } from "@radix-ui/react-icons";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { ImperativePanelHandle } from "react-resizable-panels";
|
||||
import { getRepos, search } from "../api/(client)/client";
|
||||
import { TopBar } from "../components/topBar";
|
||||
|
|
@ -25,6 +25,17 @@ import { SearchResultsPanel } from "./components/searchResultsPanel";
|
|||
const DEFAULT_MAX_MATCH_DISPLAY_COUNT = 10000;
|
||||
|
||||
export default function SearchPage() {
|
||||
// We need a suspense boundary here since we are accessing query params
|
||||
// in the top level page.
|
||||
// @see : https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
|
||||
return (
|
||||
<Suspense>
|
||||
<SearchPageInternal />
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
const SearchPageInternal = () => {
|
||||
const router = useRouter();
|
||||
const searchQuery = useNonEmptyQueryParam(SearchQueryParams.query) ?? "";
|
||||
const _maxMatchDisplayCount = parseInt(useNonEmptyQueryParam(SearchQueryParams.maxMatchDisplayCount) ?? `${DEFAULT_MAX_MATCH_DISPLAY_COUNT}`);
|
||||
|
|
|
|||
Loading…
Reference in a new issue