Skip to content

Commit 2b24a99

Browse files
committed
refactor: replace window.dispatchEvent with emit for event handling
- Updated various components to use the emit function for event dispatching instead of window.dispatchEvent. - Enhanced event management consistency across the application by standardizing the event emission method. - Modified components including CodeEditor, FileExplorer, and PermissionsToggle to improve maintainability and readability.
1 parent 6e9600e commit 2b24a99

14 files changed

Lines changed: 2033 additions & 900 deletions

components/code-editor.tsx

Lines changed: 409 additions & 192 deletions
Large diffs are not rendered by default.

components/file-explorer.tsx

Lines changed: 259 additions & 107 deletions
Large diffs are not rendered by default.

components/permissions-toggle.tsx

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,23 @@
22

33
import { useState, useRef, useEffect, useCallback } from 'react'
44
import { Icon } from '@iconify/react'
5+
import { emit } from '@/lib/events'
56

67
export type PermissionLevel = 'default' | 'full'
78

89
const LEVELS: Array<{ id: PermissionLevel; label: string; icon: string; desc: string }> = [
9-
{ id: 'default', label: 'Default permissions', icon: 'lucide:shield', desc: 'Agent proposes edits for review before applying' },
10-
{ id: 'full', label: 'Full access', icon: 'lucide:shield-off', desc: 'Agent auto-applies edits and runs commands without confirmation' },
10+
{
11+
id: 'default',
12+
label: 'Default permissions',
13+
icon: 'lucide:shield',
14+
desc: 'Agent proposes edits for review before applying',
15+
},
16+
{
17+
id: 'full',
18+
label: 'Full access',
19+
icon: 'lucide:shield-off',
20+
desc: 'Agent auto-applies edits and runs commands without confirmation',
21+
},
1122
]
1223

1324
const STORAGE_KEY = 'code-editor:agent-permissions'
@@ -32,8 +43,10 @@ export function PermissionsToggle({ size = 'sm' }: Props) {
3243
const buttonRef = useRef<HTMLButtonElement>(null)
3344

3445
useEffect(() => {
35-
try { localStorage.setItem(STORAGE_KEY, level) } catch {}
36-
window.dispatchEvent(new CustomEvent('permissions-change', { detail: { permissions: level } }))
46+
try {
47+
localStorage.setItem(STORAGE_KEY, level)
48+
} catch {}
49+
emit('permissions-change', { permissions: level })
3750
}, [level])
3851

3952
useEffect(() => {
@@ -48,7 +61,7 @@ export function PermissionsToggle({ size = 'sm' }: Props) {
4861
}, [open])
4962

5063
const toggle = useCallback(() => {
51-
setOpen(v => {
64+
setOpen((v) => {
5265
if (!v && buttonRef.current) {
5366
const rect = buttonRef.current.getBoundingClientRect()
5467
setMenuPos({ left: rect.left, bottom: window.innerHeight - rect.top + 4 })
@@ -57,7 +70,7 @@ export function PermissionsToggle({ size = 'sm' }: Props) {
5770
})
5871
}, [])
5972

60-
const current = LEVELS.find(l => l.id === level) ?? LEVELS[0]
73+
const current = LEVELS.find((l) => l.id === level) ?? LEVELS[0]
6174
const isMd = size === 'md'
6275

6376
return (
@@ -69,14 +82,17 @@ export function PermissionsToggle({ size = 'sm' }: Props) {
6982
level === 'full'
7083
? 'text-[var(--warning,#eab308)] bg-[color-mix(in_srgb,var(--warning,#eab308)_8%,transparent)] hover:bg-[color-mix(in_srgb,var(--warning,#eab308)_12%,transparent)]'
7184
: 'text-[var(--text-secondary)] bg-[color-mix(in_srgb,var(--text-primary)_4%,transparent)] hover:bg-[color-mix(in_srgb,var(--text-primary)_7%,transparent)]'
72-
} ${
73-
isMd ? 'gap-1.5 px-3 py-1.5 text-[13px]' : 'gap-1 px-2 py-1 text-[11px]'
74-
}`}
85+
} ${isMd ? 'gap-1.5 px-3 py-1.5 text-[13px]' : 'gap-1 px-2 py-1 text-[11px]'}`}
7586
title={current.desc}
7687
>
7788
<Icon icon={current.icon} width={isMd ? 14 : 12} height={isMd ? 14 : 12} />
78-
{isMd ? current.label : (level === 'full' ? 'Full' : 'Default')}
79-
<Icon icon="lucide:chevron-down" width={isMd ? 10 : 8} height={isMd ? 10 : 8} className="opacity-50" />
89+
{isMd ? current.label : level === 'full' ? 'Full' : 'Default'}
90+
<Icon
91+
icon="lucide:chevron-down"
92+
width={isMd ? 10 : 8}
93+
height={isMd ? 10 : 8}
94+
className="opacity-50"
95+
/>
8096
</button>
8197

8298
{open && menuPos && (
@@ -86,10 +102,13 @@ export function PermissionsToggle({ size = 'sm' }: Props) {
86102
className="fixed z-[9991] w-56 bg-[var(--bg-elevated)] border border-[var(--border)] rounded-xl shadow-xl py-1"
87103
style={{ left: menuPos.left, bottom: menuPos.bottom }}
88104
>
89-
{LEVELS.map(l => (
105+
{LEVELS.map((l) => (
90106
<button
91107
key={l.id}
92-
onClick={() => { setLevel(l.id); setOpen(false) }}
108+
onClick={() => {
109+
setLevel(l.id)
110+
setOpen(false)
111+
}}
93112
className={`w-full flex items-center gap-2.5 px-3 py-2 text-left transition-colors cursor-pointer ${
94113
l.id === level
95114
? l.id === 'full'
@@ -101,9 +120,13 @@ export function PermissionsToggle({ size = 'sm' }: Props) {
101120
<Icon icon={l.icon} width={14} height={14} className="shrink-0" />
102121
<div className="flex-1 min-w-0">
103122
<div className="text-[12px] font-medium">{l.label}</div>
104-
<div className="text-[10px] text-[var(--text-disabled)] leading-tight">{l.desc}</div>
123+
<div className="text-[10px] text-[var(--text-disabled)] leading-tight">
124+
{l.desc}
125+
</div>
105126
</div>
106-
{l.id === level && <Icon icon="lucide:check" width={12} height={12} className="shrink-0" />}
127+
{l.id === level && (
128+
<Icon icon="lucide:check" width={12} height={12} className="shrink-0" />
129+
)}
107130
</button>
108131
))}
109132
</div>

0 commit comments

Comments
 (0)