mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 03:45:06 +03:00
added option to disable globally
This commit is contained in:
1 parent
ab611008c6
commit
eddfb062f1
7 files changed
+101
-3
No files matched your search
@@ -5,18 +5,24 @@ import { Card, Form } from 'ui'
|
||||
import * as z from 'zod'
|
||||
|
||||
import { DashboardToggle } from './DashboardToggle'
|
||||
import { useIsInlineEditorSetting, useIsQueueOperationsSetting } from './useDashboardSettings'
|
||||
import {
|
||||
useIsInlineEditorSetting,
|
||||
useIsQueueOperationsSetting,
|
||||
useIsShortcutChordHudSetting,
|
||||
} from './useDashboardSettings'
|
||||
import { useSendEventMutation } from '@/data/telemetry/send-event-mutation'
|
||||
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
|
||||
|
||||
const DashboardSettingsSchema = z.object({
|
||||
inlineEditorEnabled: z.boolean(),
|
||||
queueOperationsEnabled: z.boolean(),
|
||||
shortcutChordHudEnabled: z.boolean(),
|
||||
})
|
||||
|
||||
export const DashboardSettingsToggles = () => {
|
||||
const { inlineEditorEnabled, setInlineEditorEnabled } = useIsInlineEditorSetting()
|
||||
const { isQueueOperationsEnabled, setIsQueueOperationsEnabled } = useIsQueueOperationsSetting()
|
||||
const { isShortcutChordHudEnabled, setIsShortcutChordHudEnabled } = useIsShortcutChordHudSetting()
|
||||
|
||||
const { data: org } = useSelectedOrganizationQuery()
|
||||
|
||||
@@ -27,6 +33,7 @@ export const DashboardSettingsToggles = () => {
|
||||
values: {
|
||||
inlineEditorEnabled: inlineEditorEnabled ?? false,
|
||||
queueOperationsEnabled: isQueueOperationsEnabled ?? false,
|
||||
shortcutChordHudEnabled: isShortcutChordHudEnabled ?? true,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -60,6 +67,21 @@ export const DashboardSettingsToggles = () => {
|
||||
)
|
||||
}
|
||||
|
||||
const handleShortcutChordHudToggle = (value: boolean) => {
|
||||
setIsShortcutChordHudEnabled(value)
|
||||
form.setValue('shortcutChordHudEnabled', value)
|
||||
|
||||
sendEvent({
|
||||
action: 'shortcut_chord_hud_setting_clicked',
|
||||
properties: { enabled: value },
|
||||
groups: { organization: org?.slug },
|
||||
})
|
||||
|
||||
toast(
|
||||
`${value ? 'Keyboard shortcut hints will now appear while typing chords' : 'Keyboard shortcut hints are now hidden'}`
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<Card>
|
||||
@@ -76,6 +98,13 @@ export const DashboardSettingsToggles = () => {
|
||||
label="Queue table operations"
|
||||
description="Review and batch table edits in Table Editor before saving them to your database."
|
||||
onToggle={handleQueueOperationsToggle}
|
||||
/>
|
||||
<DashboardToggle
|
||||
form={form}
|
||||
name="shortcutChordHudEnabled"
|
||||
label="Show keyboard shortcut hints"
|
||||
description="Show an on-screen hint while typing multi-key keyboard shortcuts."
|
||||
onToggle={handleShortcutChordHudToggle}
|
||||
isLast
|
||||
/>
|
||||
</Card>
|
||||
|
||||
@@ -25,6 +25,17 @@ export const useIsQueueOperationsSetting = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const useIsShortcutChordHudSetting = () => {
|
||||
const [isShortcutChordHudEnabled, setIsShortcutChordHudEnabled] = useLocalStorageQuery(
|
||||
LOCAL_STORAGE_KEYS.UI_SHORTCUT_CHORD_HUD,
|
||||
true
|
||||
)
|
||||
return {
|
||||
isShortcutChordHudEnabled: isShortcutChordHudEnabled ?? true,
|
||||
setIsShortcutChordHudEnabled,
|
||||
}
|
||||
}
|
||||
|
||||
export const useIsInlineEditorEnabled = () => {
|
||||
const { inlineEditorEnabled } = useIsInlineEditorSetting()
|
||||
return inlineEditorEnabled ?? false
|
||||
@@ -34,3 +45,8 @@ export const useIsQueueOperationsEnabled = () => {
|
||||
const { isQueueOperationsEnabled } = useIsQueueOperationsSetting()
|
||||
return isQueueOperationsEnabled ?? false
|
||||
}
|
||||
|
||||
export const useIsShortcutChordHudEnabled = () => {
|
||||
const { isShortcutChordHudEnabled } = useIsShortcutChordHudSetting()
|
||||
return isShortcutChordHudEnabled ?? true
|
||||
}
|
||||
@@ -4,14 +4,19 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { ShortcutChordHud } from './ShortcutChordHud'
|
||||
import type { ShortcutSequenceRegistration } from './ShortcutChordHud.utils'
|
||||
|
||||
const { mockUseHotkeyRegistrations } = vi.hoisted(() => ({
|
||||
const { mockUseHotkeyRegistrations, mockUseIsShortcutChordHudEnabled } = vi.hoisted(() => ({
|
||||
mockUseHotkeyRegistrations: vi.fn(),
|
||||
mockUseIsShortcutChordHudEnabled: vi.fn(() => true),
|
||||
}))
|
||||
|
||||
vi.mock('@tanstack/react-hotkeys', () => ({
|
||||
useHotkeyRegistrations: mockUseHotkeyRegistrations,
|
||||
}))
|
||||
|
||||
vi.mock('@/components/interfaces/Account/Preferences/useDashboardSettings', () => ({
|
||||
useIsShortcutChordHudEnabled: mockUseIsShortcutChordHudEnabled,
|
||||
}))
|
||||
|
||||
const makeSequence = (
|
||||
overrides: Partial<ShortcutSequenceRegistration> &
|
||||
Pick<ShortcutSequenceRegistration, 'id' | 'sequence'>
|
||||
@@ -30,6 +35,7 @@ describe('ShortcutChordHud', () => {
|
||||
vi.useFakeTimers()
|
||||
vi.setSystemTime(new Date('2026-05-01T10:00:00.000Z'))
|
||||
mockUseHotkeyRegistrations.mockReturnValue({ hotkeys: [], sequences: [] })
|
||||
mockUseIsShortcutChordHudEnabled.mockReturnValue(true)
|
||||
})
|
||||
|
||||
it('stays hidden when no chord is in progress', () => {
|
||||
@@ -38,6 +44,29 @@ describe('ShortcutChordHud', () => {
|
||||
expect(screen.queryByTestId('shortcut-chord-hud')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('stays hidden when the user has disabled the chord HUD preference', () => {
|
||||
mockUseIsShortcutChordHudEnabled.mockReturnValue(false)
|
||||
const now = Date.now()
|
||||
mockUseHotkeyRegistrations.mockReturnValue({
|
||||
hotkeys: [],
|
||||
sequences: [
|
||||
makeSequence({
|
||||
id: 'nav.table',
|
||||
sequence: ['G', 'T'],
|
||||
matchedStepCount: 1,
|
||||
partialMatchLastKeyTime: now - 200,
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
render(<ShortcutChordHud />)
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(20)
|
||||
})
|
||||
|
||||
expect(screen.queryByTestId('shortcut-chord-hud')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders the active chord at the bottom centre while a sequence is in progress', () => {
|
||||
const now = Date.now()
|
||||
mockUseHotkeyRegistrations.mockReturnValue({
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { cn, KeyboardShortcut } from 'ui'
|
||||
|
||||
import { getVisibleShortcutChord, isInputLikeElement } from './ShortcutChordHud.utils'
|
||||
import { useIsShortcutChordHudEnabled } from '@/components/interfaces/Account/Preferences/useDashboardSettings'
|
||||
import { useInterval } from '@/hooks/misc/useInterval'
|
||||
import { hotkeyToKeys } from '@/state/shortcuts/formatShortcut'
|
||||
|
||||
@@ -23,6 +24,7 @@ interface RenderedShortcutChord {
|
||||
}
|
||||
|
||||
export function ShortcutChordHud() {
|
||||
const isEnabled = useIsShortcutChordHudEnabled()
|
||||
const { sequences } = useHotkeyRegistrations()
|
||||
const [, setTick] = useState(0)
|
||||
const [focusVersion, setFocusVersion] = useState(0)
|
||||
@@ -167,7 +169,7 @@ export function ShortcutChordHud() {
|
||||
|
||||
const displayedHud = targetHud ?? exitingHud
|
||||
|
||||
if (!displayedHud) {
|
||||
if (!displayedHud || !isEnabled) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ export const test = base.extend<TestOptions>({
|
||||
`table-editor-queue-operations-banner-dismissed-${ref}`,
|
||||
JSON.stringify(true)
|
||||
)
|
||||
localStorage.setItem('supabase-ui-shortcut-chord-hud', JSON.stringify(false))
|
||||
}, ref)
|
||||
await use(page)
|
||||
},
|
||||
|
||||
@@ -25,6 +25,7 @@ export const LOCAL_STORAGE_KEYS = {
|
||||
UI_PREVIEW_PLATFORM_WEBHOOKS: 'supabase-ui-platform-webhooks',
|
||||
UI_PREVIEW_JIT_DB_ACCESS: 'supabase-ui-jit-db-access',
|
||||
UI_PREVIEW_RLS_TESTER: 'supabase-ui-rls-tester',
|
||||
UI_SHORTCUT_CHORD_HUD: 'supabase-ui-shortcut-chord-hud',
|
||||
|
||||
NEW_LAYOUT_NOTICE_ACKNOWLEDGED: 'new-layout-notice-acknowledge',
|
||||
TABS_INTERFACE_ACKNOWLEDGED: 'tabs-interface-acknowledge',
|
||||
@@ -155,6 +156,7 @@ const LOCAL_STORAGE_KEYS_ALLOWLIST = [
|
||||
LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS,
|
||||
LOCAL_STORAGE_KEYS.UI_PREVIEW_PLATFORM_WEBHOOKS,
|
||||
LOCAL_STORAGE_KEYS.UI_PREVIEW_JIT_DB_ACCESS,
|
||||
LOCAL_STORAGE_KEYS.UI_SHORTCUT_CHORD_HUD,
|
||||
LOCAL_STORAGE_KEYS.LAST_SIGN_IN_METHOD,
|
||||
LOCAL_STORAGE_KEYS.HIDE_PROMO_TOAST,
|
||||
LOCAL_STORAGE_KEYS.BLOG_VIEW,
|
||||
|
||||
@@ -2545,6 +2545,24 @@ export interface QueueOperationsSettingClickedEvent {
|
||||
groups: Partial<TelemetryGroups>
|
||||
}
|
||||
|
||||
/**
|
||||
* User toggled the keyboard shortcut hint HUD setting in account preferences.
|
||||
*
|
||||
* @group Events
|
||||
* @source studio
|
||||
* @page /dashboard/account/preferences
|
||||
*/
|
||||
export interface ShortcutChordHudSettingClickedEvent {
|
||||
action: 'shortcut_chord_hud_setting_clicked'
|
||||
properties: {
|
||||
/**
|
||||
* Whether the keyboard shortcut hint HUD was enabled or disabled
|
||||
*/
|
||||
enabled: boolean
|
||||
}
|
||||
groups: Partial<TelemetryGroups>
|
||||
}
|
||||
|
||||
/**
|
||||
* User clicked the save destination button in add log drains sheet.
|
||||
*
|
||||
@@ -3349,6 +3367,7 @@ export type TelemetryEvent =
|
||||
| CommandMenuCommandClickedEvent
|
||||
| InlineEditorSettingClickedEvent
|
||||
| QueueOperationsSettingClickedEvent
|
||||
| ShortcutChordHudSettingClickedEvent
|
||||
| SidebarOpenedEvent
|
||||
| LogDrainSaveButtonClickedEvent
|
||||
| LogDrainConfirmButtonSubmittedEvent
|
||||
|
||||
Reference in new issue
Block a user