mirror of
https://github.com/stablyai/orca.git
synced 2026-10-15 08:03:08 +00:00
Add a third browser contextual tour step for cookie import.
When new users reach the final browser tour step, open the toolbar menu and anchor the callout on Import Cookies so they can reuse existing logins. Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Check, Ellipsis, Import, Monitor, Plus, Settings } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { Button } from '@/components/ui/button'
|
||||
@@ -58,6 +58,9 @@ export function BrowserToolbarMenu({
|
||||
const fetchDetectedBrowsers = useAppStore((s) => s.fetchDetectedBrowsers)
|
||||
const browserSessionImportState = useAppStore((s) => s.browserSessionImportState)
|
||||
const setBrowserPageViewportPreset = useAppStore((s) => s.setBrowserPageViewportPreset)
|
||||
const browserCookieTourStepActive = useAppStore(
|
||||
(s) => s.activeContextualTourId === 'browser' && s.activeContextualTourStepIndex === 2
|
||||
)
|
||||
|
||||
const applyViewportPreset = (nextId: BrowserViewportPresetId | null): void => {
|
||||
setBrowserPageViewportPreset(browserPageId, nextId)
|
||||
@@ -72,8 +75,22 @@ export function BrowserToolbarMenu({
|
||||
const [pendingSwitchProfileId, setPendingSwitchProfileId] = useState<string | null | undefined>(
|
||||
undefined
|
||||
)
|
||||
const [menuOpen, setMenuOpen] = useState(false)
|
||||
const mountedRef = useMountedRef()
|
||||
|
||||
useEffect(() => {
|
||||
// Why: step 3 anchors on Import Cookies inside this menu, so open it when
|
||||
// the browser tour reaches the final step and close it when leaving.
|
||||
setMenuOpen(browserCookieTourStepActive)
|
||||
}, [browserCookieTourStepActive])
|
||||
|
||||
const handleMenuOpenChange = (open: boolean): void => {
|
||||
if (browserCookieTourStepActive && !open) {
|
||||
return
|
||||
}
|
||||
setMenuOpen(open)
|
||||
}
|
||||
|
||||
const effectiveProfileId = currentProfileId ?? 'default'
|
||||
|
||||
const defaultProfile = browserSessionProfiles.find((p) => p.id === 'default')
|
||||
@@ -165,7 +182,7 @@ export function BrowserToolbarMenu({
|
||||
|
||||
return (
|
||||
<>
|
||||
<DropdownMenu>
|
||||
<DropdownMenu open={menuOpen} onOpenChange={handleMenuOpenChange}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button size="icon" variant="ghost" className="h-8 w-8" title="Browser menu">
|
||||
<Ellipsis className="size-4" />
|
||||
@@ -211,7 +228,10 @@ export function BrowserToolbarMenu({
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DropdownMenuSubTrigger disabled={browserSessionImportState?.status === 'importing'}>
|
||||
<DropdownMenuSubTrigger
|
||||
disabled={browserSessionImportState?.status === 'importing'}
|
||||
data-contextual-tour-target="browser-import-cookies-control"
|
||||
>
|
||||
<Import className="mr-2 size-3.5" />
|
||||
Import Cookies
|
||||
</DropdownMenuSubTrigger>
|
||||
|
||||
@@ -1929,7 +1929,8 @@ describe('createUISlice contextual tours', () => {
|
||||
const store = createUIStore()
|
||||
const visibleSelectors = [
|
||||
'[data-contextual-tour-target="browser-grab-control"]',
|
||||
'[data-contextual-tour-target="browser-annotation-control"]'
|
||||
'[data-contextual-tour-target="browser-annotation-control"]',
|
||||
'[data-contextual-tour-target="browser-import-cookies-control"]'
|
||||
]
|
||||
stubContextualTourTargets(visibleSelectors)
|
||||
store.getState().hydratePersistedUI(makeAutoTourEligibleUI())
|
||||
@@ -1940,7 +1941,7 @@ describe('createUISlice contextual tours', () => {
|
||||
|
||||
store.getState().advanceContextualTour()
|
||||
expect(store.getState().activeContextualTourId).toBe('browser')
|
||||
expect(store.getState().activeContextualTourStepIndex).toBe(1)
|
||||
expect(store.getState().activeContextualTourStepIndex).toBe(2)
|
||||
})
|
||||
|
||||
it('advances the active split step when the split command interaction is recorded', () => {
|
||||
|
||||
@@ -97,6 +97,23 @@ describe('contextual tour definitions', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('orders the browser tour as grab, annotate, then import cookies', () => {
|
||||
const tour = CONTEXTUAL_TOURS.find((entry) => entry.id === 'browser') as
|
||||
| ContextualTour
|
||||
| undefined
|
||||
|
||||
expect(tour?.steps.map((step) => step.title)).toEqual([
|
||||
'Grab page context for agents',
|
||||
'Mark design feedback in place',
|
||||
'Stay logged in'
|
||||
])
|
||||
expect(tour?.steps[2]).toMatchObject({
|
||||
body: 'Bring your existing logins into Orca to stay signed in immediately.',
|
||||
targetSelector: '[data-contextual-tour-target="browser-import-cookies-control"]',
|
||||
preferredPlacement: 'left'
|
||||
})
|
||||
})
|
||||
|
||||
it('points the tasks tour at the row workspace action before toolbar fallbacks', () => {
|
||||
const tour = CONTEXTUAL_TOURS.find((entry) => entry.id === 'tasks') as
|
||||
| ContextualTour
|
||||
|
||||
@@ -110,6 +110,12 @@ export const CONTEXTUAL_TOURS = [
|
||||
title: 'Mark design feedback in place',
|
||||
body: 'Annotate elements and send those notes to an agent.',
|
||||
targetSelector: '[data-contextual-tour-target="browser-annotation-control"]'
|
||||
},
|
||||
{
|
||||
title: 'Stay logged in',
|
||||
body: 'Bring your existing logins into Orca to stay signed in immediately.',
|
||||
targetSelector: '[data-contextual-tour-target="browser-import-cookies-control"]',
|
||||
preferredPlacement: 'left'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user