Skip to content

Commit a2f194b

Browse files
feat(launcher): reorganize flag categories, add CLI preview, new 2026-03-26 flags (#100)
* refactor: rename BotBrowserConsole to BotBrowserLauncher * feat: add kernel management, proxy management, and setup scripts * fix: enable macOS native Edit menu for Cmd+C/V/X/A keyboard shortcuts * chore: upgrade Neutralino runtime to 6.4.0 * chore: remove Neutralino binaries from repo, download via neu update * fix: improve macOS clipboard support with JS fallback for Cmd+V paste * fix: expand macOS clipboard fallback to Cmd+C/X, auto-download Neutralino via postinstall * chore: upgrade Neutralino to 6.5.0 and simplify setup scripts * fix: fix PowerShell setup script ZIP download corruption * feat: enhance proxy workflow with IP check, quick change, and reusable input component * fix: correct checkbox color override and setup script stdin handling * feat: improve profile deletion with auto-stop, group WebRTC settings, prioritize custom exec path * feat: add port protection toggle, fix kernel auto-update cleanup and UI refresh * fix: detect kernel assets by file extension to support renamed Windows/Linux packages * fix: handle non-browser process exits, add crash detection, validate kernel executable paths * docs: add --bot-time-seed documentation, changelog 2026-03-03, value range and per-context cross-links * feat: add proxy save/check, improve table layout and kernel date display - Add "Save to proxy list" button in proxy input for reusing manually entered proxies - Add batch proxy connectivity check with IP/status display in proxy management - Sort proxy list by creation time (newest first) - Fix kernel date display: parse from asset filename, fix timezone offset bug - Simplify profile status column to icon-only (play/stop) with tooltips - Remove year from "Last Launch" date to prevent truncation - Widen window to 1080px, use fixed table layout to prevent horizontal scrollbar - Add column width constraints for profile and proxy tables * feat: redesign profile editor with left nav, advanced config modes, and new fields - Add left-side anchor navigation with scrollspy (IntersectionObserver) - Split Fingerprint into separate Noise and Rendering sections - Replace expansion panel with flat Advanced section layout - Add mode toggles for Executable (kernel/custom), Cookies and Bookmarks (file/input) - Add FPS dropdown (profile/real/custom number) instead of free-text input - Add Save IP button in proxy section for explicit IP saving - Add new fields: Time Seed, Proxy Bypass Regex, Cookies, Bookmarks, Custom Headers - Put username/password on same row in proxy input - Widen status column to prevent icon clipping * fix: replace Save IP with Save to proxy list, unify dropdown option labels * fix: include username and password in proxy duplicate detection Normalize both sides with `|| ''` to handle undefined values, and add password to the comparison so proxies with the same host:port but different credentials are treated as distinct entries. * fix: prevent editing running profiles and remove auto-save IP on proxy check - Block profile editing when browser is running/launching/stopping, show alert dialog instead of silently darkening the background - Remove onIpCheckResult that auto-saved checked IP to proxyIp field * feat(launcher): add automatic self-update with GitHub commit tracking Check for launcher updates on startup and every hour by comparing the local commit hash against the latest launcher-specific commit from GitHub API (path=launcher). When an update is found, silently download, rebuild, and prompt the user to restart. - Add UpdateService with periodic check, ZIP download, and rebuild - Show update status (checking/downloading/building/ready) in sidebar - Display current version (commit hash) at sidebar bottom - Update setup scripts to save commit hash after install/build - Fix sidebar footer layout to stay at bottom via flex container * feat(launcher): improve table UX, add new CLI flags, and proxy input enhancements - Separate row highlight (single click) from checkbox selection (batch ops) - Add double-click to edit on both profile and proxy tables - Add clear proxy button in profile editor - Combine proxy type/host/port into single row layout - Add --bot-stack-seed and --bot-network-info-override CLI flags - Update noise seed from float to integer range - Stack seed uses dropdown (profile/real/custom) like FPS - Rearrange noise settings: seed+scale+timeseed row, fps+stackseed row - Widen proxy type column in proxy list table * fix(launcher): auto-highlight new profiles/proxies and default noise text rects off - Return created profile/proxy ID from dialog so the table highlights the new row after creation, matching the edit-then-highlight behavior - Change botConfigNoiseTextRects default from on to off * feat(launcher): add new CLI flags, clear user data, and unsaved changes guard - Add --bot-config-orientation dropdown in Display & Input section with all orientation variants, noted as mobile profiles only - Add --bot-gpu-emulation toggle in Behavior section for auto GPU rendering backend selection - Add "Clear User Data" action in both profile edit dialog and profile list context menu to delete user-data-dir - Guard profile and proxy edit dialogs against accidental close: Escape, backdrop click, and Cancel now prompt when forms have unsaved changes * feat(launcher): reorganize flag categories, add CLI preview, new 2026-03-26 flags - Restructure sections: Proxy → Proxy & Network, move GPU Emulation to Rendering, History Injection to Identity (now supports count) - Add --bot-enable-variations-in-context and --bot-inject-random-history={number} - Add CLI command preview in Advanced tab + Copy CLI in context menu - Backward compat for old profiles with flags in behavior.* - Fix history count type coercion, add copy snackbar feedback
1 parent a68fafb commit a2f194b

7 files changed

Lines changed: 270 additions & 49 deletions

launcher/src/app/app.component.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@
247247
<mat-icon>upgrade</mat-icon>
248248
<span>Export</span>
249249
</button>
250+
<button mat-menu-item (click)="copyCliCommand(element)">
251+
<mat-icon>terminal</mat-icon>
252+
<span>Copy CLI</span>
253+
</button>
250254
@if (
251255
browserLauncherService.getRunningStatus(element) ==
252256
BrowserProfileStatus.Idle

launcher/src/app/app.component.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
1111
import { MatSidenavModule } from '@angular/material/sidenav';
1212
import { MatSort, MatSortModule } from '@angular/material/sort';
1313
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
14+
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
1415
import { MatToolbarModule } from '@angular/material/toolbar';
1516
import { MatTooltipModule } from '@angular/material/tooltip';
1617
import { RouterOutlet } from '@angular/router';
@@ -54,6 +55,7 @@ export type NavItem = 'profiles' | 'proxies' | 'kernels';
5455
MatListModule,
5556
MatProgressBarModule,
5657
MatTooltipModule,
58+
MatSnackBarModule,
5759
StopPropagationDirective,
5860
ProxyManagementComponent,
5961
KernelManagementComponent,
@@ -69,6 +71,7 @@ export class AppComponent implements AfterViewInit {
6971

7072
readonly AppName = AppName;
7173
readonly #dialog = inject(MatDialog);
74+
readonly #snackBar = inject(MatSnackBar);
7275
currentNav: NavItem = 'profiles';
7376
readonly formatDateTime = formatDateTime;
7477
readonly formatProxyDisplay = formatProxyDisplay;
@@ -312,6 +315,14 @@ export class AppComponent implements AfterViewInit {
312315
});
313316
}
314317

318+
async copyCliCommand(browserProfile: BrowserProfile): Promise<void> {
319+
const flags = BrowserLauncherService.buildProfileFlags(browserProfile);
320+
if (!flags.length) return;
321+
const cli = `chromium-browser \\\n --bot-profile=<path-to-profile> \\\n ${flags.join(' \\\n ')}`;
322+
await Neutralino.clipboard.writeText(cli);
323+
this.#snackBar.open('Copied to clipboard', '', { duration: 2000 });
324+
}
325+
315326
async refreshProfiles(): Promise<void> {
316327
this.loading = true;
317328
try {

launcher/src/app/data/browser-profile.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,12 @@ export const ColorSchemes: ColorScheme[] = ['light', 'dark'];
7171
export type OrientationOption = 'profile' | 'landscape' | 'portrait' | 'landscape-primary' | 'landscape-secondary' | 'portrait-primary' | 'portrait-secondary';
7272
export const OrientationOptions: OrientationOption[] = ['profile', 'landscape', 'portrait', 'landscape-primary', 'landscape-secondary', 'portrait-primary', 'portrait-secondary'];
7373

74-
// Behavior toggles
74+
// Behavior toggles (pure browser UI/runtime behavior)
7575
export interface BehaviorToggles {
76-
botLocalDns?: boolean;
7776
botDisableDebugger?: boolean;
7877
botMobileForceTouch?: boolean;
7978
botAlwaysActive?: boolean;
80-
botInjectRandomHistory?: boolean;
8179
botDisableConsoleMessage?: boolean;
82-
botPortProtection?: boolean;
83-
botNetworkInfoOverride?: boolean;
84-
botGpuEmulation?: boolean;
8580
}
8681

8782
// Identity & Locale config
@@ -93,6 +88,8 @@ export interface IdentityLocaleConfig {
9388
botConfigLocale?: string;
9489
botConfigTimezone?: string;
9590
botConfigLocation?: string;
91+
botInjectRandomHistory?: boolean | number;
92+
botEnableVariationsInContext?: boolean;
9693
}
9794

9895
// Custom User-Agent config
@@ -140,14 +137,19 @@ export interface RenderingMediaConfig {
140137
botConfigMediaTypes?: MediaTypesOption;
141138
botConfigWebrtc?: ProfileRealDisabled;
142139
botWebrtcIce?: string;
140+
botGpuEmulation?: boolean;
143141
}
144142

145-
// Proxy config
143+
// Proxy & Network config
146144
export interface ProxyConfig {
147145
proxyServer?: string;
148146
proxyIp?: string;
149147
botIpService?: string;
150148
proxyBypassRgx?: string;
149+
// Network protection (moved from Behavior)
150+
botLocalDns?: boolean;
151+
botPortProtection?: boolean;
152+
botNetworkInfoOverride?: boolean;
151153
}
152154

153155
// Advanced config

launcher/src/app/edit-browser-profile.component.html

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ <h2 mat-dialog-title>{{ isEdit ? 'Edit' : 'Create' }} Browser Profile</h2>
6767
</button>
6868
</div>
6969

70-
<!-- Proxy -->
70+
<!-- Proxy & Network -->
7171
<div class="section" id="section-proxy">
72-
<div class="section-header">Proxy</div>
72+
<div class="section-header">Proxy & Network</div>
7373
@if (proxies.length > 0) {
7474
<mat-form-field>
7575
<mat-label>Select existing proxy</mat-label>
@@ -114,6 +114,24 @@ <h2 mat-dialog-title>{{ isEdit ? 'Edit' : 'Create' }} Browser Profile</h2>
114114
<input matInput placeholder="e.g. \.(js|css|png)(\?|$)" formControlName="proxyBypassRgx" />
115115
<mat-hint>RE2 regex to bypass proxy for matching URLs</mat-hint>
116116
</mat-form-field>
117+
118+
<div class="section-title">Network Protection</div>
119+
<div class="toggle-grid">
120+
<mat-slide-toggle formControlName="botLocalDns">
121+
Local DNS Resolution
122+
<span class="toggle-hint">Resolve DNS locally instead of through proxy (default: off)</span>
123+
</mat-slide-toggle>
124+
125+
<mat-slide-toggle formControlName="botPortProtection">
126+
Port Protection
127+
<span class="toggle-hint">Protect local ports from scanning (default: off)</span>
128+
</mat-slide-toggle>
129+
130+
<mat-slide-toggle formControlName="botNetworkInfoOverride">
131+
Network Info Override
132+
<span class="toggle-hint">Use profile-defined navigator.connection values (default: off)</span>
133+
</mat-slide-toggle>
134+
</div>
117135
</form>
118136
</div>
119137

@@ -172,6 +190,34 @@ <h2 mat-dialog-title>{{ isEdit ? 'Edit' : 'Create' }} Browser Profile</h2>
172190
<mat-hint class="section-hint">Leave empty or "auto" to derive from IP address</mat-hint>
173191
</form>
174192

193+
<div class="section-title">Session Authenticity</div>
194+
<form [formGroup]="identityLocaleGroup">
195+
<div class="form-row">
196+
<mat-form-field class="flex-1">
197+
<mat-label>History Injection</mat-label>
198+
<mat-select [(value)]="historyMode" (selectionChange)="onHistoryModeChange()">
199+
<mat-option value="">Off</mat-option>
200+
<mat-option value="random">Random</mat-option>
201+
<mat-option value="number">Custom count</mat-option>
202+
</mat-select>
203+
<mat-hint>Inject browsing history entries</mat-hint>
204+
</mat-form-field>
205+
206+
@if (historyMode === 'number') {
207+
<mat-form-field class="flex-1">
208+
<mat-label>History Count</mat-label>
209+
<input matInput type="number" placeholder="e.g. 15" [(ngModel)]="historyCount" [ngModelOptions]="{standalone: true}" (input)="onHistoryCountChange()" />
210+
<mat-hint>Exact number of history entries</mat-hint>
211+
</mat-form-field>
212+
}
213+
</div>
214+
215+
<mat-slide-toggle formControlName="botEnableVariationsInContext" class="standalone-toggle">
216+
X-Client-Data in Incognito
217+
<span class="toggle-hint">Include Chrome variations headers in incognito contexts (default: off)</span>
218+
</mat-slide-toggle>
219+
</form>
220+
175221
<div class="section-title">Custom User-Agent Override</div>
176222
<form [formGroup]="customUserAgentGroup">
177223
<mat-form-field>
@@ -464,6 +510,11 @@ <h2 mat-dialog-title>{{ isEdit ? 'Edit' : 'Create' }} Browser Profile</h2>
464510
<input matInput placeholder="Custom ICE candidates" formControlName="botWebrtcIce" />
465511
</mat-form-field>
466512
</div>
513+
514+
<mat-slide-toggle formControlName="botGpuEmulation" class="standalone-toggle">
515+
GPU Emulation
516+
<span class="toggle-hint">Auto-select optimal GPU rendering backend (default: off)</span>
517+
</mat-slide-toggle>
467518
</form>
468519
</div>
469520

@@ -486,35 +537,10 @@ <h2 mat-dialog-title>{{ isEdit ? 'Edit' : 'Create' }} Browser Profile</h2>
486537
<span class="toggle-hint">Suppress console output (default: on)</span>
487538
</mat-slide-toggle>
488539

489-
<mat-slide-toggle formControlName="botLocalDns">
490-
Local DNS Resolution
491-
<span class="toggle-hint">Use local DNS (default: off)</span>
492-
</mat-slide-toggle>
493-
494540
<mat-slide-toggle formControlName="botMobileForceTouch">
495541
Force Touch (Mobile)
496542
<span class="toggle-hint">Force touch events (default: off)</span>
497543
</mat-slide-toggle>
498-
499-
<mat-slide-toggle formControlName="botInjectRandomHistory">
500-
Inject Random History
501-
<span class="toggle-hint">Add random history (default: off)</span>
502-
</mat-slide-toggle>
503-
504-
<mat-slide-toggle formControlName="botPortProtection">
505-
Port Protection
506-
<span class="toggle-hint">Protect local ports from scanning (default: off)</span>
507-
</mat-slide-toggle>
508-
509-
<mat-slide-toggle formControlName="botNetworkInfoOverride">
510-
Network Info Override
511-
<span class="toggle-hint">Use profile-defined navigator.connection values (default: off)</span>
512-
</mat-slide-toggle>
513-
514-
<mat-slide-toggle formControlName="botGpuEmulation">
515-
GPU Emulation
516-
<span class="toggle-hint">Auto-select optimal GPU rendering backend (default: off)</span>
517-
</mat-slide-toggle>
518544
</form>
519545
</div>
520546

@@ -612,6 +638,22 @@ <h2 mat-dialog-title>{{ isEdit ? 'Edit' : 'Create' }} Browser Profile</h2>
612638
<mat-hint>JSON object with header name-value pairs</mat-hint>
613639
</mat-form-field>
614640
</form>
641+
642+
<!-- CLI Preview -->
643+
<div class="section-title">CLI Command Preview</div>
644+
@if (getCliPreview(); as cli) {
645+
<div class="cli-preview">
646+
<div class="cli-header">
647+
<span class="cli-label">Command</span>
648+
<button mat-icon-button class="copy-btn" (click)="copyCliToClipboard()">
649+
<mat-icon>content_copy</mat-icon>
650+
</button>
651+
</div>
652+
<code class="cli-code">{{ cli }}</code>
653+
</div>
654+
} @else {
655+
<div class="cli-preview cli-empty">No flags configured</div>
656+
}
615657
</div>
616658
</div>
617659
</mat-dialog-content>

launcher/src/app/edit-browser-profile.component.scss

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,53 @@ mat-form-field {
212212
font-size: 13px;
213213
margin-top: 8px;
214214
}
215+
216+
.cli-preview {
217+
padding: 12px;
218+
border-radius: 4px;
219+
font-size: 13px;
220+
line-height: 1.6;
221+
background: rgba(0, 0, 0, 0.04);
222+
border: 1px solid rgba(0, 0, 0, 0.08);
223+
224+
.cli-header {
225+
display: flex;
226+
align-items: center;
227+
justify-content: space-between;
228+
}
229+
230+
.cli-label {
231+
font-weight: 500;
232+
color: rgba(0, 0, 0, 0.6);
233+
}
234+
235+
.copy-btn {
236+
width: 24px;
237+
height: 24px;
238+
padding: 0;
239+
display: inline-flex;
240+
align-items: center;
241+
justify-content: center;
242+
243+
mat-icon {
244+
font-size: 14px;
245+
width: 14px;
246+
height: 14px;
247+
line-height: 14px;
248+
}
249+
}
250+
251+
.cli-code {
252+
display: block;
253+
font-family: 'Courier New', Courier, monospace;
254+
font-size: 12px;
255+
color: rgba(0, 0, 0, 0.87);
256+
white-space: pre-wrap;
257+
word-break: break-all;
258+
margin-top: 4px;
259+
}
260+
261+
&.cli-empty {
262+
color: rgba(0, 0, 0, 0.38);
263+
}
264+
}

0 commit comments

Comments
 (0)