Skip to content

Commit b9317e2

Browse files
committed
Merge branch 'dev'
2 parents 1a44cd7 + 91ce32c commit b9317e2

26 files changed

Lines changed: 243 additions & 230 deletions

File tree

‎README.md‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,17 @@
22

33
<a href="https://marketplace.visualstudio.com/items?itemName=robertpiosik.gemini-coder" target="_blank"><img src="https://img.shields.io/badge/Install-VS_Code_Marketplace-blue" alt="Get from Visual Studio Code Marketplace" /></a> <a href="https://open-vsx.org/extension/robertpiosik/gemini-coder" target="_blank"><img src="https://img.shields.io/badge/Install-Open_VSX_Registry-a60ee5" alt="Get from Open VSX Registry" /></a> <a href="https://github.com/robertpiosik/CodeWebChat/blob/dev/LICENSE" target="_blank"><img src="https://img.shields.io/badge/License-GPL--3.0-green.svg" alt="GPL-3.0 license" /></a>
44

5-
AI coding without agents. Guide the model to production-grade code with engineer-level control over context.
5+
**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**, and **VSCodium**.
7+
Works with VS Code, and forks like Cursor, Windsurf, etc.
88

99
✅ **Send prompts anywhere**
1010

1111
- Chatbots—_ChatGPT, Claude, Gemini, AI Studio, Qwen, etc._
1212
- Model providers—_Gemini API, OpenRouter, local Ollama, etc._
1313

