Skip to content

Commit 9ca8e9e

Browse files
committed
Merge branch 'dev'
2 parents 3c05a50 + 3281357 commit 9ca8e9e

17 files changed

Lines changed: 331 additions & 51 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
**The privacy AI coding without agents.** Guide the model to production-grade code with engineer-level control over context. Community-driven, free and open-source.
66

7-
Works with VS Code, and forks like Cursor, Windsurf, etc.
7+
Works with VS Code, and forks like Cursor, Windsurf, and VSCodium.
88

99
✅ **Send prompts anywhere**
1010

@@ -37,7 +37,7 @@ Therefore, CWC is designed to align with LLMs' true capabilities—that is, code
3737

3838
Unlike coding agents that require detailed instructions to understand your intent and locate relevant files, CWC lets you provide context up front, making prompts simpler and responses faster and more accurate.
3939

40-
Select folders and files, enter prompt, and send message via...
40+
Meet the non-agentic workflow—select folders and files, enter prompt, and send message via...
4141

4242
- new chat—to continue in the connected browser
4343
- API call—to use a model provider of choice
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
.dropdown {
2+
position: relative;
3+
width: 100%;
4+
}
5+
6+
.button {
7+
display: flex;
8+
align-items: center;
9+
justify-content: space-between;
10+
gap: var(--padding-8px);
11+
background: var(--vscode-input-background);
12+
color: var(--vscode-input-foreground);
13+
border: 1px solid var(--cwc-border-color);
14+
padding: var(--padding-4px) var(--padding-8px);
15+
border-radius: var(--border-radius-4px);
16+
cursor: pointer;
17+
width: 100%;
18+
text-align: left;
19+
20+
&:hover {
21+
background: var(--vscode-list-hoverBackground);
22+
}
23+
24+
&[data-is-open='true'] {
25+
border-color: var(--vscode-focusBorder);
26+
outline: 1px solid var(--vscode-focusBorder);
27+
outline-offset: -1px;
28+
}
29+
}
30+
31+
.chevron {
32+
transition: transform 0.2s ease;
33+
color: var(--vscode-icon-foreground);
34+
}
35+
36+
.chevron_open {
37+
transform: rotate(180deg);
38+
}
39+
40+
.menu_override {
41+
left: 0;
42+
right: auto;
43+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { useState } from 'react'
2+
import { Dropdown } from './Dropdown'
3+
4+
export default {
5+
component: Dropdown
6+
}
7+
8+
const sample_options: Dropdown.Option<string>[] = [
9+
{ value: 'option1', label: 'Option 1' },
10+
{ value: 'option2', label: 'Option 2' },
11+
{ value: 'option3', label: 'Option 3' }
12+
]
13+
14+
export const Default = () => {
15+
const [value, set_value] = useState('option1')
16+
17+
return (
18+
<div style={{ width: '220px' }}>
19+
<Dropdown options={sample_options} value={value} onChange={set_value} />
20+
</div>
21+
)
22+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { useState, useRef, useEffect } from 'react'
2+
import cn from 'classnames'
3+
import { DropdownMenu } from '../DropdownMenu'
4+
import styles from './Dropdown.module.scss'
5+
6+
export namespace Dropdown {
7+
export type Option<T extends string> = {
8+
value: T
9+
label: string
10+
}
11+
12+
export type Props<T extends string> = {
13+
options: Option<T>[]
14+
value: T
15+
onChange: (value: T) => void
16+
className?: string
17+
max_width?: number
18+
}
19+
}
20+
21+
export const Dropdown = <T extends string>({
22+
options,
23+
value,
24+
onChange,
25+
className,
26+
max_width
27+
}: Dropdown.Props<T>) => {
28+
const [is_open, set_is_open] = useState(false)
29+
const dropdown_ref = useRef<HTMLDivElement>(null)
30+
31+
const selected_option = options.find((opt) => opt.value === value)
32+
33+
const handle_click_outside = (event: MouseEvent) => {
34+
if (
35+
dropdown_ref.current &&
36+
!dropdown_ref.current.contains(event.target as Node)
37+
) {
38+
set_is_open(false)
39+
}
40+
}
41+
42+
useEffect(() => {
43+
document.addEventListener('mousedown', handle_click_outside)
44+
return () => {
45+
document.removeEventListener('mousedown', handle_click_outside)
46+
}
47+
}, [])
48+
49+
const menu_items: DropdownMenu.Item[] = options.map((option) => ({
50+
label: option.label,
51+
is_selected: option.value === value,
52+
on_click: () => {
53+
onChange(option.value)
54+
set_is_open(false)
55+
}
56+
}))
57+
58+
const style = max_width ? { maxWidth: `${max_width}px` } : undefined
59+
60+
return (
61+
<div
62+
className={cn(styles.dropdown, className)}
63+
ref={dropdown_ref}
64+
style={style}
65+
>
66+
<button
67+
className={styles.button}
68+
onClick={() => set_is_open(!is_open)}
69+
data-is-open={is_open}
70+
>
71+
<span>{selected_option?.label ?? 'Select...'}</span>
72+
<span
73+
className={cn(
74+
'codicon codicon-chevron-down',
75+
styles.chevron,
76+
is_open && styles.chevron_open
77+
)}
78+
/>
79+
</button>
80+
{is_open && (
81+
<DropdownMenu items={menu_items} className={styles.menu_override} />
82+
)}
83+
</div>
84+
)
85+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './Dropdown'

‎packages/ui/src/components/editor/common/DropdownMenu/DropdownMenu.module.scss‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
border-radius: var(--border-radius-8px);
77
border: 1px solid var(--vscode-widget-border);
88
box-shadow: 0 0 8px 2px var(--vscode-widget-shadow);
9-
z-index: 1;
9+
z-index: 2;
1010
padding: var(--padding-4px);
1111
width: max-content;
1212
text-align: left;

‎packages/ui/src/components/editor/common/DropdownMenu/DropdownMenu.tsx‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,17 @@ export namespace DropdownMenu {
1212
export type Props = {
1313
items: Item[]
1414
on_mouse_enter?: React.MouseEventHandler<HTMLDivElement>
15+
className?: string
1516
}
1617
}
1718

1819
export const DropdownMenu: React.FC<DropdownMenu.Props> = ({
1920
items,
20-
on_mouse_enter
21+
on_mouse_enter,
22+
className
2123
}) => {
2224
return (
23-
<div className={cn(styles.menu)} onMouseEnter={on_mouse_enter}>
25+
<div className={cn(styles.menu, className)} onMouseEnter={on_mouse_enter}>
2426
{items.map((item, index) => (
2527
<div
2628
key={index}

‎packages/ui/src/styles/global.scss‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
body {
1313
padding: 0;
1414
font-size: var(--font-size-13px);
15-
color: var(--cwc-text-primary);
15+
color: var(--cwc-text-color);
1616
user-select: none;
1717
line-height: 1.4;
1818
}

‎packages/vscode/package.json‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "gemini-coder",
33
"displayName": "Code Web Chat",
44
"description": "The privacy AI coding without agents (CWC)",
5-
"version": "1.511.0",
5+
"version": "1.512.0",
66
"scripts": {
77
"build": "npx vsce package --no-dependencies",
88
"vscode:prepublish": "rimraf out && npm run compile",
@@ -157,7 +157,7 @@
157157
},
158158
{
159159
"command": "codeWebChat.clearChecks",
160-
"title": "Clear All Checks",
160+
"title": "Clear Checks",
161161
"category": "Code Web Chat",
162162
"icon": "$(clear-all)"
163163
},
@@ -175,7 +175,7 @@
175175
},
176176
{
177177
"command": "codeWebChat.clearChecksOpenEditors",
178-
"title": "Clear All Checks",
178+
"title": "Clear Checks",
179179
"category": "Code Web Chat",
180180
"icon": "$(clear-all)"
181181
},
@@ -542,6 +542,15 @@
542542
"default": 60000,
543543
"description": "Threshold for the context size to show a warning."
544544
},
545+
"codeWebChat.clearChecksInWorkspaceBehavior": {
546+
"type": "string",
547+
"enum": [
548+
"ignore-open-editors",
549+
"uncheck-all"
550+
],
551+
"default": "ignore-open-editors",
552+
"description": "Controls the behavior of the 'Clear Checks' action in the Workspace view."
553+
},
545554
"codeWebChat.ignorePatterns": {
546555
"type": "array",
547556
"description": "List of glob patterns to ignore files and folders in the context.",

‎packages/vscode/src/context/providers/workspace-provider.ts‎

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -394,57 +394,70 @@ export class WorkspaceProvider
394394
}, 1000) // Debounce refresh to handle bulk file changes like builds
395395
}
396396
public clear_checks(): void {
397-
// Get a list of currently open files to preserve their check state
398-
const open_files = new Set(
399-
this._get_open_editors().map((uri) => uri.fsPath)
397+
const config = vscode.workspace.getConfiguration('codeWebChat')
398+
const clear_checks_in_workspace_behavior = config.get<string>(
399+
'clearChecksInWorkspaceBehavior'
400400
)
401401

402-
const checked_open_files = Array.from(this.checked_items.entries())
403-
.filter(
404-
([path, state]) =>
405-
open_files.has(path) && state == vscode.TreeItemCheckboxState.Checked
402+
if (clear_checks_in_workspace_behavior == 'uncheck-all') {
403+
this.checked_items.clear()
404+
this.partially_checked_dirs.clear()
405+
this.directory_selected_token_counts.clear()
406+
} else {
407+
// Get a list of currently open files to preserve their check state
408+
const open_files = new Set(
409+
this._get_open_editors().map((uri) => uri.fsPath)
406410
)
407-
.map(([path]) => path)
408411

409-
const new_checked_items = new Map<string, vscode.TreeItemCheckboxState>()
412+
const checked_open_files = Array.from(this.checked_items.entries())
413+
.filter(
414+
([path, state]) =>
415+
open_files.has(path) &&
416+
state == vscode.TreeItemCheckboxState.Checked
417+
)
418+
.map(([path]) => path)
419+
420+
const new_checked_items = new Map<string, vscode.TreeItemCheckboxState>()
410421

411-
for (const [path, state] of this.checked_items.entries()) {
412-
if (open_files.has(path)) {
413-
new_checked_items.set(path, state)
422+
for (const [path, state] of this.checked_items.entries()) {
423+
if (open_files.has(path)) {
424+
new_checked_items.set(path, state)
425+
}
414426
}
415-
}
416427

417-
this.checked_items = new_checked_items
428+
this.checked_items = new_checked_items
418429

419-
this.partially_checked_dirs.clear()
420-
this.directory_selected_token_counts.clear()
430+
this.partially_checked_dirs.clear()
431+
this.directory_selected_token_counts.clear()
421432

422-
for (const file_path of open_files) {
423-
if (this.checked_items.has(file_path)) {
424-
let dir_path = path.dirname(file_path)
425-
const workspace_root = this.get_workspace_root_for_file(file_path)
426-
while (workspace_root && dir_path.startsWith(workspace_root)) {
427-
this._update_parent_state(dir_path)
428-
dir_path = path.dirname(dir_path)
433+
for (const file_path of open_files) {
434+
if (this.checked_items.has(file_path)) {
435+
let dir_path = path.dirname(file_path)
436+
const workspace_root = this.get_workspace_root_for_file(file_path)
437+
while (workspace_root && dir_path.startsWith(workspace_root)) {
438+
this._update_parent_state(dir_path)
439+
dir_path = path.dirname(dir_path)
440+
}
429441
}
430442
}
431-
}
432443

433-
if (checked_open_files.length > 0) {
434-
vscode.window
435-
.showInformationMessage(
436-
`${checked_open_files.length} file${
437-
checked_open_files.length == 1 ? '' : 's'
438-
} remain${checked_open_files.length == 1 ? 's' : ''} checked.`,
439-
'Clear open editors'
440-
)
441-
.then((selection) => {
442-
if (selection == 'Clear open editors') {
443-
vscode.commands.executeCommand('codeWebChat.clearChecksOpenEditors')
444-
}
445-
})
444+
if (checked_open_files.length > 0) {
445+
vscode.window
446+
.showInformationMessage(
447+
`${checked_open_files.length} file${
448+
checked_open_files.length == 1 ? '' : 's'
449+
} remain${checked_open_files.length == 1 ? 's' : ''} checked.`,
450+
'Clear open editors'
451+
)
452+
.then((selection) => {
453+
if (selection == 'Clear open editors') {
454+
vscode.commands.executeCommand(
455+
'codeWebChat.clearChecksOpenEditors'
456+
)
457+
}
458+
})
459+
}
446460
}
447-
448461
this.refresh()
449462
this._on_did_change_checked_files.fire()
450463
}

0 commit comments

Comments
 (0)