Skip to content

Commit a055a25

Browse files
authored
Merge pull request #53 from RoopikLabs/project-agent-integration
Project agent integration
2 parents 80eb909 + a721160 commit a055a25

18 files changed

Lines changed: 1667 additions & 190 deletions

File tree

extensions/roopik-roo/src/activate/registerCommands.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export const registerCommands = (options: RegisterCommandOptions) => {
7171
}
7272

7373
const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOptions): Record<CommandId, any> => ({
74-
activationCompleted: () => {},
74+
activationCompleted: () => { },
7575
cloudButtonClicked: () => {
7676
const visibleProvider = getVisibleProviderOrLog(outputChannel)
7777

@@ -136,8 +136,10 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
136136
},
137137
newTask: handleNewTask,
138138
externalContext: async (payload?: { promptText?: string; images?: string[]; autoSend?: boolean }) => {
139-
const promptText = payload?.promptText?.trim();
140-
if (!promptText) {
139+
const promptText = payload?.promptText?.trim() || '';
140+
141+
// Allow empty prompt if images are provided
142+
if (!promptText && (!payload?.images || payload.images.length === 0)) {
141143
return;
142144
}
143145

extensions/roopik-roo/tsconfig.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
"useDefineForClassFields": true,
2121
"useUnknownInCatchVariables": false
2222
},
23-
"include": ["."],
23+
// "include": ["."],
24+
"include": ["src"],
2425
"exclude": [
2526
"node_modules",
2627
"**/__tests__/**",
28+
"webview-ui",
2729
"**/*.spec.ts",
2830
"**/*.test.ts",
2931
"packages/evals/**"

src/vs/workbench/contrib/roopik/browser/projectMode/components/browserControlBar.ts

Lines changed: 88 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ export interface IBrowserControlBarConfig {
2727
showHardReload?: boolean;
2828
showCopyUrl?: boolean;
2929
showBookmarks?: boolean;
30-
showEditMode?: boolean;
3130
showPendingChanges?: boolean;
3231
}
3332

@@ -49,6 +48,7 @@ export interface IBrowserControlBarCallbacks {
4948
onStylePanelToggle?: () => void; // Toggle style panel visibility
5049
onHardReload?: () => void;
5150
onScreenshot?: () => void;
51+
onScreenshotClip?: () => void; // Clip mode (drag-to-select region)
5252
onCopyUrl?: () => void;
5353

5454
// Bookmarks
@@ -58,9 +58,6 @@ export interface IBrowserControlBarCallbacks {
5858
getBookmarks?: () => BrowserBookmark[];
5959
isBookmarked?: (url: string) => boolean;
6060

61-
// Edit Mode (canvas-like bottom action bar)
62-
onEditModeToggle?: (enabled: boolean) => void;
63-
6461
// Pending Changes
6562
onPendingChangesClick?: () => void;
6663
}
@@ -87,10 +84,6 @@ export class BrowserControlBar extends Disposable {
8784
private isBookmarkOverlayVisible: boolean = false;
8885
private bookmarkHideTimeout: number | undefined;
8986

90-
// Edit Mode state
91-
private editModeButton: HTMLButtonElement | undefined;
92-
private isEditModeActive: boolean = false;
93-
9487
// Feature buttons for active state styling
9588
private inspectModeButton: HTMLButtonElement | undefined;
9689
private stylePanelButton: HTMLButtonElement | undefined;
@@ -116,10 +109,11 @@ export class BrowserControlBar extends Disposable {
116109
const container = document.createElement('div');
117110
container.style.display = 'flex';
118111
container.style.alignItems = 'center';
119-
container.style.padding = '8px';
120-
container.style.gap = '8px';
121-
container.style.borderBottom = '1px solid var(--vscode-panel-border)';
122-
container.style.backgroundColor = 'var(--vscode-editor-background)';
112+
container.style.padding = '4px 8px';
113+
container.style.gap = '4px';
114+
container.style.border = '1px solid var(--vscode-panel-border)';
115+
container.style.borderTop = 'none';
116+
container.style.backgroundColor = 'var(--vscode-sideBar-background)';
123117
container.style.position = 'relative'; // Required for absolute positioning of progress bar
124118
container.style.overflow = 'hidden'; // Ensure progress bar doesn't overflow
125119
parent.appendChild(container);
@@ -172,12 +166,6 @@ export class BrowserControlBar extends Disposable {
172166
// Stop Dev Server button (placeholder - feature coming later)
173167
this.createIconButton(Codicon.debugStop, 'Stop Dev Server', () => this.callbacks.onStopDevServer());
174168

175-
// Edit Mode button (shows/hides the bottom action bar for canvas-like editing)
176-
if (this.config.showEditMode && this.callbacks.onEditModeToggle) {
177-
this.editModeButton = this.createIconButton(Codicon.edit, 'Toggle Edit Mode', () => this.toggleEditMode());
178-
this.updateEditModeButtonState();
179-
}
180-
181169
// Separator before action buttons
182170
this.createSeparator();
183171

@@ -196,9 +184,9 @@ export class BrowserControlBar extends Disposable {
196184
this.devToolsButton = this.createIconButton(Codicon.terminal, 'Toggle DevTools', () => this.callbacks.onDevTools!());
197185
}
198186

199-
// Screenshot button
200-
if (this.config.showScreenshot && this.callbacks.onScreenshot) {
201-
this.createIconButton(Codicon.deviceCamera, 'Take Screenshot', () => this.callbacks.onScreenshot!());
187+
// Screenshot button (left click = clip, right click = full)
188+
if (this.config.showScreenshot && this.callbacks.onScreenshot && this.callbacks.onScreenshotClip) {
189+
this.createDualActionScreenshotButton();
202190
}
203191

204192
// Pending Changes button with badge
@@ -404,21 +392,21 @@ export class BrowserControlBar extends Disposable {
404392
private createIconButton(icon: ThemeIcon, tooltip: string, onClick: () => void): HTMLButtonElement {
405393
const button = document.createElement('button');
406394
button.title = tooltip;
407-
button.style.padding = '4px';
395+
button.style.padding = '2px';
408396
button.style.cursor = 'pointer';
409397
button.style.border = 'none';
410398
button.style.backgroundColor = 'transparent';
411399
button.style.borderRadius = '2px';
412400
button.style.display = 'flex';
413401
button.style.alignItems = 'center';
414402
button.style.justifyContent = 'center';
415-
button.style.width = '28px';
416-
button.style.height = '28px';
403+
button.style.width = '24px';
404+
button.style.height = '24px';
417405
button.style.color = 'var(--vscode-foreground)';
418406

419407
const iconElement = document.createElement('span');
420408
iconElement.className = ThemeIcon.asClassName(icon);
421-
iconElement.style.fontSize = '16px';
409+
iconElement.style.fontSize = '14px';
422410
button.appendChild(iconElement);
423411

424412
button.onmouseenter = () => {
@@ -436,12 +424,60 @@ export class BrowserControlBar extends Disposable {
436424
return button;
437425
}
438426

427+
/**
428+
* Create dual-action screenshot button
429+
* Left click = clip mode, Right click = full screenshot
430+
*/
431+
private createDualActionScreenshotButton(): void {
432+
const button = document.createElement('button');
433+
button.title = 'Click to clip, right click to capture whole screen';
434+
button.style.padding = '2px';
435+
button.style.cursor = 'pointer';
436+
button.style.border = 'none';
437+
button.style.backgroundColor = 'transparent';
438+
button.style.borderRadius = '2px';
439+
button.style.display = 'flex';
440+
button.style.alignItems = 'center';
441+
button.style.justifyContent = 'center';
442+
button.style.width = '24px';
443+
button.style.height = '24px';
444+
button.style.color = 'var(--vscode-foreground)';
445+
446+
const iconElement = document.createElement('span');
447+
iconElement.className = ThemeIcon.asClassName(Codicon.deviceCamera);
448+
iconElement.style.fontSize = '14px';
449+
button.appendChild(iconElement);
450+
451+
button.onmouseenter = () => {
452+
button.style.backgroundColor = 'var(--vscode-toolbar-hoverBackground)';
453+
};
454+
button.onmouseleave = () => {
455+
button.style.backgroundColor = 'transparent';
456+
};
457+
458+
// Left click = clip mode
459+
button.onclick = (e) => {
460+
e.stopPropagation();
461+
e.preventDefault();
462+
this.callbacks.onScreenshotClip?.();
463+
};
464+
465+
// Right click = full screenshot
466+
button.oncontextmenu = (e) => {
467+
e.preventDefault();
468+
e.stopPropagation();
469+
this.callbacks.onScreenshot?.();
470+
};
471+
472+
this.container.appendChild(button);
473+
}
474+
439475
private createSeparator(): void {
440476
const separator = document.createElement('div');
441477
separator.style.width = '1px';
442-
separator.style.height = '20px';
478+
separator.style.height = '16px';
443479
separator.style.backgroundColor = 'var(--vscode-panel-border)';
444-
separator.style.margin = '0 4px';
480+
separator.style.margin = '0 2px';
445481
this.container.appendChild(separator);
446482
}
447483

@@ -458,14 +494,25 @@ export class BrowserControlBar extends Disposable {
458494
input.type = 'text';
459495
input.placeholder = 'Enter URL (e.g., http://localhost:3000)';
460496
input.style.width = '100%';
461-
input.style.padding = '6px 12px';
462-
input.style.paddingRight = this.config.showBookmarks ? '32px' : '12px'; // Space for star
497+
input.style.padding = '4px 8px';
498+
input.style.paddingRight = this.config.showBookmarks ? '28px' : '8px'; // Space for star
463499
input.style.border = '1px solid var(--vscode-input-border)';
464500
input.style.backgroundColor = 'var(--vscode-input-background)';
465501
input.style.color = 'var(--vscode-input-foreground)';
466-
input.style.borderRadius = '2px';
467-
input.style.fontSize = '13px';
502+
input.style.borderRadius = '3px';
503+
input.style.fontSize = '12px';
468504
input.style.boxSizing = 'border-box';
505+
input.style.outline = 'none';
506+
507+
// Focus/blur handlers for visual feedback
508+
input.onfocus = () => {
509+
input.style.border = '1px solid var(--vscode-focusBorder)';
510+
input.style.outline = '1px solid var(--vscode-focusBorder)';
511+
};
512+
input.onblur = () => {
513+
input.style.border = '1px solid var(--vscode-input-border)';
514+
input.style.outline = 'none';
515+
};
469516

470517
input.onkeydown = (e) => {
471518
if (e.key === 'Enter') {
@@ -965,54 +1012,6 @@ export class BrowserControlBar extends Disposable {
9651012
return item;
9661013
}
9671014

968-
// ============================================
969-
// Edit Mode
970-
// ============================================
971-
972-
/**
973-
* Toggle edit mode (shows/hides the bottom action bar)
974-
*/
975-
private toggleEditMode(): void {
976-
this.isEditModeActive = !this.isEditModeActive;
977-
this.updateEditModeButtonState();
978-
this.callbacks.onEditModeToggle?.(this.isEditModeActive);
979-
}
980-
981-
/**
982-
* Update the edit mode button appearance based on state
983-
*/
984-
private updateEditModeButtonState(): void {
985-
if (!this.editModeButton) {
986-
return;
987-
}
988-
989-
if (this.isEditModeActive) {
990-
// Active state - highlighted (override hover handlers)
991-
this.editModeButton.style.backgroundColor = 'var(--vscode-toolbar-activeBackground, rgba(99, 102, 241, 0.2))';
992-
this.editModeButton.style.color = 'var(--vscode-focusBorder, #007acc)';
993-
994-
// Keep highlighted even on hover
995-
this.editModeButton.onmouseenter = () => {
996-
this.editModeButton!.style.backgroundColor = 'var(--vscode-toolbar-activeBackground, rgba(99, 102, 241, 0.3))';
997-
};
998-
this.editModeButton.onmouseleave = () => {
999-
this.editModeButton!.style.backgroundColor = 'var(--vscode-toolbar-activeBackground, rgba(99, 102, 241, 0.2))';
1000-
};
1001-
} else {
1002-
// Inactive state - normal hover behavior
1003-
this.editModeButton.style.backgroundColor = 'transparent';
1004-
this.editModeButton.style.color = 'var(--vscode-foreground)';
1005-
1006-
// Restore normal hover handlers
1007-
this.editModeButton.onmouseenter = () => {
1008-
this.editModeButton!.style.backgroundColor = 'var(--vscode-toolbar-hoverBackground)';
1009-
};
1010-
this.editModeButton.onmouseleave = () => {
1011-
this.editModeButton!.style.backgroundColor = 'transparent';
1012-
};
1013-
}
1014-
}
1015-
10161015
// ============================================
10171016
// Pending Changes Button
10181017
// ============================================
@@ -1034,20 +1033,21 @@ export class BrowserControlBar extends Disposable {
10341033
display: flex;
10351034
align-items: center;
10361035
justify-content: center;
1037-
width: 26px;
1038-
height: 26px;
1036+
width: 24px;
1037+
height: 24px;
10391038
padding: 0;
10401039
border: none;
10411040
background: transparent;
10421041
color: var(--vscode-foreground);
10431042
cursor: pointer;
1044-
border-radius: 4px;
1043+
border-radius: 3px;
10451044
`;
10461045
this.pendingChangesButton.title = 'Pending Changes';
10471046

10481047
// Icon
10491048
const icon = document.createElement('span');
10501049
icon.className = ThemeIcon.asClassName(Codicon.diff);
1050+
icon.style.fontSize = '14px';
10511051
this.pendingChangesButton.appendChild(icon);
10521052

10531053
// Hover effects
@@ -1069,14 +1069,14 @@ export class BrowserControlBar extends Disposable {
10691069
position: absolute;
10701070
top: -2px;
10711071
right: -2px;
1072-
min-width: 14px;
1073-
height: 14px;
1074-
padding: 0 4px;
1075-
font-size: 10px;
1072+
min-width: 12px;
1073+
height: 12px;
1074+
padding: 0 3px;
1075+
font-size: 9px;
10761076
font-weight: 600;
1077-
line-height: 14px;
1077+
line-height: 12px;
10781078
text-align: center;
1079-
border-radius: 7px;
1079+
border-radius: 6px;
10801080
background: var(--vscode-badge-background, #007acc);
10811081
color: var(--vscode-badge-foreground, #fff);
10821082
display: none;

0 commit comments

Comments
 (0)