diff --git a/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx b/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx
index a58f00c77e4..d505347d6e3 100644
--- a/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx
+++ b/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx
@@ -1,15 +1,17 @@
-import { Command, Search, Menu } from 'lucide-react'
+import { memo, useState } from 'react'
import dynamic from 'next/dynamic'
import Image from 'next/image'
import Link from 'next/link'
-import type { FC } from 'react'
-import { memo, useState } from 'react'
+import { Command, Search, Menu } from 'lucide-react'
-import { useIsLoggedIn, useIsUserLoading } from 'common'
+import { useIsLoggedIn, useIsUserLoading, useUser } from 'common'
import { Button, buttonVariants, cn } from 'ui'
-import { CommandMenuTrigger } from 'ui-patterns/CommandMenu'
-
+import { AuthenticatedDropdownMenu, CommandMenuTrigger } from 'ui-patterns'
import GlobalNavigationMenu from './GlobalNavigationMenu'
+import useDropdownMenu from './useDropdownMenu'
+
+import type { FC } from 'react'
+
const GlobalMobileMenu = dynamic(() => import('./GlobalMobileMenu'))
const TopNavDropdown = dynamic(() => import('./TopNavDropdown'))
@@ -17,6 +19,8 @@ const TopNavBar: FC = () => {
const isLoggedIn = useIsLoggedIn()
const isUserLoading = useIsUserLoading()
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
+ const user = useUser()
+ const menu = useDropdownMenu(user)
return (
<>
@@ -95,7 +99,11 @@ const TopNavBar: FC = () => {
Dev-only secret sign-in
)}
-
+ {isLoggedIn ? (
+
+ ) : (
+
+ )}
diff --git a/apps/docs/components/Navigation/NavigationMenu/TopNavDropdown.tsx b/apps/docs/components/Navigation/NavigationMenu/TopNavDropdown.tsx
index 5b102255a38..7d7999c63c8 100644
--- a/apps/docs/components/Navigation/NavigationMenu/TopNavDropdown.tsx
+++ b/apps/docs/components/Navigation/NavigationMenu/TopNavDropdown.tsx
@@ -19,7 +19,6 @@ import {
cn,
themes,
} from 'ui'
-
import MenuIconPicker from './MenuIconPicker'
const menu = [
@@ -70,7 +69,7 @@ const TopNavDropdown = () => {
-
+
{menu.map((menuSection, sectionIdx) => (
{sectionIdx !== 0 && }
diff --git a/apps/docs/components/Navigation/NavigationMenu/useDropdownMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/useDropdownMenu.tsx
new file mode 100644
index 00000000000..ab0fb45827e
--- /dev/null
+++ b/apps/docs/components/Navigation/NavigationMenu/useDropdownMenu.tsx
@@ -0,0 +1,80 @@
+'use client'
+
+import type { User } from '@supabase/supabase-js'
+import { LogOut, Globe, LifeBuoy, Settings, UserIcon, Database } from 'lucide-react'
+import { logOut } from 'common'
+
+import type { menuItem } from 'ui-patterns/AuthenticatedDropdownMenu'
+import { IconGitHub } from './MenuIcons'
+
+const useDropdownMenu = (user: User | null) => {
+ const menu: menuItem[][] = [
+ [
+ {
+ label: user?.email ?? "You're logged in",
+ type: 'text',
+ icon: UserIcon,
+ },
+ {
+ label: 'Account Preferences',
+ icon: Settings,
+ href: 'https://supabase.com/dashboard/account/me',
+ },
+ {
+ label: 'All Projects',
+ icon: Database,
+ href: 'https://supabase.com/dashboard/projects',
+ },
+ ],
+ [
+ {
+ label: 'Supabase.com',
+ icon: Globe,
+ href: 'https://supabase.com',
+ otherProps: {
+ target: '_blank',
+ rel: 'noreferrer noopener',
+ },
+ },
+ {
+ label: 'GitHub',
+ icon: IconGitHub as any,
+ href: 'https://github.com/supabase/supabase',
+ otherProps: {
+ target: '_blank',
+ rel: 'noreferrer noopener',
+ },
+ },
+ {
+ label: 'Support',
+ icon: LifeBuoy,
+ href: 'https://supabase.com/support',
+ otherProps: {
+ target: '_blank',
+ rel: 'noreferrer noopener',
+ },
+ },
+ ],
+ [
+ {
+ label: 'Theme',
+ type: 'theme',
+ },
+ ],
+ [
+ {
+ label: 'Logout',
+ type: 'button',
+ icon: LogOut,
+ onClick: async () => {
+ await logOut()
+ window.location.reload()
+ },
+ },
+ ],
+ ]
+
+ return menu
+}
+
+export default useDropdownMenu
diff --git a/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.tsx b/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.tsx
index 41250bcb1dc..565fca8b3f2 100644
--- a/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.tsx
+++ b/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.tsx
@@ -15,7 +15,7 @@ import CopyToClipboard from 'react-copy-to-clipboard'
import { withErrorBoundary } from 'react-error-boundary'
import { proxy, useSnapshot } from 'valtio'
-import { useIsLoggedIn, useIsUserLoading } from 'common'
+import { LOCAL_STORAGE_KEYS, useIsLoggedIn, useIsUserLoading } from 'common'
import { Button_Shadcn_ as Button, Input_Shadcn_ as Input, cn } from 'ui'
import {
@@ -36,7 +36,7 @@ import { useOrganizationsQuery } from '~/lib/fetch/organizations'
import { type SupavisorConfigData, useSupavisorConfigQuery } from '~/lib/fetch/pooler'
import { useProjectApiQuery } from '~/lib/fetch/projectApi'
import { isProjectPaused, type ProjectsData, useProjectsQuery } from '~/lib/fetch/projects'
-import { LOCAL_STORAGE_KEYS, retrieve, storeOrRemoveNull } from '~/lib/storage'
+import { retrieve, storeOrRemoveNull } from '~/lib/storage'
import { useOnLogout } from '~/lib/userAuth'
type ProjectOrgDataState =
diff --git a/apps/docs/features/auth/auth.client.tsx b/apps/docs/features/auth/auth.client.tsx
index 699ff559ce2..2884fc1d2f0 100644
--- a/apps/docs/features/auth/auth.client.tsx
+++ b/apps/docs/features/auth/auth.client.tsx
@@ -1,9 +1,9 @@
'use client'
import { useQueryClient } from '@tanstack/react-query'
-import { AuthProvider } from 'common'
+import { AuthProvider, LOCAL_STORAGE_KEYS } from 'common'
import { type PropsWithChildren, useCallback } from 'react'
-import { LOCAL_STORAGE_KEYS, remove } from '~/lib/storage'
+import { remove } from '~/lib/storage'
import { useOnLogout } from '~/lib/userAuth'
/**
diff --git a/apps/docs/lib/storage.ts b/apps/docs/lib/storage.ts
index ea30f871d92..dcefeb2effe 100644
--- a/apps/docs/lib/storage.ts
+++ b/apps/docs/lib/storage.ts
@@ -1,11 +1,6 @@
-export const LOCAL_STORAGE_KEYS = {
- SAVED_ORG: 'docs.ui.user.selected.org',
- SAVED_PROJECT: 'docs.ui.user.selected.project',
- SAVED_BRANCH: 'docs.ui.user.selected.branch',
-} as const
+import { LOCAL_STORAGE_KEYS } from 'common'
type LocalStorageKey = (typeof LOCAL_STORAGE_KEYS)[keyof typeof LOCAL_STORAGE_KEYS]
-
type StorageType = 'local' | 'session'
function getStorage(storageType: StorageType) {
@@ -17,7 +12,7 @@ export function store(storageType: StorageType, key: LocalStorageKey, value: str
const storage = getStorage(storageType)
try {
- storage.setItem(key, value)
+ storage.setItem(key as string, value)
} catch {
console.error(`Failed to set storage item with key "${key}"`)
}
@@ -26,13 +21,13 @@ export function store(storageType: StorageType, key: LocalStorageKey, value: str
export function retrieve(storageType: StorageType, key: LocalStorageKey) {
if (typeof window === 'undefined') return
const storage = getStorage(storageType)
- return storage.getItem(key)
+ return storage.getItem(key as string)
}
export function remove(storageType: StorageType, key: LocalStorageKey) {
if (typeof window === 'undefined') return
const storage = getStorage(storageType)
- return storage.removeItem(key)
+ return storage.removeItem(key as string)
}
export function storeOrRemoveNull(
diff --git a/apps/studio/components/interfaces/Account/Preferences/DeleteAccountButton.tsx b/apps/studio/components/interfaces/Account/Preferences/DeleteAccountButton.tsx
index 23caa8ab8ac..91306f2d191 100644
--- a/apps/studio/components/interfaces/Account/Preferences/DeleteAccountButton.tsx
+++ b/apps/studio/components/interfaces/Account/Preferences/DeleteAccountButton.tsx
@@ -1,6 +1,5 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { SupportCategories } from '@supabase/shared-types/out/constants'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
@@ -27,6 +26,7 @@ import {
Input_Shadcn_,
Separator,
} from 'ui'
+import { LOCAL_STORAGE_KEYS } from 'common'
const setDeletionRequestFlag = () => {
const expiryDate = new Date()
diff --git a/apps/studio/components/interfaces/Account/Preferences/ThemeSettings.tsx b/apps/studio/components/interfaces/Account/Preferences/ThemeSettings.tsx
index b05c8c5cf28..762a1b6c67d 100644
--- a/apps/studio/components/interfaces/Account/Preferences/ThemeSettings.tsx
+++ b/apps/studio/components/interfaces/Account/Preferences/ThemeSettings.tsx
@@ -5,7 +5,7 @@ import SVG from 'react-inlinesvg'
import { DEFAULT_SIDEBAR_BEHAVIOR } from 'components/interfaces/Sidebar'
import Panel from 'components/ui/Panel'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { BASE_PATH, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { BASE_PATH } from 'lib/constants'
import {
Label_Shadcn_,
RadioGroup_Shadcn_,
@@ -20,6 +20,7 @@ import {
Theme,
} from 'ui'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
+import { LOCAL_STORAGE_KEYS } from 'common'
export const ThemeSettings = () => {
const [mounted, setMounted] = useState(false)
diff --git a/apps/studio/components/interfaces/App/AppBannerWrapperContext.tsx b/apps/studio/components/interfaces/App/AppBannerWrapperContext.tsx
index c6d4e302322..9ccbbf6fbb0 100644
--- a/apps/studio/components/interfaces/App/AppBannerWrapperContext.tsx
+++ b/apps/studio/components/interfaces/App/AppBannerWrapperContext.tsx
@@ -1,8 +1,7 @@
+import { LOCAL_STORAGE_KEYS } from 'common'
import { noop } from 'lodash'
import { PropsWithChildren, createContext, useContext, useEffect, useState } from 'react'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
-
const FLY_POSTGRES_DEPRECATION_WARNING_KEY = LOCAL_STORAGE_KEYS.FLY_POSTGRES_DEPRECATION_WARNING
// [Joshen] This file is meant to be dynamic - update this as and when we need to use the NoticeBanner
diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx
index d4d4b770dfa..35c3c6eca40 100644
--- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx
+++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx
@@ -1,8 +1,7 @@
import { noop } from 'lodash'
-
import { FeatureFlagContext } from 'common'
import { useFlag } from 'hooks/ui/useFlag'
-import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { IS_PLATFORM } from 'lib/constants'
import { EMPTY_OBJ } from 'lib/void'
import { PropsWithChildren, createContext, useContext, useEffect, useState } from 'react'
import { APISidePanelPreview } from './APISidePanelPreview'
@@ -11,6 +10,7 @@ import { InlineEditorPreview } from './InlineEditorPreview'
import { LayoutUpdatePreview } from './LayoutUpdatePreview'
import { SqlEditorTabsPreview } from './SqlEditorTabs'
import { TableEditorTabsPreview } from './TableEditorTabs'
+import { LOCAL_STORAGE_KEYS } from 'common'
export const FEATURE_PREVIEWS = [
{
diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx
index 5f78dde3e6b..b77e797f3d0 100644
--- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx
+++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx
@@ -2,10 +2,11 @@ import { ExternalLink, Eye, EyeOff, FlaskConical } from 'lucide-react'
import Link from 'next/link'
import { useEffect } from 'react'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
-import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { useFlag } from 'hooks/ui/useFlag'
+import { IS_PLATFORM } from 'lib/constants'
import { useAppStateSnapshot } from 'state/app-state'
import { removeTabsByEditor } from 'state/tabs'
import { Badge, Button, Modal, ScrollArea, cn } from 'ui'
diff --git a/apps/studio/components/interfaces/App/FeaturePreview/LayoutUpdatePreview.tsx b/apps/studio/components/interfaces/App/FeaturePreview/LayoutUpdatePreview.tsx
index be462dde866..643c3c0ab1c 100644
--- a/apps/studio/components/interfaces/App/FeaturePreview/LayoutUpdatePreview.tsx
+++ b/apps/studio/components/interfaces/App/FeaturePreview/LayoutUpdatePreview.tsx
@@ -1,10 +1,11 @@
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { BASE_PATH, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { BASE_PATH } from 'lib/constants'
import { ExternalLink, X } from 'lucide-react'
import Image from 'next/image'
import { Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_, Badge, Button } from 'ui'
import { useIsNewLayoutEnabled } from './FeaturePreviewContext'
+import { LOCAL_STORAGE_KEYS } from 'common'
export const LayoutUpdatePreview = () => {
return (
diff --git a/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx b/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx
index ef14cacedce..00b47042edd 100644
--- a/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx
+++ b/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx
@@ -2,13 +2,13 @@ import { useRouter } from 'next/router'
import { PropsWithChildren, useEffect } from 'react'
import { toast } from 'sonner'
-import { useIsLoggedIn, useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useIsLoggedIn, useParams } from 'common'
import { useOrganizationsQuery } from 'data/organizations/organizations-query'
import { useProjectsQuery } from 'data/projects/projects-query'
import useLatest from 'hooks/misc/useLatest'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
-import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { IS_PLATFORM } from 'lib/constants'
import { useAppStateSnapshot } from 'state/app-state'
import { useIsNewLayoutEnabled } from './FeaturePreview/FeaturePreviewContext'
diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyEditorModal/index.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyEditorModal/index.tsx
index 2d639a4649b..cbb8fea06b1 100644
--- a/apps/studio/components/interfaces/Auth/Policies/PolicyEditorModal/index.tsx
+++ b/apps/studio/components/interfaces/Auth/Policies/PolicyEditorModal/index.tsx
@@ -2,7 +2,6 @@ import { isEmpty, noop } from 'lodash'
import { useEffect, useState } from 'react'
import { toast } from 'sonner'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { useAppStateSnapshot } from 'state/app-state'
import { Modal } from 'ui'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
diff --git a/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx b/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx
index be368dbd2bc..cf79c68398a 100644
--- a/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx
+++ b/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx
@@ -5,7 +5,7 @@ import { UIEvent, useEffect, useMemo, useRef, useState } from 'react'
import DataGrid, { Column, DataGridHandle, Row } from 'react-data-grid'
import { toast } from 'sonner'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import AlertError from 'components/ui/AlertError'
@@ -18,7 +18,6 @@ import { useUserDeleteMutation } from 'data/auth/user-delete-mutation'
import { useUsersCountQuery } from 'data/auth/users-count-query'
import { User, useUsersInfiniteQuery } from 'data/auth/users-infinite-query'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import {
Button,
cn,
diff --git a/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx b/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx
index b32682ab37d..6a8dc557694 100644
--- a/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx
+++ b/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx
@@ -6,7 +6,7 @@ import { useEffect, useMemo, useState } from 'react'
import ReactFlow, { Background, BackgroundVariant, MiniMap, useReactFlow } from 'reactflow'
import 'reactflow/dist/style.css'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState'
import AlertError from 'components/ui/AlertError'
@@ -16,7 +16,6 @@ import { useSchemasQuery } from 'data/database/schemas-query'
import { useTablesQuery } from 'data/tables/tables-query'
import { useLocalStorage } from 'hooks/misc/useLocalStorage'
import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { toast } from 'sonner'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from 'ui'
import { SchemaGraphLegend } from './SchemaGraphLegend'
diff --git a/apps/studio/components/interfaces/Database/Schemas/Schemas.utils.ts b/apps/studio/components/interfaces/Database/Schemas/Schemas.utils.ts
index 89d02f304ea..2a3aaaa2828 100644
--- a/apps/studio/components/interfaces/Database/Schemas/Schemas.utils.ts
+++ b/apps/studio/components/interfaces/Database/Schemas/Schemas.utils.ts
@@ -4,9 +4,9 @@ import { uniqBy } from 'lodash'
import { Edge, Node, Position } from 'reactflow'
import 'reactflow/dist/style.css'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { tryParseJson } from 'lib/helpers'
import { TABLE_NODE_ROW_HEIGHT, TABLE_NODE_WIDTH, TableNodeData } from './SchemaTableNode'
+import { LOCAL_STORAGE_KEYS } from 'common'
const NODE_SEP = 25
const RANK_SEP = 50
diff --git a/apps/studio/components/interfaces/GraphQL/GraphiQL.tsx b/apps/studio/components/interfaces/GraphQL/GraphiQL.tsx
index 53a527e0d0c..82f5714e963 100644
--- a/apps/studio/components/interfaces/GraphQL/GraphiQL.tsx
+++ b/apps/studio/components/interfaces/GraphQL/GraphiQL.tsx
@@ -37,10 +37,10 @@ import { MouseEventHandler, useCallback, useEffect, useState } from 'react'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useLocalStorage } from 'hooks/misc/useLocalStorage'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button, cn } from 'ui'
import { RoleImpersonationSelector } from '../RoleImpersonationSelector'
import styles from './graphiql.module.css'
+import { LOCAL_STORAGE_KEYS } from 'common'
export interface GraphiQLProps {
fetcher: Fetcher
diff --git a/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx b/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx
index 923e57e8a0e..75cc9e9c0a2 100644
--- a/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx
+++ b/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx
@@ -3,12 +3,12 @@ import { useRouter } from 'next/router'
import { useState } from 'react'
import { toast } from 'sonner'
+import { LOCAL_STORAGE_KEYS } from 'common'
import { useIsNewLayoutEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { useOrganizationDeleteMutation } from 'data/organizations/organization-delete-mutation'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { Button, Form, Input, Modal } from 'ui'
const DeleteOrganizationButton = () => {
diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx
index 4426b4af278..ce93229c347 100644
--- a/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx
+++ b/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx
@@ -3,7 +3,7 @@ import { useRouter } from 'next/router'
import { useState } from 'react'
import { toast } from 'sonner'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { useIsNewLayoutEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import {
ScaffoldActionsContainer,
@@ -22,7 +22,6 @@ import { usePermissionsQuery } from 'data/permissions/permissions-query'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { useProfile } from 'lib/profile'
import { Input } from 'ui-patterns/DataInputs/Input'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
diff --git a/apps/studio/components/interfaces/QueryPerformance/QueryPerformance.tsx b/apps/studio/components/interfaces/QueryPerformance/QueryPerformance.tsx
index 585b5b9d3b0..0dbe8fdd746 100644
--- a/apps/studio/components/interfaces/QueryPerformance/QueryPerformance.tsx
+++ b/apps/studio/components/interfaces/QueryPerformance/QueryPerformance.tsx
@@ -4,14 +4,14 @@ import { useRouter } from 'next/router'
import { useEffect, useMemo, useState } from 'react'
import { toast } from 'sonner'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import { useReadReplicasQuery } from 'data/read-replicas/replicas-query'
import { formatDatabaseID } from 'data/read-replicas/replicas.utils'
import { executeSql } from 'data/sql/execute-sql-query'
import { DbQueryHook } from 'hooks/analytics/useDbQuery'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { IS_PLATFORM } from 'lib/constants'
import { useDatabaseSelectorStateSnapshot } from 'state/database-selector'
import {
Button,
diff --git a/apps/studio/components/interfaces/QueryPerformance/QueryPerformanceFilterBar.tsx b/apps/studio/components/interfaces/QueryPerformance/QueryPerformanceFilterBar.tsx
index f346b74cfc7..2e4b546c7be 100644
--- a/apps/studio/components/interfaces/QueryPerformance/QueryPerformanceFilterBar.tsx
+++ b/apps/studio/components/interfaces/QueryPerformance/QueryPerformanceFilterBar.tsx
@@ -2,14 +2,13 @@ import { ArrowDown, ArrowUp, RefreshCw } from 'lucide-react'
import { useRouter } from 'next/router'
import { useState } from 'react'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import { DownloadResultsButton } from 'components/ui/DownloadResultsButton'
import { FilterPopover } from 'components/ui/FilterPopover'
import { useDatabaseRolesQuery } from 'data/database-roles/database-roles-query'
import { DbQueryHook } from 'hooks/analytics/useDbQuery'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import {
Button,
DropdownMenu,
diff --git a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx
index 538a75b6c2a..4306d01e034 100644
--- a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx
+++ b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx
@@ -3,10 +3,9 @@ import { debounce } from 'lodash'
import { useRouter } from 'next/router'
import { MutableRefObject, useEffect, useRef } from 'react'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useSelectedProject } from 'hooks/misc/useSelectedProject'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { useProfile } from 'lib/profile'
import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state'
import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2'
diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx
index d4577ae1a8f..bcb691d950d 100644
--- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx
+++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx
@@ -8,7 +8,7 @@ import { useRouter } from 'next/router'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { toast } from 'sonner'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import ResizableAIWidget from 'components/ui/AIEditor/ResizableAIWidget'
import { GridFooter } from 'components/ui/GridFooter'
import { useSqlTitleGenerateMutation } from 'data/ai/sql-title-mutation'
@@ -24,7 +24,7 @@ import { useOrgOptedIntoAi } from 'hooks/misc/useOrgOptedIntoAi'
import { useSchemasForAi } from 'hooks/misc/useSchemasForAi'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProject } from 'hooks/misc/useSelectedProject'
-import { BASE_PATH, IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { BASE_PATH, IS_PLATFORM } from 'lib/constants'
import { formatSql } from 'lib/formatSql'
import { detectOS, uuidv4 } from 'lib/helpers'
import { useProfile } from 'lib/profile'
diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/ChartConfig.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/ChartConfig.tsx
index 87d93bbd938..ff1a708ccb1 100644
--- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/ChartConfig.tsx
+++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/ChartConfig.tsx
@@ -2,13 +2,12 @@ import dayjs from 'dayjs'
import { ArrowUpDown, X } from 'lucide-react'
import { useMemo } from 'react'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import BarChart from 'components/ui/Charts/BarChart'
import NoDataPlaceholder from 'components/ui/Charts/NoDataPlaceholder'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useFlag } from 'hooks/ui/useFlag'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import Link from 'next/link'
import {
Badge,
diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx
index be65aa24e69..2767756c532 100644
--- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx
+++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx
@@ -1,11 +1,11 @@
import { AlignLeft, Check, Heart, Keyboard, MoreVertical } from 'lucide-react'
import { toast } from 'sonner'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { RoleImpersonationPopover } from 'components/interfaces/RoleImpersonationSelector'
import DatabaseSelector from 'components/ui/DatabaseSelector'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { IS_PLATFORM } from 'lib/constants'
import { detectOS } from 'lib/helpers'
import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2'
import {
diff --git a/apps/studio/components/interfaces/SQLEditor/useAddDefinitions.ts b/apps/studio/components/interfaces/SQLEditor/useAddDefinitions.ts
index 28293fcd2fc..a3f770213eb 100644
--- a/apps/studio/components/interfaces/SQLEditor/useAddDefinitions.ts
+++ b/apps/studio/components/interfaces/SQLEditor/useAddDefinitions.ts
@@ -1,4 +1,5 @@
import { Monaco } from '@monaco-editor/react'
+import { LOCAL_STORAGE_KEYS } from 'common'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import getPgsqlCompletionProvider from 'components/ui/CodeEditor/Providers/PgSQLCompletionProvider'
import getPgsqlSignatureHelpProvider from 'components/ui/CodeEditor/Providers/PgSQLSignatureHelpProvider'
@@ -7,7 +8,6 @@ import { useKeywordsQuery } from 'data/database/keywords-query'
import { useSchemasQuery } from 'data/database/schemas-query'
import { useTableColumnsQuery } from 'data/database/table-columns-query'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { formatSql } from 'lib/formatSql'
import { IDisposable } from 'monaco-editor'
import { useEffect, useRef } from 'react'
diff --git a/apps/studio/components/interfaces/Sidebar.tsx b/apps/studio/components/interfaces/Sidebar.tsx
index 2e16dd04f4b..3a03f2d54b2 100644
--- a/apps/studio/components/interfaces/Sidebar.tsx
+++ b/apps/studio/components/interfaces/Sidebar.tsx
@@ -14,7 +14,7 @@ import Link from 'next/link'
import { useRouter } from 'next/router'
import { ComponentProps, ComponentPropsWithoutRef, FC, ReactNode, useEffect } from 'react'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import {
generateOtherRoutes,
generateProductRoutes,
@@ -30,7 +30,6 @@ import { useLints } from 'hooks/misc/useLints'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useFlag } from 'hooks/ui/useFlag'
import { Home } from 'icons'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { useAppStateSnapshot } from 'state/app-state'
import {
Button,
diff --git a/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx b/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx
index 29c32fd75b5..926eb4b256f 100644
--- a/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx
+++ b/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx
@@ -7,7 +7,8 @@ import { PropsWithChildren, useEffect } from 'react'
import { useIsNewLayoutEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { withAuth } from 'hooks/misc/withAuth'
-import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { IS_PLATFORM } from 'lib/constants'
+import { LOCAL_STORAGE_KEYS } from 'common'
import { useAppStateSnapshot } from 'state/app-state'
import { cn, NavMenu, NavMenuItem } from 'ui'
import {
diff --git a/apps/studio/components/layouts/LogsLayout/LogsLayout.tsx b/apps/studio/components/layouts/LogsLayout/LogsLayout.tsx
index 3a0d3769c6e..5c9c0d7ece7 100644
--- a/apps/studio/components/layouts/LogsLayout/LogsLayout.tsx
+++ b/apps/studio/components/layouts/LogsLayout/LogsLayout.tsx
@@ -6,9 +6,9 @@ import NoPermission from 'components/ui/NoPermission'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { withAuth } from 'hooks/misc/withAuth'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import ProjectLayout from '../ProjectLayout/ProjectLayout'
import { LogsSidebarMenuV2 } from './LogsSidebarMenuV2'
+import { LOCAL_STORAGE_KEYS } from 'common'
interface LogsLayoutProps {
title?: string
diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HomeIcon.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HomeIcon.tsx
index 84e82a0990b..573f2a8ccdf 100644
--- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HomeIcon.tsx
+++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HomeIcon.tsx
@@ -7,7 +7,8 @@ import { useOrganizationsQuery } from 'data/organizations/organizations-query'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { useShowLayoutHeader } from 'hooks/misc/useShowLayoutHeader'
-import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { IS_PLATFORM } from 'lib/constants'
+import { LOCAL_STORAGE_KEYS } from 'common'
export const HomeIcon = () => {
const newLayoutPreview = useIsNewLayoutEnabled()
diff --git a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationIconLink.tsx b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationIconLink.tsx
index 960bdf7e5eb..4316d1eb983 100644
--- a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationIconLink.tsx
+++ b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationIconLink.tsx
@@ -11,7 +11,7 @@ import { cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import type { Route } from 'components/ui/ui.types'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { LOCAL_STORAGE_KEYS } from 'common'
interface NavigationIconButtonProps extends AnchorHTMLAttributes {
route: Route
diff --git a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx
index 15b3be04104..dee5d5669c1 100644
--- a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx
+++ b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx
@@ -1,15 +1,14 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useDebounce } from '@uidotdev/usehooks'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { FilePlus, FolderPlus, Plus, X } from 'lucide-react'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { toast } from 'sonner'
-import { useParams } from 'common'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useLocalStorage } from 'hooks/misc/useLocalStorage'
import { useSelectedProject } from 'hooks/misc/useSelectedProject'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { useProfile } from 'lib/profile'
import { getAppStateSnapshot } from 'state/app-state'
import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2'
diff --git a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.tsx b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.tsx
index cb26ba3cd0c..5f3f340550d 100644
--- a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.tsx
+++ b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.tsx
@@ -1,4 +1,4 @@
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { useIsSQLEditorTabsEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import DownloadSnippetModal from 'components/interfaces/SQLEditor/DownloadSnippetModal'
import { MoveQueryModal } from 'components/interfaces/SQLEditor/MoveQueryModal'
@@ -17,7 +17,6 @@ import { Snippet, SnippetFolder, useSQLSnippetFoldersQuery } from 'data/content/
import { useSqlSnippetsQuery } from 'data/content/sql-snippets-query'
import { useLocalStorage } from 'hooks/misc/useLocalStorage'
import { useSelectedProject } from 'hooks/misc/useSelectedProject'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { useProfile } from 'lib/profile'
import uuidv4 from 'lib/uuid'
import { Eye, EyeOffIcon, Heart, Unlock } from 'lucide-react'
diff --git a/apps/studio/components/layouts/project/[ref]/settings/APIKeysLayout.tsx b/apps/studio/components/layouts/project/[ref]/settings/APIKeysLayout.tsx
index 629b34f6fa9..f813d15b207 100644
--- a/apps/studio/components/layouts/project/[ref]/settings/APIKeysLayout.tsx
+++ b/apps/studio/components/layouts/project/[ref]/settings/APIKeysLayout.tsx
@@ -16,8 +16,7 @@ import {
TabsTrigger_Shadcn_,
} from 'ui'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
const ApiKeysLayout = ({ children }: PropsWithChildren) => {
const { ref: projectRef } = useParams()
diff --git a/apps/studio/components/ui/GroupsTelemetry.tsx b/apps/studio/components/ui/GroupsTelemetry.tsx
index f76ff65466e..1c05ec91cb5 100644
--- a/apps/studio/components/ui/GroupsTelemetry.tsx
+++ b/apps/studio/components/ui/GroupsTelemetry.tsx
@@ -3,12 +3,13 @@ import * as Sentry from '@sentry/nextjs'
import { useRouter } from 'next/router'
import { useEffect } from 'react'
-import { useParams, useTelemetryCookie, useUser } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams, useTelemetryCookie, useUser } from 'common'
import { useSendGroupsIdentifyMutation } from 'data/telemetry/send-groups-identify-mutation'
import { useSendGroupsResetMutation } from 'data/telemetry/send-groups-reset-mutation'
import { usePrevious } from 'hooks/deprecated'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
-import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { useAppStateSnapshot } from 'state/app-state'
+import { IS_PLATFORM } from 'lib/constants'
const getAnonId = async (id: string) => {
const encoder = new TextEncoder()
diff --git a/apps/studio/data/integrations/github-authorization-create-mutation.ts b/apps/studio/data/integrations/github-authorization-create-mutation.ts
index 9c344ddbfe7..a9f69142bbc 100644
--- a/apps/studio/data/integrations/github-authorization-create-mutation.ts
+++ b/apps/studio/data/integrations/github-authorization-create-mutation.ts
@@ -3,7 +3,7 @@ import { toast } from 'sonner'
import { handleError, post } from 'data/fetchers'
import type { ResponseError } from 'types'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { LOCAL_STORAGE_KEYS } from 'common'
export type GitHubAuthorizationCreateVariables = {
code: string
diff --git a/apps/studio/hooks/misc/useLastSignIn.ts b/apps/studio/hooks/misc/useLastSignIn.ts
index ad860ebe748..e71f7cb8262 100644
--- a/apps/studio/hooks/misc/useLastSignIn.ts
+++ b/apps/studio/hooks/misc/useLastSignIn.ts
@@ -1,4 +1,4 @@
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { LOCAL_STORAGE_KEYS } from 'common'
import { useLocalStorage } from './useLocalStorage'
export type LastSignInType = 'github' | 'email' | 'sso' | null
diff --git a/apps/studio/hooks/misc/useSchemaQueryState.ts b/apps/studio/hooks/misc/useSchemaQueryState.ts
index b0e183c6bd2..f981ac44951 100644
--- a/apps/studio/hooks/misc/useSchemaQueryState.ts
+++ b/apps/studio/hooks/misc/useSchemaQueryState.ts
@@ -1,8 +1,7 @@
import { parseAsString, useQueryState } from 'nuqs'
import { useEffect, useMemo } from 'react'
-import { useParams } from 'common'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
/**
* This hook wraps useQueryState because useQueryState imports app router for some reason which breaks the SSR in
diff --git a/apps/studio/hooks/misc/useSchemasForAi.ts b/apps/studio/hooks/misc/useSchemasForAi.ts
index ccdebb4e268..5f32ccea672 100644
--- a/apps/studio/hooks/misc/useSchemasForAi.ts
+++ b/apps/studio/hooks/misc/useSchemasForAi.ts
@@ -1,5 +1,5 @@
+import { LOCAL_STORAGE_KEYS } from 'common'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { Dispatch, SetStateAction } from 'react'
/**
diff --git a/apps/studio/lib/auth.tsx b/apps/studio/lib/auth.tsx
index e943b89c5ef..e2ef0cdca9f 100644
--- a/apps/studio/lib/auth.tsx
+++ b/apps/studio/lib/auth.tsx
@@ -1,10 +1,9 @@
import { useQueryClient } from '@tanstack/react-query'
-import { AuthProvider as AuthProviderInternal, gotrueClient } from 'common'
+import { AuthProvider as AuthProviderInternal, clearLocalStorage, gotrueClient } from 'common'
import { PropsWithChildren, useCallback, useEffect } from 'react'
import { toast } from 'sonner'
import { GOTRUE_ERRORS, IS_PLATFORM } from './constants'
-import { clearLocalStorage } from './local-storage'
export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
// Check for unverified GitHub users after a GitHub sign in
diff --git a/apps/studio/lib/constants/index.ts b/apps/studio/lib/constants/index.ts
index 942be406eb5..81e9970dc2c 100644
--- a/apps/studio/lib/constants/index.ts
+++ b/apps/studio/lib/constants/index.ts
@@ -38,65 +38,6 @@ export const STRIPE_PUBLIC_KEY =
export const USAGE_APPROACHING_THRESHOLD = 0.75
-export const LOCAL_STORAGE_KEYS = {
- AI_ASSISTANT_STATE: (projectRef: string | undefined) =>
- `supabase-ai-assistant-state-${projectRef}`,
- SIDEBAR_BEHAVIOR: 'supabase-sidebar-behavior',
- EDITOR_PANEL_STATE: 'supabase-editor-panel-state',
-
- UI_PREVIEW_API_SIDE_PANEL: 'supabase-ui-api-side-panel',
- UI_PREVIEW_CLS: 'supabase-ui-cls',
- UI_PREVIEW_INLINE_EDITOR: 'supabase-ui-preview-inline-editor',
- UI_ONBOARDING_NEW_PAGE_SHOWN: 'supabase-ui-onboarding-new-page-shown',
- UI_TABLE_EDITOR_TABS: 'supabase-ui-table-editor-tabs',
- UI_SQL_EDITOR_TABS: 'supabase-ui-sql-editor-tabs',
- UI_NEW_LAYOUT_PREVIEW: 'supabase-ui-new-layout-preview',
- NEW_LAYOUT_NOTICE_ACKNOWLEDGED: 'new-layout-notice-acknowledge',
-
- DASHBOARD_HISTORY: (ref: string) => `dashboard-history-${ref}`,
- STORAGE_PREFERENCE: (ref: string) => `storage-explorer-${ref}`,
-
- SQL_EDITOR_INTELLISENSE: 'supabase_sql-editor-intellisense-enabled',
- SQL_EDITOR_SPLIT_SIZE: 'supabase_sql-editor-split-size',
- // Key to track which schemas are ok to be sent to AI. The project ref is intentionally put at the end for easier search in the browser console.
- SQL_EDITOR_AI_SCHEMA: (ref: string) => `supabase_sql-editor-ai-schema-enabled-${ref}`,
- SQL_EDITOR_AI_OPEN: 'supabase_sql-editor-ai-open',
- SQL_EDITOR_LAST_SELECTED_DB: (ref: string) => `sql-editor-last-selected-db-${ref}`,
- SQL_EDITOR_SQL_BLOCK_ACKNOWLEDGED: (ref: string) => `sql-editor-sql-block-acknowledged-${ref}`,
- SQL_EDITOR_SECTION_STATE: (ref: string) => `sql-editor-section-state-${ref}`,
- SQL_EDITOR_SORT: (ref: string) => `sql-editor-sort-${ref}`,
-
- LOG_EXPLORER_SPLIT_SIZE: 'supabase_log-explorer-split-size',
- GRAPHIQL_RLS_BYPASS_WARNING: 'graphiql-rls-bypass-warning-dismissed',
- CLS_DIFF_WARNING: 'cls-diff-warning-dismissed',
- CLS_SELECT_STAR_WARNING: 'cls-select-star-warning-dismissed',
- QUERY_PERF_SHOW_BOTTOM_SECTION: 'supabase-query-perf-show-bottom-section',
- // Key to track account deletion requests
- ACCOUNT_DELETION_REQUEST: 'supabase-account-deletion-request',
- // Used for storing a user id when sending reports to Sentry. The id is hashed for anonymity.
- SENTRY_USER_ID: 'supabase-sentry-user-id',
- // Used for storing the last sign in method used by the user
- LAST_SIGN_IN_METHOD: 'supabase-last-sign-in-method',
- // Key to track the last selected schema. The project ref is intentionally put at the end for easier search in the browser console.
- LAST_SELECTED_SCHEMA: (ref: string) => `last-selected-schema-${ref}`,
- // Track position of nodes for schema visualizer
- SCHEMA_VISUALIZER_POSITIONS: (ref: string, schemaId: number) =>
- `schema-visualizer-positions-${ref}-${schemaId}`,
- // Used for allowing the main nav panel to expand on hover
- EXPAND_NAVIGATION_PANEL: 'supabase-expand-navigation-panel',
- GITHUB_AUTHORIZATION_STATE: 'supabase-github-authorization-state',
- // Notice banner keys
- FLY_POSTGRES_DEPRECATION_WARNING: 'fly-postgres-deprecation-warning-dismissed',
- AUTH_USERS_COLUMNS_CONFIGURATION: (ref: string) => `supabase-auth-users-columns-${ref}`,
-
- // api keys view switcher for new and legacy api keys
- API_KEYS_VIEW: (ref: string) => `supabase-api-keys-view-${ref}`,
-
- // last visited logs page
- LAST_VISITED_LOGS_PAGE: 'supabase-last-visited-logs-page',
- LAST_VISITED_ORGANIZATION: 'last-visited-organization',
-}
-
export const OPT_IN_TAGS = {
AI_SQL: 'AI_SQL_GENERATOR_OPT_IN',
}
diff --git a/apps/studio/lib/github.tsx b/apps/studio/lib/github.tsx
index 275ac6d743e..5d96032ef12 100644
--- a/apps/studio/lib/github.tsx
+++ b/apps/studio/lib/github.tsx
@@ -1,4 +1,4 @@
-import { LOCAL_STORAGE_KEYS } from './constants'
+import { LOCAL_STORAGE_KEYS } from 'common'
import { makeRandomString } from './helpers'
const GITHUB_INTEGRATION_APP_NAME =
diff --git a/apps/studio/lib/local-storage.ts b/apps/studio/lib/local-storage.ts
deleted file mode 100644
index a4e3420d9b4..00000000000
--- a/apps/studio/lib/local-storage.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { LOCAL_STORAGE_KEYS as COMMON_LOCAL_STORAGE_KEYS } from 'common'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
-
-const LOCAL_STORAGE_KEYS_ALLOWLIST = [
- 'graphiql:theme',
- 'theme',
- 'supabaseDarkMode',
- 'supabase.dashboard.auth.debug',
- 'supabase.dashboard.auth.navigatorLock.disabled',
- COMMON_LOCAL_STORAGE_KEYS.TELEMETRY_CONSENT,
- LOCAL_STORAGE_KEYS.UI_PREVIEW_API_SIDE_PANEL,
- LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR,
- LOCAL_STORAGE_KEYS.UI_TABLE_EDITOR_TABS,
- LOCAL_STORAGE_KEYS.UI_SQL_EDITOR_TABS,
- LOCAL_STORAGE_KEYS.UI_NEW_LAYOUT_PREVIEW,
- LOCAL_STORAGE_KEYS.UI_PREVIEW_INLINE_EDITOR,
- LOCAL_STORAGE_KEYS.UI_PREVIEW_CLS,
- LOCAL_STORAGE_KEYS.LAST_SIGN_IN_METHOD,
-]
-
-export function clearLocalStorage() {
- for (const key in localStorage) {
- if (!LOCAL_STORAGE_KEYS_ALLOWLIST.includes(key)) {
- localStorage.removeItem(key)
- }
- }
-}
diff --git a/apps/studio/lib/posthog.ts b/apps/studio/lib/posthog.ts
index 96735b0b77f..347040a6af9 100644
--- a/apps/studio/lib/posthog.ts
+++ b/apps/studio/lib/posthog.ts
@@ -1,7 +1,7 @@
import { components } from 'api-types'
-import { hasConsented } from 'common'
import { handleError, post } from 'data/fetchers'
import { IS_PLATFORM } from './constants'
+import { LOCAL_STORAGE_KEYS, hasConsented } from 'common'
type TrackFeatureFlagVariables = components['schemas']['TelemetryFeatureFlagBodyDto']
diff --git a/apps/studio/localStores/storageExplorer/StorageExplorerStore.tsx b/apps/studio/localStores/storageExplorer/StorageExplorerStore.tsx
index 63fb40418ea..82db7df68a5 100644
--- a/apps/studio/localStores/storageExplorer/StorageExplorerStore.tsx
+++ b/apps/studio/localStores/storageExplorer/StorageExplorerStore.tsx
@@ -42,11 +42,12 @@ import { downloadBucketObject } from 'data/storage/bucket-object-download-mutati
import { StorageObject, listBucketObjects } from 'data/storage/bucket-objects-list-mutation'
import { Bucket } from 'data/storage/buckets-query'
import { moveStorageObject } from 'data/storage/object-move-mutation'
-import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { IS_PLATFORM } from 'lib/constants'
import { tryParseJson } from 'lib/helpers'
import { lookupMime } from 'lib/mime'
import Link from 'next/link'
import { Button, SONNER_DEFAULT_DURATION, SonnerProgress } from 'ui'
+import { LOCAL_STORAGE_KEYS } from 'common'
type CachedFile = { id: string; fetchedAt: number; expiresIn: number; url: string }
diff --git a/apps/studio/pages/project/[ref]/database/column-privileges.tsx b/apps/studio/pages/project/[ref]/database/column-privileges.tsx
index 0409e6a391a..3a632285c63 100644
--- a/apps/studio/pages/project/[ref]/database/column-privileges.tsx
+++ b/apps/studio/pages/project/[ref]/database/column-privileges.tsx
@@ -1,4 +1,4 @@
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { AlertCircle, XIcon } from 'lucide-react'
import Link from 'next/link'
import { useCallback, useMemo, useState } from 'react'
@@ -27,7 +27,6 @@ import { useTablePrivilegesQuery } from 'data/privileges/table-privileges-query'
import { useTablesQuery } from 'data/tables/tables-query'
import { useLocalStorage } from 'hooks/misc/useLocalStorage'
import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { PROTECTED_SCHEMAS } from 'lib/constants/schemas'
import { useAppStateSnapshot } from 'state/app-state'
import type { NextPageWithLayout } from 'types'
diff --git a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx
index 2d9cd94cdca..c7c5a23f57b 100644
--- a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx
+++ b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx
@@ -6,7 +6,8 @@ import { useRouter } from 'next/router'
import { useEffect, useRef, useState } from 'react'
import { toast } from 'sonner'
-import { IS_PLATFORM, useParams } from 'common'
+import { IS_PLATFORM, LOCAL_STORAGE_KEYS, useParams } from 'common'
+
import {
LOGS_LARGE_DATE_RANGE_DAYS_THRESHOLD,
LOGS_TABLES,
@@ -41,7 +42,6 @@ import useLogsQuery from 'hooks/analytics/useLogsQuery'
import { useLogsUrlState } from 'hooks/analytics/useLogsUrlState'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { useUpgradePrompt } from 'hooks/misc/useUpgradePrompt'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { uuidv4 } from 'lib/helpers'
import { useProfile } from 'lib/profile'
import type { LogSqlSnippets, NextPageWithLayout } from 'types'
diff --git a/apps/studio/pages/project/[ref]/logs/index.tsx b/apps/studio/pages/project/[ref]/logs/index.tsx
index cfb40aea392..1276db2782f 100644
--- a/apps/studio/pages/project/[ref]/logs/index.tsx
+++ b/apps/studio/pages/project/[ref]/logs/index.tsx
@@ -1,11 +1,10 @@
import { useRouter } from 'next/router'
import { useEffect } from 'react'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import DefaultLayout from 'components/layouts/DefaultLayout'
import LogsLayout from 'components/layouts/LogsLayout/LogsLayout'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import type { NextPageWithLayout } from 'types'
export const LogPage: NextPageWithLayout = () => {
diff --git a/apps/studio/pages/project/[ref]/settings/api-keys.tsx b/apps/studio/pages/project/[ref]/settings/api-keys.tsx
index 4183084380e..8eb1be93ded 100644
--- a/apps/studio/pages/project/[ref]/settings/api-keys.tsx
+++ b/apps/studio/pages/project/[ref]/settings/api-keys.tsx
@@ -1,5 +1,5 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
-import { useParams } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import LegacyAPIKeys from 'components/interfaces/APIKeys/LegacyAPIKeys'
import { PublishableAPIKeys } from 'components/interfaces/APIKeys/PublishableAPIKeys'
@@ -9,7 +9,6 @@ import ApiKeysLayout from 'components/layouts/project/[ref]/settings/APIKeysLayo
import SettingsLayout from 'components/layouts/ProjectSettingsLayout/SettingsLayout'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import type { NextPageWithLayout } from 'types'
import { Separator } from 'ui'
diff --git a/apps/studio/pages/projects.tsx b/apps/studio/pages/projects.tsx
index 1723e6bbaa4..d454494dbd6 100644
--- a/apps/studio/pages/projects.tsx
+++ b/apps/studio/pages/projects.tsx
@@ -13,9 +13,10 @@ import { useOrganizationsQuery } from 'data/organizations/organizations-query'
import { useAutoProjectsPrefetch } from 'data/projects/projects-query'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
-import { IS_PLATFORM, LOCAL_STORAGE_KEYS, PROJECT_STATUS } from 'lib/constants'
+import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants'
import type { NextPageWithLayout } from 'types'
import { cn } from 'ui'
+import { LOCAL_STORAGE_KEYS } from 'common'
const ProjectsPage: NextPageWithLayout = () => {
const newLayoutPreview = useIsNewLayoutEnabled()
diff --git a/apps/studio/state/ai-assistant-state.tsx b/apps/studio/state/ai-assistant-state.tsx
index 8b5f7edcfb4..d4ddd0d661f 100644
--- a/apps/studio/state/ai-assistant-state.tsx
+++ b/apps/studio/state/ai-assistant-state.tsx
@@ -3,8 +3,7 @@ import type { Message as MessageType } from 'ai/react'
import { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react'
import { proxy, snapshot, subscribe, useSnapshot } from 'valtio'
import { debounce } from 'lodash'
-
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { LOCAL_STORAGE_KEYS } from 'common'
type SuggestionsType = {
title: string
diff --git a/apps/studio/state/app-state.ts b/apps/studio/state/app-state.ts
index 186f4078c61..22012f85f9f 100644
--- a/apps/studio/state/app-state.ts
+++ b/apps/studio/state/app-state.ts
@@ -1,7 +1,7 @@
import { proxy, snapshot, subscribe, useSnapshot } from 'valtio'
+import { LOCAL_STORAGE_KEYS as COMMON_LOCAL_STORAGE_KEYS, LOCAL_STORAGE_KEYS } from 'common'
import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.queries'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
export type Template = {
name: string
diff --git a/apps/studio/state/storage-explorer.tsx b/apps/studio/state/storage-explorer.tsx
index 886e8eeae19..a4dfab69d5a 100644
--- a/apps/studio/state/storage-explorer.tsx
+++ b/apps/studio/state/storage-explorer.tsx
@@ -8,7 +8,7 @@ import {
STORAGE_SORT_BY_ORDER,
STORAGE_VIEWS,
} from 'components/to-be-cleaned/Storage/Storage.constants'
-import { LOCAL_STORAGE_KEYS } from 'lib/constants'
+import { LOCAL_STORAGE_KEYS } from 'common'
import { tryParseJson } from 'lib/helpers'
const DEFAULT_PREFERENCES = {
diff --git a/apps/www/components/Nav/index.tsx b/apps/www/components/Nav/index.tsx
index bced494601a..a1f59fb7928 100644
--- a/apps/www/components/Nav/index.tsx
+++ b/apps/www/components/Nav/index.tsx
@@ -4,7 +4,7 @@ import { useRouter } from 'next/router'
import React, { useState } from 'react'
import { useWindowSize } from 'react-use'
-import { useIsLoggedIn } from 'common'
+import { useIsLoggedIn, useUser } from 'common'
import { Button, buttonVariants, cn } from 'ui'
import {
NavigationMenu,
@@ -23,6 +23,8 @@ import MenuItem from './MenuItem'
import MobileMenu from './MobileMenu'
import RightClickBrandLogo from './RightClickBrandLogo'
import { useSendTelemetryEvent } from '~/lib/telemetry'
+import useDropdownMenu from './useDropdownMenu'
+import { AuthenticatedDropdownMenu } from 'ui-patterns'
interface Props {
hideNavbar: boolean
@@ -37,6 +39,8 @@ const Nav = ({ hideNavbar, stickyNavbar = true }: Props) => {
const isLoggedIn = useIsLoggedIn()
const menu = getMenu()
const sendTelemetryEvent = useSendTelemetryEvent()
+ const user = useUser()
+ const userMenu = useDropdownMenu(user)
const isHomePage = router.pathname === '/'
const isLaunchWeekPage = router.pathname.includes('/launch-week')
@@ -130,9 +134,12 @@ const Nav = ({ hideNavbar, stickyNavbar = true }: Props) => {
{isLoggedIn ? (
-
+ <>
+
+
+ >
) : (
<>