@adea-ai/ui 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/components/account-drawer.d.ts +1 -1
- package/dist/components/account-drawer.js +12 -12
- package/dist/components/on-screen-controls.js +12 -12
- package/dist/components/scene-settings.d.ts +3 -3
- package/dist/components/scene-settings.js +11 -11
- package/dist/components/theme-provider.d.ts +1 -1
- package/dist/components/theme-provider.js +2 -2
- package/dist/components/theme-toggle.js +8 -8
- package/dist/components/ui/badge.d.ts +3 -3
- package/dist/components/ui/badge.js +15 -15
- package/dist/components/ui/button.d.ts +2 -2
- package/dist/components/ui/button.js +19 -19
- package/dist/components/ui/card.d.ts +1 -1
- package/dist/components/ui/card.js +3 -3
- package/dist/components/ui/dialog.d.ts +4 -4
- package/dist/components/ui/dialog.js +10 -10
- package/dist/components/ui/drawer.d.ts +5 -5
- package/dist/components/ui/drawer.js +26 -26
- package/dist/components/ui/dropdown-menu.d.ts +5 -5
- package/dist/components/ui/dropdown-menu.js +12 -12
- package/dist/components/ui/empty.d.ts +7 -7
- package/dist/components/ui/empty.js +11 -11
- package/dist/components/ui/field.d.ts +12 -12
- package/dist/components/ui/field.js +22 -22
- package/dist/components/ui/input.d.ts +2 -2
- package/dist/components/ui/input.js +3 -3
- package/dist/components/ui/label.d.ts +2 -2
- package/dist/components/ui/label.js +3 -3
- package/dist/components/ui/radio-group.d.ts +2 -2
- package/dist/components/ui/radio-group.js +6 -6
- package/dist/components/ui/separator.d.ts +1 -1
- package/dist/components/ui/separator.js +5 -5
- package/dist/components/ui/skeleton.d.ts +1 -1
- package/dist/components/ui/skeleton.js +2 -2
- package/dist/components/ui/spinner.d.ts +2 -2
- package/dist/components/ui/spinner.js +3 -3
- package/dist/components/ui/switch.d.ts +2 -2
- package/dist/components/ui/switch.js +5 -5
- package/dist/components/ui/tabs.d.ts +2 -2
- package/dist/components/ui/tabs.js +13 -13
- package/dist/components/ui/toggle-group.d.ts +6 -6
- package/dist/components/ui/toggle-group.js +13 -13
- package/dist/components/ui/toggle.d.ts +2 -2
- package/dist/components/ui/toggle.js +11 -11
- package/dist/components/ui/tooltip.d.ts +3 -3
- package/dist/components/ui/tooltip.js +5 -5
- package/dist/components/version-dialog.d.ts +1 -1
- package/dist/components/version-dialog.js +33 -33
- package/dist/components/workspace-brand.js +1 -1
- package/dist/components/workspace-logo.d.ts +1 -1
- package/dist/index.d.ts +19 -19
- package/dist/index.js +19 -19
- package/dist/lib/utils.d.ts +1 -1
- package/dist/lib/utils.js +2 -2
- package/dist/lib/version-notes.js +18 -18
- package/package.json +24 -9
- package/src/components/account-drawer.tsx +27 -27
- package/src/components/on-screen-controls.tsx +45 -45
- package/src/components/scene-settings.tsx +55 -55
- package/src/components/theme-provider.tsx +7 -7
- package/src/components/theme-toggle.tsx +20 -20
- package/src/components/ui/badge.tsx +20 -20
- package/src/components/ui/button.tsx +24 -24
- package/src/components/ui/card.tsx +6 -6
- package/src/components/ui/dialog.tsx +24 -24
- package/src/components/ui/drawer.tsx +55 -55
- package/src/components/ui/dropdown-menu.tsx +39 -39
- package/src/components/ui/empty.tsx +25 -25
- package/src/components/ui/field.tsx +55 -55
- package/src/components/ui/input.tsx +7 -7
- package/src/components/ui/label.tsx +7 -7
- package/src/components/ui/radio-group.tsx +9 -9
- package/src/components/ui/separator.tsx +7 -7
- package/src/components/ui/skeleton.tsx +5 -5
- package/src/components/ui/spinner.tsx +6 -6
- package/src/components/ui/switch.tsx +8 -8
- package/src/components/ui/tabs.tsx +21 -21
- package/src/components/ui/toggle-group.tsx +25 -25
- package/src/components/ui/toggle.tsx +15 -15
- package/src/components/ui/tooltip.tsx +13 -13
- package/src/components/version-dialog.tsx +113 -113
- package/src/components/workspace-brand.tsx +4 -4
- package/src/components/workspace-logo.tsx +2 -2
- package/src/index.tsx +19 -19
- package/src/lib/utils.ts +3 -3
- package/src/lib/version-notes.ts +23 -23
- package/src/styles/conventional-workspace.css +26 -26
- package/src/styles/globals.css +2 -2
- package/src/styles/theme.css +1 -1
- package/src/styles/workspace-shell.css +2 -2
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
'use client'
|
|
2
2
|
|
|
3
|
-
import * as React from
|
|
4
|
-
import { Toggle as TogglePrimitive } from
|
|
5
|
-
import { ToggleGroup as ToggleGroupPrimitive } from
|
|
6
|
-
import { type VariantProps } from
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Toggle as TogglePrimitive } from '@base-ui/react/toggle'
|
|
5
|
+
import { ToggleGroup as ToggleGroupPrimitive } from '@base-ui/react/toggle-group'
|
|
6
|
+
import { type VariantProps } from 'class-variance-authority'
|
|
7
7
|
|
|
8
|
-
import { cn } from
|
|
9
|
-
import { toggleVariants } from
|
|
8
|
+
import { cn } from '#lib/utils'
|
|
9
|
+
import { toggleVariants } from '#components/ui/toggle'
|
|
10
10
|
|
|
11
11
|
const ToggleGroupContext = React.createContext<
|
|
12
12
|
VariantProps<typeof toggleVariants> & {
|
|
13
|
-
spacing?: number
|
|
14
|
-
orientation?:
|
|
13
|
+
spacing?: number
|
|
14
|
+
orientation?: 'horizontal' | 'vertical'
|
|
15
15
|
}
|
|
16
16
|
>({
|
|
17
|
-
size:
|
|
18
|
-
variant:
|
|
17
|
+
size: 'default',
|
|
18
|
+
variant: 'default',
|
|
19
19
|
spacing: 2,
|
|
20
|
-
orientation:
|
|
21
|
-
})
|
|
20
|
+
orientation: 'horizontal',
|
|
21
|
+
})
|
|
22
22
|
|
|
23
23
|
function ToggleGroup({
|
|
24
24
|
className,
|
|
25
25
|
variant,
|
|
26
26
|
size,
|
|
27
27
|
spacing = 2,
|
|
28
|
-
orientation =
|
|
28
|
+
orientation = 'horizontal',
|
|
29
29
|
children,
|
|
30
30
|
...props
|
|
31
31
|
}: ToggleGroupPrimitive.Props &
|
|
32
32
|
VariantProps<typeof toggleVariants> & {
|
|
33
|
-
spacing?: number
|
|
34
|
-
orientation?:
|
|
33
|
+
spacing?: number
|
|
34
|
+
orientation?: 'horizontal' | 'vertical'
|
|
35
35
|
}) {
|
|
36
36
|
return (
|
|
37
37
|
<ToggleGroupPrimitive
|
|
@@ -40,9 +40,9 @@ function ToggleGroup({
|
|
|
40
40
|
data-size={size}
|
|
41
41
|
data-spacing={spacing}
|
|
42
42
|
data-orientation={orientation}
|
|
43
|
-
style={{
|
|
43
|
+
style={{ '--gap': spacing } as React.CSSProperties}
|
|
44
44
|
className={cn(
|
|
45
|
-
|
|
45
|
+
'group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] rounded-lg data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-vertical:flex-col data-vertical:items-stretch',
|
|
46
46
|
className
|
|
47
47
|
)}
|
|
48
48
|
{...props}
|
|
@@ -51,17 +51,17 @@ function ToggleGroup({
|
|
|
51
51
|
{children}
|
|
52
52
|
</ToggleGroupContext.Provider>
|
|
53
53
|
</ToggleGroupPrimitive>
|
|
54
|
-
)
|
|
54
|
+
)
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
function ToggleGroupItem({
|
|
58
58
|
className,
|
|
59
59
|
children,
|
|
60
|
-
variant =
|
|
61
|
-
size =
|
|
60
|
+
variant = 'default',
|
|
61
|
+
size = 'default',
|
|
62
62
|
...props
|
|
63
63
|
}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
|
|
64
|
-
const context = React.useContext(ToggleGroupContext)
|
|
64
|
+
const context = React.useContext(ToggleGroupContext)
|
|
65
65
|
|
|
66
66
|
return (
|
|
67
67
|
<TogglePrimitive
|
|
@@ -70,7 +70,7 @@ function ToggleGroupItem({
|
|
|
70
70
|
data-size={context.size || size}
|
|
71
71
|
data-spacing={context.spacing}
|
|
72
72
|
className={cn(
|
|
73
|
-
|
|
73
|
+
'shrink-0 group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 focus:z-10 focus-visible:z-10 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-lg group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-lg group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t',
|
|
74
74
|
toggleVariants({
|
|
75
75
|
variant: context.variant || variant,
|
|
76
76
|
size: context.size || size,
|
|
@@ -81,7 +81,7 @@ function ToggleGroupItem({
|
|
|
81
81
|
>
|
|
82
82
|
{children}
|
|
83
83
|
</TogglePrimitive>
|
|
84
|
-
)
|
|
84
|
+
)
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
export { ToggleGroup, ToggleGroupItem }
|
|
87
|
+
export { ToggleGroup, ToggleGroupItem }
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
'use client'
|
|
2
2
|
|
|
3
|
-
import { Toggle as TogglePrimitive } from
|
|
4
|
-
import { cva, type VariantProps } from
|
|
3
|
+
import { Toggle as TogglePrimitive } from '@base-ui/react/toggle'
|
|
4
|
+
import { cva, type VariantProps } from 'class-variance-authority'
|
|
5
5
|
|
|
6
|
-
import { cn } from
|
|
6
|
+
import { cn } from '#lib/utils'
|
|
7
7
|
|
|
8
8
|
const toggleVariants = cva(
|
|
9
9
|
"group/toggle inline-flex items-center justify-center gap-1 rounded-lg text-sm font-medium whitespace-nowrap transition-all outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted data-[state=on]:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
10
10
|
{
|
|
11
11
|
variants: {
|
|
12
12
|
variant: {
|
|
13
|
-
default:
|
|
14
|
-
outline:
|
|
13
|
+
default: 'bg-transparent',
|
|
14
|
+
outline: 'border border-input bg-transparent hover:bg-muted',
|
|
15
15
|
},
|
|
16
16
|
size: {
|
|
17
17
|
default:
|
|
18
|
-
|
|
18
|
+
'h-8 min-w-8 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
|
|
19
19
|
sm: "h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
|
20
|
-
lg:
|
|
20
|
+
lg: 'h-9 min-w-9 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
|
|
21
21
|
},
|
|
22
22
|
},
|
|
23
23
|
defaultVariants: {
|
|
24
|
-
variant:
|
|
25
|
-
size:
|
|
24
|
+
variant: 'default',
|
|
25
|
+
size: 'default',
|
|
26
26
|
},
|
|
27
27
|
}
|
|
28
|
-
)
|
|
28
|
+
)
|
|
29
29
|
|
|
30
30
|
function Toggle({
|
|
31
31
|
className,
|
|
32
|
-
variant =
|
|
33
|
-
size =
|
|
32
|
+
variant = 'default',
|
|
33
|
+
size = 'default',
|
|
34
34
|
...props
|
|
35
35
|
}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
|
|
36
36
|
return (
|
|
@@ -39,7 +39,7 @@ function Toggle({
|
|
|
39
39
|
className={cn(toggleVariants({ variant, size, className }))}
|
|
40
40
|
{...props}
|
|
41
41
|
/>
|
|
42
|
-
)
|
|
42
|
+
)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export { Toggle, toggleVariants }
|
|
45
|
+
export { Toggle, toggleVariants }
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
'use client'
|
|
2
2
|
|
|
3
|
-
import * as React from
|
|
4
|
-
import { Tooltip as TooltipPrimitive } from
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Tooltip as TooltipPrimitive } from '@base-ui/react/tooltip'
|
|
5
5
|
|
|
6
|
-
import { cn } from
|
|
6
|
+
import { cn } from '#lib/utils'
|
|
7
7
|
|
|
8
|
-
const TOOLTIP_DELAY = 200
|
|
8
|
+
const TOOLTIP_DELAY = 200
|
|
9
9
|
|
|
10
10
|
function TooltipProvider({ delay = TOOLTIP_DELAY, ...props }: TooltipPrimitive.Provider.Props) {
|
|
11
|
-
return <TooltipPrimitive.Provider data-slot="tooltip-provider" delay={delay} {...props}
|
|
11
|
+
return <TooltipPrimitive.Provider data-slot="tooltip-provider" delay={delay} {...props} />
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
function Tooltip({ ...props }: TooltipPrimitive.Root.Props) {
|
|
15
|
-
return <TooltipPrimitive.Root data-slot="tooltip" {...props}
|
|
15
|
+
return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
|
|
19
|
-
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props}
|
|
19
|
+
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function TooltipContent({
|
|
23
23
|
className,
|
|
24
|
-
side =
|
|
24
|
+
side = 'top',
|
|
25
25
|
sideOffset = 4,
|
|
26
26
|
align,
|
|
27
27
|
alignOffset,
|
|
28
28
|
children,
|
|
29
29
|
...props
|
|
30
30
|
}: TooltipPrimitive.Popup.Props &
|
|
31
|
-
Pick<TooltipPrimitive.Positioner.Props,
|
|
31
|
+
Pick<TooltipPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) {
|
|
32
32
|
return (
|
|
33
33
|
<TooltipPrimitive.Portal>
|
|
34
34
|
<TooltipPrimitive.Positioner
|
|
@@ -41,7 +41,7 @@ function TooltipContent({
|
|
|
41
41
|
<TooltipPrimitive.Popup
|
|
42
42
|
data-slot="tooltip-content"
|
|
43
43
|
className={cn(
|
|
44
|
-
|
|
44
|
+
'max-w-72 rounded-md bg-popover px-2.5 py-1.5 text-sm leading-5 text-popover-foreground shadow-md ring-1 ring-foreground/10',
|
|
45
45
|
className
|
|
46
46
|
)}
|
|
47
47
|
{...props}
|
|
@@ -50,7 +50,7 @@ function TooltipContent({
|
|
|
50
50
|
</TooltipPrimitive.Popup>
|
|
51
51
|
</TooltipPrimitive.Positioner>
|
|
52
52
|
</TooltipPrimitive.Portal>
|
|
53
|
-
)
|
|
53
|
+
)
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider, TOOLTIP_DELAY }
|
|
56
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider, TOOLTIP_DELAY }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
'use client'
|
|
2
2
|
|
|
3
|
-
import { useCallback, useEffect, useMemo, useState } from
|
|
3
|
+
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
4
4
|
import {
|
|
5
5
|
Check,
|
|
6
6
|
Download,
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
LoaderCircle,
|
|
10
10
|
RefreshCw,
|
|
11
11
|
Sparkles,
|
|
12
|
-
} from
|
|
12
|
+
} from 'lucide-react'
|
|
13
13
|
|
|
14
|
-
import { formatReleaseDate, plainTextFromMarkdown } from
|
|
15
|
-
import { Button } from
|
|
14
|
+
import { formatReleaseDate, plainTextFromMarkdown } from '#lib/version-notes'
|
|
15
|
+
import { Button } from '#components/ui/button'
|
|
16
16
|
import {
|
|
17
17
|
Dialog,
|
|
18
18
|
DialogClose,
|
|
@@ -22,165 +22,165 @@ import {
|
|
|
22
22
|
DialogHeader,
|
|
23
23
|
DialogTitle,
|
|
24
24
|
DialogTrigger,
|
|
25
|
-
} from
|
|
25
|
+
} from '#components/ui/dialog'
|
|
26
26
|
|
|
27
27
|
export type SharedDesktopUpdate = Readonly<{
|
|
28
|
-
available_version: string | null
|
|
29
|
-
changelog: string
|
|
30
|
-
current_version: string
|
|
31
|
-
downloaded_bytes: number
|
|
32
|
-
error: string | null
|
|
33
|
-
github_url: string
|
|
28
|
+
available_version: string | null
|
|
29
|
+
changelog: string
|
|
30
|
+
current_version: string
|
|
31
|
+
downloaded_bytes: number
|
|
32
|
+
error: string | null
|
|
33
|
+
github_url: string
|
|
34
34
|
phase:
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
release_date: string | null
|
|
44
|
-
release_notes: string | null
|
|
45
|
-
restart_required: boolean
|
|
46
|
-
total_bytes: number | null
|
|
47
|
-
}
|
|
35
|
+
| 'idle'
|
|
36
|
+
| 'checking'
|
|
37
|
+
| 'current'
|
|
38
|
+
| 'available'
|
|
39
|
+
| 'downloading'
|
|
40
|
+
| 'installing'
|
|
41
|
+
| 'installed'
|
|
42
|
+
| 'failed'
|
|
43
|
+
release_date: string | null
|
|
44
|
+
release_notes: string | null
|
|
45
|
+
restart_required: boolean
|
|
46
|
+
total_bytes: number | null
|
|
47
|
+
}>
|
|
48
48
|
|
|
49
49
|
export type VersionDialogAdapter = Readonly<{
|
|
50
|
-
check(): Promise<SharedDesktopUpdate
|
|
51
|
-
getStatus(): Promise<SharedDesktopUpdate
|
|
52
|
-
install(expectedVersion: string): Promise<SharedDesktopUpdate
|
|
53
|
-
isDesktopRuntime(): boolean
|
|
54
|
-
}
|
|
50
|
+
check(): Promise<SharedDesktopUpdate>
|
|
51
|
+
getStatus(): Promise<SharedDesktopUpdate>
|
|
52
|
+
install(expectedVersion: string): Promise<SharedDesktopUpdate>
|
|
53
|
+
isDesktopRuntime(): boolean
|
|
54
|
+
}>
|
|
55
55
|
|
|
56
56
|
function errorMessage(caught: unknown, fallback: string): string {
|
|
57
|
-
if (caught instanceof Error && caught.message) return caught.message
|
|
58
|
-
if (typeof caught ===
|
|
59
|
-
return fallback
|
|
57
|
+
if (caught instanceof Error && caught.message) return caught.message
|
|
58
|
+
if (typeof caught === 'string' && caught) return caught
|
|
59
|
+
return fallback
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
function phaseLabel(update: SharedDesktopUpdate | null, fallbackVersion: string): string {
|
|
63
|
-
if (!update) return `Adea v${fallbackVersion}
|
|
64
|
-
if (update.phase ===
|
|
65
|
-
if (update.phase ===
|
|
66
|
-
return `Update v${update.available_version} available
|
|
63
|
+
if (!update) return `Adea v${fallbackVersion}`
|
|
64
|
+
if (update.phase === 'checking') return 'Checking for updates…'
|
|
65
|
+
if (update.phase === 'available' && update.available_version) {
|
|
66
|
+
return `Update v${update.available_version} available`
|
|
67
67
|
}
|
|
68
|
-
if (update.phase ===
|
|
69
|
-
return
|
|
68
|
+
if (update.phase === 'downloading' || update.phase === 'installing') {
|
|
69
|
+
return 'Installing update…'
|
|
70
70
|
}
|
|
71
|
-
if (update.phase ===
|
|
72
|
-
return `Adea v${update.current_version || fallbackVersion}
|
|
71
|
+
if (update.phase === 'failed') return `Version ${update.current_version} · Retry`
|
|
72
|
+
return `Adea v${update.current_version || fallbackVersion}`
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
function isUpdateBusy(update: SharedDesktopUpdate | null): boolean {
|
|
76
76
|
return (
|
|
77
|
-
update?.phase ===
|
|
78
|
-
update?.phase ===
|
|
79
|
-
update?.phase ===
|
|
80
|
-
)
|
|
77
|
+
update?.phase === 'checking' ||
|
|
78
|
+
update?.phase === 'downloading' ||
|
|
79
|
+
update?.phase === 'installing'
|
|
80
|
+
)
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
export function VersionDialog({
|
|
84
84
|
adapter,
|
|
85
|
-
fallbackVersion =
|
|
85
|
+
fallbackVersion = '0.1.0',
|
|
86
86
|
onOpenChange,
|
|
87
87
|
open: controlledOpen,
|
|
88
88
|
}: Readonly<{
|
|
89
|
-
adapter: VersionDialogAdapter
|
|
90
|
-
fallbackVersion?: string
|
|
91
|
-
onOpenChange?: (open: boolean) => void
|
|
92
|
-
open?: boolean
|
|
89
|
+
adapter: VersionDialogAdapter
|
|
90
|
+
fallbackVersion?: string
|
|
91
|
+
onOpenChange?: (open: boolean) => void
|
|
92
|
+
open?: boolean
|
|
93
93
|
}>) {
|
|
94
|
-
const [uncontrolledOpen, setUncontrolledOpen] = useState(false)
|
|
95
|
-
const open = controlledOpen ?? uncontrolledOpen
|
|
94
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(false)
|
|
95
|
+
const open = controlledOpen ?? uncontrolledOpen
|
|
96
96
|
const setOpen = useCallback(
|
|
97
97
|
(nextOpen: boolean) => {
|
|
98
|
-
if (controlledOpen === undefined) setUncontrolledOpen(nextOpen)
|
|
99
|
-
onOpenChange?.(nextOpen)
|
|
98
|
+
if (controlledOpen === undefined) setUncontrolledOpen(nextOpen)
|
|
99
|
+
onOpenChange?.(nextOpen)
|
|
100
100
|
},
|
|
101
101
|
[controlledOpen, onOpenChange]
|
|
102
|
-
)
|
|
103
|
-
const [desktopRuntime, setDesktopRuntime] = useState(false)
|
|
104
|
-
const [update, setUpdate] = useState<SharedDesktopUpdate | null>(null)
|
|
105
|
-
const [busy, setBusy] = useState(false)
|
|
106
|
-
const [error, setError] = useState(
|
|
102
|
+
)
|
|
103
|
+
const [desktopRuntime, setDesktopRuntime] = useState(false)
|
|
104
|
+
const [update, setUpdate] = useState<SharedDesktopUpdate | null>(null)
|
|
105
|
+
const [busy, setBusy] = useState(false)
|
|
106
|
+
const [error, setError] = useState('')
|
|
107
107
|
|
|
108
|
-
useEffect(() => setDesktopRuntime(adapter.isDesktopRuntime()), [adapter])
|
|
108
|
+
useEffect(() => setDesktopRuntime(adapter.isDesktopRuntime()), [adapter])
|
|
109
109
|
|
|
110
110
|
const loadCurrentStatus = useCallback(async () => {
|
|
111
|
-
if (!desktopRuntime) return
|
|
111
|
+
if (!desktopRuntime) return
|
|
112
112
|
try {
|
|
113
|
-
setUpdate(await adapter.getStatus())
|
|
113
|
+
setUpdate(await adapter.getStatus())
|
|
114
114
|
} catch (caught) {
|
|
115
|
-
setError(errorMessage(caught,
|
|
115
|
+
setError(errorMessage(caught, 'Version status is unavailable'))
|
|
116
116
|
}
|
|
117
|
-
}, [adapter, desktopRuntime])
|
|
117
|
+
}, [adapter, desktopRuntime])
|
|
118
118
|
|
|
119
119
|
useEffect(() => {
|
|
120
|
-
if (desktopRuntime) void loadCurrentStatus()
|
|
121
|
-
}, [desktopRuntime, loadCurrentStatus])
|
|
120
|
+
if (desktopRuntime) void loadCurrentStatus()
|
|
121
|
+
}, [desktopRuntime, loadCurrentStatus])
|
|
122
122
|
|
|
123
123
|
const checkForUpdates = useCallback(async () => {
|
|
124
124
|
if (!desktopRuntime) {
|
|
125
|
-
setError(
|
|
126
|
-
return
|
|
125
|
+
setError('Update checks are available from the desktop app.')
|
|
126
|
+
return
|
|
127
127
|
}
|
|
128
|
-
setBusy(true)
|
|
129
|
-
setError(
|
|
128
|
+
setBusy(true)
|
|
129
|
+
setError('')
|
|
130
130
|
try {
|
|
131
|
-
setUpdate(await adapter.check())
|
|
131
|
+
setUpdate(await adapter.check())
|
|
132
132
|
} catch (caught) {
|
|
133
|
-
setError(errorMessage(caught,
|
|
134
|
-
await loadCurrentStatus()
|
|
133
|
+
setError(errorMessage(caught, 'Could not check for updates'))
|
|
134
|
+
await loadCurrentStatus()
|
|
135
135
|
} finally {
|
|
136
|
-
setBusy(false)
|
|
136
|
+
setBusy(false)
|
|
137
137
|
}
|
|
138
|
-
}, [adapter, desktopRuntime, loadCurrentStatus])
|
|
138
|
+
}, [adapter, desktopRuntime, loadCurrentStatus])
|
|
139
139
|
|
|
140
140
|
useEffect(() => {
|
|
141
|
-
if (!open || !desktopRuntime) return
|
|
142
|
-
let active = true
|
|
143
|
-
setError(
|
|
144
|
-
setBusy(true)
|
|
141
|
+
if (!open || !desktopRuntime) return
|
|
142
|
+
let active = true
|
|
143
|
+
setError('')
|
|
144
|
+
setBusy(true)
|
|
145
145
|
void (async () => {
|
|
146
146
|
try {
|
|
147
|
-
const current = await adapter.getStatus()
|
|
148
|
-
if (!active) return
|
|
149
|
-
setUpdate(current)
|
|
150
|
-
const checked = await adapter.check()
|
|
151
|
-
if (active) setUpdate(checked)
|
|
147
|
+
const current = await adapter.getStatus()
|
|
148
|
+
if (!active) return
|
|
149
|
+
setUpdate(current)
|
|
150
|
+
const checked = await adapter.check()
|
|
151
|
+
if (active) setUpdate(checked)
|
|
152
152
|
} catch (caught) {
|
|
153
|
-
if (active) setError(errorMessage(caught,
|
|
153
|
+
if (active) setError(errorMessage(caught, 'Could not check for updates'))
|
|
154
154
|
} finally {
|
|
155
|
-
if (active) setBusy(false)
|
|
155
|
+
if (active) setBusy(false)
|
|
156
156
|
}
|
|
157
|
-
})()
|
|
157
|
+
})()
|
|
158
158
|
return () => {
|
|
159
|
-
active = false
|
|
160
|
-
}
|
|
161
|
-
}, [adapter, desktopRuntime, open])
|
|
159
|
+
active = false
|
|
160
|
+
}
|
|
161
|
+
}, [adapter, desktopRuntime, open])
|
|
162
162
|
|
|
163
163
|
const install = async () => {
|
|
164
|
-
const version = update?.available_version
|
|
165
|
-
if (!version) return
|
|
166
|
-
setBusy(true)
|
|
167
|
-
setError(
|
|
164
|
+
const version = update?.available_version
|
|
165
|
+
if (!version) return
|
|
166
|
+
setBusy(true)
|
|
167
|
+
setError('')
|
|
168
168
|
try {
|
|
169
|
-
setUpdate(await adapter.install(version))
|
|
169
|
+
setUpdate(await adapter.install(version))
|
|
170
170
|
} catch (caught) {
|
|
171
|
-
setError(errorMessage(caught,
|
|
172
|
-
await loadCurrentStatus()
|
|
171
|
+
setError(errorMessage(caught, 'Update installation failed'))
|
|
172
|
+
await loadCurrentStatus()
|
|
173
173
|
} finally {
|
|
174
|
-
setBusy(false)
|
|
174
|
+
setBusy(false)
|
|
175
175
|
}
|
|
176
|
-
}
|
|
176
|
+
}
|
|
177
177
|
|
|
178
178
|
const currentChangelog = useMemo(
|
|
179
|
-
() => plainTextFromMarkdown(update?.changelog ||
|
|
179
|
+
() => plainTextFromMarkdown(update?.changelog || 'Changelog is loading…'),
|
|
180
180
|
[update?.changelog]
|
|
181
|
-
)
|
|
182
|
-
const releaseNotes = update?.release_notes ? plainTextFromMarkdown(update.release_notes) :
|
|
183
|
-
const busyFromSnapshot = isUpdateBusy(update)
|
|
181
|
+
)
|
|
182
|
+
const releaseNotes = update?.release_notes ? plainTextFromMarkdown(update.release_notes) : ''
|
|
183
|
+
const busyFromSnapshot = isUpdateBusy(update)
|
|
184
184
|
|
|
185
185
|
return (
|
|
186
186
|
<Dialog open={open} onOpenChange={setOpen}>
|
|
@@ -197,7 +197,7 @@ export function VersionDialog({
|
|
|
197
197
|
/>
|
|
198
198
|
}
|
|
199
199
|
>
|
|
200
|
-
{update?.phase ===
|
|
200
|
+
{update?.phase === 'available' ? (
|
|
201
201
|
<Sparkles aria-hidden="true" />
|
|
202
202
|
) : (
|
|
203
203
|
<FileText aria-hidden="true" />
|
|
@@ -232,13 +232,13 @@ export function VersionDialog({
|
|
|
232
232
|
v{update?.current_version || fallbackVersion}
|
|
233
233
|
</p>
|
|
234
234
|
<p className="text-sm text-muted-foreground">
|
|
235
|
-
{update?.phase ===
|
|
236
|
-
?
|
|
237
|
-
: update?.phase ===
|
|
235
|
+
{update?.phase === 'current'
|
|
236
|
+
? 'You are running the latest desktop release.'
|
|
237
|
+
: update?.phase === 'available' && update.available_version
|
|
238
238
|
? `A newer desktop release, v${update.available_version}, is ready.`
|
|
239
239
|
: desktopRuntime
|
|
240
|
-
?
|
|
241
|
-
:
|
|
240
|
+
? 'Check the release channel for the latest signed build.'
|
|
241
|
+
: 'Open this dialog inside the desktop app to check for updates.'}
|
|
242
242
|
</p>
|
|
243
243
|
</div>
|
|
244
244
|
<Button
|
|
@@ -258,7 +258,7 @@ export function VersionDialog({
|
|
|
258
258
|
</div>
|
|
259
259
|
</section>
|
|
260
260
|
|
|
261
|
-
{update?.phase ===
|
|
261
|
+
{update?.phase === 'available' && update.available_version ? (
|
|
262
262
|
<section
|
|
263
263
|
className="rounded-xl border border-primary/35 bg-primary/8 p-4"
|
|
264
264
|
aria-label="Available update"
|
|
@@ -295,7 +295,7 @@ export function VersionDialog({
|
|
|
295
295
|
</section>
|
|
296
296
|
) : null}
|
|
297
297
|
|
|
298
|
-
{update?.phase ===
|
|
298
|
+
{update?.phase === 'current' ? (
|
|
299
299
|
<p
|
|
300
300
|
className="flex items-center gap-2 text-sm text-emerald-700 dark:text-emerald-300"
|
|
301
301
|
role="status"
|
|
@@ -350,7 +350,7 @@ export function VersionDialog({
|
|
|
350
350
|
type="button"
|
|
351
351
|
variant="ghost"
|
|
352
352
|
size="sm"
|
|
353
|
-
onClick={() => window.open(update.github_url,
|
|
353
|
+
onClick={() => window.open(update.github_url, '_blank', 'noopener,noreferrer')}
|
|
354
354
|
>
|
|
355
355
|
<ExternalLink aria-hidden="true" />
|
|
356
356
|
View releases
|
|
@@ -362,5 +362,5 @@ export function VersionDialog({
|
|
|
362
362
|
</DialogFooter>
|
|
363
363
|
</DialogContent>
|
|
364
364
|
</Dialog>
|
|
365
|
-
)
|
|
365
|
+
)
|
|
366
366
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export interface WorkspaceBrandProps {
|
|
2
|
-
title: string
|
|
3
|
-
eyebrow?: string
|
|
2
|
+
title: string
|
|
3
|
+
eyebrow?: string
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
export function WorkspaceBrand({ title, eyebrow =
|
|
6
|
+
export function WorkspaceBrand({ title, eyebrow = 'AGENT OPERATIONS' }: WorkspaceBrandProps) {
|
|
7
7
|
return (
|
|
8
8
|
<div className="workspace-brand">
|
|
9
9
|
<div className="workspace-brand__mark" aria-hidden="true">
|
|
@@ -14,5 +14,5 @@ export function WorkspaceBrand({ title, eyebrow = "AGENT OPERATIONS" }: Workspac
|
|
|
14
14
|
<h1>{title}</h1>
|
|
15
15
|
</div>
|
|
16
16
|
</div>
|
|
17
|
-
)
|
|
17
|
+
)
|
|
18
18
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SVGProps } from
|
|
1
|
+
import type { SVGProps } from 'react'
|
|
2
2
|
|
|
3
3
|
/** The canonical Adea mark used by web, desktop, and dialogs. */
|
|
4
4
|
export function WorkspaceLogo(props: SVGProps<SVGSVGElement>) {
|
|
@@ -13,5 +13,5 @@ export function WorkspaceLogo(props: SVGProps<SVGSVGElement>) {
|
|
|
13
13
|
/>
|
|
14
14
|
<path d="m45 35 11 11-4 4-11-11z" fill="#f8fafc" />
|
|
15
15
|
</svg>
|
|
16
|
-
)
|
|
16
|
+
)
|
|
17
17
|
}
|