14-
✅ **Apply responses**—advanced markdown parser for multi-file changes integration \
14+
✅ **Apply responses**—sophisticated markdown parser for multi-file changes integration \
1515
✅ **Fully featured**—code completions, commit messages, checkpoints, and more \
16-
👥 **Community driven**—join our [Discord server](https://discord.com/invite/KJySXsrSX5) and get involved! \
17-
❤️ **Free and open-source**—released under the GPL-3.0 license \
1816
🔒️ **Total privacy**—operates 100% on your local machine
1917

2018
<p>

‎packages/shared/src/constants/dictionary.ts‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ export const dictionary = {
4444
},
4545

4646
warning_message: {
47-
REVIEW_ONGOING:
48-
'Another response review is currently ongoing. Would you like to switch to the new one?',
47+
PREVIEW_ONGOING: 'A new response has been received, switch now?',
4948
SKIPPING_INVALID_PATH: (file_path: string) =>
5049
`Skipping applying change to invalid path: ${file_path}`,
5150
CODE_COMPLETIONS_NO_SELECTION:
@@ -84,7 +83,7 @@ export const dictionary = {
8483
URL_OVERRIDE_DIFFERENT_DOMAIN: (preset_name: string) =>
8584
`URL override for preset "${preset_name}" was discarded because it uses a different domain.`,
8685
CONTEXT_SIZE_WARNING: (threshold: string, percentage: number) =>
87-
`Context exceeds threshold of ${threshold} tokens by ${percentage}%. Unreasonably large context may degrade response quality, hurt usage allowance or incur unexpected costs.`,
86+
`Context exceeds threshold of ${threshold} tokens by ${percentage}%. Excessive context size degrades output quality and increase resource usage.`,
8887
FAILED_TO_CREATE_FILE: (file_path: string) =>
8988
`Failed to create file: ${file_path}`,
9089
FAILED_TO_APPLY_CHANGES_TO_FILE: (file_path: string) =>

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.menu {
22
position: absolute;
3-
top: calc(100% + 4px);
3+
top: calc(100% + var(--padding-4px));
44
right: 0;
55
background-color: var(--vscode-menu-background);
66
border: 1px solid var(--vscode-menu-border);
@@ -10,20 +10,23 @@
1010
padding: var(--padding-4px);
1111
width: max-content;
1212
text-align: left;
13+
min-width: 100%;
1314
}
1415

1516
.item {
1617
display: flex;
1718
justify-content: space-between;
18-
gap: var(--padding-12px);
1919
align-items: center;
20-
padding: var(--padding-4px) var(--padding-8px);
20+
gap: var(--padding-12px);
21+
padding: 0 var(--padding-6px);
22+
height: 24px;
2123
cursor: pointer;
2224
color: var(--vscode-menu-foreground);
2325
white-space: nowrap;
2426
border-radius: var(--border-radius-4px);
2527

26-
&:hover {
28+
&:hover,
29+
&[data-selected='true'] {
2730
background-color: var(--vscode-menu-selectionBackground);
2831
& > span {
2932
color: var(--vscode-menu-selectionForeground);

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,28 @@ export namespace DropdownMenu {
66
label: string
77
shortcut?: string
88
on_click: () => void
9+
is_selected?: boolean
910
}
1011

1112
export type Props = {
1213
items: Item[]
13-
className?: string
14+
on_mouse_enter?: React.MouseEventHandler<HTMLDivElement>
1415
}
1516
}
1617

1718
export const DropdownMenu: React.FC<DropdownMenu.Props> = ({
1819
items,
19-
className
20+
on_mouse_enter
2021
}) => {
2122
return (
22-
<div className={cn(styles.menu, className)}>
23+
<div className={cn(styles.menu)} onMouseEnter={on_mouse_enter}>
2324
{items.map((item, index) => (
24-
<div key={index} className={styles.item} onClick={item.on_click}>
25+
<div
26+
key={index}
27+
className={styles.item}
28+
onClick={item.on_click}
29+
data-selected={item.is_selected}
30+
>
2531
<span>{item.label}</span>
2632
{item.shortcut && (
2733
<span className={styles.shortcut}>{item.shortcut}</span>

‎packages/ui/src/components/editor/panel/ChatInput/ChatInput.module.scss‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
border-radius: var(--border-radius-10px);
99
background-color: var(--vscode-input-background);
1010
cursor: text;
11-
border: 1px solid var(--vscode-commandCenter-inactiveBorder);
11+
border: 1px solid var(--cwc-border-color);
1212
position: relative;
1313

1414
&:hover {
15-
border-color: var(--vscode-commandCenter-activeBorder);
15+
border-color: var(--cwc-border-color-hover);
1616
}
1717

1818
&:focus-within {

‎packages/ui/src/components/editor/panel/Dropdown/Dropdown.module.scss‎

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -45,40 +45,3 @@
4545
color: var(--vscode-icon-foreground);
4646
}
4747
}
48-
49-
.menu {
50-
position: absolute;
51-
right: 0;
52-
margin-top: var(--padding-2px);
53-
z-index: 1;
54-
background-color: var(--vscode-menu-background);
55-
border: 1px solid var(--vscode-menu-border);
56-
border-radius: var(--border-radius-8px);
57-
box-shadow: 0 2px 8px var(--vscode-widget-shadow);
58-
min-width: 100%;
59-
max-height: 200px;
60-
overflow-y: auto;
61-
padding: var(--padding-4px);
62-
63-
&__item {
64-
display: flex;
65-
align-items: center;
66-
height: 24px;
67-
padding: 0 var(--padding-8px);
68-
color: var(--vscode-menu-foreground);
69-
font-size: var(--font-size-13px);
70-
cursor: pointer;
71-
white-space: nowrap;
72-
border-radius: var(--border-radius-4px);
73-
74-
&:hover {
75-
background-color: var(--vscode-menu-selectionBackground);
76-
color: var(--vscode-menu-selectionForeground);
77-
}
78-
79-
&--selected {
80-
background-color: var(--vscode-menu-selectionBackground);
81-
color: var(--vscode-menu-selectionForeground);
82-
}
83-
}
84-
}

‎packages/ui/src/components/editor/panel/Dropdown/Dropdown.tsx‎

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useState, useRef, useEffect } from 'react'
22
import styles from './Dropdown.module.scss'
33
import cn from 'classnames'
4+
import { DropdownMenu } from '../../common/DropdownMenu'
45

56
export namespace Dropdown {
67
export type Option<T extends string> = {
@@ -118,20 +119,14 @@ export const Dropdown = <T extends string>(props: Dropdown.Props<T>) => {
118119
</button>
119120

120121
{is_open && (
121-
<div className={styles.menu} onMouseEnter={handle_mouse_enter}>
122-
{props.options.map((option) => (
123-
<div
124-
key={option.value}
125-
className={cn(styles.menu__item, {
126-
[styles['menu__item--selected']]:
127-
just_opened && option.value == props.selected_value
128-
})}
129-
onClick={() => handle_select(option.value)}
130-
>
131-
{option.label}
132-
</div>
133-
))}
134-
</div>
122+
<DropdownMenu
123+
on_mouse_enter={handle_mouse_enter}
124+
items={props.options.map((option) => ({
125+
label: option.label,
126+
on_click: () => handle_select(option.value),
127+
is_selected: just_opened && option.value == props.selected_value
128+
}))}
129+
/>
135130
)}
136131
</div>
137132
)

‎packages/ui/src/components/editor/panel/ResponsePreview/ResponsePreview.tsx‎

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FC, useState } from 'react'
1+
import { FC, useRef, useState } from 'react'
22
import { FileInPreview, ItemInPreview } from '@shared/types/file-in-preview'
33
import cn from 'classnames'
44
import styles from './ResponsePreview.module.scss'
@@ -29,8 +29,33 @@ export const ResponsePreview: FC<Props> = (props) => {
2929
const [expanded_text_items, set_expanded_text_items] = useState<Set<number>>(
3030
new Set()
3131
)
32+
const scroll_top_ref = useRef(0)
33+
const scrollable_ref = useRef<any>(null)
34+
35+
const toggle_expanded_text_item = (
36+
index: number,
37+
element: HTMLDivElement
38+
) => {
39+
const scrollable_instance = scrollable_ref.current
40+
if (scrollable_instance) {
41+
const scroll_container = scrollable_instance.getScrollElement()
42+
if (scroll_container) {
43+
const scroll_container_rect = scroll_container.getBoundingClientRect()
44+
const element_rect = element.getBoundingClientRect()
45+
46+
if (element_rect.top < scroll_container_rect.top) {
47+
// Element's top edge is above the scrollable viewport's top edge.
48+
// Restore scroll position to the distance of this top edge to the top.
49+
const element_position_in_scrollable_content =
50+
scroll_container.scrollTop +
51+
element_rect.top -
52+
scroll_container_rect.top -
53+
4
54+
scroll_top_ref.current = element_position_in_scrollable_content
55+
}
56+
}
57+
}
3258

33-
const toggle_expanded_text_item = (index: number) => {
3459
set_expanded_text_items((prev) => {
3560
const new_set = new Set(prev)
3661
if (new_set.has(index)) {
@@ -48,7 +73,16 @@ export const ResponsePreview: FC<Props> = (props) => {
4873
const fallback_count = files_in_preview.filter((f) => f.is_fallback).length
4974

5075
return (
51-
<Scrollable key={expanded_text_items.size}>
76+
<Scrollable
77+
ref={scrollable_ref}
78+
key={expanded_text_items.size}
79+
// Used to restore scroll on key change.
80+
// Key is changed to re-calculate simplebar container height.
81+
initial_scroll_top={scroll_top_ref.current}
82+
on_scroll={(top) => {
83+
scroll_top_ref.current = top
84+
}}
85+
>
5286
<div className={styles.container}>
5387
{props.raw_instructions && (
5488
<div className={styles.instructions} title={props.raw_instructions}>
@@ -98,18 +132,17 @@ export const ResponsePreview: FC<Props> = (props) => {
98132
}`}
99133
>
100134
<div className={styles['list__file__left']}>
101-
{files_in_preview.length > 1 && (
102-
<Checkbox
103-
checked={file.is_checked}
104-
on_change={(checked) => {
105-
props.on_toggle_file({
106-
file_path: file.file_path,
107-
workspace_name: file.workspace_name,
108-
is_checked: checked
109-
})
110-
}}
111-
/>
112-
)}
135+
<Checkbox
136+
checked={file.is_checked}
137+
disabled={files_in_preview.length == 1}
138+
on_change={(checked) => {
139+
props.on_toggle_file({
140+
file_path: file.file_path,
141+
workspace_name: file.workspace_name,
142+
is_checked: checked
143+
})
144+
}}
145+
/>
113146
<div
114147
className={cn(styles['list__file__left__label'], {
115148
[styles['list__file__left__label--new']]: file.is_new,
@@ -203,7 +236,9 @@ export const ResponsePreview: FC<Props> = (props) => {
203236
key={index}
204237
content={item.content}
205238
is_expanded={expanded_text_items.has(index)}
206-
on_toggle={() => toggle_expanded_text_item(index)}
239+
on_toggle={(element) =>
240+
toggle_expanded_text_item(index, element)
241+
}
207242
/>
208243
)
209244
}

‎packages/ui/src/components/editor/panel/ResponsePreview/components/TextItem.tsx‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import styles from './TextItem.module.scss'
66
type Props = {
77
content: string
88
is_expanded: boolean
9-
on_toggle: () => void
9+
on_toggle: (element: HTMLDivElement) => void
1010
}
1111

1212
export const TextItem: FC<Props> = ({ content, is_expanded, on_toggle }) => {
@@ -29,7 +29,11 @@ export const TextItem: FC<Props> = ({ content, is_expanded, on_toggle }) => {
2929
[styles['text--collapsed']]: !is_expanded,
3030
[styles['text--overflowing']]: !is_expanded && is_overflowing
3131
})}
32-
onClick={is_overflowing || is_expanded ? on_toggle : undefined}
32+
onClick={
33+
is_overflowing || is_expanded
34+
? () => ref.current && on_toggle(ref.current)
35+
: undefined
36+
}
3337
>
3438
<ReactMarkdown disallowedElements={['hr']}>{content}</ReactMarkdown>
3539
</div>

0 commit comments

Comments
 (0)