diff --git a/.vscode-test.mjs b/.vscode-test.mjs index e894ab22db40b..5c6e0ad583b11 100644 --- a/.vscode-test.mjs +++ b/.vscode-test.mjs @@ -4,7 +4,7 @@ export default defineConfig([ { label: 'Unit Tests', files: 'out/tests/**/*.test.js', - version: 'insiders', + version: 'stable', mocha: { ui: 'tdd', timeout: 20000, diff --git a/.vscode/launch.json b/.vscode/launch.json index 643773eecfad6..65c30e64648cb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -17,7 +17,7 @@ "sourceMapRenames": true, "sourceMaps": true, "trace": true, - // "urlFilter": "*eamodio.gitlens*", + "urlFilter": "*eamodio.gitlens*", "webRoot": "${workspaceFolder}/src/webviews/apps" }, "outFiles": ["${workspaceFolder}/dist/**/*.js"], @@ -55,7 +55,7 @@ "sourceMapRenames": true, "sourceMaps": true, "trace": true, - // "urlFilter": "*eamodio.gitlens*", + "urlFilter": "*eamodio.gitlens*", "webRoot": "${workspaceFolder}" }, "outFiles": ["${workspaceFolder}/dist/browser/**/*.js"], @@ -87,7 +87,7 @@ "sourceMapRenames": true, "sourceMaps": true, "trace": true, - // "urlFilter": "*eamodio.gitlens*", + "urlFilter": "*eamodio.gitlens*", "webRoot": "${workspaceFolder}/src/webviews/apps" }, "outFiles": ["${workspaceFolder}/dist/**/*.js"], @@ -140,7 +140,7 @@ "sourceMapRenames": true, "sourceMaps": true, "trace": true, - // "urlFilter": "*eamodio.gitlens*", + "urlFilter": "*eamodio.gitlens*", "webRoot": "${workspaceFolder}/src/webviews/apps" }, "outFiles": ["${workspaceFolder}/dist/**/*.js"], @@ -179,7 +179,7 @@ "sourceMapRenames": true, "sourceMaps": true, "trace": true, - // "urlFilter": "*eamodio.gitlens*", + "urlFilter": "*eamodio.gitlens*", "webRoot": "${workspaceFolder}" }, "outFiles": ["${workspaceFolder}/dist/browser/**/*.js"], @@ -211,7 +211,7 @@ "sourceMapRenames": true, "sourceMaps": true, "trace": true, - // "urlFilter": "*eamodio.gitlens*", + "urlFilter": "*eamodio.gitlens*", "webRoot": "${workspaceFolder}/src/webviews/apps" }, "outFiles": ["${workspaceFolder}/dist/**/*.js"], diff --git a/.vscode/settings.json b/.vscode/settings.json index 85e45283a8e1c..857995de54fed 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,10 +5,6 @@ "files.associations": { ".eslintrc*.json": "jsonc" }, - "files.exclude": { - "**/.vscode-test": true, - "**/.vscode-test-web": true - }, "files.insertFinalNewline": true, "files.trimTrailingWhitespace": true, "githubIssues.queries": [ diff --git a/AGENTS.md b/AGENTS.md index c0eed5aaedd07..b0728a82d5518 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,199 +1,598 @@ -# GitLens Copilot Instructions +# GitLens Development Guide -This workspace contains **GitLens** - a VS Code extension that supercharges Git functionality. Below are key development guidelines and architecture insights. +This workspace contains **GitLens** - a powerful VS Code extension that supercharges Git functionality. It provides blame annotations, commit history visualization, repository exploration, and many advanced Git workflows. The codebase supports both desktop VS Code (Node.js) and VS Code for Web (browser/webworker) environments. -## Core Commands +## Development Commands + +### Setup + +```bash +pnpm install # Install dependencies (requires Node >= 22.12.0, pnpm >= 10.x) +``` ### Build & Development -- `pnpm run build` - Full development build -- `pnpm run build:quick` - Fast build without linting -- `pnpm run watch` - Watch mode for development -- `pnpm run watch:quick` - Fast watch mode without linting -- `pnpm run bundle` - Production bundle +```bash +pnpm run rebuild # Complete rebuild from scratch +pnpm run build # Full development build +pnpm run build:quick # Fast build without linting +pnpm run build:extension # Build only the extension (Node.js) +pnpm run build:webviews # Build only webviews +pnpm run bundle # Production bundle +pnpm run bundle:extension # Production bundle (extension only) +``` + +### Watch Mode + +```bash +pnpm run watch # Watch mode for development +pnpm run watch:quick # Fast watch mode without linting +pnpm run watch:extension # Watch extension only +pnpm run watch:webviews # Watch webviews only +pnpm run watch:tests # Watch test files +``` ### Testing & Quality -- `pnpm run test` - Run unit tests with vscode-test -- `pnpm run test:e2e` - End-to-end tests with Playwright -- `pnpm run lint` - ESLint with TypeScript rules -- `pnpm run lint:fix` - Auto-fix linting issues -- `pnpm run pretty` - Format with Prettier +```bash +pnpm run test # Run VS Code extension tests +pnpm run test:e2e # Run Playwright E2E tests +pnpm run build:tests # Build test files with esbuild +pnpm run lint # Run ESLint with TypeScript rules +pnpm run lint:fix # Auto-fix linting issues +pnpm run pretty # Format code with Prettier +pnpm run pretty:check # Check formatting +``` ### Specialized Commands -- `pnpm run build:tests` - Build test files with esbuild -- `pnpm run generate:contributions` - Generate package.json contributions from contributions.json -- `pnpm run generate:commandTypes` - Generate command types from contributions -- `pnpm run web` - Run extension in web environment for testing +```bash +pnpm run generate:contributions # Generate package.json contributions from contributions.json +pnpm run extract:contributions # Extract contributions from package.json to contributions.json +pnpm run generate:commandTypes # Generate command types from contributions +pnpm run build:icons # Build icon font from SVG sources +pnpm run web # Run extension in web environment for testing +pnpm run package # Create VSIX package +``` -## High-Level Architecture +### Debugging + +- Use **"Watch & Run"** launch configuration (F5) for desktop debugging +- Use **"Watch & Run (web)"** for webworker/browser debugging +- Press `Ctrl+Shift+P` → "Tasks: Run Task" → "watch" to start build task +- Tests are co-located with source files in `__tests__/` directories +- Webview changes can be refreshed without restarting extension -### Core Container System +## High-Level Architecture -- **Container** (`src/container.ts`) - Main dependency injection container, singleton pattern +### Directory Structure + +``` +src/ +├── extension.ts # Extension entry point, activation logic +├── container.ts # Service Locator - manages all services (singleton) +├── @types/ # TypeScript type definitions +├── annotations/ # Editor decoration providers +├── autolinks/ # Auto-linking issues/PRs in commit messages & branch names +├── codelens/ # Editor CodeLens providers +├── commands/ # 100+ command implementations +│ ├── git/ # Git-wizard sub-commands +│ └── *.ts # Individual command files +├── env/ # Environment-specific implementations +│ ├── node/ # Node.js (desktop) implementations +│ │ └── git/ +│ │ ├── git.ts # Git command execution +│ │ ├── localGitProvider.ts # Local Git provider (child_process) +│ │ ├── vslsGitProvider.ts # Local Live Share Git provider +│ │ └── sub-providers/ # Local sub-providers for specific Git operations +│ │ ├── branches.ts +│ │ ├── commits.ts +│ │ └── ... (15 total) +│ └── browser/ # Browser/webworker implementations +├── git/ # Git abstraction layer +│ ├── gitProvider.ts # Git provider interface +│ ├── gitProviderService.ts # Manages multiple Git providers +│ ├── models/ # Git model types (Branch, Commit, etc.) +│ ├── parsers/ # Output parsers for Git command results +│ ├── remotes/ # Remote provider and integration management +│ └── sub-providers/ # Shared sub-providers for specific Git operations +├── hovers/ # Editor hover providers +├── plus/ # Pro features (non-OSS, see LICENSE.plus) +│ ├── ai/ # AI features (commit messages, explanations, changelogs) +│ ├── gk/ # GitKraken-specific features (account, subscription, etc.) +│ └── integrations/ # Rich Git host & issue tracker integrations (GitHub, GitLab, Jira, etc.) +│ └── providers/ +│ └── github/ +│ ├── githubGitProvider.ts +│ └── sub-providers/ # 11 GitHub-specific sub-providers +├── quickpicks/ # Quick pick/input (quick menus) implementations +├── statusbar/ # Status bar item management +├── system/ # Utility libraries +│ ├── utils/ # Utilities usable in both host and webviews +│ └── utils/-webview/ # Extension host-specific utilities +├── telemetry/ # Usage analytics and error reporting +├── terminal/ # Terminal integration providers +├── trackers/ # Tracks document state and blames +├── uris/ # Deep link uri handling +├── views/ # Tree view providers (sidebar views) +│ ├── commitsView.ts +│ ├── branchesView.ts +│ └── ... +├── vsls/ # Live Share support +└── webviews/ # Webview implementations + ├── apps/ # Webview UI apps (Lit only) + │ ├── shared/ # Common UI components using Lit + │ ├── commitDetails/ + │ ├── rebase/ + │ ├── settings/ + │ └── plus/ # Pro webview apps + │ ├── home/ + │ ├── graph/ + │ ├── timeline/ + │ ├── patchDetails/ + │ └── composer/ + ├── protocol.ts # IPC protocol for webview communication + └── webviewController.ts # Base controller for all webviews +tests/ # E2E and Unit tests +walkthroughs/ # Welcome and tips walkthroughs +``` + +### Core Architectural Patterns + +**1. Service Locator (Container)** + +- `src/container.ts` - Main dependency injection container using singleton pattern +- Manages 30+ services with lazy initialization - All services registered in constructor and exposed as getters - Handles lifecycle, configuration changes, and service coordination - -### Major Services & Providers +- Example services: GitProviderService, SubscriptionService, TelemetryService, AIProviderService + +**2. Provider Pattern for Git Operations** + +- `GitProviderService` manages multiple Git providers (local, remote, GitHub, etc.) +- Allows environment-specific implementations: + - **LocalGitProvider** (`src/env/node/git/localGitProvider.ts`): Executes Git via `child_process` for Node.js + - **GitHubGitProvider** (`src/plus/integrations/providers/github/githubGitProvider.ts`): Uses GitHub API for browser +- Each provider implements the `GitProvider` interface + - Both providers use a shared set of sub-providers (in `src/git/sub-providers/`) for specific Git operations + - LocalGitProvider uses 15 specialized sub-providers (in `src/env/node/git/sub-providers/`): + - `branches`, `commits`, `config`, `contributors`, `diff`, `graph`, `patch`, `refs`, `remotes`, `revision`, `staging`, `stash`, `status`, `tags`, `worktrees` + - GitHubGitProvider uses 11 specialized sub-providers (in `src/plus/integrations/providers/github/sub-providers/`): + - `branches`, `commits`, `config`, `contributors`, `diff`, `graph`, `refs`, `remotes`, `revision`, `status`, `tags` + +**3. Layered Architecture** + +``` +VS Code Extension API + ↓ +Commands (100+ command handlers in src/commands/) + ↓ +Controllers (Webviews, Views, Annotations, CodeLens) + ↓ +Services (Git, Telemetry, Storage, Integrations, AI, Subscription) + ↓ +Git Providers (LocalGitProvider, GitHubGitProvider, etc.) + ↓ +Git Execution (Node: child_process | Browser: APIs (GitHub)) +``` + +**4. Webview IPC Protocol** + +- Webviews use typed message-passing with three message types: + - **Commands**: Fire-and-forget actions (no response) + - **Requests**: Request/response pairs with Promise-based handling + - **Notifications**: Extension → Webview state updates +- Protocol defined in `src/webviews/protocol.ts` +- **Host-Guest Communication**: IPC between extension host and webviews +- Webviews built with **Lit Elements only** for reactive UI components +- **State Management**: Context providers with Lit reactive patterns and signals +- **Major webviews**: + - **Community**: Commit Details, Rebase, Settings + - **Pro** (`apps/plus/`): Home (includes Launchpad), Commit Graph, Timeline, Patch Details, Commit Composer +- Webviews bundled separately from extension (separate webpack config) + +**5. Caching Strategy** + +- Multiple caching layers for performance: + - `GitCache`: Repository-level Git data caching + - `PromiseCache`: In-flight request deduplication + - `@memoize` decorator: Function result memoization + - VS Code storage API: Persistent state across sessions + +### Major Services & Components + +**Core Services** (accessed via Container) - **GitProviderService** - Core Git operations and repository management - **SubscriptionService** - GitLens Pro subscription and account management -- **IntegrationService** - GitHub/GitLab/etc integrations -- **AIProviderService** - AI features (commit messages, explanations) -- **WebviewsController** - Manages all webview panels (Graph, Home, etc) -- **AutolinksProvider** - Auto-linking issues/PRs in commit messages +- **IntegrationService** - GitHub/GitLab/Bitbucket/Azure DevOps integrations +- **AIProviderService** - AI features (commit messages, explanations, changelogs) - **TelemetryService** - Usage analytics and error reporting +- **WebviewsController** - Manages all webview panels (Graph, Home, Settings, etc.) +- **AutolinksProvider** - Auto-linking issues/PRs in commit messages +- **DocumentTracker** - Tracks file changes and editor state +- **FileAnnotationController** - Blame, heatmap, and change annotations -### VS Code Contributions +**VS Code Contributions** -- Commands, Menus, Submenus, Keybindings, and Views are defined in `contributions.json` -- Contributions are generated from `contributions.json` into `package.json` via `pnpm run generate:contributions` -- Contributions can also be extracted from `package.json` into `contributions.json` via `pnpm run extract:contributions` +- Commands, Menus, Submenus, Keybindings, and Views defined in `contributions.json` +- Generate package.json: `pnpm run generate:contributions` +- Extract from package.json: `pnpm run extract:contributions` +- All other VS Code contributions are defined in `package.json` (activation events, settings, etc.) -### Webview Architecture +**Extension Activation** (`src/extension.ts`) -- **Shared Components** (`src/webviews/apps/shared/`) - Common UI components using Lit -- **Host-Guest Communication** - IPC between extension and webviews -- **State Management** - Context providers with Lit reactive patterns -- Major webviews: Home, Commit Graph, Timeline, Launchpad, Settings +- Activates on `onStartupFinished`, file system events, or specific webview opens +- Creates the `Container` singleton +- Registers all commands, views, providers, and decorations -### Git Integration +**Commands** (`src/commands/`) -- **GitProviderService** - Abstracts Git operations across different providers -- **Repository Models** - Strongly typed Git entities (Branch, Commit, Tag, etc) -- **DocumentTracker** - Tracks file changes and editor state -- **FileAnnotationController** - Blame, heatmap, and change annotations +- 100+ commands registered in `package.json` (generated from `contributions.json`) +- Command IDs auto-generated in `src/constants.commands.generated.ts` +- Commands grouped by functionality (git operations, views, webviews, etc.) + +**Views** (`src/views/`) + +- Tree views: Commits, Branches, Remotes, Stashes, Tags, Worktrees, Contributors, Repositories +- Each view has a tree data provider implementing VS Code's `TreeDataProvider` +- Nodes are hierarchical (repository → branch → commit → file) + +### Environment Abstraction -### Plus Features (Pro) +The extension supports both Node.js (desktop) and browser (web) environments: -- **Subscription gating** - Feature access control via SubscriptionService -- **Cloud integrations** - GitHub/GitLab APIs for PRs, issues +**Node.js Environment** (`src/env/node/`) + +- Uses `child_process` to execute Git commands via `Git.execute()` +- Direct file system access +- Full Git command support +- Commands parsed by specialized parsers in `src/git/parsers/` + +**Browser Environment** (`src/env/browser/`) + +- Uses GitHub API for Git operations +- Virtual file system via VS Code's File System API +- Limited to supported Git hosting providers +- WebWorker support for browser extension compatibility + +**Build Configuration** + +- Separate entry points: `main` (Node.js) and `browser` (webworker) +- Webpack configs in `webpack.config.mjs`: + 1. `extension:node` - Extension code for Node.js + 2. `extension:webworker` - Extension code for browser + 3. `webviews:common` - Shared webview code + 4. `webviews` - Individual webview apps + 5. `images` - Icon/image processing +- Platform detection via `@env/platform` abstractions + +**Output Structure** + +``` +dist/ +├── gitlens.js # Main extension bundle (Node.js) +├── browser/ +│ └── gitlens.js # Extension bundle for browser +└── webviews/ + ├── *.js # Individual webview apps + └── media/ # Webview assets +``` + +### Pro Features (Plus) + +Files in or under directories named "plus" fall under `LICENSE.plus` (non-OSS): + +- **Commit Graph** - Visual commit history with advanced actions - **Worktrees** - Multi-branch workflow support -- **AI features** - Commit generation, explanations using various providers +- **Launchpad** - PR/issue management hub +- **Visual File History** - Timeline visualization +- **Cloud Patches** - Private code sharing +- **Code Suggest** - In-IDE code suggestions for PRs +- **AI Features** - Commit generation, explanations using various providers + +Pro features integrate with GitKraken accounts and require authentication via SubscriptionService. + +### Testing Infrastructure + +**Test Structure** + +- Tests co-located with source files in `__tests__/` directories +- Pattern: `src/path/to/__tests__/file.test.ts` +- VS Code extension tests use `@vscode/test-cli` +- E2E tests use Playwright in `tests/e2e/` +- Build tests separately: `pnpm run build:tests` + +**Running Tests** + +```bash +pnpm run test # Run extension tests +pnpm run test:e2e # Run E2E tests +pnpm run watch:tests # Watch mode for tests +``` ## Coding Standards & Style Rules ### TypeScript Configuration -- Strict TypeScript with `strictTypeChecked` ESLint config -- No `any` usage (exceptions for external APIs) -- Explicit return types for public methods -- Prefer `type` over `interface` for unions +- **Strict TypeScript** with `strictTypeChecked` ESLint config +- **No `any` usage** (exceptions only for external APIs) +- **Explicit return types** for public methods +- **Prefer `type` over `interface`** for unions +- Multiple tsconfig files for different targets (node, browser, test) ### Import Organization -- Use path aliases: `@env/` for environment-specific code -- Import order: node built-ins → external → internal → relative -- No default exports (ESLint enforced) -- Consistent type imports with `import type` +- **Use path aliases**: `@env/` for environment-specific code +- **Import order**: node built-ins → external → internal → relative +- **No default exports** (ESLint enforced) +- **Consistent type imports** with `import type` for type-only imports + +Example: + +```typescript +import type { Disposable } from 'vscode'; +import { EventEmitter } from 'vscode'; +import type { Container } from './container'; +import { configuration } from './system/configuration'; +``` ### Naming Conventions - **Classes**: PascalCase (no `I` prefix for interfaces) - **Methods/Variables**: camelCase -- **Constants**: camelCase for module-level constants -- **Private members**: Leading underscore allowed -- **Files**: camelCase.ts, camelCase.utils.ts for related utilities -- **Folders** +- **Constants**: camelCase for module-level constants (not SCREAMING_SNAKE_CASE) +- **Private members**: Leading underscore allowed (e.g., `_cache`) +- **Files**: camelCase.ts (e.g., `gitProvider.ts`, `branchProvider.utils.ts`) +- **Folders**: - Models under a `models/` sub-folder - - Utilities under a `utils/` sub-folder if they can be used in both the extension host and webviews, or `utils/-webview/` sub-folder for extension host-specific utilities + - Utilities under a `utils/` sub-folder (usable in both host and webviews) + - Extension host-specific utilities in `utils/-webview/` sub-folder - Webview apps under `webviews/apps/` -### Code Structure +### Code Structure Principles - **Single responsibility** - Each service has focused purpose - **Dependency injection** - Services injected via Container - **Event-driven** - EventEmitter pattern for service communication - **Disposable pattern** - Proper cleanup with VS Code Disposable interface +- **Immutability** - Prefer immutable operations where possible ### Error Handling -- Use custom error types extending Error -- Log errors with context using Logger.error() +- Use custom error types extending `Error` +- Log errors with context using `Logger.error()` - Graceful degradation for network/API failures - Validate external data with schema validators +- Provide user-friendly error messages + +### Decorators -### Webview Specific +Common decorators used throughout the codebase: + +- `@memoize()` - Cache function results +- `@debug()` - Add debug logging +- `@log()` - Add logging +- `@gate()` - Throttle concurrent calls +- `@command()` - Register VS Code commands + +### Webview Development - **Lit Elements** - Use for reactive UI components - **Context providers** - For sharing state across components - **Signal patterns** - For reactive state management -- **CSS custom properties** - For theming support +- **CSS custom properties** - For VS Code theming support +- Webview UI code in `src/webviews/apps/{webviewName}/` +- Use IPC protocol for communication: `postMessage()` → `onIpc()` +- Refresh webview without restarting extension during development + +## Important Patterns and Conventions + +### Configuration Management -### Environment Abstractions +- All settings defined in `package.json` contributions +- Configuration typed in `src/config.ts` +- Access via `Container.instance.config` or `configuration.get()` +- Settings are strongly typed with intellisense support -- **Platform detection** - Use `@env/platform` abstractions -- **Node vs Browser** - Environment-specific implementations in `src/env/` -- **WebWorker support** - Browser extension compatibility +### Constants Organization + +- **Command IDs**: `src/constants.commands.ts` (manual) + `constants.commands.generated.ts` (auto-generated) +- **Context keys**: `src/constants.context.ts` +- **Telemetry events**: `src/constants.telemetry.ts` +- **View IDs**: `src/constants.views.ts` +- **AI providers**: `src/constants.ai.ts` +- **Storage keys**: `src/constants.storage.ts` + +### Git Command Execution + +- All Git commands go through `Git.execute()` in `src/env/node/git/git.ts` +- Commands are parsed and formatted consistently +- Output is parsed by specialized parsers in `src/git/parsers/` +- Results cached in GitCache for performance + +### Repository Models + +Strongly typed Git entities throughout the codebase (located in `src/git/models/`): + +- **Core models**: `GitBranch`, `GitCommit`, `GitTag`, `GitRemote`, `GitWorktree` +- **Specialized models**: `GitStashCommit` (extends `GitCommit`), `GitStash`, `GitContributor`, `GitFile`, `GitDiff` +- Models provide rich methods and computed properties +- Immutable by convention ## Repository Guidelines ### Commit Messages -- Use a future-oriented manner, third-person singular present tense (e.g., 'Fixes', 'Updates', 'Improves', 'Adds', 'Removes') +- Use future-oriented manner, third-person singular present tense +- Examples: **"Fixes"**, **"Updates"**, **"Improves"**, **"Adds"**, **"Removes"** - Reference issues with `#123` syntax for auto-linking - Keep first line under 72 characters +- Example: `Adds support for custom autolinks for Jira - fixes #1234` ### Branch Workflow - Feature branches from `main` - Prefix with feature type: `feature/`, `bug/`, `debt/` -- Use descriptive names: `feature/search-natural-language` +- Use descriptive names: `feature/search-natural-language`, `bug/graph-performance` ### Code Reviews - Check TypeScript compilation and tests pass - Verify no new ESLint violations -- Test webview changes in both themes -- Validate Plus features with subscription states - -## Key Extension Points - -### Adding New Commands - -1. Define in `src/commands/` directory -2. Register in `src/commands.ts` -3. Add to `contributions.json` for package.json generation -4. Update command types with `pnpm run generate:commandTypes` - -### New Webviews - -1. Create provider in `src/webviews/` -2. Add Lit app in `src/webviews/apps/` -3. Register in WebviewsController -4. Add protocol definitions for IPC - -### Git Provider Extensions - -- Implement GitProvider interface -- Register with GitProviderService -- Handle provider-specific authentication - -### AI Provider Integration - -- Implement AIProvider interface -- Add to AIProviderService registry -- Handle authentication and rate limiting +- Test webview changes in both light and dark themes +- Validate Plus features with different subscription states +- Ensure proper error handling and logging +- Ensure proper telemetry and usage reporting +- Ensure proper caching and performance + +### Contributing Notes + +- Update `CHANGELOG.md` for all changes (in future tense) +- Add yourself to Contributors section in `README.md` for first contribution +- Follow existing code style (Prettier enforced) +- All files in `plus/` directories are non-OSS (LICENSE.plus) +- PRs with changes to `plus/` files grant GitKraken rights to modifications + +## Common Development Tasks + +### Adding a New Command + +1. Create command file in `src/commands/` (e.g., `myCommand.ts`) +2. Register command in `src/commands.ts`: + ```typescript + registerCommand(Commands.MyCommand, () => new MyCommand(container)); + ``` +3. Add to `contributions.json` for package.json generation: + ```json + { + "command": "gitlens.myCommand", + "title": "My Command", + "category": "GitLens" + } + ``` +4. Run `pnpm run generate:contributions` to update package.json +5. Run `pnpm run generate:commandTypes` to update command constants + +### Adding a New Webview + +1. Create webview provider in `src/webviews/` (e.g., `myWebviewProvider.ts`) +2. Create Lit app in appropriate location: + - For Pro features: `src/webviews/apps/plus/my-webview/` + - For community features: `src/webviews/apps/my-webview/` + - Create `my-webview.ts` (main app component with Lit Elements) + - Add HTML template + - Add CSS styles +3. Register in `WebviewsController` (in `src/webviews/webviewsController.ts`) +4. Add protocol definitions for IPC in `src/webviews/protocol.ts`: + ```typescript + export interface MyWebviewShowingArgs { ... } + ``` +5. Add webpack entry point in `webpack.config.mjs` +6. Register webview in extension activation + +### Adding a New Tree View + +1. Create tree provider in `src/views/` (e.g., `myTreeView.ts`) + - Extend `ViewBase` or `RepositoryFolderNode` + - Implement `getChildren()` method +2. Define node types for the tree hierarchy +3. Add to `contributions.json`: + ```json + { + "id": "gitlens.views.myView", + "name": "My View", + "when": "..." + } + ``` +4. Register in extension activation (`src/extension.ts`) +5. Run `pnpm run generate:contributions` + +### Modifying Git Operations + +1. Find the relevant Git provider: + - Shared Git provider interface: `src/git/gitProvider.ts` + - Shared sub-operations: `src/git/sub-providers/` + - For Local (Node.js): `src/env/node/git/localGitProvider.ts` + - For Local sub-operations: `src/env/node/git/sub-providers/` + - For GitHub (browser): `src/plus/integrations/providers/github/githubGitProvider.ts` + - For GitHub sub-operations: `src/plus/integrations/providers/github/sub-providers/` +2. Update provider method with new logic +3. Update Git command execution in `src/env/node/git/git.ts` if needed (for LocalGitProvider) +4. Update parsers in `src/git/parsers/` if output format changes +5. Update models in `src/git/models/` if data structure changes +6. Consider caching implications (update `GitCache` if needed) +7. Add tests in `__tests__/` directory + +### Working with Icons (GL Icons Font) + +1. Add SVG icons to `images/icons/` folder +2. Append entries to `images/icons/template/mapping.json`: + ```json + "icon-name": 1234 + ``` +3. Run icon build commands: + ```bash + pnpm run icons:svgo # Optimize SVGs + pnpm run build:icons # Generate font + ``` +4. Copy new `glicons.woff2?` URL from `src/webviews/apps/shared/glicons.scss` +5. Search and replace old font URL with new one across the codebase + +### Adding New AI Provider + +1. Create new AI provider in `src/plus/ai/` extending base classes (e.g., `openAICompatibleProviderBase.ts`) +2. Add to `AIProviderService` registry in `src/plus/ai/aiProviderService.ts` +3. Handle authentication and rate limiting +4. Add provider constants to `src/constants.ai.ts` +5. Update configuration in `package.json` contributions + +### Adding Git Provider Integration + +1. Implement `GitProvider` interface (e.g., `gitLabGitProvider.ts`) +2. Register with `GitProviderService` +3. Handle provider-specific authentication +4. Add integration constants to `src/constants.integrations.ts` +5. Consider adding rich integration features (PRs, issues, avatars) ## Development Environment ### Prerequisites - **Node.js** ≥ 22.12.0 -- **pnpm** ≥ 10.x (via corepack) +- **pnpm** ≥ 10.x (install via corepack: `corepack enable`) +- **Corepack** ≥ 0.31.0 (check with `corepack -v`) - **Git** ≥ 2.7.2 -### VS Code Tasks +### VS Code Setup -- **Build** - `Ctrl+Shift+P` → "Tasks: Run Task" → "watch" -- **Test** - Use VS Code's built-in test runner +- Install recommended extensions (see `.vscode/extensions.json`) +- Use provided launch configurations: + - **"Watch & Run"** - Debug desktop extension + - **"Watch & Run (web)"** - Debug browser extension +- Use VS Code tasks: + - `Ctrl+Shift+B` to start watch task + - `Ctrl+Shift+P` → "Tasks: Run Task" → select task - **Debug** - F5 to launch Extension Development Host +- **Test** - Use VS Code's built-in test runner ### Multi-target Support -- **Node.js** - Traditional VS Code extension -- **Web Worker** - Browser/web VS Code compatibility -- Shared code with environment abstractions +GitLens supports multiple environments: + +- **Node.js** - Traditional VS Code extension (desktop) +- **Web Worker** - Browser/web VS Code compatibility (vscode.dev) +- Shared code with environment abstractions in `src/env/` +- Test both environments during development + +### Performance Considerations + +- Use lazy loading for heavy services +- Leverage caching layers (GitCache, PromiseCache, @memoize) +- Debounce expensive operations +- Consider webview refresh performance +- Monitor telemetry for performance regressions + +--- -This architecture enables GitLens to provide powerful Git tooling while maintaining clean separation of concerns and extensibility for new features. +This architecture enables GitLens to provide powerful Git tooling while maintaining clean separation of concerns, extensibility for new features, and support for multiple runtime environments. diff --git a/CHANGELOG.md b/CHANGELOG.md index 94d4e62101491..422cd53889a4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,41 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] +### Changed + +- Changes to select the "Work in progress" (WIP) row in the _Commit Graph_ by default if there are uncommitted changes ([#4716](https://github.com/gitkraken/vscode-gitlens/issues/4716)) + - Adds `gitlens.graph.initialRowSelection` setting to specify whether to select the "Work in progress" (WIP) row instead of HEAD if there are uncommitted changes +- Changes to use the "merge target" when we are creating pull requests ([#4709](https://github.com/gitkraken/vscode-gitlens/issues/4709)) +- Changes the minimum VS Code version to 1.95.0 ([#4691](https://github.com/gitkraken/vscode-gitlens/issues/4691)) + +### Fixed + +- Fixes intermittent stuck loading state on the _Commit Graph_ ([#4669](https://github.com/gitkraken/vscode-gitlens/issues/4669)) +- Fixes underlines showing on home branch actions ([#4703](https://github.com/gitkraken/vscode-gitlens/issues/4703)) +- Fixes _Inspect_ view not showing uncommitted files on the Inspect tab ([#4714](https://github.com/gitkraken/vscode-gitlens/issues/4714)) +- Fixes _Commit Graph_ losing row selection when graph updates ([#4544](https://github.com/gitkraken/vscode-gitlens/issues/4544)) + +## [17.6.2] - 2025-10-16 + +### Changed + +- Reduces view refresh frequency for showing last fetched time to improve performance and reduce overhead +- Replaces OS-specific shell-based unzip with JS solution for better cross-platform support and reliability +- Improves MCP checks and adds offline check ([#4687](https://github.com/gitkraken/vscode-gitlens/issues/4687)) +- Updates auto-compose instructions setting text to a link on _Commit Composer_ + +### Fixed + +- Fixes MCP registration from breaking VS Code chat ([#4701](https://github.com/gitkraken/vscode-gitlens/issues/4701)) +- Fixes MCP extension registration not working on Kiro ([#4691](https://github.com/gitkraken/vscode-gitlens/issues/4691)) +- Fixes intermittent issue with autolinks not showing up ([#4692](https://github.com/gitkraken/vscode-gitlens/issues/4692)) + +## [17.6.1] - 2025-10-08 + +### Fixed + +- Fixes eyebrow banner not appearing for GitLens Community on Home ([#4670](https://github.com/gitkraken/vscode-gitlens/issues/4670)) + ## [17.6.0] - 2025-10-07 ### Added @@ -6383,7 +6418,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - Initial release but still heavily a work in progress. -[unreleased]: https://github.com/gitkraken/vscode-gitlens/compare/v17.6.0...HEAD +[unreleased]: https://github.com/gitkraken/vscode-gitlens/compare/v17.6.2...HEAD +[17.6.2]: https://github.com/gitkraken/vscode-gitlens/compare/v17.6.1...gitkraken:v17.6.2 +[17.6.1]: https://github.com/gitkraken/vscode-gitlens/compare/v17.6.0...gitkraken:v17.6.1 [17.6.0]: https://github.com/gitkraken/vscode-gitlens/compare/v17.5.1...gitkraken:v17.6.0 [17.5.1]: https://github.com/gitkraken/vscode-gitlens/compare/v17.5.0...gitkraken:v17.5.1 [17.5.0]: https://github.com/gitkraken/vscode-gitlens/compare/v17.4.1...gitkraken:v17.5.0 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000000..43c994c2d3617 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index a60d3644b527f..d0495a83c30e6 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -9,17 +9,17 @@ This project incorporates components from the projects listed below. 4. @lit/context version 1.1.6 (https://github.com/lit/lit) 5. @lit/react version 1.0.8 (https://github.com/lit/lit) 6. @lit/task version 1.0.3 (https://github.com/lit/lit) -7. @octokit/graphql version 9.0.1 (https://github.com/octokit/graphql.js) -8. @octokit/request-error version 7.0.0 (https://github.com/octokit/request-error.js) -9. @octokit/request version 10.0.3 (https://github.com/octokit/request.js) -10. @octokit/types version 14.1.0 (https://github.com/octokit/types.ts) +7. @octokit/graphql version 9.0.2 (https://github.com/octokit/graphql.js) +8. @octokit/request-error version 7.0.1 (https://github.com/octokit/request-error.js) +9. @octokit/request version 10.0.5 (https://github.com/octokit/request.js) +10. @octokit/types version 15.0.0 (https://github.com/octokit/types.ts) 11. @opentelemetry/api version 1.9.0 (https://github.com/open-telemetry/opentelemetry-js) -12. @opentelemetry/exporter-trace-otlp-http version 0.205.0 (https://github.com/open-telemetry/opentelemetry-js) +12. @opentelemetry/exporter-trace-otlp-http version 0.206.0 (https://github.com/open-telemetry/opentelemetry-js) 13. @opentelemetry/resources version 2.1.0 (https://github.com/open-telemetry/opentelemetry-js) 14. @opentelemetry/sdk-trace-base version 2.1.0 (https://github.com/open-telemetry/opentelemetry-js) 15. @opentelemetry/semantic-conventions version 1.37.0 (https://github.com/open-telemetry/opentelemetry-js) 16. @shoelace-style/shoelace version 2.20.1 (https://github.com/shoelace-style/shoelace) -17. @vscode/codicons version 0.0.40 (https://github.com/microsoft/vscode-codicons) +17. @vscode/codicons version 0.0.41 (https://github.com/microsoft/vscode-codicons) 18. billboard.js version 3.17.0 (https://github.com/naver/billboard.js) 19. diff2html version 3.4.52 (https://github.com/rtfpessoa/diff2html) 20. driver.js version 1.3.6 (https://github.com/kamranahmedse/driver.js) @@ -27,7 +27,7 @@ This project incorporates components from the projects listed below. 22. https-proxy-agent version 5.0.1 (https://github.com/TooTallNate/node-https-proxy-agent) 23. iconv-lite version 0.6.3 (https://github.com/ashtuchkin/iconv-lite) 24. lit version 3.3.1 (https://github.com/lit/lit) -25. marked version 16.3.0 (https://github.com/markedjs/marked) +25. marked version 16.4.0 (https://github.com/markedjs/marked) 26. microsoft/vscode (https://github.com/microsoft/vscode) 27. node-fetch version 2.7.0 (https://github.com/bitinn/node-fetch) 28. os-browserify version 0.3.0 (https://github.com/CoderPuppy/os-browserify) @@ -37,6 +37,7 @@ This project incorporates components from the projects listed below. 32. signal-utils version 0.21.1 (https://github.com/proposal-signals/signal-utils) 33. slug version 11.0.0 (https://github.com/Trott/slug) 34. sortablejs version 1.15.6 (https://github.com/SortableJS/Sortable) +35. vscode-uri version 3.1.0 (https://github.com/microsoft/vscode-uri) %% @gk-nzaytsev/fast-string-truncated-width NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -2354,4 +2355,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF sortablejs NOTICES AND INFORMATION \ No newline at end of file +END OF sortablejs NOTICES AND INFORMATION + +%% vscode-uri NOTICES AND INFORMATION BEGIN HERE +========================================= +The MIT License (MIT) + +Copyright (c) Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= +END OF vscode-uri NOTICES AND INFORMATION \ No newline at end of file diff --git a/contributions.json b/contributions.json index 41f09ba47af95..f28ed3ee9f52b 100644 --- a/contributions.json +++ b/contributions.json @@ -370,17 +370,31 @@ ] } }, - "gitlens.ai.undoGenerateRebase": { - "label": "Undo AI Generated Changes (Preview)...", - "icon": "$(discard)" - }, "gitlens.annotations.nextChange": { "label": "Next Change", - "icon": "$(arrow-down)" + "icon": "$(arrow-down)", + "menus": { + "editor/title": [ + { + "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated =~ /computed:changes\\b/ || (resource in gitlens:tabs:annotated:changes && resource not in gitlens:tabs:annotated:computing)) && config.gitlens.menus.editorGroup.blame", + "group": "navigation", + "order": -99 + } + ] + } }, "gitlens.annotations.previousChange": { "label": "Previous Change", - "icon": "$(arrow-up)" + "icon": "$(arrow-up)", + "menus": { + "editor/title": [ + { + "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated =~ /computed:changes\\b/ || (resource in gitlens:tabs:annotated:changes && resource not in gitlens:tabs:annotated:computing)) && config.gitlens.menus.editorGroup.blame", + "group": "navigation", + "order": -100 + } + ] + } }, "gitlens.applyPatchFromClipboard": { "label": "Apply Copied Changes (Patch)", @@ -453,7 +467,7 @@ "menus": { "editor/title": [ { - "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated == computed || (resource in gitlens:tabs:annotated && resource not in gitlens:tabs:annotated:computing)) && config.gitlens.menus.editorGroup.blame", + "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated =~ /computed\\b/ || (resource in gitlens:tabs:annotated && resource not in gitlens:tabs:annotated:computing)) && config.gitlens.menus.editorGroup.blame", "group": "navigation", "order": 100 } @@ -586,7 +600,7 @@ "menus": { "editor/title": [ { - "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated == computing || resource in gitlens:tabs:annotated:computing) && config.gitlens.menus.editorGroup.blame", + "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated =~ /computed\\b/ || resource in gitlens:tabs:annotated:computing) && config.gitlens.menus.editorGroup.blame", "group": "navigation", "order": 100 } @@ -646,7 +660,33 @@ "menus": { "gitlens/share": [ { - "when": "viewItem =~ /gitlens:(commit|file\\b(?=.*?\\b\\+committed\\b))/ && !listMultiSelection", + "when": "viewItem =~ /gitlens:(commit|file\\b(?=.*?\\b\\+committed\\b))\\b/ && !listMultiSelection", + "group": "1_gitlens", + "order": 25 + } + ] + } + }, + "gitlens.copyDeepLinkToCommit:commitDetails": { + "label": "Copy Link to Commit", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && webview == gitlens.views.commitDetails", + "group": "1_gitlens", + "order": 25 + } + ] + } + }, + "gitlens.copyDeepLinkToCommit:graphDetails": { + "label": "Copy Link to Commit", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && webview == gitlens.views.graphDetails", "group": "1_gitlens", "order": 25 } @@ -692,6 +732,32 @@ ] } }, + "gitlens.copyDeepLinkToFile:commitDetails": { + "label": "Copy Link to File", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "1_gitlens", + "order": 26 + } + ] + } + }, + "gitlens.copyDeepLinkToFile:graphDetails": { + "label": "Copy Link to File", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "1_gitlens", + "order": 26 + } + ] + } + }, "gitlens.copyDeepLinkToFileAtRevision": { "label": "Copy Link to File at Revision...", "icon": "$(copy)", @@ -719,6 +785,32 @@ ] } }, + "gitlens.copyDeepLinkToFileAtRevision:commitDetails": { + "label": "Copy Link to File at Revision...", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "1_gitlens", + "order": 27 + } + ] + } + }, + "gitlens.copyDeepLinkToFileAtRevision:graphDetails": { + "label": "Copy Link to File at Revision...", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "1_gitlens", + "order": 27 + } + ] + } + }, "gitlens.copyDeepLinkToLines": { "label": "Copy Link to Code", "icon": "$(copy)", @@ -815,6 +907,18 @@ "label": "Copy Changes (Patch)", "commandPalette": "gitlens:enabled && !gitlens:untrusted && !gitlens:hasVirtualFolders" }, + "gitlens.copyPatchToClipboard:commitDetails": { + "label": "Copy Changes (Patch)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "7_gitlens_cutcopypaste", + "order": 3 + } + ] + } + }, "gitlens.copyPatchToClipboard:graph": { "label": "Copy Changes (Patch)", "menus": { @@ -827,6 +931,18 @@ ] } }, + "gitlens.copyPatchToClipboard:graphDetails": { + "label": "Copy Changes (Patch)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "7_gitlens_cutcopypaste", + "order": 3 + } + ] + } + }, "gitlens.copyPatchToClipboard:scm": { "label": "Copy Changes (Patch)", "menus": { @@ -910,6 +1026,32 @@ ] } }, + "gitlens.copyRelativePathToClipboard:commitDetails": { + "label": "Copy Relative Path", + "icon": "$(copy)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "7_gitlens_cutcopypaste", + "order": 2 + } + ] + } + }, + "gitlens.copyRelativePathToClipboard:graphDetails": { + "label": "Copy Relative Path", + "icon": "$(copy)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "7_gitlens_cutcopypaste", + "order": 2 + } + ] + } + }, "gitlens.copyRemoteBranchesUrl": { "label": "Copy Remote Branches URL", "icon": "$(copy)" @@ -1027,6 +1169,32 @@ ] } }, + "gitlens.copyRemoteFileUrlFrom:commitDetails": { + "label": "Copy Remote File URL From...", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "2_gitlens", + "order": 2 + } + ] + } + }, + "gitlens.copyRemoteFileUrlFrom:graphDetails": { + "label": "Copy Remote File URL From...", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "2_gitlens", + "order": 2 + } + ] + } + }, "gitlens.copyRemoteFileUrlToClipboard": { "label": "Copy Remote File URL", "icon": "$(copy)", @@ -1086,6 +1254,32 @@ ] } }, + "gitlens.copyRemoteFileUrlWithoutRange:commitDetails": { + "label": "Copy Remote File URL", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "2_gitlens", + "order": 1 + } + ] + } + }, + "gitlens.copyRemoteFileUrlWithoutRange:graphDetails": { + "label": "Copy Remote File URL", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "2_gitlens", + "order": 1 + } + ] + } + }, "gitlens.copyRemotePullRequestUrl": { "label": "Copy Pull Request URL", "icon": "$(copy)" @@ -1442,6 +1636,7 @@ "menus": { "gitlens/commit/file/changes": [ { + "when": "viewItem =~ /gitlens:file\\b/", "group": "1_gitlens", "order": 3 } @@ -1474,12 +1669,39 @@ ] } }, + "gitlens.diffWithRevision:commitDetails": { + "label": "Open Changes with Revision...", + "icon": "$(gitlens-prev-commit-menu)", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens", + "order": 3 + } + ] + } + }, + "gitlens.diffWithRevision:graphDetails": { + "label": "Open Changes with Revision...", + "icon": "$(gitlens-prev-commit-menu)", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens", + "order": 3 + } + ] + } + }, "gitlens.diffWithRevisionFrom": { "label": "Open Changes with Branch or Tag...", "commandPalette": "resource in gitlens:tabs:tracked", "menus": { "gitlens/commit/file/changes": [ { + "when": "viewItem =~ /gitlens:file\\b/", "group": "1_gitlens", "order": 4 } @@ -1512,6 +1734,30 @@ ] } }, + "gitlens.diffWithRevisionFrom:commitDetails": { + "label": "Open Changes with Branch or Tag...", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens", + "order": 4 + } + ] + } + }, + "gitlens.diffWithRevisionFrom:graphDetails": { + "label": "Open Changes with Branch or Tag...", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens", + "order": 4 + } + ] + } + }, "gitlens.diffWithWorking": { "label": "Open Changes with Working File", "icon": "$(gitlens-compare-ref-working)", @@ -1608,7 +1854,7 @@ { "when": "viewItem =~ /gitlens:file\\b(?!.*?\\b\\+conflicted\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders", "group": "1_gitlens_", - "order": 1 + "order": 5 } ], "gitlens/scm/resourceState/changes": [ @@ -1620,6 +1866,30 @@ ] } }, + "gitlens.externalDiff:commitDetails": { + "label": "Open Changes (difftool)", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)(?!.*?\\b\\+conflicted\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "1_gitlens_", + "order": 5 + } + ] + } + }, + "gitlens.externalDiff:graphDetails": { + "label": "Open Changes (difftool)", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)(?!.*?\\b\\+conflicted\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "1_gitlens_", + "order": 5 + } + ] + } + }, "gitlens.externalDiffAll": { "label": "Open All Changes (difftool)", "commandPalette": "gitlens:enabled && !gitlens:hasVirtualFolders", @@ -3348,9 +3618,6 @@ ] } }, - "gitlens.openCloudPatch": { - "label": "Open Cloud Patch..." - }, "gitlens.openCommitOnRemote": { "label": "Open Commit on Remote", "icon": "$(globe)", @@ -3419,7 +3686,7 @@ "menus": { "gitlens/commit/file/history": [ { - "when": "view != gitlens.views.fileHistory/", + "when": "viewItem =~ /gitlens:file\\b/ && view != gitlens.views.fileHistory/", "group": "1_gitlens", "order": 1 } @@ -3444,6 +3711,32 @@ ] } }, + "gitlens.openFileHistory:commitDetails": { + "label": "Open File History", + "icon": "$(history)", + "menus": { + "gitlens/commit/file/history": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens", + "order": 1 + } + ] + } + }, + "gitlens.openFileHistory:graphDetails": { + "label": "Open File History", + "icon": "$(history)", + "menus": { + "gitlens/commit/file/history": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens", + "order": 1 + } + ] + } + }, "gitlens.openFileOnRemote": { "label": "Open File on Remote", "icon": "$(globe)", @@ -3492,16 +3785,42 @@ "alt": "gitlens.copyRemoteFileUrlWithoutRange" }, { - "when": "viewItem =~ /gitlens:file\\b((?=.*?\\b\\+committed\\b)|:results)/ && !listMultiSelection && gitlens:repos:withRemotes", + "when": "viewItem =~ /gitlens:file\\b((?=.*?\\b\\+committed\\b)|:results)/ && !listMultiSelection && gitlens:repos:withRemotes", + "group": "2_gitlens_quickopen_file", + "order": 5, + "alt": "gitlens.copyRemoteFileUrlWithoutRange" + }, + { + "when": "viewItem =~ /gitlens:(history:(file|line)|status:file)\\b/ && !listMultiSelection && gitlens:repos:withRemotes", + "group": "5_gitlens_open", + "order": 2, + "alt": "gitlens.copyRemoteFileUrlWithoutRange" + } + ] + } + }, + "gitlens.openFileOnRemote:commitDetails": { + "label": "Open File on Remote", + "icon": "$(globe)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", "group": "2_gitlens_quickopen_file", - "order": 5, - "alt": "gitlens.copyRemoteFileUrlWithoutRange" - }, + "order": 5 + } + ] + } + }, + "gitlens.openFileOnRemote:graphDetails": { + "label": "Open File on Remote", + "icon": "$(globe)", + "menus": { + "webview/context": [ { - "when": "viewItem =~ /gitlens:(history:(file|line)|status:file)\\b/ && !listMultiSelection && gitlens:repos:withRemotes", - "group": "5_gitlens_open", - "order": 2, - "alt": "gitlens.copyRemoteFileUrlWithoutRange" + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "2_gitlens_quickopen_file", + "order": 5 } ] } @@ -3897,6 +4216,7 @@ "menus": { "gitlens/commit/file/history": [ { + "when": "viewItem =~ /gitlens:file\\b/", "group": "1_gitlens_quick", "order": 1 } @@ -3921,6 +4241,30 @@ ] } }, + "gitlens.quickOpenFileHistory:commitDetails": { + "label": "Quick Open File History", + "menus": { + "gitlens/commit/file/history": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens_quick", + "order": 1 + } + ] + } + }, + "gitlens.quickOpenFileHistory:graphDetails": { + "label": "Quick Open File History", + "menus": { + "gitlens/commit/file/history": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens_quick", + "order": 1 + } + ] + } + }, "gitlens.regenerateMarkdownDocument": { "label": "Regenerate", "icon": "$(refresh)", @@ -3949,6 +4293,42 @@ "label": "Reset Views Layout", "commandPalette": true }, + "gitlens.restore.file:commitDetails": { + "label": "Restore Changes (Checkout)", + "icon": "$(discard)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "1_gitlens_actions", + "order": 3 + }, + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "8_gitlens_actions", + "order": 3 + } + ] + } + }, + "gitlens.restore.file:graphDetails": { + "label": "Restore Changes (Checkout)", + "icon": "$(discard)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "1_gitlens_actions", + "order": 3 + }, + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "8_gitlens_actions", + "order": 3 + } + ] + } + }, "gitlens.restore.file:views": { "label": "Restore Changes (Checkout)", "menus": { @@ -3966,6 +4346,30 @@ ] } }, + "gitlens.restorePrevious.file:commitDetails": { + "label": "Restore Previous Changes", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.commitDetails", + "group": "8_gitlens_actions", + "order": 4 + } + ] + } + }, + "gitlens.restorePrevious.file:graphDetails": { + "label": "Restore Previous Changes", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.graphDetails", + "group": "8_gitlens_actions", + "order": 4 + } + ] + } + }, "gitlens.restorePrevious.file:views": { "label": "Restore Previous Changes", "menus": { @@ -4058,6 +4462,30 @@ ] } }, + "gitlens.shareAsCloudPatch:commitDetails": { + "label": "Share as Cloud Patch...", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:drafts:enabled && config.gitlens.cloudPatches.enabled && webview == gitlens.views.commitDetails", + "group": "1_a_gitlens", + "order": 1 + } + ] + } + }, + "gitlens.shareAsCloudPatch:graphDetails": { + "label": "Share as Cloud Patch...", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:drafts:enabled && config.gitlens.cloudPatches.enabled && webview == gitlens.views.graphDetails", + "group": "1_a_gitlens", + "order": 1 + } + ] + } + }, "gitlens.showAccountView": { "label": "Show Account on Home", "commandPalette": true @@ -4241,10 +4669,6 @@ ] } }, - "gitlens.showInCommitGraphView": { - "label": "Open in Commit Graph", - "icon": "$(gitlens-graph)" - }, "gitlens.showInDetailsView": { "label": "Inspect Details", "icon": "$(eye)", @@ -4344,7 +4768,8 @@ "commandPalette": "gitlens:enabled" }, "gitlens.showQuickCommitDetails": { - "label": "Quick Show Commit" + "label": "Quick Show Commit", + "commandPalette": "resource in gitlens:tabs:blameable" }, "gitlens.showQuickCommitFileDetails": { "label": "Quick Show Line Commit", @@ -4947,10 +5372,6 @@ ] } }, - "gitlens.showSettingsPage!views": { - "label": "Open Settings", - "icon": "$(gear)" - }, "gitlens.showSettingsPage!worktrees-view": { "label": "Open View Settings", "icon": "$(gear)", @@ -5585,10 +6006,6 @@ ] } }, - "gitlens.toggleFileChangesOnly": { - "label": "Toggle File Changes", - "icon": "$(gitlens-gitlens)" - }, "gitlens.toggleFileHeatmap": { "label": "Toggle File Heatmap", "icon": "$(gitlens-gitlens)", @@ -5850,11 +6267,6 @@ ] } }, - "gitlens.views.addPullRequestRemote": { - "label": "Add Pull Request Remote", - "icon": "$(add)", - "enablement": "!operationInProgress" - }, "gitlens.views.addRemote": { "label": "Add Remote...", "icon": "$(add)", @@ -5916,6 +6328,42 @@ ] } }, + "gitlens.views.applyChanges:commitDetails": { + "label": "Apply Changes", + "enablement": "!operationInProgress", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "1_gitlens_actions", + "order": 1 + }, + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "8_gitlens_actions", + "order": 1 + } + ] + } + }, + "gitlens.views.applyChanges:graphDetails": { + "label": "Apply Changes", + "enablement": "!operationInProgress", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "1_gitlens_actions", + "order": 1 + }, + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "8_gitlens_actions", + "order": 1 + } + ] + } + }, "gitlens.views.associateIssueWithBranch": { "label": "Associate Issue with Branch...", "enablement": "!operationInProgress", @@ -5952,7 +6400,7 @@ "keybindings": [ { "key": "ctrl+c", - "when": "focusedView == gitlens.views.branches", + "when": "focusedView == gitlens.views.branches || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == branches)", "mac": "cmd+c" } ] @@ -6758,7 +7206,7 @@ "keybindings": [ { "key": "ctrl+c", - "when": "focusedView == gitlens.views.commits", + "when": "focusedView == gitlens.views.commits || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == commits)", "mac": "cmd+c" } ] @@ -7419,6 +7867,30 @@ ] } }, + "gitlens.views.compareFileWithSelected:commitDetails": { + "label": "Compare with Selected", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && !listMultiSelection && gitlens:views:canCompare:file && webview == gitlens.views.commitDetails", + "group": "4_gitlens_compare", + "order": 99 + } + ] + } + }, + "gitlens.views.compareFileWithSelected:graphDetails": { + "label": "Compare with Selected", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && !listMultiSelection && gitlens:views:canCompare:file && webview == gitlens.views.graphDetails", + "group": "4_gitlens_compare", + "order": 99 + } + ] + } + }, "gitlens.views.compareWithHead": { "label": "Compare to/from HEAD", "icon": "$(compare-changes)", @@ -7543,7 +8015,7 @@ "keybindings": [ { "key": "ctrl+c", - "when": "focusedView == gitlens.views.contributors", + "when": "focusedView == gitlens.views.contributors || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == contributors)", "mac": "cmd+c" } ] @@ -8010,6 +8482,32 @@ ] } }, + "gitlens.views.copy:commitDetails": { + "label": "Copy", + "icon": "$(copy)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?!.*?\\b\\+(staged|unstaged)\\b)/ && webview == gitlens.views.commitDetails", + "group": "7_gitlens_cutcopypaste", + "order": 1 + } + ] + } + }, + "gitlens.views.copy:graphDetails": { + "label": "Copy", + "icon": "$(copy)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?!.*?\\b\\+(staged|unstaged)\\b)/ && webview == gitlens.views.graphDetails", + "group": "7_gitlens_cutcopypaste", + "order": 1 + } + ] + } + }, "gitlens.views.copyAsMarkdown": { "label": "Copy as Markdown", "icon": "$(copy)", @@ -8034,7 +8532,33 @@ "menus": { "gitlens/share": [ { - "when": "viewItem =~ /gitlens:(commit|file\\b(?=.*?\\b\\+committed\\b))/ && !listMultiSelection && gitlens:repos:withRemotes", + "when": "viewItem =~ /gitlens:(commit|file\\b(?=.*?\\b\\+committed\\b))\\b/ && !listMultiSelection && gitlens:repos:withRemotes", + "group": "2_gitlens", + "order": 25 + } + ] + } + }, + "gitlens.views.copyRemoteCommitUrl:commitDetails": { + "label": "Copy Remote Commit URL", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "2_gitlens", + "order": 25 + } + ] + } + }, + "gitlens.views.copyRemoteCommitUrl:graphDetails": { + "label": "Copy Remote Commit URL", + "icon": "$(copy)", + "menus": { + "gitlens/share": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", "group": "2_gitlens", "order": 25 } @@ -8628,7 +9152,7 @@ "keybindings": [ { "key": "ctrl+c", - "when": "focusedView == gitlens.views.fileHistory", + "when": "focusedView == gitlens.views.fileHistory || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == fileHistory)", "mac": "cmd+c" } ] @@ -9169,24 +9693,72 @@ ] } }, - "gitlens.views.highlightChanges": { - "label": "Highlight All Changes Since Before this Commit", + "gitlens.views.highlightChanges": { + "label": "Highlight All Changes Since Before this Commit", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "viewItem =~ /gitlens:file\\b((?=.*?\\b\\+(committed|stashed)\\b)|:results)/", + "group": "2_gitlens", + "order": 1 + } + ] + } + }, + "gitlens.views.highlightChanges:commitDetails": { + "label": "Highlight All Changes Since Before this Commit", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.commitDetails", + "group": "2_gitlens", + "order": 1 + } + ] + } + }, + "gitlens.views.highlightChanges:graphDetails": { + "label": "Highlight All Changes Since Before this Commit", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.graphDetails", + "group": "2_gitlens", + "order": 1 + } + ] + } + }, + "gitlens.views.highlightRevisionChanges": { + "label": "Highlight Changes from this Commit", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "viewItem =~ /gitlens:file\\b((?=.*?\\b\\+committed\\b)|:results)/", + "group": "2_gitlens", + "order": 2 + } + ] + } + }, + "gitlens.views.highlightRevisionChanges:commitDetails": { + "label": "Highlight Changes from this Commit", "menus": { "gitlens/commit/file/changes": [ { - "when": "viewItem =~ /gitlens:file\\b((?=.*?\\b\\+(committed|stashed)\\b)|:results)/", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.commitDetails", "group": "2_gitlens", - "order": 1 + "order": 2 } ] } }, - "gitlens.views.highlightRevisionChanges": { + "gitlens.views.highlightRevisionChanges:graphDetails": { "label": "Highlight Changes from this Commit", "menus": { "gitlens/commit/file/changes": [ { - "when": "viewItem =~ /gitlens:file\\b((?=.*?\\b\\+committed\\b)|:results)/", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.graphDetails", "group": "2_gitlens", "order": 2 } @@ -9392,7 +9964,14 @@ } }, "gitlens.views.launchpad.copy": { - "label": "Copy" + "label": "Copy", + "keybindings": [ + { + "key": "ctrl+c", + "when": "focusedView == gitlens.views.launchpad || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == launchpad)", + "mac": "cmd+c" + } + ] }, "gitlens.views.launchpad.info": { "label": "Learn about Launchpad...", @@ -9793,9 +10372,6 @@ ] } }, - "gitlens.views.loadMoreChildren": { - "label": "Load More" - }, "gitlens.views.mergeBranchInto": { "label": "Merge Branch into Current Branch...", "enablement": "!operationInProgress", @@ -9826,6 +10402,40 @@ ] } }, + "gitlens.views.mergeChangesWithWorking:commitDetails": { + "label": "Merge Changes (Manually)...", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens_actions", + "order": 2 + }, + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.commitDetails", + "group": "8_gitlens_actions", + "order": 2 + } + ] + } + }, + "gitlens.views.mergeChangesWithWorking:graphDetails": { + "label": "Merge Changes (Manually)...", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens_actions", + "order": 2 + }, + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.graphDetails", + "group": "8_gitlens_actions", + "order": 2 + } + ] + } + }, "gitlens.views.openBranchOnRemote": { "label": "Open Branch on Remote", "icon": "$(globe)", @@ -9972,6 +10582,32 @@ ] } }, + "gitlens.views.openChanges:commitDetails": { + "label": "Open Changes", + "icon": "$(git-compare)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "2_gitlens_quickopen", + "order": 1 + } + ] + } + }, + "gitlens.views.openChanges:graphDetails": { + "label": "Open Changes", + "icon": "$(git-compare)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "2_gitlens_quickopen", + "order": 1 + } + ] + } + }, "gitlens.views.openChangesWithMergeBase": { "label": "Open Changes with Common Base", "menus": { @@ -10004,6 +10640,32 @@ ] } }, + "gitlens.views.openChangesWithWorking:commitDetails": { + "label": "Open Changes with Working File", + "icon": "$(gitlens-compare-ref-working)", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens", + "order": 1 + } + ] + } + }, + "gitlens.views.openChangesWithWorking:graphDetails": { + "label": "Open Changes with Working File", + "icon": "$(gitlens-compare-ref-working)", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens", + "order": 1 + } + ] + } + }, "gitlens.views.openCommitOnRemote": { "label": "Open Commit on Remote", "icon": "$(globe)", @@ -10091,6 +10753,32 @@ ] } }, + "gitlens.views.openFile:commitDetails": { + "label": "Open File", + "icon": "$(go-to-file)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "2_gitlens_quickopen_file", + "order": 3 + } + ] + } + }, + "gitlens.views.openFile:graphDetails": { + "label": "Open File", + "icon": "$(go-to-file)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "2_gitlens_quickopen_file", + "order": 3 + } + ] + } + }, "gitlens.views.openFileRevision": { "label": "Open File at Revision", "icon": "$(gitlens-open-revision)", @@ -10110,6 +10798,32 @@ ] } }, + "gitlens.views.openFileRevision:commitDetails": { + "label": "Open File at Revision", + "icon": "$(gitlens-open-revision)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.commitDetails", + "group": "2_gitlens_quickopen_file", + "order": 4 + } + ] + } + }, + "gitlens.views.openFileRevision:graphDetails": { + "label": "Open File at Revision", + "icon": "$(gitlens-open-revision)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.graphDetails", + "group": "2_gitlens_quickopen_file", + "order": 4 + } + ] + } + }, "gitlens.views.openInIntegratedTerminal": { "label": "Open in Integrated Terminal", "menus": { @@ -10218,6 +10932,30 @@ ] } }, + "gitlens.views.openPreviousChangesWithWorking:commitDetails": { + "label": "Open Previous Changes with Working File", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens", + "order": 2 + } + ] + } + }, + "gitlens.views.openPreviousChangesWithWorking:graphDetails": { + "label": "Open Previous Changes with Working File", + "menus": { + "gitlens/commit/file/changes": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens", + "order": 2 + } + ] + } + }, "gitlens.views.openPullRequest": { "label": "Open Pull Request", "icon": "$(git-pull-request)", @@ -10890,7 +11628,7 @@ "keybindings": [ { "key": "ctrl+c", - "when": "focusedView == gitlens.views.remotes", + "when": "focusedView == gitlens.views.remotes || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == remotes)", "mac": "cmd+c" } ] @@ -11318,7 +12056,7 @@ "keybindings": [ { "key": "ctrl+c", - "when": "focusedView == gitlens.views.repositories", + "when": "focusedView == gitlens.views.repositories || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == repositories)", "mac": "cmd+c" } ] @@ -13553,7 +14291,7 @@ "keybindings": [ { "key": "ctrl+c", - "when": "focusedView == gitlens.views.searchAndCompare", + "when": "focusedView == gitlens.views.searchAndCompare || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == searchAndCompare)", "mac": "cmd+c" } ] @@ -13860,6 +14598,30 @@ ] } }, + "gitlens.views.selectFileForCompare:commitDetails": { + "label": "Select for Compare", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?!.*?\\b\\+conflicted\\b)/ && webview == gitlens.views.commitDetails", + "group": "4_gitlens_compare", + "order": 99 + } + ] + } + }, + "gitlens.views.selectFileForCompare:graphDetails": { + "label": "Select for Compare", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?!.*?\\b\\+conflicted\\b)/ && webview == gitlens.views.graphDetails", + "group": "4_gitlens_compare", + "order": 99 + } + ] + } + }, "gitlens.views.selectForCompare": { "label": "Select for Compare", "menus": { @@ -14543,6 +15305,32 @@ ] } }, + "gitlens.views.stageFile:commitDetails": { + "label": "Stage Changes", + "icon": "$(add)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+unstaged\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens_actions", + "order": 1 + } + ] + } + }, + "gitlens.views.stageFile:graphDetails": { + "label": "Stage Changes", + "icon": "$(add)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+unstaged\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens_actions", + "order": 1 + } + ] + } + }, "gitlens.views.stashes.attach": { "label": "Group into GitLens View", "icon": "$(close)", @@ -14566,7 +15354,7 @@ "keybindings": [ { "key": "ctrl+c", - "when": "focusedView == gitlens.views.stashes", + "when": "focusedView == gitlens.views.stashes || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == stashes)", "mac": "cmd+c" } ] @@ -14872,7 +15660,7 @@ "keybindings": [ { "key": "ctrl+c", - "when": "focusedView == gitlens.views.tags", + "when": "focusedView == gitlens.views.tags || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == tags)", "mac": "cmd+c" } ] @@ -15359,6 +16147,32 @@ ] } }, + "gitlens.views.unstageFile:commitDetails": { + "label": "Unstage Changes", + "icon": "$(remove)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+staged\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens_actions", + "order": 2 + } + ] + } + }, + "gitlens.views.unstageFile:graphDetails": { + "label": "Unstage Changes", + "icon": "$(remove)", + "menus": { + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+staged\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens_actions", + "order": 2 + } + ] + } + }, "gitlens.views.workspaces.addRepos": { "label": "Add Repositories...", "icon": "$(add)", @@ -15679,7 +16493,7 @@ "keybindings": [ { "key": "ctrl+c", - "when": "focusedView == gitlens.views.worktrees", + "when": "focusedView == gitlens.views.worktrees || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == worktrees)", "mac": "cmd+c" } ] @@ -16207,6 +17021,19 @@ "icon": "$(graph-scatter)", "commandPalette": "gitlens:enabled && resource in gitlens:tabs:tracked" }, + "gitlens.visualizeHistory.file:commitDetails": { + "label": "Open Visual File History", + "icon": "$(graph-scatter)", + "menus": { + "gitlens/commit/file/history": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens", + "order": 2 + } + ] + } + }, "gitlens.visualizeHistory.file:editor": { "label": "Open Visual File History", "icon": "$(graph-scatter)", @@ -16231,6 +17058,19 @@ ] } }, + "gitlens.visualizeHistory.file:graphDetails": { + "label": "Open Visual File History", + "icon": "$(graph-scatter)", + "menus": { + "gitlens/commit/file/history": [ + { + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens", + "order": 2 + } + ] + } + }, "gitlens.visualizeHistory.file:scm": { "label": "Open Visual File History", "icon": "$(graph-scatter)", @@ -16249,6 +17089,7 @@ "menus": { "gitlens/commit/file/history": [ { + "when": "viewItem =~ /gitlens:file\\b/", "group": "1_gitlens", "order": 2 } @@ -16358,7 +17199,7 @@ "menus": { "view/item/context": [ { - "when": "viewItem =~ /gitlens:(branch|commit|file\\b(?=.*?\\b\\+committed\\b)|stash|tag)\\b/ && !listMultiSelection && !gitlens:hasVirtualFolders", + "when": "viewItem =~ /gitlens:(branch|commit|stash|tag)\\b/ && !listMultiSelection && !gitlens:hasVirtualFolders", "group": "3_gitlens_explore", "order": 100 } @@ -16386,6 +17227,13 @@ "group": "7_gitlens_cutcopypaste", "order": 10 } + ], + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/", + "group": "7_gitlens_cutcopypaste", + "order": 10 + } ] } }, @@ -16398,6 +17246,13 @@ "group": "2_gitlens_quickopen", "order": 2 } + ], + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b/", + "group": "2_gitlens_quickopen", + "order": 2 + } ] } }, @@ -16422,6 +17277,13 @@ "group": "3_gitlens_explore", "order": 2 } + ], + "webview/context": [ + { + "when": "webviewItem =~ /gitlens:file\\b/", + "group": "3_gitlens_explore", + "order": 2 + } ] } }, @@ -16814,7 +17676,7 @@ ], "webview/context": [ { - "when": "webviewItem =~ /gitlens:(branch|commit|stash|tag)\\b/", + "when": "webviewItem =~ /gitlens:(branch|commit|stash|tag|file\\b(?=.*?\\b\\+(committed|staged|unstaged)\\b))\\b/", "group": "7_gitlens_a_share", "order": 1 } diff --git a/custom-elements.json b/custom-elements.json index 21fa5b15868d7..72ff4976b49dd 100644 --- a/custom-elements.json +++ b/custom-elements.json @@ -6,344 +6,436 @@ "kind": "javascript-module", "path": "src/webviews/apps/commitDetails/commitDetails.ts", "declarations": [ + { + "kind": "variable", + "name": "uncommittedSha", + "type": { + "text": "string" + }, + "default": "'0000000000000000000000000000000000000000'" + }, { "kind": "class", "description": "", - "name": "CommitDetailsApp", + "name": "GlCommitDetailsApp", "members": [ { "kind": "method", - "name": "onInitialize", + "name": "createStateProvider", "privacy": "protected", "return": { "type": { - "text": "void" + "text": "CommitDetailsStateProvider" } }, + "parameters": [ + { + "name": "bootstrap", + "type": { + "text": "string" + } + }, + { + "name": "ipc", + "type": { + "text": "HostIpc" + } + }, + { + "name": "logger", + "type": { + "text": "LoggerContext" + } + } + ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { "kind": "field", - "name": "_api", + "name": "explain", "type": { - "text": "HostIpcApi" + "text": "ExplainState | undefined" }, - "privacy": "private", - "readonly": true, - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + "privacy": "private" }, { "kind": "field", - "name": "_hostIpc", + "name": "generate", "type": { - "text": "HostIpc" + "text": "GenerateState | undefined" }, - "privacy": "private", - "readonly": true, - "default": "new HostIpc(this.appName)", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + "privacy": "private" }, { "kind": "field", - "name": "_logger", + "name": "draftState", "type": { - "text": "LoggerContext" + "text": "DraftState" }, "privacy": "private", - "readonly": true, - "default": "new LoggerContext(appName)", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + "default": "{ inReview: false }" }, { "kind": "field", - "name": "_promos", + "name": "isUncommitted", "type": { - "text": "PromosContext" + "text": "boolean" }, "privacy": "private", - "readonly": true, - "default": "new PromosContext(this._hostIpc)", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + "readonly": true }, { "kind": "field", - "name": "_telemetry", + "name": "isStash", "type": { - "text": "TelemetryContext" + "text": "boolean" }, - "privacy": "protected", - "readonly": true, - "default": "new TelemetryContext(this._hostIpc)", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "state", - "type": { - "text": "State" - }, - "privacy": "protected", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + "name": "wipStatus", + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "placement", + "name": "indentPreference", "type": { - "text": "'editor' | 'view'" + "text": "number" }, - "privacy": "protected", - "readonly": true, - "default": "(document.body.getAttribute('data-placement') ?? 'editor')", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + "privacy": "private", + "default": "16" }, { "kind": "method", - "name": "onBind", - "privacy": "protected", - "return": { - "type": { - "text": "Disposable[]" + "name": "updateDocumentProperties", + "privacy": "private" + }, + { + "kind": "method", + "name": "onSuggestChanges", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "CreatePatchEventDetail" + } } - }, - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + ] }, { "kind": "method", - "name": "onInitialized", - "privacy": "protected", - "return": { - "type": { - "text": "void" + "name": "onShowCodeSuggestion", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "{ id: string }" + } } - }, - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + ] }, { "kind": "method", - "name": "onMessageReceived", - "privacy": "protected", - "return": { - "type": { - "text": "void" + "name": "renderTopInspect", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderTopWip", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderRepoStatusContent", + "privacy": "private", + "parameters": [ + { + "name": "_isWip", + "type": { + "text": "boolean" + } } - }, + ] + }, + { + "kind": "method", + "name": "renderWipTooltipContent", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderTopSection", + "privacy": "private" + }, + { + "kind": "method", + "name": "onDraftStateChanged", + "privacy": "private", "parameters": [ { - "name": "msg", + "name": "inReview", "type": { - "text": "IpcMessage" + "text": "boolean" } + }, + { + "name": "silent", + "default": "false" } - ], - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + ] }, { "kind": "method", - "name": "onThemeUpdated", - "privacy": "protected", - "return": { - "type": { - "text": "void" + "name": "onBranchAction", + "privacy": "private", + "parameters": [ + { + "name": "name", + "type": { + "text": "string" + } } - }, + ] + }, + { + "kind": "method", + "name": "onCreatePatchFromWip", + "privacy": "private", "parameters": [ { - "name": "e", + "name": "checked", + "default": "true", "type": { - "text": "ThemeChangeEvent" + "text": "boolean | 'staged'" } } - ], - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + ] }, { - "kind": "field", - "name": "_focused", - "type": { - "text": "boolean | undefined" - }, + "kind": "method", + "name": "onCommandClickedCore", "privacy": "private", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + "parameters": [ + { + "name": "action", + "optional": true, + "type": { + "text": "GlCommands | `command:${GlCommands}`" + } + } + ] }, { - "kind": "field", - "name": "_inputFocused", - "type": { - "text": "boolean | undefined" - }, + "kind": "method", + "name": "onSwitchAiModel", "privacy": "private", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + "parameters": [ + { + "name": "_e", + "type": { + "text": "MouseEvent" + } + } + ] }, { - "kind": "field", - "name": "bindDisposables", - "type": { - "text": "Disposable[] | undefined" - }, + "kind": "method", + "name": "onExplainCommit", "privacy": "private", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + "parameters": [ + { + "name": "_e", + "type": { + "text": "MouseEvent" + } + } + ] }, { "kind": "method", - "name": "bind", - "privacy": "protected", - "return": { - "type": { - "text": "void" + "name": "onCreateGenerateTitle", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "CreatePatchMetadataEventDetail" + } } - }, - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + ] }, { "kind": "method", - "name": "log", - "privacy": "protected", - "return": { - "type": { - "text": "void" + "name": "onToggleFilesLayout", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "MouseEvent" + } } - }, + ] + }, + { + "kind": "method", + "name": "onExpandedChange", + "privacy": "private", "parameters": [ { - "name": "message", + "name": "e", "type": { - "text": "string" + "text": "WebviewPaneExpandedChangeEventDetail" } }, { - "name": "optionalParams", + "name": "pane", "type": { - "text": "any[]" + "text": "string" } } - ], - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + ] }, { "kind": "method", - "name": "getState", - "privacy": "protected", - "return": { - "type": { - "text": "State | undefined" + "name": "onNavigate", + "privacy": "private", + "parameters": [ + { + "name": "direction", + "type": { + "text": "'back' | 'forward'" + } } - }, - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + ] }, { "kind": "method", - "name": "sendCommand", - "privacy": "protected", - "return": { - "type": { - "text": "void" + "name": "onTogglePin", + "privacy": "private" + }, + { + "kind": "method", + "name": "onPickCommit", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "MouseEvent" + } } - }, + ] + }, + { + "kind": "method", + "name": "onSearchCommit", + "privacy": "private", "parameters": [ { - "name": "command", + "name": "_e", "type": { - "text": "TCommand" + "text": "MouseEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onSwitchMode", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "MouseEvent" } }, { - "name": "params", + "name": "mode", "type": { - "text": "IpcCallParamsType" + "text": "Mode" } } - ], - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + ] }, { "kind": "method", - "name": "sendRequest", - "privacy": "protected", - "return": { - "type": { - "text": "Promise>" + "name": "onOpenFileOnRemote", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "FileChangeListItemDetail" + } } - }, + ] + }, + { + "kind": "method", + "name": "onOpenFile", + "privacy": "private", "parameters": [ { - "name": "requestType", + "name": "e", "type": { - "text": "T" + "text": "FileChangeListItemDetail" } - }, + } + ] + }, + { + "kind": "method", + "name": "onCompareFileWithWorking", + "privacy": "private", + "parameters": [ { - "name": "params", + "name": "e", "type": { - "text": "IpcCallParamsType" + "text": "FileChangeListItemDetail" } } - ], - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } + ] }, { "kind": "method", - "name": "setState", - "privacy": "protected", + "name": "onCompareFileWithPrevious", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "FileChangeListItemDetail" + } + } + ] + }, + { + "kind": "method", + "name": "onFileMoreActions", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "FileChangeListItemDetail" + } + } + ] + }, + { + "kind": "method", + "name": "onStageFile", + "privacy": "private", "return": { "type": { "text": "void" @@ -351,219 +443,43 @@ }, "parameters": [ { - "name": "state", + "name": "e", "type": { - "text": "Partial" + "text": "FileChangeListItemDetail" } } - ], - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "field", - "name": "bootstrap", - "default": "undefined", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - } - ], - "superclass": { - "name": "App", - "module": "/src/webviews/apps/shared/appBase" - } - } - ], - "exports": [ - { - "kind": "js", - "name": "CommitDetailsApp", - "declaration": { - "name": "CommitDetailsApp", - "module": "src/webviews/apps/commitDetails/commitDetails.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/home/context.ts", - "declarations": [ - { - "kind": "variable", - "name": "stateContext" - } - ], - "exports": [ - { - "kind": "js", - "name": "stateContext", - "declaration": { - "name": "stateContext", - "module": "src/webviews/apps/home/context.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/home/home.css.ts", - "declarations": [ - { - "kind": "variable", - "name": "homeBaseStyles", - "default": "css` * { box-sizing: border-box; } :not(:defined) { visibility: hidden; } [hidden] { display: none !important; } /* roll into shared focus style */ :focus-visible { outline: 1px solid var(--vscode-focusBorder); outline-offset: -1px; } b { font-weight: 600; } p { margin-top: 0; } ul { margin-top: 0; padding-left: 1.2em; } `" - }, - { - "kind": "variable", - "name": "homeStyles", - "default": "css` .home { padding: 0; height: 100vh; display: flex; flex-direction: column; gap: 0.4rem; overflow: hidden; } .home__alerts { flex: none; padding: 0 2rem; position: relative; } .home__alerts:not([has-alerts]) { display: none; } .home__main { flex: 1; overflow: auto; padding: 0.8rem 1.2rem; } .home__main > *:last-child { margin-bottom: 0; } .home__aux, .home__header { flex: none; } .home__header { border-top: 1px solid var(--vscode-sideBarSectionHeader-border); border-bottom: 1px solid var(--vscode-sideBarSectionHeader-border); padding: 0.4rem; } .home__aux:has(gl-promo-banner:has(gl-promo:not([has-promo])):only-child) { display: none; } summary { font-size: 1.3rem; font-weight: normal; text-transform: uppercase; color: var(--vscode-foreground); cursor: pointer; } details[open] summary { margin-block-end: 0.8rem; } gl-home-header { margin: 0; } gl-repo-alerts:not([has-alerts]) { display: none; } `" - }, - { - "kind": "variable", - "name": "buttonStyles", - "default": "css` .button-container { margin: 1rem auto 0; text-align: left; max-width: 30rem; transition: max-width 0.2s ease-out; } @media (min-width: 640px) { .button-container { max-width: 100%; } } .button-container--trio > gl-button:first-child { margin-bottom: 0.4rem; } .button-group { display: inline-flex; gap: 0.4rem; } .button-group--single { width: 100%; max-width: 30rem; } .button-group gl-button { margin-top: 0; } .button-group gl-button:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .button-group gl-button:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } `" - }, - { - "kind": "variable", - "name": "alertStyles", - "default": "css` .alert { position: relative; padding: 0.8rem 1.2rem; line-height: 1.2; margin-bottom: 1.2rem; background-color: var(--color-alert-neutralBackground); border-left: 0.3rem solid var(--color-alert-neutralBorder); color: var(--color-alert-foreground); } .alert__title { font-size: 1.4rem; margin: 0; } .alert__description { font-size: 1.2rem; margin: 0.4rem 0 0; } .alert__description > :first-child { margin-top: 0; } .alert__description > :last-child { margin-bottom: 0; } .alert__close { position: absolute; top: 0.8rem; right: 0.8rem; color: inherit; opacity: 0.64; } .alert__close:hover { color: inherit; opacity: 1; } .alert.is-collapsed { cursor: pointer; } .alert.is-collapsed:hover { background-color: var(--color-alert-neutralHoverBackground); } .alert.is-collapsed .alert__description, .alert.is-collapsed .alert__close gl-tooltip:first-child, .alert:not(.is-collapsed) .alert__close gl-tooltip:last-child { display: none; } .alert--info { background-color: var(--color-alert-infoBackground); border-left-color: var(--color-alert-infoBorder); } .alert--warning { background-color: var(--color-alert-warningBackground); border-left-color: var(--color-alert-warningBorder); } .alert--danger { background-color: var(--color-alert-errorBackground); border-left-color: var(--color-alert-errorBorder); } `" - }, - { - "kind": "variable", - "name": "navListStyles", - "default": "css` .nav-list { margin-left: -1.2rem; margin-right: -1.2rem; display: flex; flex-direction: column; gap: 0.1rem; align-items: stretch; margin-bottom: 1.6rem; } .nav-list__item { display: flex; flex-direction: row; align-items: center; gap: 0.8rem; padding: 0.4rem 2rem; } .nav-list__item:hover, .nav-list__item:focus-within { background-color: var(--vscode-list-hoverBackground); color: var(--vscode-list-hoverForeground); } .nav-list__item:has(:first-child:focus) { outline: 1px solid var(--vscode-focusBorder); outline-offset: -1px; } .nav-list__item:has(:active) { background-color: var(--vscode-list-activeSelectionBackground); color: var(--vscode-list-activeSelectionForeground); } .nav-list__item:has(.is-disabled) { cursor: not-allowed; } .nav-list__link { flex: 1; display: flex; flex-direction: row; align-items: center; gap: 0.8rem; color: inherit; } .nav-list__link:hover, .nav-list__link:focus { color: inherit; text-decoration: none; } .nav-list__link:focus { outline: none; } .nav-list__link.is-disabled, .nav-list__link.is-disabled:hover { opacity: 0.5; pointer-events: none; text-decoration: none; } .nav-list__icon { flex: none; opacity: 0.5; } .nav-list__label { flex: 1; font-weight: 600; } .nav-list__desc { color: var(--color-foreground--65); font-variant: all-small-caps; margin-left: 1rem; } .nav-list__group { width: 100%; display: flex; justify-content: flex-start; } .nav-list__group .nav-list__label { width: auto; } .nav-list__access { flex: none; position: relative; left: 1.2rem; font-size: x-small; outline: none; white-space: nowrap; --gl-feature-badge-color: color-mix(in srgb, transparent 40%, currentColor); --gl-feature-badge-border-color: color-mix(in srgb, transparent 40%, var(--color-foreground--50)); } .nav-list__item:hover .nav-list__label { text-decoration: underline; } .nav-list__item:hover .is-disabled .nav-list__label { text-decoration: none; } .nav-list__item:hover .nav-list__desc { color: var(--color-foreground); } .nav-list__item:focus-within .nav-list__access, .nav-list__item:hover .nav-list__access { --gl-feature-badge-color: currentColor; --gl-feature-badge-border-color: var(--color-foreground--50); } .nav-list__title { padding: 0 2rem; } .t-eyebrow { text-transform: uppercase; font-size: 1rem; font-weight: 600; color: var(--color-foreground--50); margin: 0; } .t-eyebrow.sticky { top: -8px; } `" - }, - { - "kind": "variable", - "name": "walkthroughProgressStyles", - "default": "css` a, a:hover, a:focus, a:active { text-decoration: none; } .walkthrough-progress { display: flex; flex-direction: column; gap: 2px; padding: 2px 4px 4px; margin-top: 4px; align-items: stretch; cursor: pointer; border-radius: 4px; } .walkthrough-progress:focus-within, .walkthrough-progress:hover { background-color: var(--gl-walkthrough-hover-background); } .walkthrough-progress__title { display: flex; justify-content: space-between; align-items: center; color: var(--color-foreground--85); } .walkthrough-progress__button { --button-padding: 1px 2px 0px 2px; position: absolute; right: 0.4rem; } .walkthrough-progress__bar::-webkit-progress-bar { border-radius: 2px; background: var(--color-alert-neutralBackground); } .walkthrough-progress__bar::-webkit-progress-value { background: var(--vscode-progressBar-background, blue); transition: 0.1s ease-in; border-radius: 2px; } .walkthrough-progress__bar { pointer-events: none; border-radius: 2px; width: 100%; background: unset; height: 4px; flex-shrink: 0; z-index: 2; } `" - } - ], - "exports": [ - { - "kind": "js", - "name": "homeBaseStyles", - "declaration": { - "name": "homeBaseStyles", - "module": "src/webviews/apps/home/home.css.ts" - } - }, - { - "kind": "js", - "name": "homeStyles", - "declaration": { - "name": "homeStyles", - "module": "src/webviews/apps/home/home.css.ts" - } - }, - { - "kind": "js", - "name": "buttonStyles", - "declaration": { - "name": "buttonStyles", - "module": "src/webviews/apps/home/home.css.ts" - } - }, - { - "kind": "js", - "name": "alertStyles", - "declaration": { - "name": "alertStyles", - "module": "src/webviews/apps/home/home.css.ts" - } - }, - { - "kind": "js", - "name": "navListStyles", - "declaration": { - "name": "navListStyles", - "module": "src/webviews/apps/home/home.css.ts" - } - }, - { - "kind": "js", - "name": "walkthroughProgressStyles", - "declaration": { - "name": "walkthroughProgressStyles", - "module": "src/webviews/apps/home/home.css.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/home/home.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlHomeApp", - "members": [ - { - "kind": "field", - "name": "_activeOverviewState", - "type": { - "text": "ActiveOverviewState" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "_inactiveOverviewState", - "type": { - "text": "InactiveOverviewState" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "_header", - "type": { - "text": "GlHomeHeader" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "badgeSource", - "type": { - "text": "object" - }, - "privacy": "private", - "default": "{ source: 'home', detail: 'badge' }" + ] }, { "kind": "method", - "name": "createStateProvider", - "privacy": "protected", + "name": "onUnstageFile", + "privacy": "private", "return": { "type": { - "text": "HomeStateProvider" + "text": "void" } }, "parameters": [ { - "name": "state", + "name": "e", "type": { - "text": "State" + "text": "FileChangeListItemDetail" } - }, + } + ] + }, + { + "kind": "method", + "name": "onCommitActions", + "privacy": "private", + "parameters": [ { - "name": "ipc", + "name": "e", "type": { - "text": "HostIpc" + "text": "CustomEvent<{ action: string; alt: boolean }>" } } - ], - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + ] }, { "kind": "field", @@ -655,7 +571,7 @@ "kind": "field", "name": "bootstrap", "type": { - "text": "State" + "text": "string" }, "privacy": "private", "attribute": "bootstrap", @@ -752,31 +668,9 @@ "kind": "field", "name": "_stateProvider", "type": { - "text": "StateProvider" + "text": "Provider" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } - }, - { - "kind": "method", - "name": "onPersistState", "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "state", - "type": { - "text": "State" - } - } - ], "inheritedFrom": { "name": "GlAppHost", "module": "src/webviews/apps/shared/appHost.ts" @@ -883,7 +777,7 @@ "name": "GlAppHost", "module": "/src/webviews/apps/shared/appHost" }, - "tagName": "gl-home-app", + "tagName": "gl-commit-details-app", "customElement": true, "attributes": [ { @@ -912,7 +806,7 @@ { "name": "bootstrap", "type": { - "text": "State" + "text": "string" }, "fieldName": "bootstrap", "inheritedFrom": { @@ -926,179 +820,92 @@ "exports": [ { "kind": "js", - "name": "GlHomeApp", + "name": "uncommittedSha", "declaration": { - "name": "GlHomeApp", - "module": "src/webviews/apps/home/home.ts" + "name": "uncommittedSha", + "module": "src/webviews/apps/commitDetails/commitDetails.ts" + } + }, + { + "kind": "js", + "name": "GlCommitDetailsApp", + "declaration": { + "name": "GlCommitDetailsApp", + "module": "src/webviews/apps/commitDetails/commitDetails.ts" } }, { "kind": "custom-element-definition", - "name": "gl-home-app", + "name": "gl-commit-details-app", "declaration": { - "name": "GlHomeApp", - "module": "src/webviews/apps/home/home.ts" + "name": "GlCommitDetailsApp", + "module": "src/webviews/apps/commitDetails/commitDetails.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/home/stateProvider.ts", + "path": "src/webviews/apps/commitDetails/context.ts", "declarations": [ { - "kind": "class", - "description": "", - "name": "HomeStateProvider", - "members": [ - { - "kind": "field", - "name": "disposable", - "type": { - "text": "Disposable" - }, - "privacy": "private", - "readonly": true - }, - { - "kind": "field", - "name": "provider", - "type": { - "text": "ContextProvider<{ __context__: State }, ReactiveElementHost>" - }, - "privacy": "private", - "readonly": true, - "default": "new ContextProvider(host, { context: stateContext, initialValue: state })" - }, - { - "kind": "field", - "name": "_state", - "type": { - "text": "State" - }, - "privacy": "private", - "readonly": true, - "default": "state" - }, - { - "kind": "field", - "name": "state", - "type": { - "text": "State" - }, - "readonly": true - }, - { - "kind": "method", - "name": "dispose", - "return": { - "type": { - "text": "void" - } - } - } - ] + "kind": "variable", + "name": "stateContext" } ], "exports": [ { "kind": "js", - "name": "HomeStateProvider", + "name": "stateContext", "declaration": { - "name": "HomeStateProvider", - "module": "src/webviews/apps/home/stateProvider.ts" + "name": "stateContext", + "module": "src/webviews/apps/commitDetails/context.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/rebase/rebase.ts", - "declarations": [], - "exports": [] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/settings/settings.ts", + "path": "src/webviews/apps/commitDetails/stateProvider.ts", "declarations": [ { "kind": "class", "description": "", - "name": "SettingsApp", + "name": "CommitDetailsStateProvider", "members": [ { "kind": "field", - "name": "_scopes", - "type": { - "text": "HTMLSelectElement | null" - }, - "privacy": "private", - "default": "null" - }, - { - "kind": "field", - "name": "_observer", - "type": { - "text": "IntersectionObserver | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "_activeSection", - "type": { - "text": "string | undefined" - }, - "privacy": "private", - "default": "'general'" - }, - { - "kind": "field", - "name": "_changes", - "privacy": "private", - "default": "Object.create(null)" - }, - { - "kind": "field", - "name": "_sections", - "privacy": "private", - "default": "new Map()" - }, - { - "kind": "field", - "name": "_updating", + "name": "deferBootstrap", "type": { "text": "boolean" }, - "privacy": "private", - "default": "false" - }, - { - "kind": "method", - "name": "onInitialize", "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, + "readonly": true, "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "method", - "name": "onBind", + "name": "createContextProvider", "privacy": "protected", "return": { "type": { - "text": "Disposable[]" + "text": "ContextProvider" } }, + "parameters": [ + { + "name": "state", + "type": { + "text": "State" + } + } + ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { @@ -1119,455 +926,448 @@ } ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "method", - "name": "applyChanges", - "privacy": "private" - }, - { - "kind": "method", - "name": "getSettingsScope", - "privacy": "private", - "return": { - "type": { - "text": "'user' | 'workspace'" - } + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "method", - "name": "onInputBlurred", - "privacy": "private", - "parameters": [ - { - "name": "element", - "type": { - "text": "HTMLInputElement" - } - } - ] - }, - { - "kind": "method", - "name": "onButtonClicked", - "privacy": "private", - "parameters": [ - { - "name": "element", - "type": { - "text": "HTMLButtonElement" - } - } - ] - }, - { - "kind": "method", - "name": "onInputChanged", + "name": "onDraftStateChanged", "privacy": "private", "parameters": [ { - "name": "element", + "name": "host", "type": { - "text": "HTMLInputElement" + "text": "ReactiveElementHost" } - } - ] - }, - { - "kind": "method", - "name": "onInputChecked", - "privacy": "private", - "parameters": [ + }, { - "name": "element", + "name": "inReview", "type": { - "text": "HTMLInputElement" + "text": "boolean" } - } - ] - }, - { - "kind": "method", - "name": "onInputFocused", - "privacy": "private", - "parameters": [ + }, { - "name": "element", - "type": { - "text": "HTMLInputElement" - } + "name": "silent", + "default": "false" } ] }, { "kind": "method", - "name": "onInputSelected", - "privacy": "private", + "name": "switchMode", "parameters": [ { - "name": "element", + "name": "mode", "type": { - "text": "HTMLSelectElement" + "text": "State['mode']" } } ] }, { "kind": "method", - "name": "onTokenMouseDown", - "privacy": "private", + "name": "updatePreferences", "parameters": [ { - "name": "element", - "type": { - "text": "HTMLElement" - } - }, - { - "name": "e", + "name": "preferenceChange", "type": { - "text": "MouseEvent" + "text": "UpdateablePreferences" } } ] }, { - "kind": "method", - "name": "scrollToAnchor", - "privacy": "private", - "parameters": [ - { - "name": "anchor", - "type": { - "text": "string" - } - }, - { - "name": "behavior", - "type": { - "text": "ScrollBehavior" - } - }, - { - "name": "offset", - "optional": true, - "type": { - "text": "number" - } - } - ] + "kind": "field", + "name": "disposable", + "type": { + "text": "Disposable" + }, + "privacy": "protected", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "_scrollTimer", + "name": "provider", "type": { - "text": "ReturnType | undefined" + "text": "ContextProvider" }, - "privacy": "private" + "privacy": "protected", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { - "kind": "method", - "name": "scrollTo", - "privacy": "private", - "parameters": [ - { - "name": "el", - "type": { - "text": "HTMLElement" - } - }, - { - "name": "behavior", - "type": { - "text": "ScrollBehavior" - } - }, - { - "name": "offset", - "optional": true, - "type": { - "text": "number" - } - } - ] + "kind": "field", + "name": "_state", + "type": { + "text": "State" + }, + "privacy": "protected", + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + }, + { + "kind": "field", + "name": "state", + "type": { + "text": "State" + }, + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + }, + { + "kind": "field", + "name": "webviewId", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + }, + { + "kind": "field", + "name": "webviewInstanceId", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + }, + { + "kind": "field", + "name": "timestamp", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "method", - "name": "evaluateStateExpression", - "privacy": "private", + "name": "dispose", "return": { "type": { - "text": "boolean" + "text": "void" } }, - "parameters": [ - { - "name": "expression", - "type": { - "text": "string" - } - }, - { - "name": "changes", - "type": { - "text": "Record" - } - } - ] + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "method", - "name": "getCustomSettingValue", - "privacy": "private", + "name": "initializeState", + "privacy": "protected", "return": { "type": { - "text": "boolean | undefined" + "text": "Promise" } }, - "parameters": [ - { - "name": "path", - "type": { - "text": "string" - } - } - ] + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "method", - "name": "getSettingValue", - "privacy": "private", + "name": "onPersistState", + "privacy": "protected", "return": { "type": { - "text": "T | undefined" + "text": "void" } }, "parameters": [ { - "name": "path", + "name": "state", "type": { - "text": "string" + "text": "State" } } - ] - }, + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + } + ], + "superclass": { + "name": "StateProviderBase", + "module": "/src/webviews/apps/shared/stateProviderBase" + } + } + ], + "exports": [ + { + "kind": "js", + "name": "CommitDetailsStateProvider", + "declaration": { + "name": "CommitDetailsStateProvider", + "module": "src/webviews/apps/commitDetails/stateProvider.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/home/context.ts", + "declarations": [ + { + "kind": "variable", + "name": "stateContext" + } + ], + "exports": [ + { + "kind": "js", + "name": "stateContext", + "declaration": { + "name": "stateContext", + "module": "src/webviews/apps/home/context.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/home/home.css.ts", + "declarations": [ + { + "kind": "variable", + "name": "homeBaseStyles", + "default": "css` * { box-sizing: border-box; } :not(:defined) { visibility: hidden; } [hidden] { display: none !important; } /* roll into shared focus style */ :focus-visible { outline: 1px solid var(--vscode-focusBorder); outline-offset: -1px; } b { font-weight: 600; } p { margin-top: 0; } ul { margin-top: 0; padding-left: 1.2em; } `" + }, + { + "kind": "variable", + "name": "homeStyles", + "default": "css` .home { padding: 0; height: 100vh; display: flex; flex-direction: column; gap: 0.4rem; overflow: hidden; } .home__alerts { flex: none; padding: 0 2rem; position: relative; } .home__alerts:not([has-alerts]) { display: none; } .home__main { flex: 1; overflow: auto; padding: 0.8rem 1.2rem; } .home__main > *:last-child { margin-bottom: 0; } .home__aux, .home__header { flex: none; } .home__header { border-top: 1px solid var(--vscode-sideBarSectionHeader-border); border-bottom: 1px solid var(--vscode-sideBarSectionHeader-border); padding: 0.4rem; } .home__aux:has(gl-promo-banner:has(gl-promo:not([has-promo])):only-child) { display: none; } summary { font-size: 1.3rem; font-weight: normal; text-transform: uppercase; color: var(--vscode-foreground); cursor: pointer; } details[open] summary { margin-block-end: 0.8rem; } gl-home-header { margin: 0; } gl-repo-alerts:not([has-alerts]) { display: none; } `" + }, + { + "kind": "variable", + "name": "buttonStyles", + "default": "css` .button-container { margin: 1rem auto 0; text-align: left; max-width: 30rem; transition: max-width 0.2s ease-out; } @media (min-width: 640px) { .button-container { max-width: 100%; } } .button-container--trio > gl-button:first-child { margin-bottom: 0.4rem; } .button-group { display: inline-flex; gap: 0.4rem; } .button-group--single { width: 100%; max-width: 30rem; } .button-group gl-button { margin-top: 0; } .button-group gl-button:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .button-group gl-button:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } `" + }, + { + "kind": "variable", + "name": "alertStyles", + "default": "css` .alert { position: relative; padding: 0.8rem 1.2rem; line-height: 1.2; margin-bottom: 1.2rem; background-color: var(--color-alert-neutralBackground); border-left: 0.3rem solid var(--color-alert-neutralBorder); color: var(--color-alert-foreground); } .alert__title { font-size: 1.4rem; margin: 0; } .alert__description { font-size: 1.2rem; margin: 0.4rem 0 0; } .alert__description > :first-child { margin-top: 0; } .alert__description > :last-child { margin-bottom: 0; } .alert__close { position: absolute; top: 0.8rem; right: 0.8rem; color: inherit; opacity: 0.64; } .alert__close:hover { color: inherit; opacity: 1; } .alert.is-collapsed { cursor: pointer; } .alert.is-collapsed:hover { background-color: var(--color-alert-neutralHoverBackground); } .alert.is-collapsed .alert__description, .alert.is-collapsed .alert__close gl-tooltip:first-child, .alert:not(.is-collapsed) .alert__close gl-tooltip:last-child { display: none; } .alert--info { --color-alert-foreground: var(--color-alert-infoForeground); background-color: var(--color-alert-infoBackground); border-left-color: var(--color-alert-infoBorder); } .alert--warning { --color-alert-foreground: var(--color-alert-warningForeground); background-color: var(--color-alert-warningBackground); border-left-color: var(--color-alert-warningBorder); } .alert--danger { --color-alert-foreground: var(--color-alert-errorForeground); background-color: var(--color-alert-errorBackground); border-left-color: var(--color-alert-errorBorder); } .alert a:not(:hover) { color: color-mix(in srgb, var(--color-alert-foreground) 50%, var(--vscode-textLink-foreground)); } .alert a:hover { color: color-mix(in srgb, var(--color-alert-foreground) 50%, var(--vscode-textLink-activeForeground)); } `" + }, + { + "kind": "variable", + "name": "navListStyles", + "default": "css` .nav-list { margin-left: -1.2rem; margin-right: -1.2rem; display: flex; flex-direction: column; gap: 0.1rem; align-items: stretch; margin-bottom: 1.6rem; } .nav-list__item { display: flex; flex-direction: row; align-items: center; gap: 0.8rem; padding: 0.4rem 2rem; } .nav-list__item:hover, .nav-list__item:focus-within { background-color: var(--vscode-list-hoverBackground); color: var(--vscode-list-hoverForeground); } .nav-list__item:has(:first-child:focus) { outline: 1px solid var(--vscode-focusBorder); outline-offset: -1px; } .nav-list__item:has(:active) { background-color: var(--vscode-list-activeSelectionBackground); color: var(--vscode-list-activeSelectionForeground); } .nav-list__item:has(.is-disabled) { cursor: not-allowed; } .nav-list__link { flex: 1; display: flex; flex-direction: row; align-items: center; gap: 0.8rem; color: inherit; } .nav-list__link:hover, .nav-list__link:focus { color: inherit; text-decoration: none; } .nav-list__link:focus { outline: none; } .nav-list__link.is-disabled, .nav-list__link.is-disabled:hover { opacity: 0.5; pointer-events: none; text-decoration: none; } .nav-list__icon { flex: none; opacity: 0.5; } .nav-list__label { flex: 1; font-weight: 600; } .nav-list__desc { color: var(--color-foreground--65); font-variant: all-small-caps; margin-left: 1rem; } .nav-list__group { width: 100%; display: flex; justify-content: flex-start; } .nav-list__group .nav-list__label { width: auto; } .nav-list__access { flex: none; position: relative; left: 1.2rem; font-size: x-small; outline: none; white-space: nowrap; --gl-feature-badge-color: color-mix(in srgb, transparent 40%, currentColor); --gl-feature-badge-border-color: color-mix(in srgb, transparent 40%, var(--color-foreground--50)); } .nav-list__item:hover .nav-list__label { text-decoration: underline; } .nav-list__item:hover .is-disabled .nav-list__label { text-decoration: none; } .nav-list__item:hover .nav-list__desc { color: var(--color-foreground); } .nav-list__item:focus-within .nav-list__access, .nav-list__item:hover .nav-list__access { --gl-feature-badge-color: currentColor; --gl-feature-badge-border-color: var(--color-foreground--50); } .nav-list__title { padding: 0 2rem; } .t-eyebrow { text-transform: uppercase; font-size: 1rem; font-weight: 600; color: var(--color-foreground--50); margin: 0; } .t-eyebrow.sticky { top: -8px; } `" + }, + { + "kind": "variable", + "name": "walkthroughProgressStyles", + "default": "css` a, a:hover, a:focus, a:active { text-decoration: none; } .walkthrough-progress { display: flex; flex-direction: column; gap: 2px; padding: 2px 4px 4px; margin-top: 4px; align-items: stretch; cursor: pointer; border-radius: 4px; } .walkthrough-progress:focus-within, .walkthrough-progress:hover { background-color: var(--gl-walkthrough-hover-background); } .walkthrough-progress__title { display: flex; justify-content: space-between; align-items: center; color: var(--color-foreground--85); } .walkthrough-progress__button { --button-padding: 1px 2px 0px 2px; position: absolute; right: 0.4rem; } .walkthrough-progress__bar::-webkit-progress-bar { border-radius: 2px; background: var(--color-alert-neutralBackground); } .walkthrough-progress__bar::-webkit-progress-value { background: var(--vscode-progressBar-background, blue); transition: 0.1s ease-in; border-radius: 2px; } .walkthrough-progress__bar { pointer-events: none; border-radius: 2px; width: 100%; background: unset; height: 4px; flex-shrink: 0; z-index: 2; } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "homeBaseStyles", + "declaration": { + "name": "homeBaseStyles", + "module": "src/webviews/apps/home/home.css.ts" + } + }, + { + "kind": "js", + "name": "homeStyles", + "declaration": { + "name": "homeStyles", + "module": "src/webviews/apps/home/home.css.ts" + } + }, + { + "kind": "js", + "name": "buttonStyles", + "declaration": { + "name": "buttonStyles", + "module": "src/webviews/apps/home/home.css.ts" + } + }, + { + "kind": "js", + "name": "alertStyles", + "declaration": { + "name": "alertStyles", + "module": "src/webviews/apps/home/home.css.ts" + } + }, + { + "kind": "js", + "name": "navListStyles", + "declaration": { + "name": "navListStyles", + "module": "src/webviews/apps/home/home.css.ts" + } + }, + { + "kind": "js", + "name": "walkthroughProgressStyles", + "declaration": { + "name": "walkthroughProgressStyles", + "module": "src/webviews/apps/home/home.css.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/home/home.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlHomeApp", + "members": [ { - "kind": "method", - "name": "updateState", + "kind": "field", + "name": "_activeOverviewState", + "type": { + "text": "ActiveOverviewState" + }, "privacy": "private" }, { - "kind": "method", - "name": "setAdditionalSettings", - "privacy": "private", - "parameters": [ - { - "name": "expression", - "type": { - "text": "string | undefined" - } - } - ] - }, - { - "kind": "method", - "name": "setEnablement", - "privacy": "private", - "parameters": [ - { - "name": "state", - "type": { - "text": "Record" - } - } - ] - }, - { - "kind": "method", - "name": "setVisibility", - "privacy": "private", - "parameters": [ - { - "name": "state", - "type": { - "text": "Record" - } - } - ] + "kind": "field", + "name": "_inactiveOverviewState", + "type": { + "text": "InactiveOverviewState" + }, + "privacy": "private" }, { - "kind": "method", - "name": "updatePreview", - "privacy": "private", - "parameters": [ - { - "name": "el", - "type": { - "text": "HTMLSpanElement" - } - }, - { - "name": "value", - "optional": true, - "type": { - "text": "string" - } - } - ] + "kind": "field", + "name": "_header", + "type": { + "text": "GlHomeHeader" + }, + "privacy": "private" }, { - "kind": "method", - "name": "onObserver", - "privacy": "private", - "parameters": [ - { - "name": "entries", - "type": { - "text": "IntersectionObserverEntry[]" - } - }, - { - "name": "_observer", - "type": { - "text": "IntersectionObserver" - } - } - ] + "kind": "field", + "name": "allAccessPromoBanner", + "type": { + "text": "GlAiAllAccessBanner" + }, + "privacy": "private" }, { - "kind": "method", - "name": "onActionLinkClicked", + "kind": "field", + "name": "badgeSource", + "type": { + "text": "object" + }, "privacy": "private", - "parameters": [ - { - "name": "element", - "type": { - "text": "HTMLElement" - } - }, - { - "name": "e", - "type": { - "text": "MouseEvent" - } - } - ] + "default": "{ source: 'home', detail: 'badge' }" }, { "kind": "method", - "name": "onJumpToLinkClicked", - "privacy": "private", - "parameters": [ - { - "name": "element", - "type": { - "text": "HTMLAnchorElement" - } - }, - { - "name": "e", - "type": { - "text": "MouseEvent" - } + "name": "createStateProvider", + "privacy": "protected", + "return": { + "type": { + "text": "HomeStateProvider" } - ] - }, - { - "kind": "method", - "name": "onSectionHeaderClicked", - "privacy": "private", + }, "parameters": [ { - "name": "element", + "name": "bootstrap", "type": { - "text": "HTMLElement" + "text": "string" } }, { - "name": "e", - "type": { - "text": "MouseEvent" - } - } - ] - }, - { - "kind": "method", - "name": "onSettingExpanderCicked", - "privacy": "private", - "parameters": [ - { - "name": "element", + "name": "ipc", "type": { - "text": "HTMLElement" + "text": "HostIpc" } }, { - "name": "_e", + "name": "logger", "type": { - "text": "MouseEvent" + "text": "LoggerContext" } } - ] + ], + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "method", - "name": "toggleJumpLink", - "privacy": "private", - "parameters": [ - { - "name": "anchor", - "type": { - "text": "string" - } - }, - { - "name": "active", - "type": { - "text": "boolean" - } + "name": "refreshAiAllAccessPromo", + "return": { + "type": { + "text": "void" } - ] + } }, { - "kind": "method", - "name": "renderAutolinkIntegration", - "privacy": "private" + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "method", - "name": "renderAutolinks", - "privacy": "private" + "kind": "field", + "name": "name", + "type": { + "text": "string" + }, + "attribute": "name", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "field", - "name": "_api", + "name": "placement", "type": { - "text": "HostIpcApi" + "text": "'editor' | 'view'" }, - "privacy": "private", - "readonly": true, + "default": "'editor'", + "attribute": "placement", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { "kind": "field", - "name": "_hostIpc", + "name": "_ipc", "type": { "text": "HostIpc" }, - "privacy": "private", - "readonly": true, - "default": "new HostIpc(this.appName)", + "privacy": "protected", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { @@ -1576,12 +1376,10 @@ "type": { "text": "LoggerContext" }, - "privacy": "private", - "readonly": true, - "default": "new LoggerContext(appName)", + "privacy": "protected", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { @@ -1590,12 +1388,10 @@ "type": { "text": "PromosContext" }, - "privacy": "private", - "readonly": true, - "default": "new PromosContext(this._hostIpc)", + "privacy": "protected", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { @@ -1605,51 +1401,22 @@ "text": "TelemetryContext" }, "privacy": "protected", - "readonly": true, - "default": "new TelemetryContext(this._hostIpc)", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { "kind": "field", - "name": "state", + "name": "bootstrap", "type": { - "text": "State" + "text": "string" }, - "privacy": "protected", + "privacy": "private", + "attribute": "bootstrap", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "field", - "name": "placement", - "type": { - "text": "'editor' | 'view'" - }, - "privacy": "protected", - "readonly": true, - "default": "(document.body.getAttribute('data-placement') ?? 'editor')", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "method", - "name": "onInitialized", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { @@ -1670,8 +1437,34 @@ } ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "state", + "type": { + "text": "State" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "disposables", + "type": { + "text": "Disposable[]" + }, + "privacy": "protected", + "readonly": true, + "default": "[]", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { @@ -1682,8 +1475,8 @@ }, "privacy": "private", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { @@ -1694,39 +1487,37 @@ }, "privacy": "private", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { "kind": "field", - "name": "bindDisposables", + "name": "_sendWebviewFocusChangedCommandDebounced", "type": { - "text": "Disposable[] | undefined" + "text": "Deferrable<(params: WebviewFocusChangedParams) => void>" }, "privacy": "private", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { - "kind": "method", - "name": "bind", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } + "kind": "field", + "name": "_stateProvider", + "type": { + "text": "Provider" }, + "privacy": "protected", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { "kind": "method", - "name": "log", + "name": "onWebviewFocusChanged", "privacy": "protected", "return": { "type": { @@ -1735,40 +1526,20 @@ }, "parameters": [ { - "name": "message", - "type": { - "text": "string" - } - }, - { - "name": "optionalParams", + "name": "focused", "type": { - "text": "any[]" + "text": "boolean" } } ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "method", - "name": "getState", - "privacy": "protected", - "return": { - "type": { - "text": "State | undefined" - } - }, - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { "kind": "method", - "name": "sendCommand", + "name": "onWebviewVisibilityChanged", "privacy": "protected", "return": { "type": { @@ -1777,157 +1548,223 @@ }, "parameters": [ { - "name": "command", - "type": { - "text": "TCommand" - } - }, - { - "name": "params", + "name": "visible", "type": { - "text": "IpcCallParamsType" + "text": "boolean" } } ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "onFocusIn", + "privacy": "private", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "onFocusOut", + "privacy": "private", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { "kind": "method", - "name": "sendRequest", - "privacy": "protected", + "name": "emit", "return": { "type": { - "text": "Promise>" + "text": "CustomEventType" } }, "parameters": [ { - "name": "requestType", + "name": "name", "type": { "text": "T" } }, { - "name": "params", + "name": "detail", "type": { - "text": "IpcCallParamsType" + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" } } ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "superclass": { + "name": "GlAppHost", + "module": "/src/webviews/apps/shared/appHost" + }, + "tagName": "gl-home-app", + "customElement": true, + "attributes": [ + { + "name": "name", + "type": { + "text": "string" + }, + "fieldName": "name", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { - "kind": "method", - "name": "setState", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } + "name": "placement", + "type": { + "text": "'editor' | 'view'" }, - "parameters": [ - { - "name": "state", - "type": { - "text": "Partial" - } - } - ], + "default": "'editor'", + "fieldName": "placement", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { - "kind": "field", "name": "bootstrap", - "default": "undefined", + "type": { + "text": "string" + }, + "fieldName": "bootstrap", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } } - ], - "superclass": { - "name": "App", - "module": "/src/webviews/apps/shared/appBase" - } + ] } ], "exports": [ { "kind": "js", - "name": "SettingsApp", + "name": "GlHomeApp", "declaration": { - "name": "SettingsApp", - "module": "src/webviews/apps/settings/settings.ts" + "name": "GlHomeApp", + "module": "src/webviews/apps/home/home.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-home-app", + "declaration": { + "name": "GlHomeApp", + "module": "src/webviews/apps/home/home.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/appBase.ts", + "path": "src/webviews/apps/home/stateProvider.ts", "declarations": [ { "kind": "class", "description": "", - "name": "App", + "name": "HomeStateProvider", "members": [ { - "kind": "field", - "name": "_api", - "type": { - "text": "HostIpcApi" + "kind": "method", + "name": "createContextProvider", + "privacy": "protected", + "return": { + "type": { + "text": "ContextProvider" + } }, - "privacy": "private", - "readonly": true + "parameters": [ + { + "name": "state", + "type": { + "text": "State" + } + } + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { - "kind": "field", - "name": "_hostIpc", - "type": { - "text": "HostIpc" + "kind": "method", + "name": "onMessageReceived", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "privacy": "private", - "readonly": true, - "default": "new HostIpc(this.appName)" + "parameters": [ + { + "name": "msg", + "type": { + "text": "IpcMessage" + } + } + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "_logger", + "name": "disposable", "type": { - "text": "LoggerContext" + "text": "Disposable" }, - "privacy": "private", + "privacy": "protected", "readonly": true, - "default": "new LoggerContext(appName)" + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "_promos", + "name": "provider", "type": { - "text": "PromosContext" + "text": "ContextProvider" }, - "privacy": "private", + "privacy": "protected", "readonly": true, - "default": "new PromosContext(this._hostIpc)" + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "_telemetry", + "name": "_state", "type": { - "text": "TelemetryContext" + "text": "State" }, "privacy": "protected", - "readonly": true, - "default": "new TelemetryContext(this._hostIpc)" + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", @@ -1935,69 +1772,82 @@ "type": { "text": "State" }, - "privacy": "protected" + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "placement", - "type": { - "text": "'editor' | 'view'" - }, - "privacy": "protected", + "name": "webviewId", "readonly": true, - "default": "(document.body.getAttribute('data-placement') ?? 'editor')" + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { - "kind": "method", - "name": "onInitialize", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } + "kind": "field", + "name": "webviewInstanceId", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { - "kind": "method", - "name": "onBind", - "privacy": "protected", - "return": { - "type": { - "text": "Disposable[]" - } + "kind": "field", + "name": "timestamp", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "method", - "name": "onInitialized", - "privacy": "protected", + "name": "dispose", "return": { "type": { "text": "void" } + }, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + }, + { + "kind": "field", + "name": "deferBootstrap", + "type": { + "text": "boolean" + }, + "privacy": "protected", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "method", - "name": "onMessageReceived", + "name": "initializeState", "privacy": "protected", "return": { "type": { - "text": "void" + "text": "Promise" } }, - "parameters": [ - { - "name": "msg", - "type": { - "text": "IpcMessage" - } - } - ] + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "method", - "name": "onThemeUpdated", + "name": "onPersistState", "privacy": "protected", "return": { "type": { @@ -2006,74 +1856,128 @@ }, "parameters": [ { - "name": "e", + "name": "state", "type": { - "text": "ThemeChangeEvent" + "text": "State" } } - ] + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + } + ], + "superclass": { + "name": "StateProviderBase", + "module": "/src/webviews/apps/shared/stateProviderBase" + } + } + ], + "exports": [ + { + "kind": "js", + "name": "HomeStateProvider", + "declaration": { + "name": "HomeStateProvider", + "module": "src/webviews/apps/home/stateProvider.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/rebase/rebase.ts", + "declarations": [], + "exports": [] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/settings/settings.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "SettingsApp", + "members": [ + { + "kind": "field", + "name": "_scopes", + "type": { + "text": "HTMLSelectElement | null" + }, + "privacy": "private", + "default": "null" }, { "kind": "field", - "name": "_focused", + "name": "_observer", "type": { - "text": "boolean | undefined" + "text": "IntersectionObserver | undefined" }, "privacy": "private" }, { "kind": "field", - "name": "_inputFocused", + "name": "_activeSection", "type": { - "text": "boolean | undefined" + "text": "string | undefined" }, - "privacy": "private" + "privacy": "private", + "default": "'general'" }, { "kind": "field", - "name": "bindDisposables", + "name": "_changes", + "privacy": "private", + "default": "Object.create(null)" + }, + { + "kind": "field", + "name": "_sections", + "privacy": "private", + "default": "new Map()" + }, + { + "kind": "field", + "name": "_updating", "type": { - "text": "Disposable[] | undefined" + "text": "boolean" }, - "privacy": "private" + "privacy": "private", + "default": "false" }, { "kind": "method", - "name": "bind", + "name": "onInitialize", "privacy": "protected", "return": { "type": { "text": "void" } + }, + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { "kind": "method", - "name": "log", + "name": "onBind", "privacy": "protected", "return": { "type": { - "text": "void" + "text": "Disposable[]" } }, - "parameters": [ - { - "name": "message", - "type": { - "text": "string" - } - }, - { - "name": "optionalParams", - "type": { - "text": "any[]" - } - } - ] + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { "kind": "method", - "name": "log", + "name": "onMessageReceived", "privacy": "protected", "return": { "type": { @@ -2082,903 +1986,969 @@ }, "parameters": [ { - "name": "scope", - "type": { - "text": "LogScope | undefined" - } - }, - { - "name": "message", - "type": { - "text": "string" - } - }, - { - "name": "optionalParams", + "name": "msg", "type": { - "text": "any[]" + "text": "IpcMessage" } } - ] + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { "kind": "method", - "name": "log", - "privacy": "protected", - "return": { - "type": { - "text": "void" + "name": "applyChanges", + "privacy": "private" + }, + { + "kind": "method", + "name": "getSettingsScope", + "privacy": "private", + "return": { + "type": { + "text": "'user' | 'workspace'" } - }, + } + }, + { + "kind": "method", + "name": "onInputBlurred", + "privacy": "private", "parameters": [ { - "name": "scopeOrMessage", + "name": "element", "type": { - "text": "LogScope | string | undefined" + "text": "HTMLInputElement" } - }, + } + ] + }, + { + "kind": "method", + "name": "onButtonClicked", + "privacy": "private", + "parameters": [ { - "name": "optionalParams", + "name": "element", "type": { - "text": "any[]" + "text": "HTMLButtonElement" } } ] }, { "kind": "method", - "name": "getState", - "privacy": "protected", - "return": { - "type": { - "text": "State | undefined" + "name": "onInputChanged", + "privacy": "private", + "parameters": [ + { + "name": "element", + "type": { + "text": "HTMLInputElement" + } } - } + ] }, { "kind": "method", - "name": "sendCommand", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, + "name": "onInputChecked", + "privacy": "private", "parameters": [ { - "name": "command", + "name": "element", "type": { - "text": "TCommand" + "text": "HTMLInputElement" } - }, + } + ] + }, + { + "kind": "method", + "name": "onInputFocused", + "privacy": "private", + "parameters": [ { - "name": "params", + "name": "element", "type": { - "text": "IpcCallParamsType" + "text": "HTMLInputElement" } } ] }, { "kind": "method", - "name": "sendRequest", - "privacy": "protected", - "return": { - "type": { - "text": "Promise>" + "name": "onInputSelected", + "privacy": "private", + "parameters": [ + { + "name": "element", + "type": { + "text": "HTMLSelectElement" + } } - }, + ] + }, + { + "kind": "method", + "name": "onTokenMouseDown", + "privacy": "private", "parameters": [ { - "name": "requestType", + "name": "element", "type": { - "text": "T" + "text": "HTMLElement" } }, { - "name": "params", + "name": "e", "type": { - "text": "IpcCallParamsType" + "text": "MouseEvent" } } ] }, { "kind": "method", - "name": "setState", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, + "name": "scrollToAnchor", + "privacy": "private", "parameters": [ { - "name": "state", + "name": "anchor", "type": { - "text": "Partial" + "text": "string" + } + }, + { + "name": "behavior", + "type": { + "text": "ScrollBehavior" + } + }, + { + "name": "offset", + "optional": true, + "type": { + "text": "number" } } ] }, { "kind": "field", - "name": "bootstrap", - "default": "undefined" - } - ] - } - ], - "exports": [ - { - "kind": "js", - "name": "App", - "declaration": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/appHost.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlAppHost", - "members": [ - { - "kind": "field", - "name": "shadowRootOptions", - "type": { - "text": "ShadowRootInit" - }, - "static": true, - "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" - }, - { - "kind": "field", - "name": "name", - "type": { - "text": "string" - }, - "attribute": "name" - }, - { - "kind": "field", - "name": "placement", - "type": { - "text": "'editor' | 'view'" - }, - "default": "'editor'", - "attribute": "placement" - }, - { - "kind": "field", - "name": "_ipc", - "type": { - "text": "HostIpc" - }, - "privacy": "protected" - }, - { - "kind": "field", - "name": "_logger", - "type": { - "text": "LoggerContext" - }, - "privacy": "protected" - }, - { - "kind": "field", - "name": "_promos", - "type": { - "text": "PromosContext" - }, - "privacy": "protected" - }, - { - "kind": "field", - "name": "_telemetry", + "name": "_scrollTimer", "type": { - "text": "TelemetryContext" + "text": "ReturnType | undefined" }, - "privacy": "protected" + "privacy": "private" }, { - "kind": "field", - "name": "bootstrap", - "type": { - "text": "State" - }, + "kind": "method", + "name": "scrollTo", "privacy": "private", - "attribute": "bootstrap" + "parameters": [ + { + "name": "el", + "type": { + "text": "HTMLElement" + } + }, + { + "name": "behavior", + "type": { + "text": "ScrollBehavior" + } + }, + { + "name": "offset", + "optional": true, + "type": { + "text": "number" + } + } + ] }, { "kind": "method", - "name": "onThemeUpdated", - "privacy": "protected", + "name": "evaluateStateExpression", + "privacy": "private", "return": { "type": { - "text": "void" + "text": "boolean" } }, "parameters": [ { - "name": "e", + "name": "expression", "type": { - "text": "ThemeChangeEvent" + "text": "string" + } + }, + { + "name": "changes", + "type": { + "text": "Record" } } ] }, { - "kind": "field", - "name": "state", - "type": { - "text": "State" + "kind": "method", + "name": "getCustomSettingValue", + "privacy": "private", + "return": { + "type": { + "text": "boolean | undefined" + } }, - "readonly": true + "parameters": [ + { + "name": "path", + "type": { + "text": "string" + } + } + ] }, { - "kind": "field", - "name": "disposables", - "type": { - "text": "Disposable[]" + "kind": "method", + "name": "getSettingValue", + "privacy": "private", + "return": { + "type": { + "text": "T | undefined" + } }, - "privacy": "protected", - "readonly": true, - "default": "[]" + "parameters": [ + { + "name": "path", + "type": { + "text": "string" + } + } + ] }, { - "kind": "field", - "name": "_focused", - "type": { - "text": "boolean | undefined" - }, + "kind": "method", + "name": "updateState", "privacy": "private" }, { - "kind": "field", - "name": "_inputFocused", - "type": { - "text": "boolean | undefined" - }, - "privacy": "private" + "kind": "method", + "name": "setAdditionalSettings", + "privacy": "private", + "parameters": [ + { + "name": "expression", + "type": { + "text": "string | undefined" + } + } + ] }, { - "kind": "field", - "name": "_sendWebviewFocusChangedCommandDebounced", - "type": { - "text": "Deferrable<(params: WebviewFocusChangedParams) => void>" - }, - "privacy": "private" + "kind": "method", + "name": "setEnablement", + "privacy": "private", + "parameters": [ + { + "name": "state", + "type": { + "text": "Record" + } + } + ] }, { - "kind": "field", - "name": "_stateProvider", - "type": { - "text": "StateProvider" - }, - "privacy": "private" + "kind": "method", + "name": "setVisibility", + "privacy": "private", + "parameters": [ + { + "name": "state", + "type": { + "text": "Record" + } + } + ] }, { "kind": "method", - "name": "createStateProvider", - "privacy": "protected", - "return": { - "type": { - "text": "StateProvider" - } - }, + "name": "updatePreview", + "privacy": "private", "parameters": [ { - "name": "state", + "name": "el", "type": { - "text": "State" + "text": "HTMLSpanElement" } }, { - "name": "ipc", + "name": "value", + "optional": true, "type": { - "text": "HostIpc" + "text": "string" } } ] }, { "kind": "method", - "name": "onPersistState", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, + "name": "onObserver", + "privacy": "private", "parameters": [ { - "name": "state", + "name": "entries", "type": { - "text": "State" + "text": "IntersectionObserverEntry[]" + } + }, + { + "name": "_observer", + "type": { + "text": "IntersectionObserver" } } ] }, { "kind": "method", - "name": "onWebviewFocusChanged", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, + "name": "onActionLinkClicked", + "privacy": "private", "parameters": [ { - "name": "focused", + "name": "element", "type": { - "text": "boolean" + "text": "HTMLElement" + } + }, + { + "name": "e", + "type": { + "text": "MouseEvent" } } ] }, { "kind": "method", - "name": "onWebviewVisibilityChanged", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, + "name": "onJumpToLinkClicked", + "privacy": "private", "parameters": [ { - "name": "visible", + "name": "element", "type": { - "text": "boolean" + "text": "HTMLAnchorElement" + } + }, + { + "name": "e", + "type": { + "text": "MouseEvent" } } ] }, { - "kind": "field", - "name": "onFocusIn", - "privacy": "private" - }, - { - "kind": "field", - "name": "onFocusOut", - "privacy": "private" + "kind": "method", + "name": "onSectionHeaderClicked", + "privacy": "private", + "parameters": [ + { + "name": "element", + "type": { + "text": "HTMLElement" + } + }, + { + "name": "e", + "type": { + "text": "MouseEvent" + } + } + ] }, { "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } - }, + "name": "onSettingExpanderCicked", + "privacy": "private", "parameters": [ { - "name": "name", + "name": "element", "type": { - "text": "T" + "text": "HTMLElement" } }, { - "name": "detail", + "name": "_e", "type": { - "text": "CustomEventDetailType" + "text": "MouseEvent" + } + } + ] + }, + { + "kind": "method", + "name": "toggleJumpLink", + "privacy": "private", + "parameters": [ + { + "name": "anchor", + "type": { + "text": "string" } }, { - "name": "options", - "optional": true, + "name": "active", "type": { - "text": "Omit>, 'detail'>" + "text": "boolean" } } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } - } - ], - "attributes": [ + ] + }, { - "name": "name", - "type": { - "text": "string" - }, - "fieldName": "name" + "kind": "method", + "name": "renderAutolinkIntegration", + "privacy": "private" }, { - "name": "placement", - "type": { - "text": "'editor' | 'view'" - }, - "default": "'editor'", - "fieldName": "placement" + "kind": "method", + "name": "renderAutolinks", + "privacy": "private" }, { - "name": "bootstrap", + "kind": "field", + "name": "_api", "type": { - "text": "State" + "text": "HostIpcApi" }, - "fieldName": "bootstrap" - } - ], - "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" - } - } - ], - "exports": [ - { - "kind": "js", - "name": "GlAppHost", - "declaration": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/date.ts", - "declarations": [], - "exports": [ - { - "kind": "js", - "name": "*", - "declaration": { - "name": "*", - "package": "../../../system/date" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/dom.ts", - "declarations": [ - { - "kind": "function", - "name": "on", - "return": { - "type": { - "text": "Disposable" - } - }, - "parameters": [ - { - "name": "window", - "type": { - "text": "Window" + "privacy": "private", + "readonly": true, + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "name", + "kind": "field", + "name": "_hostIpc", "type": { - "text": "K" + "text": "HostIpc" + }, + "privacy": "private", + "readonly": true, + "default": "new HostIpc(this.appName)", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "listener", + "kind": "field", + "name": "_logger", "type": { - "text": "(e: WindowEventMap[K], target: Window) => void" + "text": "LoggerContext" + }, + "privacy": "private", + "readonly": true, + "default": "new LoggerContext(appName)", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "options", - "optional": true, - "type": { - "text": "boolean | AddEventListenerOptions" - } - } - ] - }, - { - "kind": "function", - "name": "on", - "return": { - "type": { - "text": "Disposable" - } - }, - "parameters": [ - { - "name": "document", + "kind": "field", + "name": "_promos", "type": { - "text": "Document" + "text": "PromosContext" + }, + "privacy": "private", + "readonly": true, + "default": "new PromosContext(this._hostIpc)", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "name", + "kind": "field", + "name": "_telemetry", "type": { - "text": "K" + "text": "TelemetryContext" + }, + "privacy": "protected", + "readonly": true, + "default": "new TelemetryContext(this._hostIpc)", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "listener", + "kind": "field", + "name": "state", "type": { - "text": "(e: DocumentEventMap[K], target: Document) => void" + "text": "State" + }, + "privacy": "protected", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "options", - "optional": true, + "kind": "field", + "name": "placement", "type": { - "text": "boolean | AddEventListenerOptions" + "text": "'editor' | 'view'" + }, + "privacy": "protected", + "readonly": true, + "default": "(document.body.getAttribute('data-placement') ?? 'editor')", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } - } - ] - }, - { - "kind": "function", - "name": "on", - "return": { - "type": { - "text": "Disposable" - } - }, - "parameters": [ + }, { - "name": "element", - "type": { - "text": "T" + "kind": "method", + "name": "onInitialized", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "name", - "type": { - "text": "K" + "kind": "method", + "name": "onThemeUpdated", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "e", + "type": { + "text": "ThemeChangeEvent" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "listener", + "kind": "field", + "name": "_focused", "type": { - "text": "(e: DocumentEventMap[K] & { target: HTMLElement | null }, target: T) => void" + "text": "boolean | undefined" + }, + "privacy": "private", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "options", - "optional": true, + "kind": "field", + "name": "_inputFocused", "type": { - "text": "boolean | AddEventListenerOptions" + "text": "boolean | undefined" + }, + "privacy": "private", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } - } - ] - }, - { - "kind": "function", - "name": "on", - "return": { - "type": { - "text": "Disposable" - } - }, - "parameters": [ + }, { - "name": "element", + "kind": "field", + "name": "bindDisposables", "type": { - "text": "T" + "text": "Disposable[] | undefined" + }, + "privacy": "private", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "name", - "type": { - "text": "string" + "kind": "method", + "name": "bind", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "listener", - "type": { - "text": "(e: CustomEvent & { target: HTMLElement | null }, target: T) => void" + "kind": "method", + "name": "log", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "message", + "type": { + "text": "string" + } + }, + { + "name": "optionalParams", + "type": { + "text": "any[]" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "options", - "optional": true, - "type": { - "text": "boolean | AddEventListenerOptions" + "kind": "method", + "name": "getState", + "privacy": "protected", + "return": { + "type": { + "text": "State | undefined" + } + }, + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } - } - ] - }, - { - "kind": "function", - "name": "on", - "return": { - "type": { - "text": "Disposable" - } - }, - "parameters": [ + }, { - "name": "selector", - "type": { - "text": "string" + "kind": "method", + "name": "sendCommand", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "command", + "type": { + "text": "TCommand" + } + }, + { + "name": "params", + "type": { + "text": "IpcCallParamsType" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "name", - "type": { - "text": "K" + "kind": "method", + "name": "sendRequest", + "privacy": "protected", + "return": { + "type": { + "text": "Promise>" + } + }, + "parameters": [ + { + "name": "requestType", + "type": { + "text": "T" + } + }, + { + "name": "params", + "type": { + "text": "IpcCallParamsType" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "listener", - "type": { - "text": "(e: DocumentEventMap[K] & { target: HTMLElement | null }, target: T) => void" + "kind": "method", + "name": "setState", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "state", + "type": { + "text": "Partial" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "options", - "optional": true, - "type": { - "text": "boolean | AddEventListenerOptions" + "kind": "field", + "name": "bootstrap", + "default": "undefined", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } } - ] - }, + ], + "superclass": { + "name": "App", + "module": "/src/webviews/apps/shared/appBase" + } + } + ], + "exports": [ { - "kind": "function", - "name": "on", - "return": { - "type": { - "text": "Disposable" - } - }, - "parameters": [ + "kind": "js", + "name": "SettingsApp", + "declaration": { + "name": "SettingsApp", + "module": "src/webviews/apps/settings/settings.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/appBase.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "App", + "members": [ { - "name": "selector", + "kind": "field", + "name": "_api", "type": { - "text": "string" - } + "text": "HostIpcApi" + }, + "privacy": "private", + "readonly": true }, { - "name": "name", + "kind": "field", + "name": "_hostIpc", "type": { - "text": "string" - } + "text": "HostIpc" + }, + "privacy": "private", + "readonly": true, + "default": "new HostIpc(this.appName)" }, { - "name": "listener", + "kind": "field", + "name": "_logger", "type": { - "text": "(e: CustomEvent & { target: HTMLElement | null }, target: T) => void" - } + "text": "LoggerContext" + }, + "privacy": "private", + "readonly": true, + "default": "new LoggerContext(appName)" }, { - "name": "options", - "optional": true, - "type": { - "text": "boolean | AddEventListenerOptions" - } - } - ] - }, - { - "kind": "function", - "name": "on", - "return": { - "type": { - "text": "Disposable" - } - }, - "parameters": [ - { - "name": "sourceOrSelector", + "kind": "field", + "name": "_promos", "type": { - "text": "string | Window | Document | Element" - } + "text": "PromosContext" + }, + "privacy": "private", + "readonly": true, + "default": "new PromosContext(this._hostIpc)" }, { - "name": "name", + "kind": "field", + "name": "_telemetry", "type": { - "text": "K" - } + "text": "TelemetryContext" + }, + "privacy": "protected", + "readonly": true, + "default": "new TelemetryContext(this._hostIpc)" }, { - "name": "listener", - "type": { - "text": "(e: (DocumentEventMap | WindowEventMap)[K] | CustomEvent, target: T) => void" - } + "kind": "field", + "name": "state", + "type": { + "text": "State" + }, + "privacy": "protected" }, { - "name": "options", - "optional": true, + "kind": "field", + "name": "placement", "type": { - "text": "boolean | AddEventListenerOptions" - } - } - ] - }, - { - "kind": "function", - "name": "parseDuration", - "return": { - "type": { - "text": "number" - } - }, - "parameters": [ + "text": "'editor' | 'view'" + }, + "privacy": "protected", + "readonly": true, + "default": "(document.body.getAttribute('data-placement') ?? 'editor')" + }, { - "name": "delay", - "type": { - "text": "number | string" + "kind": "method", + "name": "onInitialize", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } } - } - ], - "description": "Parses a CSS duration and returns the number of milliseconds." - }, - { - "kind": "function", - "name": "waitForEvent", - "return": { - "type": { - "text": "Promise" - } - }, - "parameters": [ + }, { - "name": "el", - "type": { - "text": "HTMLElement" + "kind": "method", + "name": "onBind", + "privacy": "protected", + "return": { + "type": { + "text": "Disposable[]" + } } }, { - "name": "eventName", - "type": { - "text": "string" + "kind": "method", + "name": "onInitialized", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } } - } - ], - "description": "Waits for a specific event to be emitted from an element. Ignores events that bubble up from child elements." - } - ], - "exports": [ - { - "kind": "js", - "name": "on", - "declaration": { - "name": "on", - "module": "src/webviews/apps/shared/dom.ts" - } - }, - { - "kind": "js", - "name": "on", - "declaration": { - "name": "on", - "module": "src/webviews/apps/shared/dom.ts" - } - }, - { - "kind": "js", - "name": "on", - "declaration": { - "name": "on", - "module": "src/webviews/apps/shared/dom.ts" - } - }, - { - "kind": "js", - "name": "on", - "declaration": { - "name": "on", - "module": "src/webviews/apps/shared/dom.ts" - } - }, - { - "kind": "js", - "name": "on", - "declaration": { - "name": "on", - "module": "src/webviews/apps/shared/dom.ts" - } - }, - { - "kind": "js", - "name": "on", - "declaration": { - "name": "on", - "module": "src/webviews/apps/shared/dom.ts" - } - }, - { - "kind": "js", - "name": "on", - "declaration": { - "name": "on", - "module": "src/webviews/apps/shared/dom.ts" - } - }, - { - "kind": "js", - "name": "parseDuration", - "declaration": { - "name": "parseDuration", - "module": "src/webviews/apps/shared/dom.ts" - } - }, - { - "kind": "js", - "name": "waitForEvent", - "declaration": { - "name": "waitForEvent", - "module": "src/webviews/apps/shared/dom.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/events.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "Emitter", - "members": [ + }, { - "kind": "field", - "name": "_noop", - "privacy": "private", - "static": true, - "readonly": true, - "default": "function (this: void) { /* noop */ }" + "kind": "method", + "name": "onMessageReceived", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "msg", + "type": { + "text": "IpcMessage" + } + } + ] }, { - "kind": "field", - "name": "_disposed", - "type": { - "text": "boolean" + "kind": "method", + "name": "onThemeUpdated", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "privacy": "private", - "default": "false" + "parameters": [ + { + "name": "e", + "type": { + "text": "ThemeChangeEvent" + } + } + ] }, { "kind": "field", - "name": "_event", + "name": "_focused", "type": { - "text": "Event | undefined" + "text": "boolean | undefined" }, "privacy": "private" }, { "kind": "field", - "name": "_deliveryQueue", + "name": "_inputFocused", "type": { - "text": "LinkedList<[Listener, T]> | undefined" + "text": "boolean | undefined" }, "privacy": "private" }, { "kind": "field", - "name": "listeners", + "name": "bindDisposables", "type": { - "text": "LinkedList> | undefined" + "text": "Disposable[] | undefined" }, - "privacy": "protected" + "privacy": "private" }, { - "kind": "field", - "name": "event", - "type": { - "text": "Event" + "kind": "method", + "name": "bind", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + } + }, + { + "kind": "method", + "name": "log", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "description": "For the public to allow to subscribe\nto events from this Emitter", - "readonly": true + "parameters": [ + { + "name": "message", + "type": { + "text": "string" + } + }, + { + "name": "optionalParams", + "type": { + "text": "any[]" + } + } + ] }, { "kind": "method", - "name": "fire", + "name": "log", + "privacy": "protected", "return": { "type": { "text": "void" @@ -2986,22 +2956,129 @@ }, "parameters": [ { - "name": "event", + "name": "scope", "type": { - "text": "T" + "text": "LogScope | undefined" + } + }, + { + "name": "message", + "type": { + "text": "string" + } + }, + { + "name": "optionalParams", + "type": { + "text": "any[]" } } - ], - "description": "To be kept private to fire an event to\nsubscribers" + ] }, { "kind": "method", - "name": "dispose", + "name": "log", + "privacy": "protected", "return": { "type": { "text": "void" } + }, + "parameters": [ + { + "name": "scopeOrMessage", + "type": { + "text": "LogScope | string | undefined" + } + }, + { + "name": "optionalParams", + "type": { + "text": "any[]" + } + } + ] + }, + { + "kind": "method", + "name": "getState", + "privacy": "protected", + "return": { + "type": { + "text": "State | undefined" + } } + }, + { + "kind": "method", + "name": "sendCommand", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "command", + "type": { + "text": "TCommand" + } + }, + { + "name": "params", + "type": { + "text": "IpcCallParamsType" + } + } + ] + }, + { + "kind": "method", + "name": "sendRequest", + "privacy": "protected", + "return": { + "type": { + "text": "Promise>" + } + }, + "parameters": [ + { + "name": "requestType", + "type": { + "text": "T" + } + }, + { + "name": "params", + "type": { + "text": "IpcCallParamsType" + } + } + ] + }, + { + "kind": "method", + "name": "setState", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "state", + "type": { + "text": "Partial" + } + } + ] + }, + { + "kind": "field", + "name": "bootstrap", + "default": "undefined" } ] } @@ -3009,341 +3086,192 @@ "exports": [ { "kind": "js", - "name": "Emitter", + "name": "App", "declaration": { - "name": "Emitter", - "module": "src/webviews/apps/shared/events.ts" + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/git-utils.ts", + "path": "src/webviews/apps/shared/appHost.ts", "declarations": [ { - "kind": "function", - "name": "getRemoteNameSlashIndex", - "return": { - "type": { - "text": "number" - } - }, - "parameters": [ + "kind": "class", + "description": "", + "name": "GlAppHost", + "members": [ { - "name": "name", + "kind": "field", + "name": "shadowRootOptions", "type": { - "text": "string" - } - } - ] - }, - { - "kind": "function", - "name": "getBranchNameWithoutRemote", - "return": { - "type": { - "text": "string" - } - }, - "parameters": [ + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + }, { + "kind": "field", "name": "name", "type": { "text": "string" - } - } - ] - }, - { - "kind": "function", - "name": "getRemoteNameFromBranchName", - "return": { - "type": { - "text": "string" - } - }, - "parameters": [ + }, + "attribute": "name" + }, { - "name": "name", + "kind": "field", + "name": "placement", "type": { - "text": "string" - } - } - ] - }, - { - "kind": "function", - "name": "isRevisionRange", - "return": { - "type": { - "text": "ref is GitRevisionRange" - } - }, - "parameters": [ + "text": "'editor' | 'view'" + }, + "default": "'editor'", + "attribute": "placement" + }, { - "name": "ref", + "kind": "field", + "name": "_ipc", "type": { - "text": "string | undefined" - } + "text": "HostIpc" + }, + "privacy": "protected" }, { - "name": "rangeType", - "default": "'any'", + "kind": "field", + "name": "_logger", "type": { - "text": "'any' | 'qualified' | 'qualified-double-dot' | 'qualified-triple-dot'" - } - } - ] - }, - { - "kind": "function", - "name": "isShaParent", - "return": { - "type": { - "text": "boolean" - } - }, - "parameters": [ + "text": "LoggerContext" + }, + "privacy": "protected" + }, { - "name": "ref", + "kind": "field", + "name": "_promos", "type": { - "text": "string" - } - } - ] - }, - { - "kind": "function", - "name": "isStashReference", - "return": { - "type": { - "text": "ref is GitStashReference" - } - }, - "parameters": [ + "text": "PromosContext" + }, + "privacy": "protected" + }, { - "name": "ref", - "type": { - "text": "GitReference | undefined" - } - } - ] - }, - { - "kind": "function", - "name": "getReferenceLabel", - "return": { - "type": { - "text": "string" - } - }, - "parameters": [ - { - "name": "refs", + "kind": "field", + "name": "_telemetry", "type": { - "text": "GitReference | undefined" - } + "text": "TelemetryContext" + }, + "privacy": "protected" }, - { - "name": "options", - "optional": true, - "type": { - "text": "{ capitalize?: boolean; expand?: boolean; icon?: boolean; label?: boolean; quoted?: boolean } | false" - } - } - ] - } - ], - "exports": [ - { - "kind": "js", - "name": "getRemoteNameSlashIndex", - "declaration": { - "name": "getRemoteNameSlashIndex", - "module": "src/webviews/apps/shared/git-utils.ts" - } - }, - { - "kind": "js", - "name": "getBranchNameWithoutRemote", - "declaration": { - "name": "getBranchNameWithoutRemote", - "module": "src/webviews/apps/shared/git-utils.ts" - } - }, - { - "kind": "js", - "name": "getRemoteNameFromBranchName", - "declaration": { - "name": "getRemoteNameFromBranchName", - "module": "src/webviews/apps/shared/git-utils.ts" - } - }, - { - "kind": "js", - "name": "isRevisionRange", - "declaration": { - "name": "isRevisionRange", - "module": "src/webviews/apps/shared/git-utils.ts" - } - }, - { - "kind": "js", - "name": "isShaParent", - "declaration": { - "name": "isShaParent", - "module": "src/webviews/apps/shared/git-utils.ts" - } - }, - { - "kind": "js", - "name": "isStashReference", - "declaration": { - "name": "isStashReference", - "module": "src/webviews/apps/shared/git-utils.ts" - } - }, - { - "kind": "js", - "name": "getReferenceLabel", - "declaration": { - "name": "getReferenceLabel", - "module": "src/webviews/apps/shared/git-utils.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/ipc.ts", - "declarations": [ - { - "kind": "function", - "name": "getHostIpcApi", - "return": { - "type": { - "text": "HostIpcApi" - } - } - }, - { - "kind": "class", - "description": "", - "name": "HostIpc", - "members": [ { "kind": "field", - "name": "_onReceiveMessage", + "name": "bootstrap", + "type": { + "text": "string" + }, "privacy": "private", - "default": "new Emitter()" + "attribute": "bootstrap" }, { - "kind": "field", - "name": "onReceiveMessage", - "type": { - "text": "Event" + "kind": "method", + "name": "onThemeUpdated", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "readonly": true + "parameters": [ + { + "name": "e", + "type": { + "text": "ThemeChangeEvent" + } + } + ] }, { "kind": "field", - "name": "_api", + "name": "state", "type": { - "text": "HostIpcApi" + "text": "State" }, - "privacy": "private", "readonly": true }, { "kind": "field", - "name": "_disposable", + "name": "disposables", "type": { - "text": "Disposable" + "text": "Disposable[]" }, - "privacy": "private", - "readonly": true + "privacy": "protected", + "readonly": true, + "default": "[]" }, { "kind": "field", - "name": "_pendingHandlers", - "privacy": "private", - "default": "new Map()" + "name": "_focused", + "type": { + "text": "boolean | undefined" + }, + "privacy": "private" }, { "kind": "field", - "name": "_textDecoder", + "name": "_inputFocused", "type": { - "text": "TextDecoder | undefined" + "text": "boolean | undefined" }, "privacy": "private" }, { - "kind": "method", - "name": "dispose", - "return": { - "type": { - "text": "void" - } - } + "kind": "field", + "name": "_sendWebviewFocusChangedCommandDebounced", + "type": { + "text": "Deferrable<(params: WebviewFocusChangedParams) => void>" + }, + "privacy": "private" }, { - "kind": "method", - "name": "onMessageReceived", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "MessageEvent" - } - } - ] + "kind": "field", + "name": "_stateProvider", + "type": { + "text": "Provider" + }, + "privacy": "protected" }, { "kind": "method", - "name": "replaceIpcPromisesWithPromises", + "name": "createStateProvider", + "privacy": "protected", "return": { "type": { - "text": "void" + "text": "Provider" } }, "parameters": [ { - "name": "data", + "name": "bootstrap", "type": { - "text": "unknown" + "text": "string" } - } - ] - }, - { - "kind": "method", - "name": "sendCommand", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ + }, { - "name": "commandType", + "name": "ipc", "type": { - "text": "T" + "text": "HostIpc" } }, { - "name": "params", - "optional": true, + "name": "logger", "type": { - "text": "never" + "text": "LoggerContext" } } ] }, { "kind": "method", - "name": "sendCommand", + "name": "onWebviewFocusChanged", + "privacy": "protected", "return": { "type": { "text": "void" @@ -3351,22 +3279,17 @@ }, "parameters": [ { - "name": "commandType", - "type": { - "text": "T" - } - }, - { - "name": "params", + "name": "focused", "type": { - "text": "IpcCallParamsType" + "text": "boolean" } } ] }, { "kind": "method", - "name": "sendCommand", + "name": "onWebviewVisibilityChanged", + "privacy": "protected", "return": { "type": { "text": "void" @@ -3374,766 +3297,996 @@ }, "parameters": [ { - "name": "commandType", - "type": { - "text": "T" - } - }, - { - "name": "params", - "optional": true, + "name": "visible", "type": { - "text": "IpcCallParamsType" + "text": "boolean" } } ] }, + { + "kind": "field", + "name": "onFocusIn", + "privacy": "private" + }, + { + "kind": "field", + "name": "onFocusOut", + "privacy": "private" + }, { "kind": "method", - "name": "sendRequest", + "name": "emit", "return": { "type": { - "text": "Promise>" + "text": "CustomEventType" } }, "parameters": [ { - "name": "requestType", + "name": "name", "type": { "text": "T" } }, { - "name": "params", - "type": { - "text": "IpcCallParamsType" - } - } - ] - }, - { - "kind": "method", - "name": "getResponsePromise", - "privacy": "private", - "parameters": [ - { - "name": "method", + "name": "detail", "type": { - "text": "string" + "text": "CustomEventDetailType" } }, { - "name": "id", + "name": "options", + "optional": true, "type": { - "text": "string" + "text": "Omit>, 'detail'>" } } - ] - }, + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "attributes": [ { - "kind": "method", - "name": "setPersistedState", - "return": { - "type": { - "text": "void" - } + "name": "name", + "type": { + "text": "string" }, - "parameters": [ - { - "name": "state", - "type": { - "text": "Partial" - } - } - ] + "fieldName": "name" }, { - "kind": "method", - "name": "updatePersistedState", - "return": { - "type": { - "text": "void" - } + "name": "placement", + "type": { + "text": "'editor' | 'view'" }, - "parameters": [ - { - "name": "update", - "type": { - "text": "Partial" - } - } - ] + "default": "'editor'", + "fieldName": "placement" }, { - "kind": "method", - "name": "postMessage", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "IpcMessage" - } - } - ] - } - ] - }, - { - "kind": "function", - "name": "assertsSerialized", - "return": { - "type": { - "text": "asserts obj is Serialized" - } - }, - "parameters": [ - { - "name": "obj", + "name": "bootstrap", "type": { - "text": "unknown" - } + "text": "string" + }, + "fieldName": "bootstrap" } - ] + ], + "superclass": { + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" + } } ], "exports": [ { "kind": "js", - "name": "getHostIpcApi", - "declaration": { - "name": "getHostIpcApi", - "module": "src/webviews/apps/shared/ipc.ts" - } - }, - { - "kind": "js", - "name": "HostIpc", + "name": "GlAppHost", "declaration": { - "name": "HostIpc", - "module": "src/webviews/apps/shared/ipc.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } - }, + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/date.ts", + "declarations": [], + "exports": [ { "kind": "js", - "name": "assertsSerialized", + "name": "*", "declaration": { - "name": "assertsSerialized", - "module": "src/webviews/apps/shared/ipc.ts" + "name": "*", + "module": "src/system/date" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/telemetry.ts", + "path": "src/webviews/apps/shared/dom.ts", "declarations": [ - { - "kind": "variable", - "name": "telemetryEventName", - "type": { - "text": "string" - }, - "default": "'gl-telemetry-fired'" - }, { "kind": "function", - "name": "emitTelemetrySentEvent", + "name": "on", "return": { "type": { - "text": "void" + "text": "Disposable" } }, "parameters": [ { - "name": "el", + "name": "window", "type": { - "text": "EventTarget" + "text": "Window" } }, { - "name": "params", + "name": "name", "type": { - "text": "TelemetrySendEventParams" + "text": "K" + } + }, + { + "name": "listener", + "type": { + "text": "(e: WindowEventMap[K], target: Window) => void" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "boolean | AddEventListenerOptions" } } ] - } - ], - "exports": [ - { - "kind": "js", - "name": "telemetryEventName", - "declaration": { - "name": "telemetryEventName", - "module": "src/webviews/apps/shared/telemetry.ts" - } - }, - { - "kind": "js", - "name": "emitTelemetrySentEvent", - "declaration": { - "name": "emitTelemetrySentEvent", - "module": "src/webviews/apps/shared/telemetry.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/theme.ts", - "declarations": [ - { - "kind": "variable", - "name": "onDidChangeTheme", - "type": { - "text": "Event" - } }, { "kind": "function", - "name": "computeThemeColors", + "name": "on", "return": { "type": { - "text": "ThemeChangeEvent" + "text": "Disposable" } }, "parameters": [ { - "name": "mutations", + "name": "document", + "type": { + "text": "Document" + } + }, + { + "name": "name", + "type": { + "text": "K" + } + }, + { + "name": "listener", + "type": { + "text": "(e: DocumentEventMap[K], target: Document) => void" + } + }, + { + "name": "options", "optional": true, "type": { - "text": "MutationRecord[]" + "text": "boolean | AddEventListenerOptions" } } ] }, { "kind": "function", - "name": "watchThemeColors", + "name": "on", "return": { "type": { "text": "Disposable" } - } - } - ], - "exports": [ - { - "kind": "js", - "name": "onDidChangeTheme", - "declaration": { - "name": "onDidChangeTheme", - "module": "src/webviews/apps/shared/theme.ts" - } - }, - { - "kind": "js", - "name": "computeThemeColors", - "declaration": { - "name": "computeThemeColors", - "module": "src/webviews/apps/shared/theme.ts" - } - }, - { - "kind": "js", - "name": "watchThemeColors", - "declaration": { - "name": "watchThemeColors", - "module": "src/webviews/apps/shared/theme.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/commitDetails/components/button.css.ts", - "declarations": [ - { - "kind": "variable", - "name": "buttonStyles", - "default": "css` .button-container { margin: 1rem auto 0; text-align: left; max-width: 30rem; transition: max-width 0.2s ease-out; } @media (min-width: 640px) { .button-container { max-width: 100%; } } .button-group { display: inline-flex; gap: 0.1rem; } .button-group--single { width: 100%; max-width: 30rem; } .button-group > *:not(:first-child), .button-group > *:not(:first-child) gl-button { border-top-left-radius: 0; border-bottom-left-radius: 0; } .button-group > *:not(:last-child), .button-group > *:not(:last-child) gl-button { border-top-right-radius: 0; border-bottom-right-radius: 0; } `" - } - ], - "exports": [ - { - "kind": "js", - "name": "buttonStyles", - "declaration": { - "name": "buttonStyles", - "module": "src/webviews/apps/commitDetails/components/button.css.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/commitDetails/components/commit-action.css.ts", - "declarations": [ - { - "kind": "variable", - "name": "commitActionStyles", - "default": "css` .commit-action { display: inline-flex; justify-content: center; align-items: center; height: 21px; border-radius: 0.25em; color: inherit; padding: 0.2rem; vertical-align: text-bottom; text-decoration: none; gap: 0.2rem; } .commit-action > * { pointer-events: none; } .commit-action:focus { outline: 1px solid var(--vscode-focusBorder); outline-offset: -1px; } .commit-action:hover { color: var(--vscode-foreground); text-decoration: none; } :host-context(.vscode-dark) .commit-action:hover, :host-context(.vscode-high-contrast:not(.vscode-high-contrast-light)) .commit-action:hover { background-color: var(--color-background--lighten-15); } :host-context(.vscode-light) .commit-action:hover, :host-context(.vscode-high-contrast-light) .commit-action:hover { background-color: var(--color-background--darken-15); } :host-context(.vscode-dark) .commit-action.is-active, :host-context(.vscode-high-contrast:not(.vscode-high-contrast-light)) .commit-action.is-active { background-color: var(--color-background--lighten-10); } :host-context(.vscode-light) .commit-action.is-active, :host-context(.vscode-high-contrast-light) .commit-action.is-active { background-color: var(--color-background--darken-10); } .commit-action.is-disabled { opacity: 0.5; pointer-events: none; } .commit-action.is-hidden { display: none; } .commit-action--emphasis-low:not(:hover, :focus, :active) { opacity: 0.5; } .pr--opened { color: var(--vscode-gitlens-openPullRequestIconColor); } .pr--closed { color: var(--vscode-gitlens-closedPullRequestIconColor); } .pr--merged { color: var(--vscode-gitlens-mergedPullRequestIconColor); } `" - } - ], - "exports": [ - { - "kind": "js", - "name": "commitActionStyles", - "declaration": { - "name": "commitActionStyles", - "module": "src/webviews/apps/commitDetails/components/commit-action.css.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/commitDetails/components/commit-details-app.ts", - "declarations": [ - { - "kind": "variable", - "name": "uncommittedSha", - "type": { - "text": "string" }, - "default": "'0000000000000000000000000000000000000000'" - }, - { - "kind": "class", - "description": "", - "name": "GlCommitDetailsApp", - "members": [ + "parameters": [ { - "kind": "field", - "name": "state", + "name": "element", "type": { - "text": "Serialized | undefined" - }, - "attribute": "state" + "text": "T" + } }, { - "kind": "field", - "name": "explain", + "name": "name", "type": { - "text": "ExplainState | undefined" - }, - "attribute": "explain" + "text": "K" + } }, { - "kind": "field", - "name": "generate", + "name": "listener", "type": { - "text": "GenerateState | undefined" - }, - "attribute": "generate" + "text": "(e: DocumentEventMap[K] & { target: HTMLElement | null }, target: T) => void" + } }, { - "kind": "field", - "name": "draftState", + "name": "options", + "optional": true, "type": { - "text": "DraftState" - }, - "default": "{ inReview: false }" - }, + "text": "boolean | AddEventListenerOptions" + } + } + ] + }, + { + "kind": "function", + "name": "on", + "return": { + "type": { + "text": "Disposable" + } + }, + "parameters": [ { - "kind": "field", - "name": "isUncommitted", + "name": "element", "type": { - "text": "boolean" - }, - "readonly": true + "text": "T" + } }, { - "kind": "field", - "name": "hasCommit", + "name": "name", "type": { - "text": "boolean" - }, - "readonly": true + "text": "string" + } }, { - "kind": "field", - "name": "isStash", + "name": "listener", "type": { - "text": "boolean" - }, - "readonly": true + "text": "(e: CustomEvent & { target: HTMLElement | null }, target: T) => void" + } }, { - "kind": "field", - "name": "wipStatus", - "readonly": true + "name": "options", + "optional": true, + "type": { + "text": "boolean | AddEventListenerOptions" + } + } + ] + }, + { + "kind": "function", + "name": "on", + "return": { + "type": { + "text": "Disposable" + } + }, + "parameters": [ + { + "name": "selector", + "type": { + "text": "string" + } }, { - "kind": "field", - "name": "navigation", - "readonly": true + "name": "name", + "type": { + "text": "K" + } }, { - "kind": "field", - "name": "_disposables", + "name": "listener", "type": { - "text": "Disposable[]" - }, - "privacy": "private", - "default": "[]" + "text": "(e: DocumentEventMap[K] & { target: HTMLElement | null }, target: T) => void" + } }, { - "kind": "field", - "name": "_hostIpc", + "name": "options", + "optional": true, "type": { - "text": "HostIpc" - }, - "privacy": "private" + "text": "boolean | AddEventListenerOptions" + } + } + ] + }, + { + "kind": "function", + "name": "on", + "return": { + "type": { + "text": "Disposable" + } + }, + "parameters": [ + { + "name": "selector", + "type": { + "text": "string" + } }, { - "kind": "field", - "name": "indentPreference", + "name": "name", "type": { - "text": "number" - }, - "privacy": "private", - "default": "16" + "text": "string" + } }, { - "kind": "method", - "name": "updateDocumentProperties", - "privacy": "private" + "name": "listener", + "type": { + "text": "(e: CustomEvent & { target: HTMLElement | null }, target: T) => void" + } }, { - "kind": "method", - "name": "onSuggestChanges", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "CreatePatchEventDetail" - } - } - ] + "name": "options", + "optional": true, + "type": { + "text": "boolean | AddEventListenerOptions" + } + } + ] + }, + { + "kind": "function", + "name": "on", + "return": { + "type": { + "text": "Disposable" + } + }, + "parameters": [ + { + "name": "sourceOrSelector", + "type": { + "text": "string | Window | Document | Element" + } }, { - "kind": "method", - "name": "onShowCodeSuggestion", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "{ id: string }" - } - } - ] + "name": "name", + "type": { + "text": "K" + } }, { - "kind": "method", - "name": "onMessageReceived", - "privacy": "private", - "parameters": [ - { - "name": "msg", - "type": { - "text": "IpcMessage" - } - } - ] + "name": "listener", + "type": { + "text": "(e: (DocumentEventMap | WindowEventMap)[K] | CustomEvent, target: T) => void" + } }, { - "kind": "method", - "name": "renderTopInspect", - "privacy": "private" + "name": "options", + "optional": true, + "type": { + "text": "boolean | AddEventListenerOptions" + } + } + ] + }, + { + "kind": "function", + "name": "parseDuration", + "return": { + "type": { + "text": "number" + } + }, + "parameters": [ + { + "name": "delay", + "type": { + "text": "number | string" + } + } + ], + "description": "Parses a CSS duration and returns the number of milliseconds." + }, + { + "kind": "function", + "name": "waitForEvent", + "return": { + "type": { + "text": "Promise" + } + }, + "parameters": [ + { + "name": "el", + "type": { + "text": "HTMLElement" + } }, { - "kind": "method", - "name": "renderTopWip", - "privacy": "private" + "name": "eventName", + "type": { + "text": "string" + } + } + ], + "description": "Waits for a specific event to be emitted from an element. Ignores events that bubble up from child elements." + } + ], + "exports": [ + { + "kind": "js", + "name": "on", + "declaration": { + "name": "on", + "module": "src/webviews/apps/shared/dom.ts" + } + }, + { + "kind": "js", + "name": "on", + "declaration": { + "name": "on", + "module": "src/webviews/apps/shared/dom.ts" + } + }, + { + "kind": "js", + "name": "on", + "declaration": { + "name": "on", + "module": "src/webviews/apps/shared/dom.ts" + } + }, + { + "kind": "js", + "name": "on", + "declaration": { + "name": "on", + "module": "src/webviews/apps/shared/dom.ts" + } + }, + { + "kind": "js", + "name": "on", + "declaration": { + "name": "on", + "module": "src/webviews/apps/shared/dom.ts" + } + }, + { + "kind": "js", + "name": "on", + "declaration": { + "name": "on", + "module": "src/webviews/apps/shared/dom.ts" + } + }, + { + "kind": "js", + "name": "on", + "declaration": { + "name": "on", + "module": "src/webviews/apps/shared/dom.ts" + } + }, + { + "kind": "js", + "name": "parseDuration", + "declaration": { + "name": "parseDuration", + "module": "src/webviews/apps/shared/dom.ts" + } + }, + { + "kind": "js", + "name": "waitForEvent", + "declaration": { + "name": "waitForEvent", + "module": "src/webviews/apps/shared/dom.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/events.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "Emitter", + "members": [ + { + "kind": "field", + "name": "_noop", + "privacy": "private", + "static": true, + "readonly": true, + "default": "function (this: void) { /* noop */ }" }, { - "kind": "method", - "name": "renderRepoStatusContent", + "kind": "field", + "name": "_disposed", + "type": { + "text": "boolean" + }, "privacy": "private", - "parameters": [ - { - "name": "_isWip", - "type": { - "text": "boolean" - } - } - ] + "default": "false" }, { - "kind": "method", - "name": "renderWipTooltipContent", + "kind": "field", + "name": "_event", + "type": { + "text": "Event | undefined" + }, "privacy": "private" }, { - "kind": "method", - "name": "renderTopSection", + "kind": "field", + "name": "_deliveryQueue", + "type": { + "text": "LinkedList<[Listener, T]> | undefined" + }, "privacy": "private" }, { - "kind": "method", - "name": "onDraftStateChanged", - "privacy": "private", - "parameters": [ - { - "name": "inReview", - "type": { - "text": "boolean" - } - }, - { - "name": "silent", - "default": "false" - } - ] + "kind": "field", + "name": "listeners", + "type": { + "text": "LinkedList> | undefined" + }, + "privacy": "protected" }, { - "kind": "method", - "name": "onBranchAction", - "privacy": "private", - "parameters": [ - { - "name": "name", - "type": { - "text": "string" - } - } - ] + "kind": "field", + "name": "event", + "type": { + "text": "Event" + }, + "description": "For the public to allow to subscribe\nto events from this Emitter", + "readonly": true }, { "kind": "method", - "name": "onCreatePatchFromWip", - "privacy": "private", + "name": "fire", + "return": { + "type": { + "text": "void" + } + }, "parameters": [ { - "name": "checked", - "default": "true", + "name": "event", "type": { - "text": "boolean | 'staged'" + "text": "T" } } - ] + ], + "description": "To be kept private to fire an event to\nsubscribers" }, { "kind": "method", - "name": "onCommandClickedCore", - "privacy": "private", - "parameters": [ - { - "name": "action", - "optional": true, - "type": { - "text": "GlCommands | `command:${GlCommands}`" - } + "name": "dispose", + "return": { + "type": { + "text": "void" } - ] + } + } + ] + } + ], + "exports": [ + { + "kind": "js", + "name": "Emitter", + "declaration": { + "name": "Emitter", + "module": "src/webviews/apps/shared/events.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/git-utils.ts", + "declarations": [ + { + "kind": "function", + "name": "getRemoteNameSlashIndex", + "return": { + "type": { + "text": "number" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "function", + "name": "getBranchNameWithoutRemote", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "function", + "name": "getRemoteNameFromBranchName", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "function", + "name": "isRevisionRange", + "return": { + "type": { + "text": "ref is GitRevisionRange" + } + }, + "parameters": [ + { + "name": "ref", + "type": { + "text": "string | undefined" + } }, { - "kind": "method", - "name": "onSwitchAiModel", + "name": "rangeType", + "default": "'any'", + "type": { + "text": "'any' | 'qualified' | 'qualified-double-dot' | 'qualified-triple-dot'" + } + } + ] + }, + { + "kind": "function", + "name": "isShaParent", + "return": { + "type": { + "text": "boolean" + } + }, + "parameters": [ + { + "name": "ref", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "function", + "name": "isStashReference", + "return": { + "type": { + "text": "ref is GitStashReference" + } + }, + "parameters": [ + { + "name": "ref", + "type": { + "text": "GitReference | undefined" + } + } + ] + }, + { + "kind": "function", + "name": "getReferenceLabel", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "refs", + "type": { + "text": "GitReference | undefined" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "{ capitalize?: boolean; expand?: boolean; icon?: boolean; label?: boolean; quoted?: boolean } | false" + } + } + ] + } + ], + "exports": [ + { + "kind": "js", + "name": "getRemoteNameSlashIndex", + "declaration": { + "name": "getRemoteNameSlashIndex", + "module": "src/webviews/apps/shared/git-utils.ts" + } + }, + { + "kind": "js", + "name": "getBranchNameWithoutRemote", + "declaration": { + "name": "getBranchNameWithoutRemote", + "module": "src/webviews/apps/shared/git-utils.ts" + } + }, + { + "kind": "js", + "name": "getRemoteNameFromBranchName", + "declaration": { + "name": "getRemoteNameFromBranchName", + "module": "src/webviews/apps/shared/git-utils.ts" + } + }, + { + "kind": "js", + "name": "isRevisionRange", + "declaration": { + "name": "isRevisionRange", + "module": "src/webviews/apps/shared/git-utils.ts" + } + }, + { + "kind": "js", + "name": "isShaParent", + "declaration": { + "name": "isShaParent", + "module": "src/webviews/apps/shared/git-utils.ts" + } + }, + { + "kind": "js", + "name": "isStashReference", + "declaration": { + "name": "isStashReference", + "module": "src/webviews/apps/shared/git-utils.ts" + } + }, + { + "kind": "js", + "name": "getReferenceLabel", + "declaration": { + "name": "getReferenceLabel", + "module": "src/webviews/apps/shared/git-utils.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/ipc.ts", + "declarations": [ + { + "kind": "function", + "name": "getHostIpcApi", + "return": { + "type": { + "text": "HostIpcApi" + } + } + }, + { + "kind": "class", + "description": "", + "name": "HostIpc", + "members": [ + { + "kind": "field", + "name": "_onReceiveMessage", "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "MouseEvent" - } - } - ] + "default": "new Emitter()" }, { - "kind": "method", - "name": "onExplainCommit", + "kind": "field", + "name": "onReceiveMessage", + "type": { + "text": "Event" + }, + "readonly": true + }, + { + "kind": "field", + "name": "_api", + "type": { + "text": "HostIpcApi" + }, "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "MouseEvent" - } - } - ] + "readonly": true }, { - "kind": "method", - "name": "onCreateGenerateTitle", + "kind": "field", + "name": "_disposable", + "type": { + "text": "Disposable" + }, "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "CreatePatchMetadataEventDetail" - } - } - ] + "readonly": true }, { - "kind": "method", - "name": "onToggleFilesLayout", + "kind": "field", + "name": "_pendingHandlers", "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "MouseEvent" - } + "default": "new Map()" + }, + { + "kind": "method", + "name": "dispose", + "return": { + "type": { + "text": "void" } - ] + } }, { "kind": "method", - "name": "onExpandedChange", + "name": "onMessageReceived", "privacy": "private", "parameters": [ { "name": "e", "type": { - "text": "WebviewPaneExpandedChangeEventDetail" - } - }, - { - "name": "pane", - "type": { - "text": "string" + "text": "MessageEvent" } } ] }, { "kind": "method", - "name": "onNavigate", - "privacy": "private", + "name": "deserializeIpcData", + "return": { + "type": { + "text": "T" + } + }, "parameters": [ { - "name": "direction", + "name": "data", "type": { - "text": "'back' | 'forward'" + "text": "string" } } ] }, { "kind": "method", - "name": "onTogglePin", - "privacy": "private" - }, - { - "kind": "method", - "name": "onPickCommit", - "privacy": "private", + "name": "sendCommand", + "return": { + "type": { + "text": "void" + } + }, "parameters": [ { - "name": "_e", + "name": "commandType", "type": { - "text": "MouseEvent" + "text": "T" } - } - ] - }, - { - "kind": "method", - "name": "onSearchCommit", - "privacy": "private", - "parameters": [ + }, { - "name": "_e", + "name": "params", + "optional": true, "type": { - "text": "MouseEvent" + "text": "never" } } ] }, { "kind": "method", - "name": "onSwitchMode", - "privacy": "private", + "name": "sendCommand", + "return": { + "type": { + "text": "void" + } + }, "parameters": [ { - "name": "_e", + "name": "commandType", "type": { - "text": "MouseEvent" + "text": "T" } }, { - "name": "mode", + "name": "params", "type": { - "text": "Mode" + "text": "IpcCallParamsType" } } ] }, { "kind": "method", - "name": "onOpenFileOnRemote", - "privacy": "private", + "name": "sendCommand", + "return": { + "type": { + "text": "void" + } + }, "parameters": [ { - "name": "e", + "name": "commandType", "type": { - "text": "FileChangeListItemDetail" + "text": "T" } - } - ] - }, - { - "kind": "method", - "name": "onOpenFile", - "privacy": "private", - "parameters": [ + }, { - "name": "e", + "name": "params", + "optional": true, "type": { - "text": "FileChangeListItemDetail" + "text": "IpcCallParamsType" } } ] }, { "kind": "method", - "name": "onCompareFileWithWorking", - "privacy": "private", + "name": "sendRequest", + "return": { + "type": { + "text": "Promise>" + } + }, "parameters": [ { - "name": "e", + "name": "requestType", "type": { - "text": "FileChangeListItemDetail" + "text": "T" } - } - ] - }, - { - "kind": "method", - "name": "onCompareFileWithPrevious", - "privacy": "private", - "parameters": [ + }, { - "name": "e", + "name": "params", "type": { - "text": "FileChangeListItemDetail" + "text": "IpcCallParamsType" } } ] }, { "kind": "method", - "name": "onFileMoreActions", + "name": "getResponsePromise", "privacy": "private", "parameters": [ { - "name": "e", + "name": "method", "type": { - "text": "FileChangeListItemDetail" + "text": "string" + } + }, + { + "name": "id", + "type": { + "text": "string" } } ] }, { "kind": "method", - "name": "onStageFile", - "privacy": "private", + "name": "setPersistedState", "return": { "type": { "text": "void" @@ -4141,17 +4294,16 @@ }, "parameters": [ { - "name": "e", + "name": "state", "type": { - "text": "FileChangeListItemDetail" + "text": "Partial" } } ] }, { "kind": "method", - "name": "onUnstageFile", - "privacy": "private", + "name": "updatePersistedState", "return": { "type": { "text": "void" @@ -4159,89 +4311,433 @@ }, "parameters": [ { - "name": "e", + "name": "update", "type": { - "text": "FileChangeListItemDetail" + "text": "Partial" } } ] }, { "kind": "method", - "name": "onCommitActions", + "name": "postMessage", "privacy": "private", "parameters": [ { "name": "e", "type": { - "text": "CustomEvent<{ action: string; alt: boolean }>" + "text": "IpcMessage" } } ] } - ], - "events": [ - { - "name": "state-changed", - "type": { - "text": "CustomEvent" - } + ] + }, + { + "kind": "function", + "name": "assertsSerialized", + "return": { + "type": { + "text": "asserts obj is Serialized" } - ], - "attributes": [ - { - "name": "state", - "type": { - "text": "Serialized | undefined" - }, - "fieldName": "state" - }, - { - "name": "explain", - "type": { - "text": "ExplainState | undefined" - }, - "fieldName": "explain" - }, + }, + "parameters": [ { - "name": "generate", + "name": "obj", "type": { - "text": "GenerateState | undefined" - }, - "fieldName": "generate" + "text": "unknown" + } } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-commit-details-app", - "customElement": true + ] } ], "exports": [ { "kind": "js", - "name": "uncommittedSha", + "name": "getHostIpcApi", "declaration": { - "name": "uncommittedSha", - "module": "src/webviews/apps/commitDetails/components/commit-details-app.ts" + "name": "getHostIpcApi", + "module": "src/webviews/apps/shared/ipc.ts" } }, { "kind": "js", - "name": "GlCommitDetailsApp", + "name": "HostIpc", "declaration": { - "name": "GlCommitDetailsApp", - "module": "src/webviews/apps/commitDetails/components/commit-details-app.ts" + "name": "HostIpc", + "module": "src/webviews/apps/shared/ipc.ts" } }, { - "kind": "custom-element-definition", - "name": "gl-commit-details-app", + "kind": "js", + "name": "assertsSerialized", "declaration": { - "name": "GlCommitDetailsApp", - "module": "src/webviews/apps/commitDetails/components/commit-details-app.ts" + "name": "assertsSerialized", + "module": "src/webviews/apps/shared/ipc.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/onboarding.ts", + "declarations": [ + { + "kind": "function", + "name": "createOnboarding", + "return": { + "type": { + "text": "Driver" + } + }, + "parameters": [ + { + "name": "steps", + "type": { + "text": "KeyedDriveStep[]" + } + }, + { + "name": "config", + "default": "{}", + "type": { + "text": "Exclude" + } + }, + { + "name": "onHighlightedByKey", + "optional": true, + "type": { + "text": "KeyedDriverHook" + } + } + ] + } + ], + "exports": [ + { + "kind": "js", + "name": "createOnboarding", + "declaration": { + "name": "createOnboarding", + "module": "src/webviews/apps/shared/onboarding.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/stateProviderBase.ts", + "declarations": [ + { + "kind": "class", + "description": "Base class for webview state providers that handles bootstrap initialization.\n\nSubclasses declare their bootstrap strategy ('sync' or 'async') and implement\nmessage handling. The base class automatically handles state initialization:\n- Sync: Uses bootstrap state from HTML\n- Async: Requests full state from extension after connection", + "name": "StateProviderBase", + "members": [ + { + "kind": "field", + "name": "disposable", + "type": { + "text": "Disposable" + }, + "privacy": "protected", + "readonly": true + }, + { + "kind": "field", + "name": "provider", + "type": { + "text": "ContextProvider" + }, + "privacy": "protected", + "readonly": true + }, + { + "kind": "field", + "name": "_state", + "type": { + "text": "State" + }, + "privacy": "protected" + }, + { + "kind": "field", + "name": "state", + "type": { + "text": "State" + }, + "readonly": true + }, + { + "kind": "field", + "name": "webviewId", + "readonly": true + }, + { + "kind": "field", + "name": "webviewInstanceId", + "readonly": true + }, + { + "kind": "field", + "name": "timestamp", + "readonly": true + }, + { + "kind": "method", + "name": "dispose", + "return": { + "type": { + "text": "void" + } + } + }, + { + "kind": "field", + "name": "deferBootstrap", + "type": { + "text": "boolean" + }, + "privacy": "protected", + "readonly": true + }, + { + "kind": "method", + "name": "createContextProvider", + "privacy": "protected", + "return": { + "type": { + "text": "ContextProvider" + } + }, + "parameters": [ + { + "name": "state", + "type": { + "text": "State" + } + } + ] + }, + { + "kind": "method", + "name": "initializeState", + "privacy": "protected", + "return": { + "type": { + "text": "Promise" + } + } + }, + { + "kind": "method", + "name": "onMessageReceived", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "msg", + "type": { + "text": "IpcMessage" + } + } + ] + }, + { + "kind": "method", + "name": "onPersistState", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "state", + "type": { + "text": "State" + } + } + ] + } + ] + } + ], + "exports": [ + { + "kind": "js", + "name": "StateProviderBase", + "declaration": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/telemetry.ts", + "declarations": [ + { + "kind": "variable", + "name": "telemetryEventName", + "type": { + "text": "string" + }, + "default": "'gl-telemetry-fired'" + }, + { + "kind": "function", + "name": "emitTelemetrySentEvent", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "el", + "type": { + "text": "EventTarget" + } + }, + { + "name": "params", + "type": { + "text": "TelemetrySendEventParams" + } + } + ] + } + ], + "exports": [ + { + "kind": "js", + "name": "telemetryEventName", + "declaration": { + "name": "telemetryEventName", + "module": "src/webviews/apps/shared/telemetry.ts" + } + }, + { + "kind": "js", + "name": "emitTelemetrySentEvent", + "declaration": { + "name": "emitTelemetrySentEvent", + "module": "src/webviews/apps/shared/telemetry.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/theme.ts", + "declarations": [ + { + "kind": "variable", + "name": "onDidChangeTheme", + "type": { + "text": "Event" + } + }, + { + "kind": "function", + "name": "computeThemeColors", + "return": { + "type": { + "text": "ThemeChangeEvent" + } + }, + "parameters": [ + { + "name": "mutations", + "optional": true, + "type": { + "text": "MutationRecord[]" + } + } + ] + }, + { + "kind": "function", + "name": "watchThemeColors", + "return": { + "type": { + "text": "Disposable" + } + } + } + ], + "exports": [ + { + "kind": "js", + "name": "onDidChangeTheme", + "declaration": { + "name": "onDidChangeTheme", + "module": "src/webviews/apps/shared/theme.ts" + } + }, + { + "kind": "js", + "name": "computeThemeColors", + "declaration": { + "name": "computeThemeColors", + "module": "src/webviews/apps/shared/theme.ts" + } + }, + { + "kind": "js", + "name": "watchThemeColors", + "declaration": { + "name": "watchThemeColors", + "module": "src/webviews/apps/shared/theme.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/commitDetails/components/button.css.ts", + "declarations": [ + { + "kind": "variable", + "name": "buttonStyles", + "default": "css` .button-container { margin: 1rem auto 0; text-align: left; max-width: 30rem; transition: max-width 0.2s ease-out; } @media (min-width: 640px) { .button-container { max-width: 100%; } } .button-group { display: inline-flex; gap: 0.1rem; } .button-group--single { width: 100%; max-width: 30rem; } .button-group > *:not(:first-child), .button-group > *:not(:first-child) gl-button { border-top-left-radius: 0; border-bottom-left-radius: 0; } .button-group > *:not(:last-child), .button-group > *:not(:last-child) gl-button { border-top-right-radius: 0; border-bottom-right-radius: 0; } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "buttonStyles", + "declaration": { + "name": "buttonStyles", + "module": "src/webviews/apps/commitDetails/components/button.css.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/commitDetails/components/commit-action.css.ts", + "declarations": [ + { + "kind": "variable", + "name": "commitActionStyles", + "default": "css` .commit-action { display: inline-flex; justify-content: center; align-items: center; height: 21px; border-radius: 0.25em; color: inherit; padding: 0.2rem; vertical-align: text-bottom; text-decoration: none; gap: 0.2rem; } .commit-action > * { pointer-events: none; } .commit-action:focus { outline: 1px solid var(--vscode-focusBorder); outline-offset: -1px; } .commit-action:hover { color: var(--vscode-foreground); text-decoration: none; } :host-context(.vscode-dark) .commit-action:hover, :host-context(.vscode-high-contrast:not(.vscode-high-contrast-light)) .commit-action:hover { background-color: var(--color-background--lighten-15); } :host-context(.vscode-light) .commit-action:hover, :host-context(.vscode-high-contrast-light) .commit-action:hover { background-color: var(--color-background--darken-15); } :host-context(.vscode-dark) .commit-action.is-active, :host-context(.vscode-high-contrast:not(.vscode-high-contrast-light)) .commit-action.is-active { background-color: var(--color-background--lighten-10); } :host-context(.vscode-light) .commit-action.is-active, :host-context(.vscode-high-contrast-light) .commit-action.is-active { background-color: var(--color-background--darken-10); } .commit-action.is-disabled { opacity: 0.5; pointer-events: none; } .commit-action.is-hidden { display: none; } .commit-action--emphasis-low:not(:hover, :focus, :active) { opacity: 0.5; } .pr--opened { color: var(--vscode-gitlens-openPullRequestIconColor); } .pr--closed { color: var(--vscode-gitlens-closedPullRequestIconColor); } .pr--merged { color: var(--vscode-gitlens-mergedPullRequestIconColor); } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "commitActionStyles", + "declaration": { + "name": "commitActionStyles", + "module": "src/webviews/apps/commitDetails/components/commit-action.css.ts" } } ] @@ -4272,7 +4768,7 @@ "kind": "field", "name": "state", "type": { - "text": "Serialized | undefined" + "text": "State | undefined" }, "attribute": "state" }, @@ -4308,6 +4804,52 @@ }, "attribute": "explain" }, + { + "kind": "field", + "name": "_commit", + "type": { + "text": "State['commit']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "commit", + "type": { + "text": "State['commit']" + } + }, + { + "kind": "field", + "name": "_enriched", + "type": { + "text": "Awaited['enriched']>" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "enriched", + "type": { + "text": "Awaited['enriched']>" + }, + "readonly": true + }, + { + "kind": "field", + "name": "_enrichedPromise", + "type": { + "text": "NonNullable['enriched']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "enrichedPromise", + "type": { + "text": "NonNullable['enriched']" + } + }, { "kind": "field", "name": "navigation", @@ -4406,6 +4948,28 @@ "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" } }, + { + "kind": "method", + "name": "getFileContextData", + "privacy": "protected", + "return": { + "type": { + "text": "string | undefined" + } + }, + "parameters": [ + { + "name": "file", + "type": { + "text": "File" + } + } + ], + "inheritedFrom": { + "name": "GlDetailsBase", + "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" + } + }, { "kind": "field", "name": "files", @@ -4443,6 +5007,18 @@ "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" } }, + { + "kind": "field", + "name": "orgSettings", + "type": { + "text": "State['orgSettings'] | undefined" + }, + "attribute": "orgSettings", + "inheritedFrom": { + "name": "GlDetailsBase", + "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" + } + }, { "kind": "field", "name": "emptyText", @@ -4533,6 +5109,20 @@ "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" } }, + { + "kind": "method", + "name": "renderChangedFilesActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult<1> | undefined" + } + }, + "inheritedFrom": { + "name": "GlDetailsBase", + "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" + } + }, { "kind": "method", "name": "onShareWipChanges", @@ -5093,7 +5683,7 @@ { "name": "state", "type": { - "text": "Serialized | undefined" + "text": "State | undefined" }, "fieldName": "state" }, @@ -5138,6 +5728,17 @@ "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" } }, + { + "name": "orgSettings", + "type": { + "text": "State['orgSettings'] | undefined" + }, + "fieldName": "orgSettings", + "inheritedFrom": { + "name": "GlDetailsBase", + "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" + } + }, { "name": "empty-text", "type": { @@ -5221,6 +5822,14 @@ }, "attribute": "preferences" }, + { + "kind": "field", + "name": "orgSettings", + "type": { + "text": "State['orgSettings'] | undefined" + }, + "attribute": "orgSettings" + }, { "kind": "field", "name": "emptyText", @@ -5287,6 +5896,16 @@ } ] }, + { + "kind": "method", + "name": "renderChangedFilesActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult<1> | undefined" + } + } + }, { "kind": "method", "name": "onShareWipChanges", @@ -5512,6 +6131,24 @@ } ] }, + { + "kind": "method", + "name": "getFileContextData", + "privacy": "protected", + "return": { + "type": { + "text": "string | undefined" + } + }, + "parameters": [ + { + "name": "_file", + "type": { + "text": "File" + } + } + ] + }, { "kind": "method", "name": "fileToTreeModel", @@ -5799,6 +6436,13 @@ }, "fieldName": "preferences" }, + { + "name": "orgSettings", + "type": { + "text": "State['orgSettings'] | undefined" + }, + "fieldName": "orgSettings" + }, { "name": "empty-text", "type": { @@ -6256,14 +6900,6 @@ }, "attribute": "wip" }, - { - "kind": "field", - "name": "orgSettings", - "type": { - "text": "State['orgSettings'] | undefined" - }, - "attribute": "orgSettings" - }, { "kind": "field", "name": "draftState", @@ -6280,6 +6916,15 @@ }, "attribute": "generate" }, + { + "kind": "field", + "name": "experimentalComposerEnabled", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "experimentalComposerEnabled" + }, { "kind": "field", "name": "inReview", @@ -6328,6 +6973,9 @@ { "kind": "field", "name": "patchCreateState", + "type": { + "text": "CreatePatchState" + }, "readonly": true }, { @@ -6347,10 +6995,30 @@ "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" } }, + { + "kind": "method", + "name": "renderChangedFilesActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult<1> | undefined" + } + }, + "inheritedFrom": { + "name": "GlDetailsBase", + "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" + } + }, { "kind": "method", "name": "renderSecondaryAction", - "privacy": "private" + "privacy": "private", + "parameters": [ + { + "name": "hasPrimary", + "default": "true" + } + ] }, { "kind": "method", @@ -6411,6 +7079,28 @@ "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" } }, + { + "kind": "method", + "name": "getFileContextData", + "privacy": "protected", + "return": { + "type": { + "text": "string | undefined" + } + }, + "parameters": [ + { + "name": "file", + "type": { + "text": "File" + } + } + ], + "inheritedFrom": { + "name": "GlDetailsBase", + "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" + } + }, { "kind": "method", "name": "onDataActionClick", @@ -6487,6 +7177,18 @@ "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" } }, + { + "kind": "field", + "name": "orgSettings", + "type": { + "text": "State['orgSettings'] | undefined" + }, + "attribute": "orgSettings", + "inheritedFrom": { + "name": "GlDetailsBase", + "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" + } + }, { "kind": "field", "name": "emptyText", @@ -7155,13 +7857,6 @@ }, "fieldName": "wip" }, - { - "name": "orgSettings", - "type": { - "text": "State['orgSettings'] | undefined" - }, - "fieldName": "orgSettings" - }, { "name": "draftState", "type": { @@ -7176,6 +7871,14 @@ }, "fieldName": "generate" }, + { + "name": "experimentalComposerEnabled", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "experimentalComposerEnabled" + }, { "name": "files", "type": { @@ -7210,6 +7913,17 @@ "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" } }, + { + "name": "orgSettings", + "type": { + "text": "State['orgSettings'] | undefined" + }, + "fieldName": "orgSettings", + "inheritedFrom": { + "name": "GlDetailsBase", + "module": "src/webviews/apps/commitDetails/components/gl-details-base.ts" + } + }, { "name": "empty-text", "type": { @@ -7252,13 +7966,30 @@ }, { "kind": "javascript-module", - "path": "src/webviews/apps/home/components/ama-banner.ts", + "path": "src/webviews/apps/home/components/ai-all-access-banner.ts", "declarations": [ + { + "kind": "variable", + "name": "aiAllAccessBannerTagName", + "type": { + "text": "string" + }, + "default": "'gl-ai-all-access-banner'" + }, { "kind": "class", "description": "", - "name": "GlAmaBanner", + "name": "GlAiAllAccessBanner", "members": [ + { + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + }, { "kind": "field", "name": "_state", @@ -7277,198 +8008,298 @@ }, { "kind": "field", - "name": "closed", + "name": "shouldShow", "type": { "text": "boolean" }, "privacy": "private", - "default": "false" + "readonly": true }, - { - "kind": "method", - "name": "onClose", - "privacy": "private" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-ama-banner", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "GlAmaBanner", - "declaration": { - "name": "GlAmaBanner", - "module": "src/webviews/apps/home/components/ama-banner.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-ama-banner", - "declaration": { - "name": "GlAmaBanner", - "module": "src/webviews/apps/home/components/ama-banner.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/home/components/feature-nav.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlFeatureNav", - "members": [ { "kind": "field", - "name": "badgeSource", + "name": "bodyLabel", "type": { - "text": "Source" + "text": "string" }, "privacy": "private", - "default": "{ source: 'home', detail: 'badge' }", - "attribute": "badgeSource" + "readonly": true }, { "kind": "field", - "name": "_state", + "name": "primaryButtonLabel", "type": { - "text": "State" + "text": "string" }, - "privacy": "private" + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "orgAllowsDrafts", + "name": "hasAdvancedOrHigher", "type": { "text": "boolean" }, - "readonly": true - }, - { - "kind": "field", - "name": "blockRepoFeatures", "privacy": "private", "readonly": true }, { "kind": "method", - "name": "onRepoFeatureClicked", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "MouseEvent" - } - } - ] - }, - { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } - } - ], - "attributes": [ - { - "name": "badgeSource", - "type": { - "text": "Source" - }, - "default": "{ source: 'home', detail: 'badge' }", - "fieldName": "badgeSource" + "name": "onSecondaryClick", + "privacy": "private" } ], "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" + "name": "LitElement", + "package": "lit" }, - "tagName": "gl-feature-nav", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlFeatureNav", + "name": "aiAllAccessBannerTagName", "declaration": { - "name": "GlFeatureNav", - "module": "src/webviews/apps/home/components/feature-nav.ts" + "name": "aiAllAccessBannerTagName", + "module": "src/webviews/apps/home/components/ai-all-access-banner.ts" + } + }, + { + "kind": "js", + "name": "GlAiAllAccessBanner", + "declaration": { + "name": "GlAiAllAccessBanner", + "module": "src/webviews/apps/home/components/ai-all-access-banner.ts" } }, { "kind": "custom-element-definition", - "name": "gl-feature-nav", "declaration": { - "name": "GlFeatureNav", - "module": "src/webviews/apps/home/components/feature-nav.ts" + "name": "GlAiAllAccessBanner", + "module": "src/webviews/apps/home/components/ai-all-access-banner.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/home/components/integration-banner.ts", + "path": "src/webviews/apps/home/components/ama-banner.ts", "declarations": [ - { - "kind": "variable", - "name": "integrationBannerTagName", - "type": { - "text": "string" - }, - "default": "'gl-integration-banner'" - }, { "kind": "class", "description": "", - "name": "GlIntegrationBanner", + "name": "GlAmaBanner", "members": [ - { - "kind": "field", - "name": "shadowRootOptions", - "type": { - "text": "ShadowRootInit" - }, - "static": true, - "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" - }, + { + "kind": "field", + "name": "_state", + "type": { + "text": "State" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_ipc", + "type": { + "text": "HostIpc" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "closed", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "method", + "name": "onClose", + "privacy": "private" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-ama-banner", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlAmaBanner", + "declaration": { + "name": "GlAmaBanner", + "module": "src/webviews/apps/home/components/ama-banner.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-ama-banner", + "declaration": { + "name": "GlAmaBanner", + "module": "src/webviews/apps/home/components/ama-banner.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/home/components/feature-nav.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlFeatureNav", + "members": [ + { + "kind": "field", + "name": "badgeSource", + "type": { + "text": "Source" + }, + "privacy": "private", + "default": "{ source: 'home', detail: 'badge' }", + "attribute": "badgeSource" + }, + { + "kind": "field", + "name": "_state", + "type": { + "text": "State" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "orgAllowsDrafts", + "type": { + "text": "boolean" + }, + "readonly": true + }, + { + "kind": "field", + "name": "blockRepoFeatures", + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "onRepoFeatureClicked", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "MouseEvent" + } + } + ] + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "attributes": [ + { + "name": "badgeSource", + "type": { + "text": "Source" + }, + "default": "{ source: 'home', detail: 'badge' }", + "fieldName": "badgeSource" + } + ], + "superclass": { + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" + }, + "tagName": "gl-feature-nav", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlFeatureNav", + "declaration": { + "name": "GlFeatureNav", + "module": "src/webviews/apps/home/components/feature-nav.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-feature-nav", + "declaration": { + "name": "GlFeatureNav", + "module": "src/webviews/apps/home/components/feature-nav.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/home/components/integration-banner.ts", + "declarations": [ + { + "kind": "variable", + "name": "integrationBannerTagName", + "type": { + "text": "string" + }, + "default": "'gl-integration-banner'" + }, + { + "kind": "class", + "description": "", + "name": "GlIntegrationBanner", + "members": [ + { + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + }, { "kind": "field", "name": "_state", @@ -7575,6 +8406,16 @@ }, "privacy": "private" }, + { + "kind": "method", + "name": "renderWalkthroughProgress", + "privacy": "private", + "return": { + "type": { + "text": "unknown" + } + } + }, { "kind": "field", "name": "onDismissWalkthrough", @@ -7885,52 +8726,149 @@ }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/patchDetails/patchDetails.ts", + "path": "src/webviews/apps/plus/composer/composer.ts", "declarations": [ - { - "kind": "variable", - "name": "uncommittedSha", - "type": { - "text": "string" - }, - "default": "'0000000000000000000000000000000000000000'" - }, { "kind": "class", "description": "", - "name": "PatchDetailsApp", + "name": "ComposerAppHost", "members": [ { "kind": "method", - "name": "onInitialize", + "name": "createStateProvider", "privacy": "protected", "return": { "type": { - "text": "void" + "text": "ComposerStateProvider" } }, + "parameters": [ + { + "name": "bootstrap", + "type": { + "text": "string" + } + }, + { + "name": "ipc", + "type": { + "text": "HostIpc" + } + }, + { + "name": "logger", + "type": { + "text": "LoggerContext" + } + } + ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { - "kind": "method", - "name": "onBind", + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "name", + "type": { + "text": "string" + }, + "attribute": "name", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "placement", + "type": { + "text": "'editor' | 'view'" + }, + "default": "'editor'", + "attribute": "placement", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "_ipc", + "type": { + "text": "HostIpc" + }, "privacy": "protected", - "return": { - "type": { - "text": "Disposable[]" - } + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "_logger", + "type": { + "text": "LoggerContext" }, + "privacy": "protected", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "_promos", + "type": { + "text": "PromosContext" + }, + "privacy": "protected", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "_telemetry", + "type": { + "text": "TelemetryContext" + }, + "privacy": "protected", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "kind": "field", + "name": "bootstrap", + "type": { + "text": "string" + }, + "privacy": "private", + "attribute": "bootstrap", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { "kind": "method", - "name": "onMessageReceived", + "name": "onThemeUpdated", "privacy": "protected", "return": { "type": { @@ -7939,470 +8877,444 @@ }, "parameters": [ { - "name": "msg", + "name": "e", "type": { - "text": "IpcMessage" + "text": "ThemeChangeEvent" } } ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { - "kind": "method", - "name": "onPatchChecked", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "PatchCheckedDetail" - } - } - ] + "kind": "field", + "name": "state", + "type": { + "text": "State" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "method", - "name": "onCreateCheckRepo", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "CreatePatchCheckRepositoryEventDetail" - } - } - ] + "kind": "field", + "name": "disposables", + "type": { + "text": "Disposable[]" + }, + "privacy": "protected", + "readonly": true, + "default": "[]", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "method", - "name": "onCreateUpdateMetadata", + "kind": "field", + "name": "_focused", + "type": { + "text": "boolean | undefined" + }, "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "CreatePatchMetadataEventDetail" - } - } - ] + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "method", - "name": "onCreateGenerateTitle", + "kind": "field", + "name": "_inputFocused", + "type": { + "text": "boolean | undefined" + }, "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "CreatePatchMetadataEventDetail" - } - } - ] + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "method", - "name": "onDraftUpdateMetadata", + "kind": "field", + "name": "_sendWebviewFocusChangedCommandDebounced", + "type": { + "text": "Deferrable<(params: WebviewFocusChangedParams) => void>" + }, "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "{ visibility: DraftVisibility }" - } - } - ] + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "method", - "name": "onDraftUpdatePermissions", - "privacy": "private" + "kind": "field", + "name": "_stateProvider", + "type": { + "text": "Provider" + }, + "privacy": "protected", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "method", - "name": "onShowPatchInGraph", - "privacy": "private", + "name": "onWebviewFocusChanged", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, "parameters": [ { - "name": "_e", + "name": "focused", "type": { - "text": "ShowPatchInGraphDetail" + "text": "boolean" } } - ] + ], + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "method", - "name": "onCreatePatch", - "privacy": "private", + "name": "onWebviewVisibilityChanged", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, "parameters": [ { - "name": "e", + "name": "visible", "type": { - "text": "CreatePatchEventDetail" + "text": "boolean" } } - ] - }, - { - "kind": "method", - "name": "onShareLocalPatch", - "privacy": "private" - }, - { - "kind": "method", - "name": "onCopyCloudLink", - "privacy": "private" + ], + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "method", - "name": "onModeClicked", + "kind": "field", + "name": "onFocusIn", "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "Event" - } - } - ] + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "method", - "name": "onApplyPatch", + "kind": "field", + "name": "onFocusOut", "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "ApplyPatchDetail" - } - } - ] + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "method", - "name": "onArchiveDraft", - "privacy": "private", - "parameters": [ - { - "name": "reason", - "optional": true, - "type": { - "text": "DraftReasonEventDetail['reason']" - } + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" } - ] - }, - { - "kind": "method", - "name": "onChangePatchBase", - "privacy": "private", + }, "parameters": [ { - "name": "e", + "name": "name", "type": { - "text": "ChangePatchBaseDetail" + "text": "T" } - } - ] - }, - { - "kind": "method", - "name": "onSelectPatchRepo", - "privacy": "private", - "parameters": [ + }, { - "name": "e", + "name": "detail", "type": { - "text": "SelectPatchRepoDetail" + "text": "CustomEventDetailType" } - } - ] - }, - { - "kind": "method", - "name": "onCommandClickedCore", - "privacy": "private", - "parameters": [ + }, { - "name": "action", + "name": "options", "optional": true, "type": { - "text": "GlCommands | `command:${GlCommands}`" - } - } - ] - }, - { - "kind": "method", - "name": "onSwitchAIModel", - "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "MouseEvent" - } - } - ] - }, - { - "kind": "method", - "name": "onAIExplain", - "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "MouseEvent" - } - } - ] - }, - { - "kind": "method", - "name": "onToggleFilesLayout", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "MouseEvent" + "text": "Omit>, 'detail'>" } } - ] - }, + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "superclass": { + "name": "GlAppHost", + "module": "/src/webviews/apps/shared/appHost" + }, + "tagName": "gl-composer-apphost", + "customElement": true, + "attributes": [ { - "kind": "method", - "name": "onInviteUsers", - "privacy": "private" + "name": "name", + "type": { + "text": "string" + }, + "fieldName": "name", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "method", - "name": "onUpdateUserSelection", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "CreatePatchUpdateSelectionEventDetail | PatchDetailsUpdateSelectionEventDetail" - } - } - ] + "name": "placement", + "type": { + "text": "'editor' | 'view'" + }, + "default": "'editor'", + "fieldName": "placement", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "method", - "name": "onOpenFileOnRemote", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "FileChangeListItemDetail" - } - } - ] - }, + "name": "bootstrap", + "type": { + "text": "string" + }, + "fieldName": "bootstrap", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + } + ] + } + ], + "exports": [ + { + "kind": "js", + "name": "ComposerAppHost", + "declaration": { + "name": "ComposerAppHost", + "module": "src/webviews/apps/plus/composer/composer.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-composer-apphost", + "declaration": { + "name": "ComposerAppHost", + "module": "src/webviews/apps/plus/composer/composer.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/composer/context.ts", + "declarations": [ + { + "kind": "variable", + "name": "stateContext" + } + ], + "exports": [ + { + "kind": "js", + "name": "stateContext", + "declaration": { + "name": "stateContext", + "module": "src/webviews/apps/plus/composer/context.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/composer/stateProvider.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "ComposerStateProvider", + "members": [ { "kind": "method", - "name": "onOpenFile", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "FileChangeListItemDetail" - } + "name": "createContextProvider", + "privacy": "protected", + "return": { + "type": { + "text": "ContextProvider" } - ] - }, - { - "kind": "method", - "name": "onCompareFileWithWorking", - "privacy": "private", + }, "parameters": [ { - "name": "e", + "name": "state", "type": { - "text": "FileChangeListItemDetail" + "text": "State" } } - ] + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "method", - "name": "onCompareFileWithPrevious", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "FileChangeListItemDetail" - } + "name": "onMessageReceived", + "privacy": "protected", + "return": { + "type": { + "text": "void" } - ] - }, - { - "kind": "method", - "name": "onFileMoreActions", - "privacy": "private", + }, "parameters": [ { - "name": "e", + "name": "msg", "type": { - "text": "FileChangeListItemDetail" + "text": "IpcMessage" } } - ] + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "_component", + "name": "disposable", "type": { - "text": "GlPatchDetailsApp | undefined" + "text": "Disposable" }, - "privacy": "private" - }, - { - "kind": "field", - "name": "component", - "privacy": "private", - "readonly": true - }, - { - "kind": "method", - "name": "attachState", - "privacy": "private", - "parameters": [ - { - "name": "_force", - "optional": true, - "type": { - "text": "boolean" - } - } - ] - }, - { - "kind": "field", - "name": "debouncedAttachState", - "privacy": "private" + "privacy": "protected", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "_api", + "name": "provider", "type": { - "text": "HostIpcApi" + "text": "ContextProvider" }, - "privacy": "private", + "privacy": "protected", "readonly": true, "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "field", - "name": "_hostIpc", + "name": "_state", "type": { - "text": "HostIpc" + "text": "State" }, - "privacy": "private", - "readonly": true, - "default": "new HostIpc(this.appName)", + "privacy": "protected", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "field", - "name": "_logger", + "name": "state", "type": { - "text": "LoggerContext" + "text": "State" }, - "privacy": "private", "readonly": true, - "default": "new LoggerContext(appName)", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "field", - "name": "_promos", - "type": { - "text": "PromosContext" - }, - "privacy": "private", + "name": "webviewId", "readonly": true, - "default": "new PromosContext(this._hostIpc)", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "field", - "name": "_telemetry", - "type": { - "text": "TelemetryContext" - }, - "privacy": "protected", + "name": "webviewInstanceId", "readonly": true, - "default": "new TelemetryContext(this._hostIpc)", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "field", - "name": "state", - "type": { - "text": "State" + "name": "timestamp", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + }, + { + "kind": "method", + "name": "dispose", + "return": { + "type": { + "text": "void" + } }, - "privacy": "protected", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "field", - "name": "placement", + "name": "deferBootstrap", "type": { - "text": "'editor' | 'view'" + "text": "boolean" }, "privacy": "protected", "readonly": true, - "default": "(document.body.getAttribute('data-placement') ?? 'editor')", "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "method", - "name": "onInitialized", + "name": "initializeState", "privacy": "protected", "return": { "type": { - "text": "void" + "text": "Promise" } }, "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { "kind": "method", - "name": "onThemeUpdated", + "name": "onPersistState", "privacy": "protected", "return": { "type": { @@ -8411,291 +9323,90 @@ }, "parameters": [ { - "name": "e", + "name": "state", "type": { - "text": "ThemeChangeEvent" + "text": "State" } } ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "field", - "name": "_focused", - "type": { - "text": "boolean | undefined" - }, - "privacy": "private", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "field", - "name": "_inputFocused", - "type": { - "text": "boolean | undefined" - }, - "privacy": "private", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } - }, + } + ], + "superclass": { + "name": "StateProviderBase", + "module": "/src/webviews/apps/shared/stateProviderBase" + } + } + ], + "exports": [ + { + "kind": "js", + "name": "ComposerStateProvider", + "declaration": { + "name": "ComposerStateProvider", + "module": "src/webviews/apps/plus/composer/stateProvider.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/graph/gate.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlGraphGate", + "members": [ { "kind": "field", - "name": "bindDisposables", + "name": "graphState", "type": { - "text": "Disposable[] | undefined" - }, - "privacy": "private", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "method", - "name": "bind", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "text": "typeof graphStateContext.__context__" } }, { "kind": "method", - "name": "log", - "privacy": "protected", + "name": "emit", "return": { "type": { - "text": "void" + "text": "CustomEventType" } }, "parameters": [ { - "name": "message", + "name": "name", "type": { - "text": "string" + "text": "T" } }, { - "name": "optionalParams", + "name": "detail", "type": { - "text": "any[]" + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" } } ], "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" } - }, + } + ], + "mixins": [ { - "kind": "method", - "name": "getState", - "privacy": "protected", - "return": { - "type": { - "text": "State | undefined" - } - }, - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "method", - "name": "sendCommand", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "command", - "type": { - "text": "TCommand" - } - }, - { - "name": "params", - "type": { - "text": "IpcCallParamsType" - } - } - ], - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "method", - "name": "sendRequest", - "privacy": "protected", - "return": { - "type": { - "text": "Promise>" - } - }, - "parameters": [ - { - "name": "requestType", - "type": { - "text": "T" - } - }, - { - "name": "params", - "type": { - "text": "IpcCallParamsType" - } - } - ], - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "method", - "name": "setState", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "state", - "type": { - "text": "Partial" - } - } - ], - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - }, - { - "kind": "field", - "name": "bootstrap", - "default": "undefined", - "inheritedFrom": { - "name": "App", - "module": "src/webviews/apps/shared/appBase.ts" - } - } - ], - "superclass": { - "name": "App", - "module": "/src/webviews/apps/shared/appBase" - } - } - ], - "exports": [ - { - "kind": "js", - "name": "uncommittedSha", - "declaration": { - "name": "uncommittedSha", - "module": "src/webviews/apps/plus/patchDetails/patchDetails.ts" - } - }, - { - "kind": "js", - "name": "PatchDetailsApp", - "declaration": { - "name": "PatchDetailsApp", - "module": "src/webviews/apps/plus/patchDetails/patchDetails.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/context.ts", - "declarations": [ - { - "kind": "variable", - "name": "stateContext" - } - ], - "exports": [ - { - "kind": "js", - "name": "stateContext", - "declaration": { - "name": "stateContext", - "module": "src/webviews/apps/plus/graph/context.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/gate.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlGraphGate", - "members": [ - { - "kind": "field", - "name": "state", - "type": { - "text": "State" - } - }, - { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } + "name": "SignalWatcher", + "package": "@lit-labs/signals" } ], "superclass": { @@ -8746,14 +9457,7 @@ }, { "kind": "field", - "name": "state", - "type": { - "text": "typeof stateContext.__context__" - } - }, - { - "kind": "field", - "name": "graphApp", + "name": "graphState", "type": { "text": "typeof graphStateContext.__context__" } @@ -8993,17 +9697,19 @@ }, { "kind": "field", - "name": "hostState", + "name": "graphState", "type": { - "text": "typeof stateContext.__context__" + "text": "typeof graphStateContext.__context__" } }, { "kind": "field", - "name": "appState", + "name": "aiAllowed", "type": { - "text": "typeof graphStateContext.__context__" - } + "text": "boolean" + }, + "privacy": "private", + "default": "true" }, { "kind": "field", @@ -9543,16 +10249,6 @@ }, "privacy": "private" }, - { - "kind": "field", - "name": "_graphState", - "type": { - "text": "typeof graphStateContext.__context__" - }, - "privacy": "private", - "readonly": true, - "default": "new GraphAppState()" - }, { "kind": "field", "name": "searching", @@ -9579,14 +10275,14 @@ "privacy": "protected", "return": { "type": { - "text": "StateProvider" + "text": "GraphStateProvider" } }, "parameters": [ { - "name": "state", + "name": "bootstrap", "type": { - "text": "State" + "text": "string" } }, { @@ -9645,29 +10341,6 @@ "module": "src/webviews/apps/shared/appHost.ts" } }, - { - "kind": "method", - "name": "applyTheme", - "privacy": "private", - "parameters": [ - { - "name": "theme", - "type": { - "text": "{ cssVariables: CssVariables; themeOpacityFactor: number }" - } - } - ] - }, - { - "kind": "method", - "name": "getGraphTheming", - "privacy": "private", - "return": { - "type": { - "text": "{ cssVariables: CssVariables; themeOpacityFactor: number }" - } - } - }, { "kind": "field", "name": "shadowRootOptions", @@ -9758,7 +10431,7 @@ "kind": "field", "name": "bootstrap", "type": { - "text": "State" + "text": "string" }, "privacy": "private", "attribute": "bootstrap", @@ -9833,31 +10506,9 @@ "kind": "field", "name": "_stateProvider", "type": { - "text": "StateProvider" + "text": "Provider" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } - }, - { - "kind": "method", - "name": "onPersistState", "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "state", - "type": { - "text": "State" - } - } - ], "inheritedFrom": { "name": "GlAppHost", "module": "src/webviews/apps/shared/appHost.ts" @@ -9971,7 +10622,7 @@ { "name": "bootstrap", "type": { - "text": "State" + "text": "string" }, "fieldName": "bootstrap", "inheritedFrom": { @@ -10005,10 +10656,14 @@ "kind": "javascript-module", "path": "src/webviews/apps/plus/graph/stateProvider.ts", "declarations": [ + { + "kind": "variable", + "name": "graphStateContext" + }, { "kind": "class", "description": "", - "name": "GraphAppState", + "name": "GraphStateProvider", "members": [ { "kind": "field", @@ -10048,13 +10703,6 @@ "text": "AppState['visibleDays']" } }, - { - "kind": "field", - "name": "theming", - "type": { - "text": "AppState['theming']" - } - }, { "kind": "field", "name": "filter", @@ -10074,18 +10722,22 @@ "kind": "field", "name": "searchResultsResponse", "type": { - "text": "undefined | GraphSearchResults | GraphSearchResultsError" + "text": "GraphSearchResults | GraphSearchResultsError | undefined" } }, { "kind": "field", "name": "searchResults", - "readonly": true + "type": { + "text": "GraphSearchResults | undefined" + } }, { "kind": "field", "name": "searchResultsError", - "readonly": true + "type": { + "text": "GraphSearchResultsError | undefined" + } }, { "kind": "field", @@ -10093,1449 +10745,1473 @@ "type": { "text": "undefined | GraphSelectedRows" } - } - ] - }, - { - "kind": "variable", - "name": "graphStateContext" - }, - { - "kind": "class", - "description": "", - "name": "GraphStateProvider", - "members": [ + }, { "kind": "field", - "name": "disposable", + "name": "windowFocused", "type": { - "text": "Disposable" - }, - "privacy": "private", - "readonly": true + "text": "boolean | undefined" + } }, { "kind": "field", - "name": "provider", + "name": "webroot", "type": { - "text": "ContextProvider<{ __context__: State }, ReactiveElementHost>" - }, - "privacy": "private", - "readonly": true, - "default": "new ContextProvider(host, { context: stateContext, initialValue: state })" + "text": "string | undefined" + } }, { "kind": "field", - "name": "_state", + "name": "repositories", "type": { - "text": "State" - }, - "privacy": "private", - "readonly": true, - "default": "state" + "text": "State['repositories']" + } }, { "kind": "field", - "name": "state", - "readonly": true - }, - { - "kind": "method", - "name": "updateState", - "privacy": "private", - "parameters": [ - { - "name": "partial", - "type": { - "text": "Partial" - } - } - ] + "name": "selectedRepository", + "type": { + "text": "string | undefined" + } }, { - "kind": "method", - "name": "dispose", - "return": { - "type": { - "text": "void" - } + "kind": "field", + "name": "selectedRepositoryVisibility", + "type": { + "text": "State['selectedRepositoryVisibility']" } - } - ] - } - ], - "exports": [ - { - "kind": "js", - "name": "GraphAppState", - "declaration": { - "name": "GraphAppState", - "module": "src/webviews/apps/plus/graph/stateProvider.ts" - } - }, - { - "kind": "js", - "name": "graphStateContext", - "declaration": { - "name": "graphStateContext", - "module": "src/webviews/apps/plus/graph/stateProvider.ts" - } - }, - { - "kind": "js", - "name": "GraphStateProvider", - "declaration": { - "name": "GraphStateProvider", - "module": "src/webviews/apps/plus/graph/stateProvider.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/timeline/context.ts", - "declarations": [ - { - "kind": "variable", - "name": "stateContext" - } - ], - "exports": [ - { - "kind": "js", - "name": "stateContext", - "declaration": { - "name": "stateContext", - "module": "src/webviews/apps/plus/timeline/context.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/timeline/stateProvider.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "TimelineStateProvider", - "members": [ + }, { "kind": "field", - "name": "disposable", + "name": "branchesVisibility", "type": { - "text": "Disposable" - }, - "privacy": "private", - "readonly": true + "text": "State['branchesVisibility']" + } }, { "kind": "field", - "name": "provider", + "name": "branch", "type": { - "text": "ContextProvider<{ __context__: State }, ReactiveElementHost>" - }, - "privacy": "private", - "readonly": true, - "default": "new ContextProvider(host, { context: stateContext, initialValue: state })" + "text": "State['branch']" + } }, { "kind": "field", - "name": "_state", + "name": "branchState", "type": { - "text": "State" - }, - "privacy": "private", - "default": "state" + "text": "State['branchState']" + } }, { "kind": "field", - "name": "state", + "name": "lastFetched", "type": { - "text": "State" - }, - "readonly": true + "text": "Date | undefined" + } }, { - "kind": "method", - "name": "dispose", - "return": { - "type": { - "text": "void" - } + "kind": "field", + "name": "subscription", + "type": { + "text": "State['subscription']" } - } - ] - } - ], - "exports": [ - { - "kind": "js", - "name": "TimelineStateProvider", - "declaration": { - "name": "TimelineStateProvider", - "module": "src/webviews/apps/plus/timeline/stateProvider.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/timeline/timeline.css.ts", - "declarations": [ - { - "kind": "variable", - "name": "timelineBaseStyles", - "default": "css` * { box-sizing: border-box; } :not(:defined) { visibility: hidden; } [hidden] { display: none !important; } /* roll into shared focus style */ :focus-visible { outline: 1px solid var(--vscode-focusBorder); outline-offset: -1px; } a { text-decoration: none; &:hover { text-decoration: underline; } } b { font-weight: 600; } p { margin-top: 0; } ul { margin-top: 0; padding-left: 1.2em; } section, header { display: flex; flex-direction: column; padding: 0; } h2 { font-weight: 400; } h3 { border: none; color: var(--color-view-header-foreground); font-size: 1.5rem; font-weight: 600; margin-bottom: 0; white-space: nowrap; } h4 { font-size: 1.5rem; font-weight: 400; margin: 0.5rem 0 1rem 0; } `" - }, - { - "kind": "variable", - "name": "timelineStyles", - "default": "css` :host { display: block; color: var(--color-view-foreground); font-family: var(--font-family); font-size: var(--font-size); margin: 0; padding: 0; height: 100vh; overflow: hidden; } .container { display: flex; flex-direction: column; height: 100%; } .header { flex: none; display: grid; grid-template-columns: 1fr min-content; align-items: center; grid-template-areas: 'details toolbox'; margin: 0.5rem 1rem; } :host-context(body[data-placement='editor']) .header { margin-top: 1rem; margin-right: 1.5rem; } .details { grid-area: details; display: flex; gap: 1rem; align-items: center; font-size: var(--font-size); min-width: 0; margin-right: 1rem; } .details gl-breadcrumbs { flex: 1; min-width: 0; padding: 0.1rem 0; overflow: hidden; } .details .details__ref, .details .details__timeframe { min-width: 0; margin: 0; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .details .details__ref { flex: 0 100000000 auto; color: var(--color-foreground--75); font-size: 1.2rem; margin-left: auto; } .details .details__ref .ref { margin-left: 0.25rem; } .details .details__timeframe { flex: 0 0 auto; color: var(--color-foreground--75); margin-right: 0.6rem; user-select: none; white-space: nowrap; font-size: 1.2rem; margin-left: auto; } .toolbox { grid-area: toolbox; align-items: center; display: flex; gap: 0.3rem; } .toolbox gl-feature-badge { padding-bottom: 0.4rem; } :host-context(body[data-placement='editor']) .toolbox gl-feature-badge { padding-left: 0.4rem; } .select-container { display: flex; align-items: center; justify-content: space-between; flex: 100% 0 1; position: relative; } .select-container label { margin: 0 1rem 0 0; font-size: var(--font-size); user-select: none; } .select-container::after { font-family: codicon; content: '\\\\eab4'; font-size: 1.4rem; pointer-events: none; top: 50%; right: 8px; transform: translateY(-50%); position: absolute; color: var(--vscode-foreground); } .select { -webkit-appearance: none; -moz-appearance: none; appearance: none; border: 1px solid var(--vscode-dropdown-border); cursor: pointer; font-family: inherit; min-height: 100%; padding: 2px 26px 2px 8px; background-color: var(--vscode-dropdown-background); border-radius: 0.3rem; box-sizing: border-box; color: var(--vscode-foreground); font-family: var(--font-family); height: 26px; user-select: none; } .timeline { flex: 1; min-height: 0; } .timeline__empty { padding: 0.4rem 2rem 1.3rem 2rem; font-size: var(--font-size); } .timeline__empty p { margin-top: 0; } :host-context(body[data-placement='view']) gl-feature-gate { background-color: var(--vscode-sideBar-background); } gl-feature-gate gl-feature-badge { vertical-align: super; margin-left: 0.4rem; margin-right: 0.4rem; } label { min-width: fit-content; } label[disabled] { opacity: 0.5; } .config__content { display: flex; flex-direction: column; gap: 0.8rem; max-width: 30rem; min-width: 20rem; margin-bottom: 0.4rem; } .config__content menu-label { padding: 0; margin-bottom: -0.4rem; } .config__content section { display: flex; flex-direction: row; align-items: center; justify-content: space-between; gap: 0.5rem; } .breadcrumb-item-children { display: flex; } .breadcrumb-folder { cursor: pointer; } `" - } - ], - "exports": [ - { - "kind": "js", - "name": "timelineBaseStyles", - "declaration": { - "name": "timelineBaseStyles", - "module": "src/webviews/apps/plus/timeline/timeline.css.ts" - } - }, - { - "kind": "js", - "name": "timelineStyles", - "declaration": { - "name": "timelineStyles", - "module": "src/webviews/apps/plus/timeline/timeline.css.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/timeline/timeline.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlTimelineApp", - "members": [ + }, { "kind": "field", - "name": "shadowRootOptions", + "name": "allowed", "type": { - "text": "ShadowRootInit" + "text": "boolean" }, - "static": true, - "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "default": "false" }, { "kind": "field", - "name": "_chart", + "name": "avatars", "type": { - "text": "GlTimelineChart | undefined" - }, - "privacy": "private" + "text": "State['avatars']" + } }, { - "kind": "method", - "name": "createStateProvider", - "privacy": "protected", - "return": { - "type": { - "text": "TimelineStateProvider" - } - }, - "parameters": [ - { - "name": "state", - "type": { - "text": "State" - } - }, - { - "name": "ipc", - "type": { - "text": "HostIpc" - } - } - ], - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" + "kind": "field", + "name": "refsMetadata", + "type": { + "text": "State['refsMetadata']" } }, { - "kind": "method", - "name": "onPersistState", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "state", - "type": { - "text": "State" - } - } - ], - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" + "kind": "field", + "name": "rows", + "type": { + "text": "State['rows']" } }, { "kind": "field", - "name": "_loading", + "name": "rowsStats", "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" + "text": "State['rowsStats']" + } }, { "kind": "field", - "name": "allowed", - "readonly": true + "name": "rowsStatsLoading", + "type": { + "text": "boolean | undefined" + } }, { "kind": "field", - "name": "base", - "readonly": true + "name": "downstreams", + "type": { + "text": "State['downstreams']" + } }, { "kind": "field", - "name": "config", - "readonly": true + "name": "paging", + "type": { + "text": "State['paging']" + } }, { "kind": "field", - "name": "head", - "readonly": true + "name": "columns", + "type": { + "text": "State['columns']" + } }, { "kind": "field", - "name": "repository", - "readonly": true + "name": "config", + "type": { + "text": "State['config']" + } }, { "kind": "field", - "name": "scope", - "readonly": true + "name": "context", + "type": { + "text": "State['context']" + } }, { "kind": "field", - "name": "isShowAllBranchesSupported", - "readonly": true + "name": "nonce", + "type": { + "text": "string | undefined" + } }, { "kind": "field", - "name": "isSliceBySupported", - "readonly": true + "name": "workingTreeStats", + "type": { + "text": "State['workingTreeStats']" + } }, { "kind": "field", - "name": "sliceBy", - "readonly": true + "name": "defaultSearchMode", + "type": { + "text": "State['defaultSearchMode']" + } }, { "kind": "field", - "name": "subscription", - "readonly": true + "name": "useNaturalLanguageSearch", + "type": { + "text": "boolean | undefined" + } }, { - "kind": "method", - "name": "renderGate", - "privacy": "private" + "kind": "field", + "name": "excludeRefs", + "type": { + "text": "State['excludeRefs']" + } }, { - "kind": "method", - "name": "renderBreadcrumbs", - "privacy": "private" + "kind": "field", + "name": "excludeTypes", + "type": { + "text": "State['excludeTypes']" + } }, { - "kind": "method", - "name": "renderRepositoryBreadcrumbItem", - "privacy": "private" + "kind": "field", + "name": "includeOnlyRefs", + "type": { + "text": "State['includeOnlyRefs']" + } }, { - "kind": "method", - "name": "renderBranchBreadcrumbItem", - "privacy": "private" + "kind": "field", + "name": "featurePreview", + "type": { + "text": "State['featurePreview']" + } }, { - "kind": "method", - "name": "renderBreadcrumbPathItems", - "privacy": "private" + "kind": "field", + "name": "orgSettings", + "type": { + "text": "State['orgSettings']" + } }, { - "kind": "method", - "name": "renderChart", - "privacy": "private" + "kind": "field", + "name": "isBusy", + "readonly": true }, { "kind": "method", - "name": "renderConfigPopover", - "privacy": "private" + "name": "createContextProvider", + "privacy": "protected", + "return": { + "type": { + "text": "ContextProvider" + } + }, + "parameters": [ + { + "name": "_state", + "type": { + "text": "State" + } + } + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "method", - "name": "renderConfigHead", - "privacy": "private" + "name": "initializeState", + "privacy": "protected", + "return": { + "type": { + "text": "Promise" + } + }, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "method", - "name": "renderConfigBase", - "privacy": "private" + "name": "onMessageReceived", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "msg", + "type": { + "text": "IpcMessage" + } + } + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { - "kind": "method", - "name": "renderConfigShowAllBranches", + "kind": "field", + "name": "fireProviderUpdate", "privacy": "private" }, { "kind": "method", - "name": "renderPeriodSelect", - "privacy": "private", + "name": "updateState", + "privacy": "protected", "parameters": [ { - "name": "period", + "name": "partial", "type": { - "text": "TimelinePeriod" + "text": "Partial" + } + }, + { + "name": "silent", + "optional": true, + "type": { + "text": "boolean" } } ] }, { - "kind": "method", - "name": "renderConfigSliceBy", - "privacy": "private" + "kind": "field", + "name": "disposable", + "type": { + "text": "Disposable" + }, + "privacy": "protected", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { - "kind": "method", - "name": "renderTimeframe", - "privacy": "private" + "kind": "field", + "name": "provider", + "type": { + "text": "ContextProvider" + }, + "privacy": "protected", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "onChooseBaseRef", - "privacy": "private" + "name": "_state", + "type": { + "text": "State" + }, + "privacy": "protected", + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "onChooseHeadRef", - "privacy": "private" + "name": "state", + "type": { + "text": "State" + }, + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "onChoosePath", - "privacy": "private" + "name": "webviewId", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "onChangeScope", - "privacy": "private" + "name": "webviewInstanceId", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { - "kind": "method", - "name": "onChartCommitSelected", + "kind": "field", + "name": "timestamp", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + }, + { + "kind": "method", + "name": "dispose", + "return": { + "type": { + "text": "void" + } + }, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + }, + { + "kind": "field", + "name": "deferBootstrap", + "type": { + "text": "boolean" + }, + "privacy": "protected", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + }, + { + "kind": "method", + "name": "onPersistState", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "state", + "type": { + "text": "State" + } + } + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } + } + ], + "superclass": { + "name": "StateProviderBase", + "module": "/src/webviews/apps/shared/stateProviderBase" + } + } + ], + "exports": [ + { + "kind": "js", + "name": "graphStateContext", + "declaration": { + "name": "graphStateContext", + "module": "src/webviews/apps/plus/graph/stateProvider.ts" + } + }, + { + "kind": "js", + "name": "GraphStateProvider", + "declaration": { + "name": "GraphStateProvider", + "module": "src/webviews/apps/plus/graph/stateProvider.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/patchDetails/patchDetails.ts", + "declarations": [ + { + "kind": "variable", + "name": "uncommittedSha", + "type": { + "text": "string" + }, + "default": "'0000000000000000000000000000000000000000'" + }, + { + "kind": "class", + "description": "", + "name": "PatchDetailsApp", + "members": [ + { + "kind": "method", + "name": "onInitialize", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } + }, + { + "kind": "method", + "name": "onBind", + "privacy": "protected", + "return": { + "type": { + "text": "Disposable[]" + } + }, + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } + }, + { + "kind": "method", + "name": "onMessageReceived", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "msg", + "type": { + "text": "IpcMessage" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } + }, + { + "kind": "method", + "name": "onPatchChecked", "privacy": "private", "parameters": [ { "name": "e", "type": { - "text": "CustomEvent" + "text": "PatchCheckedDetail" } } ] }, { "kind": "method", - "name": "onPeriodChanged", + "name": "onCreateCheckRepo", "privacy": "private", "parameters": [ { "name": "e", "type": { - "text": "Event" + "text": "CreatePatchCheckRepositoryEventDetail" } } ] }, { "kind": "method", - "name": "onSliceByChanged", + "name": "onCreateUpdateMetadata", "privacy": "private", "parameters": [ { "name": "e", "type": { - "text": "Event" + "text": "CreatePatchMetadataEventDetail" } } ] }, { - "kind": "field", - "name": "_fireSelectDataPointDebounced", - "type": { - "text": "Deferrable<(e: CommitEventDetail) => void> | undefined" - }, - "privacy": "private" + "kind": "method", + "name": "onCreateGenerateTitle", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "CreatePatchMetadataEventDetail" + } + } + ] }, { "kind": "method", - "name": "fireSelectDataPoint", + "name": "onDraftUpdateMetadata", "privacy": "private", "parameters": [ { "name": "e", "type": { - "text": "CommitEventDetail" + "text": "{ visibility: DraftVisibility }" } } ] }, { - "kind": "field", - "name": "name", - "type": { - "text": "string" - }, - "attribute": "name", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } - }, - { - "kind": "field", - "name": "placement", - "type": { - "text": "'editor' | 'view'" - }, - "default": "'editor'", - "attribute": "placement", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "kind": "method", + "name": "onDraftUpdatePermissions", + "privacy": "private" }, { - "kind": "field", - "name": "_ipc", - "type": { - "text": "HostIpc" - }, - "privacy": "protected", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "kind": "method", + "name": "onShowPatchInGraph", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "ShowPatchInGraphDetail" + } + } + ] }, { - "kind": "field", - "name": "_logger", - "type": { - "text": "LoggerContext" - }, - "privacy": "protected", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "kind": "method", + "name": "onCreatePatch", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "CreatePatchEventDetail" + } + } + ] }, { - "kind": "field", - "name": "_promos", - "type": { - "text": "PromosContext" - }, - "privacy": "protected", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "kind": "method", + "name": "onShareLocalPatch", + "privacy": "private" }, { - "kind": "field", - "name": "_telemetry", - "type": { - "text": "TelemetryContext" - }, - "privacy": "protected", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "kind": "method", + "name": "onCopyCloudLink", + "privacy": "private" }, { - "kind": "field", - "name": "bootstrap", - "type": { - "text": "State" - }, + "kind": "method", + "name": "onModeClicked", "privacy": "private", - "attribute": "bootstrap", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "parameters": [ + { + "name": "e", + "type": { + "text": "Event" + } + } + ] }, { "kind": "method", - "name": "onThemeUpdated", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, + "name": "onApplyPatch", + "privacy": "private", "parameters": [ { "name": "e", "type": { - "text": "ThemeChangeEvent" + "text": "ApplyPatchDetail" } } - ], - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } - }, - { - "kind": "field", - "name": "state", - "type": { - "text": "State" - }, - "readonly": true, - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } - }, - { - "kind": "field", - "name": "disposables", - "type": { - "text": "Disposable[]" - }, - "privacy": "protected", - "readonly": true, - "default": "[]", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + ] }, { - "kind": "field", - "name": "_focused", - "type": { - "text": "boolean | undefined" - }, + "kind": "method", + "name": "onArchiveDraft", "privacy": "private", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "parameters": [ + { + "name": "reason", + "optional": true, + "type": { + "text": "DraftReasonEventDetail['reason']" + } + } + ] }, { - "kind": "field", - "name": "_inputFocused", - "type": { - "text": "boolean | undefined" - }, + "kind": "method", + "name": "onChangePatchBase", "privacy": "private", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "parameters": [ + { + "name": "e", + "type": { + "text": "ChangePatchBaseDetail" + } + } + ] }, { - "kind": "field", - "name": "_sendWebviewFocusChangedCommandDebounced", - "type": { - "text": "Deferrable<(params: WebviewFocusChangedParams) => void>" - }, + "kind": "method", + "name": "onSelectPatchRepo", "privacy": "private", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "parameters": [ + { + "name": "e", + "type": { + "text": "SelectPatchRepoDetail" + } + } + ] }, { - "kind": "field", - "name": "_stateProvider", - "type": { - "text": "StateProvider" - }, + "kind": "method", + "name": "onCommandClickedCore", "privacy": "private", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "parameters": [ + { + "name": "action", + "optional": true, + "type": { + "text": "GlCommands | `command:${GlCommands}`" + } + } + ] }, { "kind": "method", - "name": "onWebviewFocusChanged", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, + "name": "onSwitchAIModel", + "privacy": "private", "parameters": [ { - "name": "focused", + "name": "_e", "type": { - "text": "boolean" + "text": "MouseEvent" } } - ], - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + ] }, { "kind": "method", - "name": "onWebviewVisibilityChanged", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, + "name": "onAIExplain", + "privacy": "private", "parameters": [ { - "name": "visible", + "name": "_e", "type": { - "text": "boolean" + "text": "MouseEvent" } } - ], - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + ] }, { - "kind": "field", - "name": "onFocusIn", + "kind": "method", + "name": "onToggleFilesLayout", "privacy": "private", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "parameters": [ + { + "name": "e", + "type": { + "text": "MouseEvent" + } + } + ] }, { - "kind": "field", - "name": "onFocusOut", - "privacy": "private", - "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" - } + "kind": "method", + "name": "onInviteUsers", + "privacy": "private" }, { "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } - }, + "name": "onUpdateUserSelection", + "privacy": "private", "parameters": [ { - "name": "name", + "name": "e", "type": { - "text": "T" + "text": "CreatePatchUpdateSelectionEventDetail | PatchDetailsUpdateSelectionEventDetail" } - }, + } + ] + }, + { + "kind": "method", + "name": "onOpenFileOnRemote", + "privacy": "private", + "parameters": [ { - "name": "detail", + "name": "e", "type": { - "text": "CustomEventDetailType" + "text": "FileChangeListItemDetail" } - }, + } + ] + }, + { + "kind": "method", + "name": "onOpenFile", + "privacy": "private", + "parameters": [ { - "name": "options", - "optional": true, + "name": "e", "type": { - "text": "Omit>, 'detail'>" + "text": "FileChangeListItemDetail" } } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" + ] + }, + { + "kind": "method", + "name": "onCompareFileWithWorking", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "FileChangeListItemDetail" + } + } + ] + }, + { + "kind": "method", + "name": "onCompareFileWithPrevious", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "FileChangeListItemDetail" + } + } + ] + }, + { + "kind": "method", + "name": "onFileMoreActions", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "FileChangeListItemDetail" + } + } + ] + }, + { + "kind": "field", + "name": "_component", + "type": { + "text": "GlPatchDetailsApp | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "component", + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "attachState", + "privacy": "private", + "parameters": [ + { + "name": "_force", + "optional": true, + "type": { + "text": "boolean" + } + } + ] + }, + { + "kind": "field", + "name": "debouncedAttachState", + "privacy": "private" + }, + { + "kind": "field", + "name": "_api", + "type": { + "text": "HostIpcApi" + }, + "privacy": "private", + "readonly": true, + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } - } - ], - "superclass": { - "name": "GlAppHost", - "module": "/src/webviews/apps/shared/appHost" - }, - "tagName": "gl-timeline-app", - "customElement": true, - "attributes": [ + }, { - "name": "name", + "kind": "field", + "name": "_hostIpc", "type": { - "text": "string" + "text": "HostIpc" }, - "fieldName": "name", + "privacy": "private", + "readonly": true, + "default": "new HostIpc(this.appName)", "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "placement", + "kind": "field", + "name": "_logger", "type": { - "text": "'editor' | 'view'" + "text": "LoggerContext" }, - "default": "'editor'", - "fieldName": "placement", + "privacy": "private", + "readonly": true, + "default": "new LoggerContext(appName)", "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } }, { - "name": "bootstrap", + "kind": "field", + "name": "_promos", "type": { - "text": "State" + "text": "PromosContext" }, - "fieldName": "bootstrap", + "privacy": "private", + "readonly": true, + "default": "new PromosContext(this._hostIpc)", "inheritedFrom": { - "name": "GlAppHost", - "module": "src/webviews/apps/shared/appHost.ts" + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" } - } - ] - } - ], - "exports": [ - { - "kind": "js", - "name": "GlTimelineApp", - "declaration": { - "name": "GlTimelineApp", - "module": "src/webviews/apps/plus/timeline/timeline.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-timeline-app", - "declaration": { - "name": "GlTimelineApp", - "module": "src/webviews/apps/plus/timeline/timeline.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/branch-icon.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlBranchIcon", - "members": [ + }, { "kind": "field", - "name": "branch", + "name": "_telemetry", "type": { - "text": "string | undefined" + "text": "TelemetryContext" }, - "attribute": "branch" + "privacy": "protected", + "readonly": true, + "default": "new TelemetryContext(this._hostIpc)", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { "kind": "field", - "name": "status", + "name": "state", "type": { - "text": "GitBranchStatus | undefined" + "text": "State" }, - "attribute": "status" + "privacy": "protected", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { "kind": "field", - "name": "hasChanges", + "name": "placement", "type": { - "text": "boolean" + "text": "'editor' | 'view'" }, - "default": "false", - "attribute": "hasChanges" + "privacy": "protected", + "readonly": true, + "default": "(document.body.getAttribute('data-placement') ?? 'editor')", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } + }, + { + "kind": "method", + "name": "onInitialized", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } + }, + { + "kind": "method", + "name": "onThemeUpdated", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "e", + "type": { + "text": "ThemeChangeEvent" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { "kind": "field", - "name": "upstream", + "name": "_focused", "type": { - "text": "string | undefined" + "text": "boolean | undefined" }, - "attribute": "upstream" + "privacy": "private", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { "kind": "field", - "name": "worktree", + "name": "_inputFocused", "type": { - "text": "boolean" + "text": "boolean | undefined" }, - "default": "false", - "attribute": "worktree" + "privacy": "private", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { "kind": "field", - "name": "isDefault", + "name": "bindDisposables", "type": { - "text": "boolean" + "text": "Disposable[] | undefined" }, - "default": "false", - "attribute": "is-default" + "privacy": "private", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { "kind": "method", - "name": "renderIcon", - "privacy": "private" + "name": "bind", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { "kind": "method", - "name": "renderTooltipContent", - "privacy": "private" - } - ], - "attributes": [ - { - "name": "branch", - "type": { - "text": "string | undefined" + "name": "log", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "fieldName": "branch" + "parameters": [ + { + "name": "message", + "type": { + "text": "string" + } + }, + { + "name": "optionalParams", + "type": { + "text": "any[]" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { - "name": "status", - "type": { - "text": "GitBranchStatus | undefined" + "kind": "method", + "name": "getState", + "privacy": "protected", + "return": { + "type": { + "text": "State | undefined" + } }, - "fieldName": "status" + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { - "name": "hasChanges", - "type": { - "text": "boolean" + "kind": "method", + "name": "sendCommand", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "default": "false", - "fieldName": "hasChanges" + "parameters": [ + { + "name": "command", + "type": { + "text": "TCommand" + } + }, + { + "name": "params", + "type": { + "text": "IpcCallParamsType" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { - "name": "upstream", - "type": { - "text": "string | undefined" + "kind": "method", + "name": "sendRequest", + "privacy": "protected", + "return": { + "type": { + "text": "Promise>" + } }, - "fieldName": "upstream" + "parameters": [ + { + "name": "requestType", + "type": { + "text": "T" + } + }, + { + "name": "params", + "type": { + "text": "IpcCallParamsType" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { - "name": "worktree", - "type": { - "text": "boolean" + "kind": "method", + "name": "setState", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "default": "false", - "fieldName": "worktree" + "parameters": [ + { + "name": "state", + "type": { + "text": "Partial" + } + } + ], + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } }, { - "name": "is-default", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "isDefault" + "kind": "field", + "name": "bootstrap", + "default": "undefined", + "inheritedFrom": { + "name": "App", + "module": "src/webviews/apps/shared/appBase.ts" + } } ], "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-branch-icon", - "customElement": true + "name": "App", + "module": "/src/webviews/apps/shared/appBase" + } } ], "exports": [ { "kind": "js", - "name": "GlBranchIcon", + "name": "uncommittedSha", "declaration": { - "name": "GlBranchIcon", - "module": "src/webviews/apps/shared/components/branch-icon.ts" + "name": "uncommittedSha", + "module": "src/webviews/apps/plus/patchDetails/patchDetails.ts" } }, { - "kind": "custom-element-definition", - "name": "gl-branch-icon", + "kind": "js", + "name": "PatchDetailsApp", "declaration": { - "name": "GlBranchIcon", - "module": "src/webviews/apps/shared/components/branch-icon.ts" + "name": "PatchDetailsApp", + "module": "src/webviews/apps/plus/patchDetails/patchDetails.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/branch-name.ts", + "path": "src/webviews/apps/plus/timeline/context.ts", + "declarations": [ + { + "kind": "variable", + "name": "stateContext" + } + ], + "exports": [ + { + "kind": "js", + "name": "stateContext", + "declaration": { + "name": "stateContext", + "module": "src/webviews/apps/plus/timeline/context.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/timeline/stateProvider.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlBranchName", + "name": "TimelineStateProvider", "members": [ { - "kind": "field", - "name": "name", - "type": { - "text": "string | undefined" + "kind": "method", + "name": "createContextProvider", + "privacy": "protected", + "return": { + "type": { + "text": "ContextProvider" + } }, - "attribute": "name" + "parameters": [ + { + "name": "state", + "type": { + "text": "State" + } + } + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { - "kind": "field", - "name": "size", - "type": { - "text": "number" + "kind": "method", + "name": "onMessageReceived", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "default": "12", - "attribute": "size" - }, - { - "kind": "field", - "name": "worktree", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "worktree" - } - ], - "attributes": [ - { - "name": "name", - "type": { - "text": "string | undefined" - }, - "fieldName": "name" - }, - { - "name": "size", - "type": { - "text": "number" - }, - "default": "12", - "fieldName": "size" - }, - { - "name": "worktree", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "worktree" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-branch-name", - "customElement": true - }, - { - "kind": "function", - "name": "renderBranchName", - "return": { - "type": { - "text": "TemplateResult" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "string | undefined" + "parameters": [ + { + "name": "msg", + "type": { + "text": "IpcMessage" + } + } + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" } }, { - "name": "worktree", - "optional": true, - "type": { - "text": "boolean" - } - } - ] - } - ], - "exports": [ - { - "kind": "js", - "name": "GlBranchName", - "declaration": { - "name": "GlBranchName", - "module": "src/webviews/apps/shared/components/branch-name.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-branch-name", - "declaration": { - "name": "GlBranchName", - "module": "src/webviews/apps/shared/components/branch-name.ts" - } - }, - { - "kind": "js", - "name": "renderBranchName", - "declaration": { - "name": "renderBranchName", - "module": "src/webviews/apps/shared/components/branch-name.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/breadcrumbs.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlBreadcrumbs", - "members": [], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-breadcrumbs", - "customElement": true - }, - { - "kind": "class", - "description": "", - "name": "GlBreadcrumbItem", - "members": [ - { - "kind": "field", - "name": "_collapsed", - "type": { - "text": "boolean | undefined" + "kind": "method", + "name": "onPersistState", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "privacy": "private" + "parameters": [ + { + "name": "state", + "type": { + "text": "State" + } + } + ], + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "collapsed", + "name": "disposable", "type": { - "text": "boolean" + "text": "Disposable" }, - "privacy": "private", - "attribute": "collapsed", - "reflects": true + "privacy": "protected", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "collapsible", + "name": "provider", "type": { - "text": "boolean" + "text": "ContextProvider" }, - "privacy": "private", - "readonly": true + "privacy": "protected", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "collapsibleState", + "name": "_state", "type": { - "text": "CollapsibleState" + "text": "State" }, - "default": "'none'", - "attribute": "collapsibleState" + "privacy": "protected", + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "icon", + "name": "state", "type": { - "text": "string | undefined" + "text": "State" }, - "attribute": "icon" + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "iconTooltip", - "type": { - "text": "string | undefined" - }, - "attribute": "iconTooltip" + "name": "webviewId", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "_shrink", - "type": { - "text": "number" - }, - "privacy": "private", - "default": "1" + "name": "webviewInstanceId", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "shrink", - "type": { - "text": "number" - }, - "attribute": "shrink" + "name": "timestamp", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "method", - "name": "renderIcon", - "privacy": "private", - "parameters": [ - { - "name": "collapsible", - "type": { - "text": "boolean" - } - }, - { - "name": "collapsed", - "type": { - "text": "boolean" - } + "name": "dispose", + "return": { + "type": { + "text": "void" } - ] + }, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { "kind": "field", - "name": "onToggleCollapse", - "privacy": "private" - } - ], - "attributes": [ - { - "name": "collapsed", + "name": "deferBootstrap", "type": { "text": "boolean" }, - "fieldName": "collapsed" - }, - { - "name": "collapsibleState", - "type": { - "text": "CollapsibleState" - }, - "default": "'none'", - "fieldName": "collapsibleState" - }, - { - "name": "icon", - "type": { - "text": "string | undefined" - }, - "fieldName": "icon" - }, - { - "name": "iconTooltip", - "type": { - "text": "string | undefined" - }, - "fieldName": "iconTooltip" + "privacy": "protected", + "readonly": true, + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } }, { - "name": "shrink", - "type": { - "text": "number" + "kind": "method", + "name": "initializeState", + "privacy": "protected", + "return": { + "type": { + "text": "Promise" + } }, - "fieldName": "shrink" + "inheritedFrom": { + "name": "StateProviderBase", + "module": "src/webviews/apps/shared/stateProviderBase.ts" + } } ], "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-breadcrumb-item", - "customElement": true - }, - { - "kind": "class", - "description": "", - "name": "GlBreadcrumbItemChild", - "members": [], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-breadcrumb-item-child", - "customElement": true + "name": "StateProviderBase", + "module": "/src/webviews/apps/shared/stateProviderBase" + } } ], "exports": [ { "kind": "js", - "name": "GlBreadcrumbs", - "declaration": { - "name": "GlBreadcrumbs", - "module": "src/webviews/apps/shared/components/breadcrumbs.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-breadcrumbs", - "declaration": { - "name": "GlBreadcrumbs", - "module": "src/webviews/apps/shared/components/breadcrumbs.ts" - } - }, - { - "kind": "js", - "name": "GlBreadcrumbItem", - "declaration": { - "name": "GlBreadcrumbItem", - "module": "src/webviews/apps/shared/components/breadcrumbs.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-breadcrumb-item", - "declaration": { - "name": "GlBreadcrumbItem", - "module": "src/webviews/apps/shared/components/breadcrumbs.ts" - } - }, - { - "kind": "js", - "name": "GlBreadcrumbItemChild", - "declaration": { - "name": "GlBreadcrumbItemChild", - "module": "src/webviews/apps/shared/components/breadcrumbs.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-breadcrumb-item-child", + "name": "TimelineStateProvider", "declaration": { - "name": "GlBreadcrumbItemChild", - "module": "src/webviews/apps/shared/components/breadcrumbs.ts" + "name": "TimelineStateProvider", + "module": "src/webviews/apps/plus/timeline/stateProvider.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/button-container.ts", + "path": "src/webviews/apps/plus/timeline/timeline.css.ts", "declarations": [ { - "kind": "class", - "description": "", - "name": "ButtonContainer", - "members": [ - { - "kind": "field", - "name": "editor", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "editor" - }, - { - "kind": "field", - "name": "layout", - "type": { - "text": "'shift' | 'editor' | 'full'" - }, - "default": "'shift'", - "attribute": "layout", - "reflects": true - }, - { - "kind": "field", - "name": "grouping", - "type": { - "text": "'gap' | 'split' | 'gap-wide'" - }, - "default": "'gap'", - "attribute": "grouping", - "reflects": true - } - ], - "attributes": [ - { - "name": "editor", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "editor" - }, - { - "name": "layout", - "type": { - "text": "'shift' | 'editor' | 'full'" - }, - "default": "'shift'", - "fieldName": "layout" - }, - { - "name": "grouping", - "type": { - "text": "'gap' | 'split' | 'gap-wide'" - }, - "default": "'gap'", - "fieldName": "grouping" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "button-container", - "customElement": true + "kind": "variable", + "name": "timelineBaseStyles", + "default": "css` * { box-sizing: border-box; } :not(:defined) { visibility: hidden; } [hidden] { display: none !important; } /* roll into shared focus style */ :focus-visible { outline: 1px solid var(--vscode-focusBorder); outline-offset: -1px; } a { text-decoration: none; &:hover { text-decoration: underline; } } b { font-weight: 600; } p { margin-top: 0; } ul { margin-top: 0; padding-left: 1.2em; } section, header { display: flex; flex-direction: column; padding: 0; } h2 { font-weight: 400; } h3 { border: none; color: var(--color-view-header-foreground); font-size: 1.5rem; font-weight: 600; margin-bottom: 0; white-space: nowrap; } h4 { font-size: 1.5rem; font-weight: 400; margin: 0.5rem 0 1rem 0; } `" + }, + { + "kind": "variable", + "name": "timelineStyles", + "default": "css` :host { display: block; color: var(--color-view-foreground); font-family: var(--font-family); font-size: var(--font-size); margin: 0; padding: 0; height: 100vh; overflow: hidden; } .container { display: flex; flex-direction: column; height: 100%; } .header { flex: none; display: grid; grid-template-columns: 1fr min-content; align-items: center; grid-template-areas: 'details toolbox'; margin: 0.5rem 1rem; } :host-context(body[data-placement='editor']) .header { margin-top: 1rem; margin-right: 1.5rem; } .details { grid-area: details; display: flex; gap: 1rem; align-items: center; font-size: var(--font-size); min-width: 0; margin-right: 1rem; } .details gl-breadcrumbs { flex: 1; min-width: 0; padding: 0.1rem 0; overflow: hidden; } .details .details__ref, .details .details__timeframe { min-width: 0; margin: 0; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .details .details__ref { flex: 0 100000000 auto; color: var(--color-foreground--75); font-size: 1.2rem; margin-left: auto; } .details .details__ref .ref { margin-left: 0.25rem; } .details .details__timeframe { flex: 0 0 auto; color: var(--color-foreground--75); margin-right: 0.6rem; user-select: none; white-space: nowrap; font-size: 1.2rem; margin-left: auto; } .toolbox { grid-area: toolbox; align-items: center; display: flex; gap: 0.3rem; } .toolbox gl-feature-badge { padding-bottom: 0.4rem; } :host-context(body[data-placement='editor']) .toolbox gl-feature-badge { padding-left: 0.4rem; } .select-container { display: flex; align-items: center; justify-content: space-between; flex: 100% 0 1; position: relative; } .select-container label { margin: 0 1rem 0 0; font-size: var(--font-size); user-select: none; } .select-container::after { font-family: codicon; content: '\\\\eab4'; font-size: 1.4rem; pointer-events: none; top: 50%; right: 8px; transform: translateY(-50%); position: absolute; color: var(--vscode-foreground); } .select { -webkit-appearance: none; -moz-appearance: none; appearance: none; border: 1px solid var(--vscode-dropdown-border); cursor: pointer; font-family: inherit; min-height: 100%; padding: 2px 26px 2px 8px; background-color: var(--vscode-dropdown-background); border-radius: 0.3rem; box-sizing: border-box; color: var(--vscode-foreground); font-family: var(--font-family); height: 26px; user-select: none; } .timeline { flex: 1; min-height: 0; } .timeline__empty { padding: 0.4rem 2rem 1.3rem 2rem; font-size: var(--font-size); } .timeline__empty p { margin-top: 0; } :host-context(body[data-placement='view']) gl-feature-gate { background-color: var(--vscode-sideBar-background); } gl-feature-gate gl-feature-badge { vertical-align: super; margin-left: 0.4rem; margin-right: 0.4rem; } label { min-width: fit-content; } label[disabled] { opacity: 0.5; } .config__content { display: flex; flex-direction: column; gap: 0.8rem; max-width: 30rem; min-width: 20rem; margin-bottom: 0.4rem; } .config__content menu-label { padding: 0; margin-bottom: -0.4rem; } .config__content section { display: flex; flex-direction: row; align-items: center; justify-content: space-between; gap: 0.5rem; } .breadcrumb-item-children { display: flex; } .breadcrumb-folder { cursor: pointer; } `" } ], "exports": [ { "kind": "js", - "name": "ButtonContainer", + "name": "timelineBaseStyles", "declaration": { - "name": "ButtonContainer", - "module": "src/webviews/apps/shared/components/button-container.ts" + "name": "timelineBaseStyles", + "module": "src/webviews/apps/plus/timeline/timeline.css.ts" } }, { - "kind": "custom-element-definition", - "name": "button-container", + "kind": "js", + "name": "timelineStyles", "declaration": { - "name": "ButtonContainer", - "module": "src/webviews/apps/shared/components/button-container.ts" + "name": "timelineStyles", + "module": "src/webviews/apps/plus/timeline/timeline.css.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/button.ts", + "path": "src/webviews/apps/plus/timeline/timeline.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlButton", + "name": "GlTimelineApp", "members": [ { "kind": "field", @@ -11544,416 +12220,584 @@ "text": "ShadowRootInit" }, "static": true, - "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "field", - "name": "control", + "name": "_chart", "type": { - "text": "HTMLElement" + "text": "GlTimelineChart | undefined" }, - "privacy": "protected" + "privacy": "private" }, { - "kind": "field", - "name": "appearance", - "type": { - "text": "'alert' | 'secondary' | 'toolbar' | 'input' | undefined" + "kind": "method", + "name": "createStateProvider", + "privacy": "protected", + "return": { + "type": { + "text": "TimelineStateProvider" + } }, - "attribute": "appearance", - "reflects": true + "parameters": [ + { + "name": "bootstrap", + "type": { + "text": "string" + } + }, + { + "name": "ipc", + "type": { + "text": "HostIpc" + } + }, + { + "name": "logger", + "type": { + "text": "LoggerContext" + } + } + ], + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "field", - "name": "disabled", + "name": "_loading", "type": { "text": "boolean" }, - "default": "false", - "attribute": "disabled", - "reflects": true + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "density", - "type": { - "text": "'compact' | 'tight' | undefined" - }, - "attribute": "density", - "reflects": true + "name": "allowed", + "readonly": true }, { "kind": "field", - "name": "full", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "full", - "reflects": true + "name": "base", + "readonly": true }, { "kind": "field", - "name": "href", - "type": { - "text": "string | undefined" - }, - "attribute": "href" + "name": "config", + "readonly": true }, { "kind": "field", - "name": "tooltip", - "type": { - "text": "string | undefined" - }, - "attribute": "tooltip" - }, + "name": "head", + "readonly": true + }, { "kind": "field", - "name": "tooltipPlacement", - "type": { - "text": "GlTooltip['placement'] | undefined" - }, - "default": "'bottom'", - "attribute": "tooltipPlacement" + "name": "repository", + "readonly": true + }, + { + "kind": "field", + "name": "scope", + "readonly": true + }, + { + "kind": "field", + "name": "isShowAllBranchesSupported", + "readonly": true + }, + { + "kind": "field", + "name": "isSliceBySupported", + "readonly": true + }, + { + "kind": "field", + "name": "sliceBy", + "readonly": true + }, + { + "kind": "field", + "name": "subscription", + "readonly": true }, { "kind": "method", - "name": "renderControl", + "name": "renderGate", "privacy": "private" }, { "kind": "method", - "name": "onLinkKeypress", + "name": "renderBreadcrumbs", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderRepositoryBreadcrumbItem", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderBranchBreadcrumbItem", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderBreadcrumbPathItems", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderChart", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderConfigPopover", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderConfigHead", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderConfigBase", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderConfigShowAllBranches", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderPeriodSelect", "privacy": "private", "parameters": [ { - "name": "e", + "name": "period", "type": { - "text": "KeyboardEvent" + "text": "TimelinePeriod" } } ] }, { "kind": "method", - "name": "focus", - "return": { - "type": { - "text": "void" - } - }, + "name": "renderConfigSliceBy", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderTimeframe", + "privacy": "private" + }, + { + "kind": "field", + "name": "onChooseBaseRef", + "privacy": "private" + }, + { + "kind": "field", + "name": "onChooseHeadRef", + "privacy": "private" + }, + { + "kind": "field", + "name": "onChoosePath", + "privacy": "private" + }, + { + "kind": "field", + "name": "onChangeScope", + "privacy": "private" + }, + { + "kind": "method", + "name": "onChartCommitSelected", + "privacy": "private", "parameters": [ { - "name": "options", - "optional": true, + "name": "e", "type": { - "text": "FocusOptions" + "text": "CustomEvent" } } ] }, { "kind": "method", - "name": "blur", - "return": { - "type": { - "text": "void" + "name": "onPeriodChanged", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "Event" + } } - } + ] }, { "kind": "method", - "name": "click", - "return": { - "type": { - "text": "void" + "name": "onSliceByChanged", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "Event" + } } - } - } - ], - "attributes": [ + ] + }, { - "name": "appearance", + "kind": "field", + "name": "_fireSelectDataPointDebounced", "type": { - "text": "'alert' | 'secondary' | 'toolbar' | 'input' | undefined" + "text": "Deferrable<(e: CommitEventDetail) => void> | undefined" }, - "fieldName": "appearance" + "privacy": "private" }, { - "name": "disabled", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "disabled" + "kind": "method", + "name": "fireSelectDataPoint", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "CommitEventDetail" + } + } + ] }, { - "name": "density", + "kind": "field", + "name": "name", "type": { - "text": "'compact' | 'tight' | undefined" + "text": "string" }, - "fieldName": "density" + "attribute": "name", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "name": "full", + "kind": "field", + "name": "placement", "type": { - "text": "boolean" + "text": "'editor' | 'view'" }, - "default": "false", - "fieldName": "full" + "default": "'editor'", + "attribute": "placement", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "name": "href", + "kind": "field", + "name": "_ipc", "type": { - "text": "string | undefined" + "text": "HostIpc" }, - "fieldName": "href" + "privacy": "protected", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "name": "tooltip", + "kind": "field", + "name": "_logger", "type": { - "text": "string | undefined" + "text": "LoggerContext" }, - "fieldName": "tooltip" + "privacy": "protected", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "name": "tooltipPlacement", + "kind": "field", + "name": "_promos", "type": { - "text": "GlTooltip['placement'] | undefined" + "text": "PromosContext" }, - "default": "'bottom'", - "fieldName": "tooltipPlacement" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-button", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "GlButton", - "declaration": { - "name": "GlButton", - "module": "src/webviews/apps/shared/components/button.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-button", - "declaration": { - "name": "GlButton", - "module": "src/webviews/apps/shared/components/button.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/code-icon.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "CodeIcon", - "members": [ + "privacy": "protected", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, { "kind": "field", - "name": "icon", + "name": "_telemetry", "type": { - "text": "string" + "text": "TelemetryContext" }, - "default": "''", - "attribute": "icon", - "reflects": true + "privacy": "protected", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "field", - "name": "modifier", + "name": "bootstrap", "type": { "text": "string" }, - "default": "''", - "attribute": "modifier", - "reflects": true + "privacy": "private", + "attribute": "bootstrap", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "kind": "field", - "name": "size", - "type": { - "text": "number | undefined" + "kind": "method", + "name": "onThemeUpdated", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "default": "undefined", - "attribute": "size" + "parameters": [ + { + "name": "e", + "type": { + "text": "ThemeChangeEvent" + } + } + ], + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "field", - "name": "flip", + "name": "state", "type": { - "text": "'inline' | 'block' | undefined" + "text": "State" }, - "attribute": "flip", - "reflects": true + "readonly": true, + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "field", - "name": "rotate", + "name": "disposables", "type": { - "text": "'45' | undefined" + "text": "Disposable[]" }, - "attribute": "rotate", - "reflects": true - } - ], - "attributes": [ + "privacy": "protected", + "readonly": true, + "default": "[]", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, { - "name": "icon", + "kind": "field", + "name": "_focused", "type": { - "text": "string" + "text": "boolean | undefined" }, - "default": "''", - "fieldName": "icon" + "privacy": "private", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "name": "modifier", + "kind": "field", + "name": "_inputFocused", "type": { - "text": "string" + "text": "boolean | undefined" }, - "default": "''", - "fieldName": "modifier" + "privacy": "private", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "name": "size", + "kind": "field", + "name": "_sendWebviewFocusChangedCommandDebounced", "type": { - "text": "number | undefined" + "text": "Deferrable<(params: WebviewFocusChangedParams) => void>" }, - "default": "undefined", - "fieldName": "size" + "privacy": "private", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "name": "flip", + "kind": "field", + "name": "_stateProvider", "type": { - "text": "'inline' | 'block' | undefined" + "text": "Provider" }, - "fieldName": "flip" + "privacy": "protected", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "name": "rotate", - "type": { - "text": "'45' | undefined" + "kind": "method", + "name": "onWebviewFocusChanged", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "fieldName": "rotate" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "code-icon", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "CodeIcon", - "declaration": { - "name": "CodeIcon", - "module": "src/webviews/apps/shared/components/code-icon.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "code-icon", - "declaration": { - "name": "CodeIcon", - "module": "src/webviews/apps/shared/components/code-icon.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/commit-sha.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlCommitSha", - "members": [ + "parameters": [ + { + "name": "focused", + "type": { + "text": "boolean" + } + } + ], + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, { - "kind": "field", - "name": "sha", - "type": { - "text": "string | undefined" + "kind": "method", + "name": "onWebviewVisibilityChanged", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "attribute": "sha" + "parameters": [ + { + "name": "visible", + "type": { + "text": "boolean" + } + } + ], + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "field", - "name": "size", - "type": { - "text": "number" - }, - "default": "12", - "attribute": "size" + "name": "onFocusIn", + "privacy": "private", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { "kind": "field", - "name": "label", + "name": "onFocusOut", "privacy": "private", - "readonly": true - } - ], - "attributes": [ - { - "name": "sha", - "type": { - "text": "string | undefined" - }, - "fieldName": "sha" + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } }, { - "name": "size", - "type": { - "text": "number" + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } }, - "default": "12", - "fieldName": "size" + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } } ], "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-commit-sha", - "customElement": true - }, - { - "kind": "function", - "name": "renderCommitSha", - "return": { - "type": { - "text": "TemplateResult" - } + "name": "GlAppHost", + "module": "/src/webviews/apps/shared/appHost" }, - "parameters": [ + "tagName": "gl-timeline-app", + "customElement": true, + "attributes": [ { - "name": "sha", + "name": "name", "type": { - "text": "string | undefined" + "text": "string" + }, + "fieldName": "name", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } }, { - "name": "size", - "default": "12", + "name": "placement", "type": { - "text": "number" + "text": "'editor' | 'view'" + }, + "default": "'editor'", + "fieldName": "placement", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" + } + }, + { + "name": "bootstrap", + "type": { + "text": "string" + }, + "fieldName": "bootstrap", + "inheritedFrom": { + "name": "GlAppHost", + "module": "src/webviews/apps/shared/appHost.ts" } } ] @@ -11962,1401 +12806,1641 @@ "exports": [ { "kind": "js", - "name": "GlCommitSha", + "name": "GlTimelineApp", "declaration": { - "name": "GlCommitSha", - "module": "src/webviews/apps/shared/components/commit-sha.ts" + "name": "GlTimelineApp", + "module": "src/webviews/apps/plus/timeline/timeline.ts" } }, { "kind": "custom-element-definition", - "name": "gl-commit-sha", - "declaration": { - "name": "GlCommitSha", - "module": "src/webviews/apps/shared/components/commit-sha.ts" - } - }, - { - "kind": "js", - "name": "renderCommitSha", + "name": "gl-timeline-app", "declaration": { - "name": "renderCommitSha", - "module": "src/webviews/apps/shared/components/commit-sha.ts" + "name": "GlTimelineApp", + "module": "src/webviews/apps/plus/timeline/timeline.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/copy-container.ts", + "path": "src/webviews/apps/shared/components/branch-icon.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlCopyContainer", + "name": "GlBranchIcon", "members": [ { "kind": "field", - "name": "tagName", - "static": true, - "readonly": true, - "default": "'gl-copy-container'", - "type": { - "text": "string" - } - }, - { - "kind": "field", - "name": "content", + "name": "branch", "type": { "text": "string | undefined" }, - "attribute": "content" - }, - { - "kind": "field", - "name": "copyLabel", - "type": { - "text": "string" - }, - "default": "'Copy'", - "attribute": "copyLabel" + "attribute": "branch" }, { "kind": "field", - "name": "copiedLabel", + "name": "status", "type": { - "text": "string" + "text": "GitBranchStatus | undefined" }, - "default": "'Copied'", - "attribute": "copiedLabel" + "attribute": "status" }, { "kind": "field", - "name": "placement", + "name": "hasChanges", "type": { - "text": "GlTooltip['placement'] | undefined" + "text": "boolean" }, - "default": "'top'", - "attribute": "placement" + "default": "false", + "attribute": "hasChanges" }, { "kind": "field", - "name": "timeout", + "name": "upstream", "type": { - "text": "number" + "text": "string | undefined" }, - "default": "1000", - "attribute": "timeout" + "attribute": "upstream" }, { "kind": "field", - "name": "_resetTimer", + "name": "worktree", "type": { - "text": "ReturnType | undefined" + "text": "boolean" }, - "privacy": "private" + "default": "false", + "attribute": "worktree" }, { "kind": "field", - "name": "label", + "name": "isDefault", "type": { - "text": "string" + "text": "boolean" }, - "privacy": "private" - }, - { - "kind": "method", - "name": "onClick", - "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "MouseEvent" - } - } - ] + "default": "false", + "attribute": "is-default" }, { "kind": "method", - "name": "cancelResetTimer", + "name": "renderIcon", "privacy": "private" }, { "kind": "method", - "name": "createResetTimer", + "name": "renderTooltipContent", "privacy": "private" } ], "attributes": [ { - "name": "content", + "name": "branch", "type": { "text": "string | undefined" }, - "fieldName": "content" + "fieldName": "branch" }, { - "name": "copyLabel", + "name": "status", "type": { - "text": "string" + "text": "GitBranchStatus | undefined" }, - "default": "'Copy'", - "fieldName": "copyLabel" + "fieldName": "status" }, { - "name": "copiedLabel", + "name": "hasChanges", "type": { - "text": "string" + "text": "boolean" }, - "default": "'Copied'", - "fieldName": "copiedLabel" + "default": "false", + "fieldName": "hasChanges" }, { - "name": "placement", + "name": "upstream", "type": { - "text": "GlTooltip['placement'] | undefined" + "text": "string | undefined" }, - "default": "'top'", - "fieldName": "placement" + "fieldName": "upstream" }, { - "name": "timeout", + "name": "worktree", "type": { - "text": "number" + "text": "boolean" }, - "default": "1000", - "fieldName": "timeout" + "default": "false", + "fieldName": "worktree" + }, + { + "name": "is-default", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "isDefault" } ], "superclass": { "name": "LitElement", "package": "lit" }, + "tagName": "gl-branch-icon", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlCopyContainer", + "name": "GlBranchIcon", "declaration": { - "name": "GlCopyContainer", - "module": "src/webviews/apps/shared/components/copy-container.ts" + "name": "GlBranchIcon", + "module": "src/webviews/apps/shared/components/branch-icon.ts" } }, { "kind": "custom-element-definition", + "name": "gl-branch-icon", "declaration": { - "name": "GlCopyContainer", - "module": "src/webviews/apps/shared/components/copy-container.ts" + "name": "GlBranchIcon", + "module": "src/webviews/apps/shared/components/branch-icon.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/element.ts", + "path": "src/webviews/apps/shared/components/branch-name.ts", "declarations": [ { - "kind": "function", - "name": "observe", - "parameters": [ + "kind": "class", + "description": "", + "name": "GlBranchName", + "members": [ { - "name": "keys", + "kind": "field", + "name": "name", "type": { - "text": "keyof T | (keyof T)[]" - } + "text": "string | undefined" + }, + "attribute": "name" }, { - "name": "options", - "optional": true, + "kind": "field", + "name": "size", "type": { - "text": "{ afterFirstUpdate?: boolean }" - } + "text": "number" + }, + "default": "12", + "attribute": "size" + }, + { + "kind": "field", + "name": "worktree", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "worktree" } - ] - }, - { - "kind": "class", - "description": "", - "name": "GlElement", - "members": [ + ], + "attributes": [ { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } + "name": "name", + "type": { + "text": "string | undefined" }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ] + "fieldName": "name" }, { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } + "name": "size", + "type": { + "text": "number" }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "optional": true, - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ] + "default": "12", + "fieldName": "size" }, { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } + "name": "worktree", + "type": { + "text": "boolean" }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ] + "default": "false", + "fieldName": "worktree" } ], "superclass": { "name": "LitElement", "package": "lit" }, + "tagName": "gl-branch-name", "customElement": true + }, + { + "kind": "function", + "name": "renderBranchName", + "return": { + "type": { + "text": "TemplateResult" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "string | undefined" + } + }, + { + "name": "worktree", + "optional": true, + "type": { + "text": "boolean" + } + } + ] } ], "exports": [ { "kind": "js", - "name": "observe", + "name": "GlBranchName", "declaration": { - "name": "observe", - "module": "src/webviews/apps/shared/components/element.ts" + "name": "GlBranchName", + "module": "src/webviews/apps/shared/components/branch-name.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-branch-name", + "declaration": { + "name": "GlBranchName", + "module": "src/webviews/apps/shared/components/branch-name.ts" } }, { "kind": "js", - "name": "GlElement", + "name": "renderBranchName", "declaration": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" + "name": "renderBranchName", + "module": "src/webviews/apps/shared/components/branch-name.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/feature-badge.ts", + "path": "src/webviews/apps/shared/components/breadcrumbs.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlFeatureBadge", + "name": "GlBreadcrumbs", + "members": [], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-breadcrumbs", + "customElement": true + }, + { + "kind": "class", + "description": "", + "name": "GlBreadcrumbItem", "members": [ { "kind": "field", - "name": "cloud", + "name": "_collapsed", "type": { - "text": "boolean" + "text": "boolean | undefined" }, - "default": "false", - "attribute": "cloud" + "privacy": "private" }, { "kind": "field", - "name": "placement", + "name": "collapsed", "type": { - "text": "GlPopover['placement']" + "text": "boolean" }, - "default": "'bottom'", - "attribute": "placement", + "privacy": "private", + "attribute": "collapsed", "reflects": true }, { "kind": "field", - "name": "preview", + "name": "collapsible", "type": { "text": "boolean" }, - "default": "false", - "attribute": "preview" + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "promos", + "name": "collapsibleState", "type": { - "text": "PromosContext" + "text": "CollapsibleState" }, - "privacy": "private" + "default": "'none'", + "attribute": "collapsibleState" }, { "kind": "field", - "name": "source", + "name": "icon", "type": { - "text": "Source | undefined" + "text": "string | undefined" }, - "attribute": "source" + "attribute": "icon" }, { "kind": "field", - "name": "subscription", + "name": "iconTooltip", "type": { - "text": "Subscription | undefined" - } + "text": "string | undefined" + }, + "attribute": "iconTooltip" }, { "kind": "field", - "name": "daysRemaining", + "name": "_shrink", + "type": { + "text": "number" + }, "privacy": "private", - "readonly": true + "default": "1" }, { "kind": "field", - "name": "state", - "privacy": "private", - "readonly": true - }, - { - "kind": "method", - "name": "renderBadge", - "privacy": "private" + "name": "shrink", + "type": { + "text": "number" + }, + "attribute": "shrink" }, { "kind": "method", - "name": "renderPopoverHeader", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderPopoverContent", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderStartTrialActions", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderUpgradeActions", + "name": "renderIcon", "privacy": "private", "parameters": [ { - "name": "leadin", - "optional": true, + "name": "collapsible", "type": { - "text": "TemplateResult" + "text": "boolean" + } + }, + { + "name": "collapsed", + "type": { + "text": "boolean" } } ] }, { - "kind": "method", - "name": "renderPromo", + "kind": "field", + "name": "onToggleCollapse", "privacy": "private" } ], "attributes": [ { - "name": "cloud", + "name": "collapsed", + "type": { + "text": "boolean" + }, + "fieldName": "collapsed" + }, + { + "name": "collapsibleState", + "type": { + "text": "CollapsibleState" + }, + "default": "'none'", + "fieldName": "collapsibleState" + }, + { + "name": "icon", + "type": { + "text": "string | undefined" + }, + "fieldName": "icon" + }, + { + "name": "iconTooltip", + "type": { + "text": "string | undefined" + }, + "fieldName": "iconTooltip" + }, + { + "name": "shrink", + "type": { + "text": "number" + }, + "fieldName": "shrink" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-breadcrumb-item", + "customElement": true + }, + { + "kind": "class", + "description": "", + "name": "GlBreadcrumbItemChild", + "members": [], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-breadcrumb-item-child", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlBreadcrumbs", + "declaration": { + "name": "GlBreadcrumbs", + "module": "src/webviews/apps/shared/components/breadcrumbs.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-breadcrumbs", + "declaration": { + "name": "GlBreadcrumbs", + "module": "src/webviews/apps/shared/components/breadcrumbs.ts" + } + }, + { + "kind": "js", + "name": "GlBreadcrumbItem", + "declaration": { + "name": "GlBreadcrumbItem", + "module": "src/webviews/apps/shared/components/breadcrumbs.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-breadcrumb-item", + "declaration": { + "name": "GlBreadcrumbItem", + "module": "src/webviews/apps/shared/components/breadcrumbs.ts" + } + }, + { + "kind": "js", + "name": "GlBreadcrumbItemChild", + "declaration": { + "name": "GlBreadcrumbItemChild", + "module": "src/webviews/apps/shared/components/breadcrumbs.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-breadcrumb-item-child", + "declaration": { + "name": "GlBreadcrumbItemChild", + "module": "src/webviews/apps/shared/components/breadcrumbs.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/button-container.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "ButtonContainer", + "members": [ + { + "kind": "field", + "name": "editor", "type": { "text": "boolean" }, "default": "false", - "fieldName": "cloud" + "attribute": "editor" }, { - "name": "placement", + "kind": "field", + "name": "layout", "type": { - "text": "GlPopover['placement']" + "text": "'shift' | 'editor' | 'full'" }, - "default": "'bottom'", - "fieldName": "placement" + "default": "'shift'", + "attribute": "layout", + "reflects": true }, { - "name": "preview", + "kind": "field", + "name": "grouping", + "type": { + "text": "'gap' | 'split' | 'gap-wide'" + }, + "default": "'gap'", + "attribute": "grouping", + "reflects": true + } + ], + "attributes": [ + { + "name": "editor", "type": { "text": "boolean" }, "default": "false", - "fieldName": "preview" + "fieldName": "editor" }, { - "name": "source", + "name": "layout", "type": { - "text": "Source | undefined" + "text": "'shift' | 'editor' | 'full'" }, - "fieldName": "source" + "default": "'shift'", + "fieldName": "layout" + }, + { + "name": "grouping", + "type": { + "text": "'gap' | 'split' | 'gap-wide'" + }, + "default": "'gap'", + "fieldName": "grouping" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-feature-badge", + "tagName": "button-container", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlFeatureBadge", + "name": "ButtonContainer", "declaration": { - "name": "GlFeatureBadge", - "module": "src/webviews/apps/shared/components/feature-badge.ts" + "name": "ButtonContainer", + "module": "src/webviews/apps/shared/components/button-container.ts" } }, { "kind": "custom-element-definition", - "name": "gl-feature-badge", + "name": "button-container", "declaration": { - "name": "GlFeatureBadge", - "module": "src/webviews/apps/shared/components/feature-badge.ts" + "name": "ButtonContainer", + "module": "src/webviews/apps/shared/components/button-container.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/feature-gate.ts", + "path": "src/webviews/apps/shared/components/button.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlFeatureGate", + "name": "GlButton", "members": [ + { + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + }, + { + "kind": "field", + "name": "control", + "type": { + "text": "HTMLElement" + }, + "privacy": "protected" + }, { "kind": "field", "name": "appearance", "type": { - "text": "'alert' | 'welcome' | undefined" + "text": "'alert' | 'secondary' | 'toolbar' | 'input' | undefined" }, "attribute": "appearance", "reflects": true }, { "kind": "field", - "name": "featurePreview", + "name": "disabled", "type": { - "text": "FeaturePreview | undefined" + "text": "boolean" }, - "attribute": "featurePreview" + "default": "false", + "attribute": "disabled", + "reflects": true }, { "kind": "field", - "name": "featurePreviewCommandLink", + "name": "density", "type": { - "text": "string | undefined" + "text": "'compact' | 'tight' | undefined" }, - "attribute": "featurePreviewCommandLink" + "attribute": "density", + "reflects": true }, { "kind": "field", - "name": "featureWithArticleIfNeeded", + "name": "full", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "full", + "reflects": true + }, + { + "kind": "field", + "name": "href", "type": { "text": "string | undefined" }, - "attribute": "featureWithArticleIfNeeded" + "attribute": "href" }, { "kind": "field", - "name": "source", + "name": "tooltip", "type": { - "text": "Source | undefined" + "text": "string | undefined" }, - "attribute": "source" + "attribute": "tooltip" }, { "kind": "field", - "name": "state", + "name": "tooltipPlacement", "type": { - "text": "SubscriptionState | undefined" - } + "text": "GlTooltip['placement'] | undefined" + }, + "default": "'bottom'", + "attribute": "tooltipPlacement" }, { "kind": "field", - "name": "webroot", + "name": "truncate", "type": { - "text": "string | undefined" + "text": "boolean" }, - "attribute": "webroot" + "default": "false", + "attribute": "truncate", + "reflects": true + }, + { + "kind": "method", + "name": "renderControl", + "privacy": "private" + }, + { + "kind": "method", + "name": "onLinkKeypress", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "KeyboardEvent" + } + } + ] + }, + { + "kind": "method", + "name": "focus", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "options", + "optional": true, + "type": { + "text": "FocusOptions" + } + } + ] + }, + { + "kind": "method", + "name": "blur", + "return": { + "type": { + "text": "void" + } + } + }, + { + "kind": "method", + "name": "click", + "return": { + "type": { + "text": "void" + } + } } ], "attributes": [ { "name": "appearance", "type": { - "text": "'alert' | 'welcome' | undefined" + "text": "'alert' | 'secondary' | 'toolbar' | 'input' | undefined" }, "fieldName": "appearance" }, { - "name": "featurePreview", + "name": "disabled", "type": { - "text": "FeaturePreview | undefined" + "text": "boolean" }, - "fieldName": "featurePreview" + "default": "false", + "fieldName": "disabled" }, { - "name": "featurePreviewCommandLink", + "name": "density", + "type": { + "text": "'compact' | 'tight' | undefined" + }, + "fieldName": "density" + }, + { + "name": "full", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "full" + }, + { + "name": "href", "type": { "text": "string | undefined" }, - "fieldName": "featurePreviewCommandLink" + "fieldName": "href" }, { - "name": "featureWithArticleIfNeeded", + "name": "tooltip", "type": { "text": "string | undefined" }, - "fieldName": "featureWithArticleIfNeeded" + "fieldName": "tooltip" }, { - "name": "source", + "name": "tooltipPlacement", "type": { - "text": "Source | undefined" + "text": "GlTooltip['placement'] | undefined" }, - "fieldName": "source" + "default": "'bottom'", + "fieldName": "tooltipPlacement" }, { - "name": "webroot", + "name": "truncate", "type": { - "text": "string | undefined" + "text": "boolean" }, - "fieldName": "webroot" + "default": "false", + "fieldName": "truncate" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-feature-gate", + "tagName": "gl-button", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlFeatureGate", + "name": "GlButton", "declaration": { - "name": "GlFeatureGate", - "module": "src/webviews/apps/shared/components/feature-gate.ts" + "name": "GlButton", + "module": "src/webviews/apps/shared/components/button.ts" } }, { "kind": "custom-element-definition", - "name": "gl-feature-gate", + "name": "gl-button", "declaration": { - "name": "GlFeatureGate", - "module": "src/webviews/apps/shared/components/feature-gate.ts" + "name": "GlButton", + "module": "src/webviews/apps/shared/components/button.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/formatted-date.ts", + "path": "src/webviews/apps/shared/components/code-icon.ts", "declarations": [ { "kind": "class", "description": "", - "name": "FormattedDate", + "name": "CodeIcon", "members": [ { "kind": "field", - "name": "format", + "name": "icon", "type": { - "text": "string | undefined" + "text": "string" }, - "attribute": "format" + "default": "''", + "attribute": "icon", + "reflects": true }, { "kind": "field", - "name": "dateStyle", + "name": "modifier", "type": { - "text": "'relative' | 'absolute'" + "text": "string" }, - "default": "'relative'", - "attribute": "date-style" - }, - { - "kind": "field", - "name": "date", - "default": "new Date()", - "attribute": "date", + "default": "''", + "attribute": "modifier", "reflects": true }, { "kind": "field", - "name": "tooltip", + "name": "size", "type": { - "text": "string" + "text": "number | undefined" }, - "default": "''", - "attribute": "tooltip" + "default": "undefined", + "attribute": "size" }, { "kind": "field", - "name": "absoluteDate", + "name": "flip", "type": { - "text": "string" + "text": "'inline' | 'block' | undefined" }, - "readonly": true + "attribute": "flip", + "reflects": true }, { "kind": "field", - "name": "dateLabel", + "name": "rotate", "type": { - "text": "string" + "text": "'45' | undefined" }, - "readonly": true + "attribute": "rotate", + "reflects": true } ], "attributes": [ { - "name": "format", + "name": "icon", "type": { - "text": "string | undefined" + "text": "string" }, - "fieldName": "format" + "default": "''", + "fieldName": "icon" }, { - "name": "date-style", + "name": "modifier", "type": { - "text": "'relative' | 'absolute'" + "text": "string" }, - "default": "'relative'", - "fieldName": "dateStyle" + "default": "''", + "fieldName": "modifier" }, { - "name": "date", - "default": "new Date()", - "fieldName": "date" + "name": "size", + "type": { + "text": "number | undefined" + }, + "default": "undefined", + "fieldName": "size" }, { - "name": "tooltip", + "name": "flip", "type": { - "text": "string" + "text": "'inline' | 'block' | undefined" }, - "default": "''", - "fieldName": "tooltip" + "fieldName": "flip" + }, + { + "name": "rotate", + "type": { + "text": "'45' | undefined" + }, + "fieldName": "rotate" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "formatted-date", + "tagName": "code-icon", "customElement": true } ], "exports": [ { "kind": "js", - "name": "FormattedDate", + "name": "CodeIcon", "declaration": { - "name": "FormattedDate", - "module": "src/webviews/apps/shared/components/formatted-date.ts" + "name": "CodeIcon", + "module": "src/webviews/apps/shared/components/code-icon.ts" } }, { "kind": "custom-element-definition", - "name": "formatted-date", + "name": "code-icon", "declaration": { - "name": "FormattedDate", - "module": "src/webviews/apps/shared/components/formatted-date.ts" + "name": "CodeIcon", + "module": "src/webviews/apps/shared/components/code-icon.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/gitlens-logo.ts", + "path": "src/webviews/apps/shared/components/commit-sha.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GitLensLogo", - "members": [], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gitlens-logo", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "GitLensLogo", - "declaration": { - "name": "GitLensLogo", - "module": "src/webviews/apps/shared/components/gitlens-logo.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gitlens-logo", - "declaration": { - "name": "GitLensLogo", - "module": "src/webviews/apps/shared/components/gitlens-logo.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/progress.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "ProgressIndicator", + "name": "GlCommitSha", "members": [ { "kind": "field", - "name": "mode", + "name": "sha", "type": { - "text": "string" + "text": "string | undefined" }, - "default": "'infinite'", - "attribute": "mode", - "reflects": true + "attribute": "sha" }, { "kind": "field", - "name": "active", + "name": "size", "type": { - "text": "boolean" + "text": "number" }, - "default": "false", - "attribute": "active" + "default": "12", + "attribute": "size" }, { "kind": "field", - "name": "position", - "type": { - "text": "'top' | 'bottom'" - }, - "default": "'bottom'", - "attribute": "position" + "name": "label", + "privacy": "private", + "readonly": true } ], "attributes": [ { - "name": "mode", - "type": { - "text": "string" - }, - "default": "'infinite'", - "fieldName": "mode" - }, - { - "name": "active", + "name": "sha", "type": { - "text": "boolean" + "text": "string | undefined" }, - "default": "false", - "fieldName": "active" + "fieldName": "sha" }, { - "name": "position", + "name": "size", "type": { - "text": "'top' | 'bottom'" + "text": "number" }, - "default": "'bottom'", - "fieldName": "position" + "default": "12", + "fieldName": "size" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "progress-indicator", + "tagName": "gl-commit-sha", "customElement": true + }, + { + "kind": "function", + "name": "renderCommitSha", + "return": { + "type": { + "text": "TemplateResult" + } + }, + "parameters": [ + { + "name": "sha", + "type": { + "text": "string | undefined" + } + }, + { + "name": "size", + "default": "12", + "type": { + "text": "number" + } + } + ] } ], "exports": [ { "kind": "js", - "name": "ProgressIndicator", + "name": "GlCommitSha", "declaration": { - "name": "ProgressIndicator", - "module": "src/webviews/apps/shared/components/progress.ts" + "name": "GlCommitSha", + "module": "src/webviews/apps/shared/components/commit-sha.ts" } }, { "kind": "custom-element-definition", - "name": "progress-indicator", + "name": "gl-commit-sha", "declaration": { - "name": "ProgressIndicator", - "module": "src/webviews/apps/shared/components/progress.ts" + "name": "GlCommitSha", + "module": "src/webviews/apps/shared/components/commit-sha.ts" + } + }, + { + "kind": "js", + "name": "renderCommitSha", + "declaration": { + "name": "renderCommitSha", + "module": "src/webviews/apps/shared/components/commit-sha.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/promo.ts", + "path": "src/webviews/apps/shared/components/copy-container.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlPromo", + "name": "GlCopyContainer", "members": [ { "kind": "field", - "name": "shadowRootOptions", + "name": "tagName", + "static": true, + "readonly": true, + "default": "'gl-copy-container'", "type": { - "text": "ShadowRootInit" + "text": "string" + } + }, + { + "kind": "field", + "name": "appearance", + "type": { + "text": "'toolbar' | undefined" }, - "static": true, - "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + "attribute": "appearance", + "reflects": true }, { "kind": "field", - "name": "_focusable", + "name": "content", "type": { - "text": "HTMLElement | undefined" + "text": "string | undefined" }, - "privacy": "private" + "attribute": "content" }, { "kind": "field", - "name": "promoPromise", + "name": "copyLabel", "type": { - "text": "Promise | undefined" + "text": "string" }, - "attribute": "promoPromise" + "default": "'Copy'", + "attribute": "copyLabel" }, { "kind": "field", - "name": "source", + "name": "copiedLabel", "type": { - "text": "Source | undefined" + "text": "string" }, - "attribute": "source" + "default": "'Copied'", + "attribute": "copiedLabel" }, { "kind": "field", - "name": "type", + "name": "disabled", "type": { - "text": "'icon' | 'info' | 'link'" + "text": "boolean" }, - "default": "'info'", - "attribute": "type", + "default": "false", + "attribute": "disabled", "reflects": true }, { "kind": "field", - "name": "_hasPromo", + "name": "placement", "type": { - "text": "boolean" + "text": "GlTooltip['placement'] | undefined" }, - "privacy": "private", - "default": "false" + "default": "'top'", + "attribute": "placement" }, { "kind": "field", - "name": "hasPromo", - "privacy": "private", - "attribute": "has-promo", - "reflects": true + "name": "timeout", + "type": { + "text": "number" + }, + "default": "1000", + "attribute": "timeout" + }, + { + "kind": "field", + "name": "_resetTimer", + "type": { + "text": "ReturnType | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "label", + "type": { + "text": "string" + }, + "privacy": "private" }, { "kind": "method", - "name": "renderPromo", + "name": "onClick", "privacy": "private", "parameters": [ { - "name": "promo", + "name": "_e", "type": { - "text": "Promo | undefined" + "text": "MouseEvent" } } ] }, { "kind": "method", - "name": "getCommandUrl", - "privacy": "private", - "parameters": [ - { - "name": "promo", - "type": { - "text": "Promo | undefined" - } - } - ] + "name": "cancelResetTimer", + "privacy": "private" }, { "kind": "method", - "name": "focus", - "return": { - "type": { - "text": "void" - } - } + "name": "createResetTimer", + "privacy": "private" } ], "attributes": [ { - "name": "promoPromise", + "name": "appearance", "type": { - "text": "Promise | undefined" + "text": "'toolbar' | undefined" }, - "fieldName": "promoPromise" + "fieldName": "appearance" }, { - "name": "source", + "name": "content", "type": { - "text": "Source | undefined" + "text": "string | undefined" }, - "fieldName": "source" + "fieldName": "content" }, { - "name": "type", + "name": "copyLabel", "type": { - "text": "'icon' | 'info' | 'link'" + "text": "string" }, - "default": "'info'", - "fieldName": "type" + "default": "'Copy'", + "fieldName": "copyLabel" }, { - "name": "has-promo", - "fieldName": "hasPromo" + "name": "copiedLabel", + "type": { + "text": "string" + }, + "default": "'Copied'", + "fieldName": "copiedLabel" + }, + { + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "disabled" + }, + { + "name": "placement", + "type": { + "text": "GlTooltip['placement'] | undefined" + }, + "default": "'top'", + "fieldName": "placement" + }, + { + "name": "timeout", + "type": { + "text": "number" + }, + "default": "1000", + "fieldName": "timeout" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-promo", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlPromo", + "name": "GlCopyContainer", "declaration": { - "name": "GlPromo", - "module": "src/webviews/apps/shared/components/promo.ts" + "name": "GlCopyContainer", + "module": "src/webviews/apps/shared/components/copy-container.ts" } }, { "kind": "custom-element-definition", - "name": "gl-promo", "declaration": { - "name": "GlPromo", - "module": "src/webviews/apps/shared/components/promo.ts" + "name": "GlCopyContainer", + "module": "src/webviews/apps/shared/components/copy-container.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/ref-button.ts", + "path": "src/webviews/apps/shared/components/element.ts", "declarations": [ { - "kind": "class", - "description": "", - "name": "GlRefButton", - "members": [ - { - "kind": "field", - "name": "disabled", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "disabled", - "reflects": true - }, - { - "kind": "field", - "name": "href", - "type": { - "text": "string | undefined" - }, - "attribute": "href", - "reflects": true - }, - { - "kind": "field", - "name": "icon", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "icon", - "reflects": true - }, - { - "kind": "field", - "name": "ref", - "type": { - "text": "GitReference | undefined" - }, - "attribute": "ref" - }, + "kind": "function", + "name": "observe", + "parameters": [ { - "kind": "field", - "name": "size", + "name": "keys", "type": { - "text": "number" - }, - "default": "16", - "attribute": "size" + "text": "keyof T | (keyof T)[]" + } }, { - "kind": "field", - "name": "worktree", + "name": "options", + "optional": true, "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "worktree" + "text": "{ afterFirstUpdate?: boolean }" + } } - ], - "attributes": [ - { - "name": "disabled", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "disabled" - }, - { - "name": "href", - "type": { - "text": "string | undefined" - }, - "fieldName": "href" - }, - { - "name": "icon", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "icon" - }, + ] + }, + { + "kind": "class", + "description": "", + "name": "GlElement", + "members": [ { - "name": "ref", - "type": { - "text": "GitReference | undefined" + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } }, - "fieldName": "ref" + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ] }, { - "name": "size", - "type": { - "text": "number" + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } }, - "default": "16", - "fieldName": "size" + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "optional": true, + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ] }, { - "name": "worktree", - "type": { - "text": "boolean" + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } }, - "default": "false", - "fieldName": "worktree" + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ] } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-ref-button", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlRefButton", + "name": "observe", "declaration": { - "name": "GlRefButton", - "module": "src/webviews/apps/shared/components/ref-button.ts" + "name": "observe", + "module": "src/webviews/apps/shared/components/element.ts" } }, { - "kind": "custom-element-definition", - "name": "gl-ref-button", + "kind": "js", + "name": "GlElement", "declaration": { - "name": "GlRefButton", - "module": "src/webviews/apps/shared/components/ref-button.ts" + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/ref-name.ts", + "path": "src/webviews/apps/shared/components/feature-badge.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlRefName", + "name": "GlFeatureBadge", "members": [ { "kind": "field", - "name": "icon", + "name": "cloud", "type": { "text": "boolean" }, "default": "false", - "attribute": "icon", - "reflects": true + "attribute": "cloud" }, { "kind": "field", - "name": "ref", + "name": "placement", "type": { - "text": "GitReference | undefined" + "text": "GlPopover['placement']" }, - "attribute": "ref" + "default": "'bottom'", + "attribute": "placement", + "reflects": true }, { "kind": "field", - "name": "size", + "name": "preview", "type": { - "text": "number" + "text": "boolean" }, - "default": "13", - "attribute": "size" + "default": "false", + "attribute": "preview" }, { "kind": "field", - "name": "worktree", + "name": "promos", "type": { - "text": "boolean" + "text": "PromosContext" }, - "default": "false", - "attribute": "worktree" + "privacy": "private" + }, + { + "kind": "field", + "name": "source", + "type": { + "text": "Source | undefined" + }, + "attribute": "source" + }, + { + "kind": "field", + "name": "subscription", + "type": { + "text": "Subscription | undefined" + } + }, + { + "kind": "field", + "name": "daysRemaining", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "state", + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "renderBadge", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderPopoverHeader", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderPopoverContent", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderStartTrialActions", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderUpgradeActions", + "privacy": "private", + "parameters": [ + { + "name": "leadin", + "optional": true, + "type": { + "text": "TemplateResult" + } + } + ] + }, + { + "kind": "method", + "name": "renderPromo", + "privacy": "private" } ], "attributes": [ { - "name": "icon", + "name": "cloud", "type": { "text": "boolean" }, "default": "false", - "fieldName": "icon" + "fieldName": "cloud" }, { - "name": "ref", + "name": "placement", "type": { - "text": "GitReference | undefined" + "text": "GlPopover['placement']" }, - "fieldName": "ref" + "default": "'bottom'", + "fieldName": "placement" }, { - "name": "size", + "name": "preview", "type": { - "text": "number" + "text": "boolean" }, - "default": "13", - "fieldName": "size" + "default": "false", + "fieldName": "preview" }, { - "name": "worktree", + "name": "source", "type": { - "text": "boolean" + "text": "Source | undefined" }, - "default": "false", - "fieldName": "worktree" + "fieldName": "source" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-ref-name", + "tagName": "gl-feature-badge", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlRefName", + "name": "GlFeatureBadge", "declaration": { - "name": "GlRefName", - "module": "src/webviews/apps/shared/components/ref-name.ts" + "name": "GlFeatureBadge", + "module": "src/webviews/apps/shared/components/feature-badge.ts" } }, { "kind": "custom-element-definition", - "name": "gl-ref-name", - "declaration": { - "name": "GlRefName", - "module": "src/webviews/apps/shared/components/ref-name.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/ref.css.ts", - "declarations": [ - { - "kind": "variable", - "name": "refButtonBaseStyles", - "default": "css` :host { box-sizing: border-box; display: flex; align-items: center; max-width: 100%; min-width: 4.6rem; } * { box-sizing: border-box; } `" - }, - { - "kind": "variable", - "name": "pickerIconStyles", - "default": "css` code-icon.picker-icon { font-size: 1rem; /* margin-top: 0.4rem; */ margin-right: -0.25rem; } code-icon.picker-icon::before { margin-left: -0.4rem; } `" - }, - { - "kind": "variable", - "name": "truncatedButtonStyles", - "default": "css` .truncated-button { max-width: 100%; min-width: 4rem; } gl-button[disabled] { opacity: 1; cursor: default; } .truncated-button__label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } `" - } - ], - "exports": [ - { - "kind": "js", - "name": "refButtonBaseStyles", - "declaration": { - "name": "refButtonBaseStyles", - "module": "src/webviews/apps/shared/components/ref.css.ts" - } - }, - { - "kind": "js", - "name": "pickerIconStyles", - "declaration": { - "name": "pickerIconStyles", - "module": "src/webviews/apps/shared/components/ref.css.ts" - } - }, - { - "kind": "js", - "name": "truncatedButtonStyles", + "name": "gl-feature-badge", "declaration": { - "name": "truncatedButtonStyles", - "module": "src/webviews/apps/shared/components/ref.css.ts" + "name": "GlFeatureBadge", + "module": "src/webviews/apps/shared/components/feature-badge.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/repo-button-group.ts", + "path": "src/webviews/apps/shared/components/feature-gate.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlRepoButtonGroup", + "name": "GlFeatureGate", "members": [ { "kind": "field", - "name": "connectIcon", - "type": { - "text": "boolean" - }, - "default": "true", - "attribute": "connectIcon" - }, - { - "kind": "field", - "name": "disabled", + "name": "appearance", "type": { - "text": "boolean" + "text": "'alert' | 'welcome' | undefined" }, - "default": "false", - "attribute": "disabled" + "attribute": "appearance", + "reflects": true }, { "kind": "field", - "name": "icon", + "name": "featurePreview", "type": { - "text": "boolean" + "text": "FeaturePreview | undefined" }, - "default": "true", - "attribute": "icon" + "attribute": "featurePreview" }, { "kind": "field", - "name": "repository", + "name": "featurePreviewCommandLink", "type": { - "text": "RepositoryShape | undefined" + "text": "string | undefined" }, - "attribute": "repository" + "attribute": "featurePreviewCommandLink" }, { "kind": "field", - "name": "hasMultipleRepositories", + "name": "featureWithArticleIfNeeded", "type": { - "text": "boolean | undefined" + "text": "string | undefined" }, - "default": "false", - "attribute": "hasMultipleRepositories" + "attribute": "featureWithArticleIfNeeded" }, { "kind": "field", @@ -13368,114 +14452,48 @@ }, { "kind": "field", - "name": "expandable", + "name": "state", "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "expandable", - "reflects": true - }, - { - "kind": "field", - "name": "icons", - "readonly": true, - "attribute": "icons", - "reflects": true + "text": "SubscriptionState | undefined" + } }, { "kind": "field", - "name": "displayName", + "name": "webroot", "type": { - "text": "string" - }, - "privacy": "private", - "readonly": true - }, - { - "kind": "method", - "name": "renderProviderIcon", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderConnectIcon", - "privacy": "private" - }, - { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } + "text": "string | undefined" }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } + "attribute": "webroot" } ], "attributes": [ { - "name": "connectIcon", - "type": { - "text": "boolean" - }, - "default": "true", - "fieldName": "connectIcon" - }, - { - "name": "disabled", + "name": "appearance", "type": { - "text": "boolean" + "text": "'alert' | 'welcome' | undefined" }, - "default": "false", - "fieldName": "disabled" + "fieldName": "appearance" }, { - "name": "icon", + "name": "featurePreview", "type": { - "text": "boolean" + "text": "FeaturePreview | undefined" }, - "default": "true", - "fieldName": "icon" + "fieldName": "featurePreview" }, { - "name": "repository", + "name": "featurePreviewCommandLink", "type": { - "text": "RepositoryShape | undefined" + "text": "string | undefined" }, - "fieldName": "repository" + "fieldName": "featurePreviewCommandLink" }, { - "name": "hasMultipleRepositories", + "name": "featureWithArticleIfNeeded", "type": { - "text": "boolean | undefined" + "text": "string | undefined" }, - "default": "false", - "fieldName": "hasMultipleRepositories" + "fieldName": "featureWithArticleIfNeeded" }, { "name": "source", @@ -13485,1161 +14503,1170 @@ "fieldName": "source" }, { - "name": "expandable", + "name": "webroot", "type": { - "text": "boolean" + "text": "string | undefined" }, - "default": "false", - "fieldName": "expandable" - }, - { - "name": "icons", - "readonly": true, - "fieldName": "icons" + "fieldName": "webroot" } ], "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" + "name": "LitElement", + "package": "lit" }, - "tagName": "gl-repo-button-group", + "tagName": "gl-feature-gate", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlRepoButtonGroup", + "name": "GlFeatureGate", "declaration": { - "name": "GlRepoButtonGroup", - "module": "src/webviews/apps/shared/components/repo-button-group.ts" + "name": "GlFeatureGate", + "module": "src/webviews/apps/shared/components/feature-gate.ts" } }, { "kind": "custom-element-definition", - "name": "gl-repo-button-group", + "name": "gl-feature-gate", "declaration": { - "name": "GlRepoButtonGroup", - "module": "src/webviews/apps/shared/components/repo-button-group.ts" + "name": "GlFeatureGate", + "module": "src/webviews/apps/shared/components/feature-gate.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/signal-utils.ts", + "path": "src/webviews/apps/shared/components/formatted-date.ts", "declarations": [ - { - "kind": "function", - "name": "renderAsyncComputed", - "return": { - "type": { - "text": "R | undefined" - } - }, - "parameters": [ - { - "name": "v", - "type": { - "text": "AsyncComputed" - } - }, - { - "name": "{\n\t\tinitial,\n\t\tpending,\n\t\tcomplete,\n\t\terror,\n\t}", - "type": { - "text": "{\n\t\tinitial?: () => R;\n\t\tpending?: () => R;\n\t\tcomplete?: (value: T | undefined) => R;\n\t\terror?: (error: unknown) => R;\n\t}" - } - } - ] - }, { "kind": "class", "description": "", - "name": "AsyncComputedState", + "name": "FormattedDate", "members": [ { "kind": "field", - "name": "_debounce", + "name": "format", "type": { - "text": "number" + "text": "string | undefined" }, - "privacy": "private", - "default": "500" - }, - { - "kind": "field", - "name": "_invalidate", - "privacy": "private" + "attribute": "format" }, { "kind": "field", - "name": "_computed", + "name": "dateStyle", "type": { - "text": "AsyncComputed | undefined" + "text": "'relative' | 'absolute'" }, - "privacy": "private" + "default": "'relative'", + "attribute": "date-style" }, { "kind": "field", - "name": "_state", - "privacy": "private" + "name": "date", + "default": "new Date()" }, { "kind": "field", - "name": "state", + "name": "tooltip", "type": { - "text": "T | undefined" + "text": "string" }, - "readonly": true + "default": "''", + "attribute": "tooltip" }, { "kind": "field", - "name": "computed", + "name": "absoluteDate", "type": { - "text": "AsyncComputed" + "text": "string" }, "readonly": true }, - { - "kind": "method", - "name": "_runCore", - "privacy": "private" - }, { "kind": "field", - "name": "_runDebounced", + "name": "dateLabel", "type": { - "text": "Deferrable<() => void> | undefined" - }, - "privacy": "private" - }, - { - "kind": "method", - "name": "_run", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "immediate", - "default": "false" - } - ] - }, - { - "kind": "method", - "name": "run", - "return": { - "type": { - "text": "void" - } + "text": "string" }, - "parameters": [ - { - "name": "force", - "default": "false" - } - ] - }, - { - "kind": "method", - "name": "invalidate", - "return": { - "type": { - "text": "void" - } - } + "readonly": true } - ] - }, - { - "kind": "function", - "name": "signalState", - "parameters": [ + ], + "attributes": [ { - "name": "initialValue", - "optional": true, + "name": "format", "type": { - "text": "T" - } - } - ] - }, - { - "kind": "function", - "name": "signalObjectState", - "parameters": [ + "text": "string | undefined" + }, + "fieldName": "format" + }, { - "name": "initialValue", - "optional": true, + "name": "date-style", "type": { - "text": "T" - } + "text": "'relative' | 'absolute'" + }, + "default": "'relative'", + "fieldName": "dateStyle" }, { - "name": "options", - "default": "{}", + "name": "tooltip", "type": { - "text": "{ afterChange?: (target: any, value: T) => void }" - } + "text": "string" + }, + "default": "''", + "fieldName": "tooltip" } - ] + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "formatted-date", + "customElement": true } ], "exports": [ { "kind": "js", - "name": "renderAsyncComputed", + "name": "FormattedDate", "declaration": { - "name": "renderAsyncComputed", - "module": "src/webviews/apps/shared/components/signal-utils.ts" + "name": "FormattedDate", + "module": "src/webviews/apps/shared/components/formatted-date.ts" } }, { - "kind": "js", - "name": "AsyncComputedState", + "kind": "custom-element-definition", + "name": "formatted-date", "declaration": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } - }, - { - "kind": "js", - "name": "signalState", - "declaration": { - "name": "signalState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } - }, - { - "kind": "js", - "name": "signalObjectState", - "declaration": { - "name": "signalObjectState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" + "name": "FormattedDate", + "module": "src/webviews/apps/shared/components/formatted-date.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/skeleton-loader.ts", + "path": "src/webviews/apps/shared/components/gitlens-logo.ts", "declarations": [ { "kind": "class", "description": "", - "name": "SkeletonLoader", - "members": [ - { - "kind": "field", - "name": "lines", - "type": { - "text": "number" - }, - "default": "1", - "attribute": "lines" - } - ], - "attributes": [ - { - "name": "lines", - "type": { - "text": "number" - }, - "default": "1", - "fieldName": "lines" - } - ], + "name": "GitLensLogo", + "members": [], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "skeleton-loader", + "tagName": "gitlens-logo", "customElement": true } ], "exports": [ { "kind": "js", - "name": "SkeletonLoader", + "name": "GitLensLogo", "declaration": { - "name": "SkeletonLoader", - "module": "src/webviews/apps/shared/components/skeleton-loader.ts" + "name": "GitLensLogo", + "module": "src/webviews/apps/shared/components/gitlens-logo.ts" } }, { "kind": "custom-element-definition", - "name": "skeleton-loader", + "name": "gitlens-logo", "declaration": { - "name": "SkeletonLoader", - "module": "src/webviews/apps/shared/components/skeleton-loader.ts" + "name": "GitLensLogo", + "module": "src/webviews/apps/shared/components/gitlens-logo.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/snow.ts", + "path": "src/webviews/apps/shared/components/mcp-banner.ts", "declarations": [ + { + "kind": "variable", + "name": "mcpBannerTagName", + "type": { + "text": "string" + }, + "default": "'gl-mcp-banner'" + }, { "kind": "class", "description": "", - "name": "GlSnow", + "name": "GlMcpBanner", "members": [ { "kind": "field", - "name": "snowing", + "name": "shadowRootOptions", "type": { - "text": "boolean" + "text": "ShadowRootInit" }, - "default": "false", - "attribute": "snowing", - "reflects": true + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" }, { "kind": "field", - "name": "_canvas", + "name": "source", "type": { - "text": "HTMLCanvasElement | undefined" + "text": "string" }, - "privacy": "private" + "default": "'unknown'", + "attribute": "source" }, { "kind": "field", - "name": "_ctx", + "name": "layout", "type": { - "text": "CanvasRenderingContext2D | undefined" + "text": "'default' | 'responsive'" }, - "privacy": "private" + "default": "'default'", + "attribute": "layout" }, { "kind": "field", - "name": "_snowflakes", + "name": "collapsed", "type": { - "text": "Snowflake[]" + "text": "boolean" }, - "privacy": "private", - "default": "[]" + "default": "false", + "attribute": "collapsed" }, { "kind": "field", - "name": "_animationFrame", + "name": "canAutoRegister", "type": { - "text": "number | undefined" + "text": "boolean" }, - "privacy": "private" - }, + "privacy": "private", + "default": "false", + "attribute": "canAutoRegister" + } + ], + "attributes": [ { - "kind": "field", - "name": "_resizeObserver", + "name": "source", "type": { - "text": "ResizeObserver | undefined" + "text": "string" }, - "privacy": "private" - }, - { - "kind": "method", - "name": "renderToggle", - "privacy": "private" + "default": "'unknown'", + "fieldName": "source" }, { - "kind": "method", - "name": "onToggle", - "privacy": "private", - "return": { - "type": { - "text": "void" - } + "name": "layout", + "type": { + "text": "'default' | 'responsive'" }, - "parameters": [ - { - "name": "snowing", - "type": { - "text": "boolean" - } - } - ] - }, - { - "kind": "method", - "name": "updateCanvasSize", - "privacy": "private", - "return": { - "type": { - "text": "void" - } - } - }, - { - "kind": "method", - "name": "clear", - "privacy": "private", - "return": { - "type": { - "text": "void" - } - } + "default": "'default'", + "fieldName": "layout" }, { - "kind": "method", - "name": "createSnowflakes", - "privacy": "private", - "return": { - "type": { - "text": "void" - } - } + "name": "collapsed", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "collapsed" }, { - "kind": "method", - "name": "updateAnimation", - "privacy": "private", - "return": { - "type": { - "text": "void" - } - } - } - ], - "attributes": [ - { - "name": "snowing", + "name": "canAutoRegister", "type": { "text": "boolean" }, "default": "false", - "fieldName": "snowing" + "fieldName": "canAutoRegister" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-snow", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlSnow", + "name": "mcpBannerTagName", "declaration": { - "name": "GlSnow", - "module": "src/webviews/apps/shared/components/snow.ts" + "name": "mcpBannerTagName", + "module": "src/webviews/apps/shared/components/mcp-banner.ts" + } + }, + { + "kind": "js", + "name": "GlMcpBanner", + "declaration": { + "name": "GlMcpBanner", + "module": "src/webviews/apps/shared/components/mcp-banner.ts" } }, { "kind": "custom-element-definition", - "name": "gl-snow", "declaration": { - "name": "GlSnow", - "module": "src/webviews/apps/shared/components/snow.ts" + "name": "GlMcpBanner", + "module": "src/webviews/apps/shared/components/mcp-banner.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/webview-pane.ts", + "path": "src/webviews/apps/shared/components/progress.ts", "declarations": [ { "kind": "class", "description": "", - "name": "WebviewPane", + "name": "ProgressIndicator", "members": [ { "kind": "field", - "name": "collapsable", + "name": "mode", "type": { - "text": "boolean" + "text": "string" }, - "default": "false", - "attribute": "collapsable", + "default": "'infinite'", + "attribute": "mode", "reflects": true }, { "kind": "field", - "name": "expanded", + "name": "active", "type": { "text": "boolean" }, "default": "false", - "attribute": "expanded", - "reflects": true + "attribute": "active" }, { "kind": "field", - "name": "loading", + "name": "position", "type": { - "text": "boolean" + "text": "'top' | 'bottom'" }, - "default": "false", - "attribute": "loading", - "reflects": true - }, - { - "kind": "method", - "name": "renderTitle", - "privacy": "private" - }, - { - "kind": "method", - "name": "toggleExpanded", - "privacy": "private" - } - ], - "events": [ - { - "name": "expanded-change", - "type": { - "text": "CustomEvent" - } + "default": "'bottom'", + "attribute": "position" } ], "attributes": [ { - "name": "collapsable", + "name": "mode", "type": { - "text": "boolean" + "text": "string" }, - "default": "false", - "fieldName": "collapsable" + "default": "'infinite'", + "fieldName": "mode" }, { - "name": "expanded", + "name": "active", "type": { "text": "boolean" }, "default": "false", - "fieldName": "expanded" + "fieldName": "active" }, { - "name": "loading", + "name": "position", "type": { - "text": "boolean" + "text": "'top' | 'bottom'" }, - "default": "false", - "fieldName": "loading" + "default": "'bottom'", + "fieldName": "position" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "webview-pane", + "tagName": "progress-indicator", "customElement": true } ], "exports": [ { "kind": "js", - "name": "WebviewPane", + "name": "ProgressIndicator", "declaration": { - "name": "WebviewPane", - "module": "src/webviews/apps/shared/components/webview-pane.ts" + "name": "ProgressIndicator", + "module": "src/webviews/apps/shared/components/progress.ts" } }, { "kind": "custom-element-definition", - "name": "webview-pane", - "declaration": { - "name": "WebviewPane", - "module": "src/webviews/apps/shared/components/webview-pane.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/contexts/ipc.ts", - "declarations": [ - { - "kind": "variable", - "name": "ipcContext" - } - ], - "exports": [ - { - "kind": "js", - "name": "ipcContext", + "name": "progress-indicator", "declaration": { - "name": "ipcContext", - "module": "src/webviews/apps/shared/contexts/ipc.ts" + "name": "ProgressIndicator", + "module": "src/webviews/apps/shared/components/progress.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/contexts/logger.ts", + "path": "src/webviews/apps/shared/components/promo.ts", "declarations": [ { "kind": "class", "description": "", - "name": "LoggerContext", + "name": "GlPromo", "members": [ { "kind": "field", - "name": "scope", + "name": "shadowRootOptions", "type": { - "text": "LogScope" + "text": "ShadowRootInit" }, - "privacy": "private", - "readonly": true + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" }, { - "kind": "method", - "name": "log", - "return": { - "type": { - "text": "void" - } + "kind": "field", + "name": "_focusable", + "type": { + "text": "HTMLElement | undefined" }, - "parameters": [ - { - "name": "messageOrScope", - "type": { - "text": "string | LogScope | undefined" - } - }, - { - "name": "optionalParams", - "type": { - "text": "any[]" - } - } - ] - } - ] - }, - { - "kind": "variable", - "name": "loggerContext" - } - ], - "exports": [ - { - "kind": "js", - "name": "LoggerContext", - "declaration": { - "name": "LoggerContext", - "module": "src/webviews/apps/shared/contexts/logger.ts" - } - }, - { - "kind": "js", - "name": "loggerContext", - "declaration": { - "name": "loggerContext", - "module": "src/webviews/apps/shared/contexts/logger.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/contexts/promos.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "PromosContext", - "members": [ + "privacy": "private" + }, { "kind": "field", - "name": "ipc", + "name": "promoPromise", "type": { - "text": "HostIpc" + "text": "Promise | undefined" }, - "privacy": "private", - "readonly": true, - "default": "ipc" + "attribute": "promoPromise" }, { "kind": "field", - "name": "disposables", + "name": "source", "type": { - "text": "Disposable[]" + "text": "Source | undefined" + }, + "attribute": "source" + }, + { + "kind": "field", + "name": "type", + "type": { + "text": "'icon' | 'info' | 'link'" + }, + "default": "'info'", + "attribute": "type", + "reflects": true + }, + { + "kind": "field", + "name": "_hasPromo", + "type": { + "text": "boolean" }, "privacy": "private", - "readonly": true, - "default": "[]" + "default": "false" }, { "kind": "field", - "name": "_promos", + "name": "hasPromo", "privacy": "private", - "default": "new Map<`${PromoPlans | undefined}|${PromoLocation | undefined}`, Promise>()" + "attribute": "has-promo", + "reflects": true }, { "kind": "method", - "name": "getApplicablePromo", - "return": { - "type": { - "text": "Promise" - } - }, + "name": "renderPromo", + "privacy": "private", "parameters": [ { - "name": "plan", - "optional": true, + "name": "promo", "type": { - "text": "PromoPlans" + "text": "Promo | undefined" } - }, + } + ] + }, + { + "kind": "method", + "name": "getCommandUrl", + "privacy": "private", + "parameters": [ { - "name": "location", - "optional": true, + "name": "promo", "type": { - "text": "PromoLocation" + "text": "Promo | undefined" } } ] }, { "kind": "method", - "name": "dispose", + "name": "focus", "return": { "type": { "text": "void" } } } - ] - }, - { - "kind": "variable", - "name": "promosContext" + ], + "attributes": [ + { + "name": "promoPromise", + "type": { + "text": "Promise | undefined" + }, + "fieldName": "promoPromise" + }, + { + "name": "source", + "type": { + "text": "Source | undefined" + }, + "fieldName": "source" + }, + { + "name": "type", + "type": { + "text": "'icon' | 'info' | 'link'" + }, + "default": "'info'", + "fieldName": "type" + }, + { + "name": "has-promo", + "fieldName": "hasPromo" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-promo", + "customElement": true } ], "exports": [ { "kind": "js", - "name": "PromosContext", + "name": "GlPromo", "declaration": { - "name": "PromosContext", - "module": "src/webviews/apps/shared/contexts/promos.ts" + "name": "GlPromo", + "module": "src/webviews/apps/shared/components/promo.ts" } }, { - "kind": "js", - "name": "promosContext", + "kind": "custom-element-definition", + "name": "gl-promo", "declaration": { - "name": "promosContext", - "module": "src/webviews/apps/shared/contexts/promos.ts" + "name": "GlPromo", + "module": "src/webviews/apps/shared/components/promo.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/contexts/telemetry.ts", + "path": "src/webviews/apps/shared/components/ref-button.ts", "declarations": [ { "kind": "class", "description": "", - "name": "TelemetryContext", + "name": "GlRefButton", "members": [ { "kind": "field", - "name": "ipc", + "name": "disabled", "type": { - "text": "HostIpc" + "text": "boolean" }, - "privacy": "private", - "readonly": true, - "default": "ipc" + "default": "false", + "attribute": "disabled", + "reflects": true }, { "kind": "field", - "name": "disposables", + "name": "href", "type": { - "text": "Disposable[]" + "text": "string | undefined" }, - "privacy": "private", - "readonly": true, - "default": "[]" + "attribute": "href", + "reflects": true }, { - "kind": "method", - "name": "sendEvent", - "return": { - "type": { - "text": "void" - } + "kind": "field", + "name": "icon", + "type": { + "text": "boolean" }, - "parameters": [ - { - "name": "detail", - "type": { - "text": "TelemetrySendEventParams" - } - } - ] + "default": "false", + "attribute": "icon", + "reflects": true }, { - "kind": "method", - "name": "dispose", - "return": { - "type": { - "text": "void" - } - } + "kind": "field", + "name": "ref", + "type": { + "text": "GitReference | undefined" + }, + "attribute": "ref" + }, + { + "kind": "field", + "name": "size", + "type": { + "text": "number" + }, + "default": "16", + "attribute": "size" + }, + { + "kind": "field", + "name": "worktree", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "worktree" } - ] - }, - { - "kind": "variable", - "name": "telemetryContext" + ], + "attributes": [ + { + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "disabled" + }, + { + "name": "href", + "type": { + "text": "string | undefined" + }, + "fieldName": "href" + }, + { + "name": "icon", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "icon" + }, + { + "name": "ref", + "type": { + "text": "GitReference | undefined" + }, + "fieldName": "ref" + }, + { + "name": "size", + "type": { + "text": "number" + }, + "default": "16", + "fieldName": "size" + }, + { + "name": "worktree", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "worktree" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-ref-button", + "customElement": true } ], "exports": [ { "kind": "js", - "name": "TelemetryContext", + "name": "GlRefButton", "declaration": { - "name": "TelemetryContext", - "module": "src/webviews/apps/shared/contexts/telemetry.ts" + "name": "GlRefButton", + "module": "src/webviews/apps/shared/components/ref-button.ts" } }, { - "kind": "js", - "name": "telemetryContext", + "kind": "custom-element-definition", + "name": "gl-ref-button", "declaration": { - "name": "telemetryContext", - "module": "src/webviews/apps/shared/contexts/telemetry.ts" + "name": "GlRefButton", + "module": "src/webviews/apps/shared/components/ref-button.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/patchDetails/components/gl-draft-details.ts", + "path": "src/webviews/apps/shared/components/ref-name.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlDraftDetails", + "name": "GlRefName", "members": [ { "kind": "field", - "name": "state", + "name": "icon", "type": { - "text": "State" + "text": "boolean" }, - "attribute": "state" + "default": "false", + "attribute": "icon", + "reflects": true }, { "kind": "field", - "name": "explainBusy", + "name": "ref", "type": { - "text": "boolean" + "text": "GitReference | undefined" }, - "default": "false" + "attribute": "ref" }, { "kind": "field", - "name": "explain", + "name": "size", "type": { - "text": "ExplainState | undefined" + "text": "number" }, - "attribute": "explain" + "default": "13", + "attribute": "size" }, { "kind": "field", - "name": "selectedPatches", + "name": "worktree", "type": { - "text": "string[]" + "text": "boolean" }, - "default": "[]" - }, + "default": "false", + "attribute": "worktree" + } + ], + "attributes": [ { - "kind": "field", - "name": "validityMessage", + "name": "icon", "type": { - "text": "string | undefined" - } + "text": "boolean" + }, + "default": "false", + "fieldName": "icon" }, { - "kind": "field", - "name": "_copiedLink", + "name": "ref", "type": { - "text": "boolean" + "text": "GitReference | undefined" }, - "privacy": "private", - "default": "false" + "fieldName": "ref" }, { - "kind": "field", - "name": "cloudDraft", - "readonly": true + "name": "size", + "type": { + "text": "number" + }, + "default": "13", + "fieldName": "size" }, + { + "name": "worktree", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "worktree" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-ref-name", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlRefName", + "declaration": { + "name": "GlRefName", + "module": "src/webviews/apps/shared/components/ref-name.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-ref-name", + "declaration": { + "name": "GlRefName", + "module": "src/webviews/apps/shared/components/ref-name.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/ref.css.ts", + "declarations": [ + { + "kind": "variable", + "name": "refButtonBaseStyles", + "default": "css` :host { box-sizing: border-box; display: flex; align-items: center; max-width: 100%; min-width: 4.6rem; } * { box-sizing: border-box; } `" + }, + { + "kind": "variable", + "name": "pickerIconStyles", + "default": "css` code-icon.picker-icon { font-size: 1rem; /* margin-top: 0.4rem; */ margin-right: -0.25rem; } code-icon.picker-icon::before { margin-left: -0.4rem; } `" + }, + { + "kind": "variable", + "name": "truncatedButtonStyles", + "default": "css` .truncated-button { max-width: 100%; min-width: 4rem; } gl-button[disabled] { opacity: 1; cursor: default; } .truncated-button__label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "refButtonBaseStyles", + "declaration": { + "name": "refButtonBaseStyles", + "module": "src/webviews/apps/shared/components/ref.css.ts" + } + }, + { + "kind": "js", + "name": "pickerIconStyles", + "declaration": { + "name": "pickerIconStyles", + "module": "src/webviews/apps/shared/components/ref.css.ts" + } + }, + { + "kind": "js", + "name": "truncatedButtonStyles", + "declaration": { + "name": "truncatedButtonStyles", + "module": "src/webviews/apps/shared/components/ref.css.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/repo-button-group.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlRepoButtonGroup", + "members": [ { "kind": "field", - "name": "isCodeSuggestion", + "name": "connectIcon", "type": { "text": "boolean" }, - "readonly": true + "default": "true", + "attribute": "connectIcon" }, { "kind": "field", - "name": "canSubmit", + "name": "disabled", "type": { "text": "boolean" }, - "readonly": true + "default": "false", + "attribute": "disabled" }, { - "kind": "method", - "name": "renderEmptyContent", - "privacy": "private" + "kind": "field", + "name": "icon", + "type": { + "text": "boolean" + }, + "default": "true", + "attribute": "icon" }, { - "kind": "method", - "name": "renderPatchMessage", - "privacy": "private" + "kind": "field", + "name": "repository", + "type": { + "text": "RepositoryShape | undefined" + }, + "attribute": "repository" }, { - "kind": "method", - "name": "renderExplainAi", - "privacy": "private" + "kind": "field", + "name": "hasMultipleRepositories", + "type": { + "text": "boolean | undefined" + }, + "default": "false", + "attribute": "hasMultipleRepositories" }, { - "kind": "method", - "name": "renderChangedFiles", - "privacy": "private" + "kind": "field", + "name": "source", + "type": { + "text": "Source | undefined" + }, + "attribute": "source" }, { "kind": "field", - "name": "treeModel", + "name": "expandable", "type": { - "text": "TreeModel[]" + "text": "boolean" }, - "readonly": true + "default": "false", + "attribute": "expandable", + "reflects": true }, { - "kind": "method", - "name": "renderUserSelection", - "privacy": "private", - "parameters": [ - { - "name": "userSelection", - "type": { - "text": "DraftUserSelection" - } - }, - { - "name": "role", - "type": { - "text": "DraftRole" - } - } - ] + "kind": "field", + "name": "icons", + "readonly": true, + "attribute": "icons", + "reflects": true }, { - "kind": "method", - "name": "renderUserSelectionList", + "kind": "field", + "name": "displayName", + "type": { + "text": "string" + }, "privacy": "private", - "parameters": [ - { - "name": "draft", - "type": { - "text": "CloudDraftDetails" - } - }, - { - "name": "includeOwner", - "default": "false" - } - ] - }, - { - "kind": "method", - "name": "renderPatchPermissions", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderCodeSuggectionActions", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderPatches", - "privacy": "private" + "readonly": true }, { "kind": "method", - "name": "renderActionbar", + "name": "renderProviderIcon", "privacy": "private" }, { "kind": "method", - "name": "renderDraftInfo", + "name": "renderConnectIcon", "privacy": "private" }, { "kind": "method", - "name": "onInviteUsers", - "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "Event" - } + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" } - ] - }, - { - "kind": "method", - "name": "onChangeSelectionRole", - "privacy": "private", + }, "parameters": [ { - "name": "e", + "name": "name", "type": { - "text": "MouseEvent" + "text": "T" } }, { - "name": "selection", + "name": "detail", "type": { - "text": "DraftUserSelection" + "text": "CustomEventDetailType" } }, { - "name": "role", + "name": "options", + "optional": true, "type": { - "text": "PatchDetailsUpdateSelectionEventDetail['role']" + "text": "Omit>, 'detail'>" } } - ] - }, + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "attributes": [ { - "kind": "method", - "name": "onVisibilityChange", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "Event" - } - } - ] + "name": "connectIcon", + "type": { + "text": "boolean" + }, + "default": "true", + "fieldName": "connectIcon" }, { - "kind": "method", - "name": "onUpdatePatch", - "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "Event" - } - } - ] + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "disabled" }, { - "kind": "method", - "name": "onExplainChanges", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "MouseEvent | KeyboardEvent" - } - } - ] + "name": "icon", + "type": { + "text": "boolean" + }, + "default": "true", + "fieldName": "icon" }, { - "kind": "method", - "name": "onTreeItemActionClicked", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } + "name": "repository", + "type": { + "text": "RepositoryShape | undefined" }, - "parameters": [ - { - "name": "e", - "type": { - "text": "CustomEvent" - } - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + "fieldName": "repository" }, { - "kind": "method", - "name": "fireFileEvent", - "return": { - "type": { - "text": "void" - } + "name": "hasMultipleRepositories", + "type": { + "text": "boolean | undefined" }, - "parameters": [ - { - "name": "name", - "type": { - "text": "string" - } - }, - { - "name": "file", - "type": { - "text": "DraftPatchFileChange" - } - }, - { - "name": "showOptions", - "optional": true, - "type": { - "text": "TextDocumentShowOptions" - } - } - ] + "default": "false", + "fieldName": "hasMultipleRepositories" }, { - "kind": "method", - "name": "onCompareWorking", + "name": "source", + "type": { + "text": "Source | undefined" + }, + "fieldName": "source" + }, + { + "name": "expandable", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "expandable" + }, + { + "name": "icons", + "readonly": true, + "fieldName": "icons" + } + ], + "superclass": { + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" + }, + "tagName": "gl-repo-button-group", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlRepoButtonGroup", + "declaration": { + "name": "GlRepoButtonGroup", + "module": "src/webviews/apps/shared/components/repo-button-group.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-repo-button-group", + "declaration": { + "name": "GlRepoButtonGroup", + "module": "src/webviews/apps/shared/components/repo-button-group.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/signal-utils.ts", + "declarations": [ + { + "kind": "function", + "name": "renderAsyncComputed", + "return": { + "type": { + "text": "R | undefined" + } + }, + "parameters": [ + { + "name": "v", + "type": { + "text": "AsyncComputed" + } + }, + { + "name": "{\n\t\tinitial,\n\t\tpending,\n\t\tcomplete,\n\t\terror,\n\t}", + "type": { + "text": "{\n\t\tinitial?: () => R;\n\t\tpending?: () => R;\n\t\tcomplete?: (value: T | undefined) => R;\n\t\terror?: (error: unknown) => R;\n\t}" + } + } + ] + }, + { + "kind": "class", + "description": "", + "name": "AsyncComputedState", + "members": [ + { + "kind": "field", + "name": "_debounce", + "type": { + "text": "number" + }, "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "CustomEvent" - } - } - ] + "default": "500" + }, + { + "kind": "field", + "name": "_invalidate", + "privacy": "private" + }, + { + "kind": "field", + "name": "_computed", + "type": { + "text": "AsyncComputed | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_state", + "privacy": "private" + }, + { + "kind": "field", + "name": "state", + "type": { + "text": "T | undefined" + }, + "readonly": true + }, + { + "kind": "field", + "name": "computed", + "type": { + "text": "AsyncComputed" + }, + "readonly": true }, { "kind": "method", - "name": "onOpenFile", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "CustomEvent" - } - } - ] + "name": "_runCore", + "privacy": "private" + }, + { + "kind": "field", + "name": "_runDebounced", + "type": { + "text": "Deferrable<() => void> | undefined" + }, + "privacy": "private" }, { "kind": "method", - "name": "onTreeItemChecked", + "name": "_run", "privacy": "protected", "return": { "type": { @@ -14648,21 +15675,14 @@ }, "parameters": [ { - "name": "e", - "type": { - "text": "CustomEvent" - } + "name": "immediate", + "default": "false" } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "onTreeItemSelected", - "privacy": "protected", + "name": "run", "return": { "type": { "text": "void" @@ -14670,745 +15690,467 @@ }, "parameters": [ { - "name": "e", - "type": { - "text": "CustomEvent" - } + "name": "force", + "default": "false" } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "onApplyPatch", - "privacy": "private", - "parameters": [ - { - "name": "_e", - "optional": true, - "type": { - "text": "MouseEvent | KeyboardEvent" - } - }, - { - "name": "target", - "default": "'current'", - "type": { - "text": "'current' | 'branch' | 'worktree'" - } + "name": "invalidate", + "return": { + "type": { + "text": "void" } - ] + } + } + ] + }, + { + "kind": "function", + "name": "signalState", + "parameters": [ + { + "name": "initialValue", + "optional": true, + "type": { + "text": "T" + } }, { - "kind": "method", - "name": "onArchiveDraft", - "privacy": "private", - "parameters": [ - { - "name": "reason", - "type": { - "text": "DraftReasonEventDetail['reason']" - } - } - ] + "name": "options", + "optional": true, + "type": { + "text": "{ afterChange?: (target: any, value: T) => void }" + } + } + ] + }, + { + "kind": "function", + "name": "signalObjectState", + "parameters": [ + { + "name": "initialValue", + "optional": true, + "type": { + "text": "T" + } }, { - "kind": "method", - "name": "onSelectApplyOption", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "CustomEvent<{ target: MenuItem }>" - } - } - ] + "name": "options", + "optional": true, + "type": { + "text": "{ afterChange?: (target: any, value: T) => void }" + } + } + ] + } + ], + "exports": [ + { + "kind": "js", + "name": "renderAsyncComputed", + "declaration": { + "name": "renderAsyncComputed", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "js", + "name": "AsyncComputedState", + "declaration": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "js", + "name": "signalState", + "declaration": { + "name": "signalState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "js", + "name": "signalObjectState", + "declaration": { + "name": "signalObjectState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/skeleton-loader.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "SkeletonLoader", + "members": [ + { + "kind": "field", + "name": "lines", + "type": { + "text": "number" + }, + "default": "1", + "attribute": "lines" + } + ], + "attributes": [ + { + "name": "lines", + "type": { + "text": "number" + }, + "default": "1", + "fieldName": "lines" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "skeleton-loader", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "SkeletonLoader", + "declaration": { + "name": "SkeletonLoader", + "module": "src/webviews/apps/shared/components/skeleton-loader.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "skeleton-loader", + "declaration": { + "name": "SkeletonLoader", + "module": "src/webviews/apps/shared/components/skeleton-loader.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/snow.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlSnow", + "members": [ + { + "kind": "field", + "name": "snowing", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "snowing", + "reflects": true }, { - "kind": "method", - "name": "onChangePatchBase", - "privacy": "private", - "parameters": [ - { - "name": "_e", - "optional": true, - "type": { - "text": "MouseEvent | KeyboardEvent" - } - } - ] + "kind": "field", + "name": "_canvas", + "type": { + "text": "HTMLCanvasElement | undefined" + }, + "privacy": "private" }, { - "kind": "method", - "name": "onSelectPatchRepo", - "privacy": "private", - "parameters": [ - { - "name": "_e", - "optional": true, - "type": { - "text": "MouseEvent | KeyboardEvent" - } - } - ] + "kind": "field", + "name": "_ctx", + "type": { + "text": "CanvasRenderingContext2D | undefined" + }, + "privacy": "private" }, { - "kind": "method", - "name": "onShowInGraph", + "kind": "field", + "name": "_snowflakes", + "type": { + "text": "Snowflake[]" + }, "privacy": "private", - "parameters": [ - { - "name": "_e", - "optional": true, - "type": { - "text": "MouseEvent | KeyboardEvent" - } - } - ] + "default": "[]" }, { - "kind": "method", - "name": "onCopyCloudLink", + "kind": "field", + "name": "_animationFrame", + "type": { + "text": "number | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_resizeObserver", + "type": { + "text": "ResizeObserver | undefined" + }, "privacy": "private" }, { "kind": "method", - "name": "onShareLocalPatch", + "name": "renderToggle", "privacy": "private" }, { "kind": "method", - "name": "draftPatchToTreeModel", + "name": "onToggle", + "privacy": "private", "return": { "type": { - "text": "TreeModel" + "text": "void" } }, "parameters": [ { - "name": "patch", - "type": { - "text": "NonNullable[0]" - } - }, - { - "name": "isTree", - "default": "false" - }, - { - "name": "compact", - "default": "true" - }, - { - "name": "options", - "optional": true, + "name": "snowing", "type": { - "text": "Partial" + "text": "boolean" } } ] }, { "kind": "method", - "name": "getFileActions", - "privacy": "protected", + "name": "updateCanvasSize", + "privacy": "private", "return": { "type": { - "text": "{ icon: string; label: string; action: string }[]" + "text": "void" } - }, - "parameters": [ - { - "name": "_file", - "type": { - "text": "DraftPatchFileChange" - } - }, - { - "name": "_options", - "optional": true, - "type": { - "text": "Partial" - } - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } - }, - { - "kind": "method", - "name": "renderLoading", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult" - } - }, - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } - }, - { - "kind": "method", - "name": "renderLayoutAction", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | typeof nothing" - } - }, - "parameters": [ - { - "name": "layout", - "type": { - "text": "string" - } - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } - }, - { - "kind": "method", - "name": "renderTreeView", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult" - } - }, - "parameters": [ - { - "name": "treeModel", - "type": { - "text": "TreeModel[]" - } - }, - { - "name": "guides", - "default": "'none'", - "type": { - "text": "'none' | 'onHover' | 'always'" - } - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } - }, - { - "kind": "method", - "name": "renderFiles", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel[]" - } - }, - "parameters": [ - { - "name": "files", - "type": { - "text": "GitFileChangeShape[]" - } - }, - { - "name": "isTree", - "default": "false" - }, - { - "name": "compact", - "default": "false" - }, - { - "name": "level", - "default": "2" - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } - }, - { - "kind": "method", - "name": "walkFileTree", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, - "parameters": [ - { - "name": "item", - "type": { - "text": "HierarchicalItem" - } - }, - { - "name": "options", - "default": "{ level: 1 }", - "type": { - "text": "Partial" - } - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } - }, - { - "kind": "method", - "name": "folderToTreeModel", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "string" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Partial" - } - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } - }, - { - "kind": "method", - "name": "getRepoActions", - "privacy": "protected", - "return": { - "type": { - "text": "TreeItemAction[]" - } - }, - "parameters": [ - { - "name": "_name", - "type": { - "text": "string" - } - }, - { - "name": "_path", - "type": { - "text": "string" - } - }, - { - "name": "_options", - "optional": true, - "type": { - "text": "Partial" - } - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } - }, - { - "kind": "method", - "name": "emptyTreeModel", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "string" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Partial" - } - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" } }, { "kind": "method", - "name": "repoToTreeModel", - "privacy": "protected", + "name": "clear", + "privacy": "private", "return": { "type": { - "text": "TreeModel" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "string" - } - }, - { - "name": "path", - "type": { - "text": "string" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Partial" - } - }, - { - "name": "description", - "optional": true, - "type": { - "text": "string" - } + "text": "void" } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" } }, { "kind": "method", - "name": "fileToTreeModel", - "privacy": "protected", + "name": "createSnowflakes", + "privacy": "private", "return": { "type": { - "text": "TreeModel" - } - }, - "parameters": [ - { - "name": "file", - "type": { - "text": "GitFileChangeShape" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Partial" - } - }, - { - "name": "flat", - "default": "false" - }, - { - "name": "glue", - "default": "'/'" + "text": "void" } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" } }, { "kind": "method", - "name": "emit", + "name": "updateAnimation", + "privacy": "private", "return": { "type": { - "text": "CustomEventType" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } + "text": "void" } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" } } ], "attributes": [ { - "name": "state", - "type": { - "text": "State" - }, - "fieldName": "state" - }, - { - "name": "explain", + "name": "snowing", "type": { - "text": "ExplainState | undefined" + "text": "boolean" }, - "fieldName": "explain" + "default": "false", + "fieldName": "snowing" } ], "superclass": { - "name": "GlTreeBase", - "module": "/src/webviews/apps/plus/patchDetails/components/gl-tree-base" + "name": "LitElement", + "package": "lit" }, - "tagName": "gl-draft-details", + "tagName": "gl-snow", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlDraftDetails", + "name": "GlSnow", "declaration": { - "name": "GlDraftDetails", - "module": "src/webviews/apps/plus/patchDetails/components/gl-draft-details.ts" + "name": "GlSnow", + "module": "src/webviews/apps/shared/components/snow.ts" } }, { "kind": "custom-element-definition", - "name": "gl-draft-details", + "name": "gl-snow", "declaration": { - "name": "GlDraftDetails", - "module": "src/webviews/apps/plus/patchDetails/components/gl-draft-details.ts" + "name": "GlSnow", + "module": "src/webviews/apps/shared/components/snow.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/patchDetails/components/gl-patch-create.ts", + "path": "src/webviews/apps/shared/components/webview-pane.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlPatchCreate", + "name": "WebviewPane", "members": [ { "kind": "field", - "name": "state", - "type": { - "text": "Serialized | undefined" - }, - "attribute": "state" - }, - { - "kind": "field", - "name": "review", + "name": "collapsable", "type": { "text": "boolean" }, "default": "false", - "attribute": "review" - }, - { - "kind": "field", - "name": "generate", - "type": { - "text": "GenerateState | undefined" - }, - "attribute": "generate" + "attribute": "collapsable", + "reflects": true }, { "kind": "field", - "name": "generateBusy", + "name": "expanded", "type": { "text": "boolean" }, - "default": "false" + "default": "false", + "attribute": "expanded", + "reflects": true }, { "kind": "field", - "name": "creationBusy", + "name": "loading", "type": { "text": "boolean" }, - "default": "false" - }, - { - "kind": "field", - "name": "titleInput", - "type": { - "text": "HTMLInputElement" - } + "default": "false", + "attribute": "loading", + "reflects": true }, { - "kind": "field", - "name": "descInput", - "type": { - "text": "HTMLInputElement" - } + "kind": "method", + "name": "renderTitle", + "privacy": "private" }, { - "kind": "field", - "name": "generateAiButton", - "type": { - "text": "HTMLElement" - } - }, + "kind": "method", + "name": "toggleExpanded", + "privacy": "private" + } + ], + "events": [ { - "kind": "field", - "name": "validityMessage", + "name": "expanded-change", "type": { - "text": "string | undefined" + "text": "CustomEvent" } - }, - { - "kind": "field", - "name": "create", - "type": { - "text": "NonNullable" - }, - "readonly": true - }, - { - "kind": "field", - "name": "createChanges", - "type": { - "text": "Change[]" - }, - "readonly": true - }, - { - "kind": "field", - "name": "createEntries", - "type": { - "text": "[string, Change][]" - }, - "readonly": true - }, + } + ], + "attributes": [ { - "kind": "field", - "name": "hasWipChanges", + "name": "collapsable", "type": { "text": "boolean" }, - "readonly": true - }, - { - "kind": "field", - "name": "selectedChanges", - "type": { - "text": "[string, Change][]" - }, - "readonly": true + "default": "false", + "fieldName": "collapsable" }, { - "kind": "field", - "name": "canSubmit", + "name": "expanded", "type": { "text": "boolean" }, - "readonly": true - }, - { - "kind": "field", - "name": "fileLayout", - "type": { - "text": "ViewFilesLayout" - }, - "readonly": true + "default": "false", + "fieldName": "expanded" }, { - "kind": "field", - "name": "isCompact", + "name": "loading", "type": { "text": "boolean" }, - "readonly": true - }, - { - "kind": "field", - "name": "filesModified", - "type": { - "text": "number" - }, - "readonly": true - }, - { - "kind": "field", - "name": "draftVisibility", - "type": { - "text": "DraftVisibility" - }, - "readonly": true - }, - { - "kind": "method", - "name": "renderUserSelection", - "privacy": "private", - "parameters": [ - { - "name": "userSelection", - "type": { - "text": "DraftUserSelection" - } - } - ] - }, - { - "kind": "method", - "name": "renderUserSelectionList", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderForm", - "privacy": "private" - }, + "default": "false", + "fieldName": "loading" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "webview-pane", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "WebviewPane", + "declaration": { + "name": "WebviewPane", + "module": "src/webviews/apps/shared/components/webview-pane.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "webview-pane", + "declaration": { + "name": "WebviewPane", + "module": "src/webviews/apps/shared/components/webview-pane.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/contexts/ipc.ts", + "declarations": [ + { + "kind": "variable", + "name": "ipcContext" + } + ], + "exports": [ + { + "kind": "js", + "name": "ipcContext", + "declaration": { + "name": "ipcContext", + "module": "src/webviews/apps/shared/contexts/ipc.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/contexts/logger.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "LoggerContext", + "members": [ { - "kind": "method", - "name": "renderChangedFiles", - "privacy": "private" + "kind": "field", + "name": "scope", + "type": { + "text": "LogScope" + }, + "privacy": "private", + "readonly": true }, { "kind": "method", - "name": "onTreeItemChecked", - "privacy": "protected", + "name": "log", "return": { "type": { "text": "void" @@ -15416,2209 +16158,2297 @@ }, "parameters": [ { - "name": "e", + "name": "messageOrScope", "type": { - "text": "CustomEvent" + "text": "string | LogScope | undefined" } - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } - }, - { - "kind": "method", - "name": "onTreeItemSelected", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ + }, { - "name": "e", + "name": "optionalParams", "type": { - "text": "CustomEvent" + "text": "any[]" } } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] + } + ] + }, + { + "kind": "variable", + "name": "loggerContext" + } + ], + "exports": [ + { + "kind": "js", + "name": "LoggerContext", + "declaration": { + "name": "LoggerContext", + "module": "src/webviews/apps/shared/contexts/logger.ts" + } + }, + { + "kind": "js", + "name": "loggerContext", + "declaration": { + "name": "loggerContext", + "module": "src/webviews/apps/shared/contexts/logger.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/contexts/promos.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "PromosContext", + "members": [ + { + "kind": "field", + "name": "ipc", + "type": { + "text": "HostIpc" + }, + "privacy": "private", + "readonly": true, + "default": "ipc" }, { - "kind": "method", - "name": "renderTreeViewWithModel", - "privacy": "private" + "kind": "field", + "name": "disposables", + "type": { + "text": "Disposable[]" + }, + "privacy": "private", + "readonly": true, + "default": "[]" }, { - "kind": "method", - "name": "getTreeForChange", + "kind": "field", + "name": "_promos", "privacy": "private", + "default": "new Map<`${PromoPlans | undefined}|${PromoLocation | undefined}`, Promise>()" + }, + { + "kind": "method", + "name": "getApplicablePromo", "return": { "type": { - "text": "TreeModel[] | undefined" + "text": "Promise" } }, "parameters": [ { - "name": "change", + "name": "plan", + "optional": true, "type": { - "text": "Change" + "text": "PromoPlans" } }, { - "name": "isMulti", - "default": "false" - }, - { - "name": "isTree", - "default": "false" - }, - { - "name": "compact", - "default": "true" - } - ] - }, - { - "kind": "method", - "name": "isTree", - "privacy": "private", - "parameters": [ - { - "name": "count", + "name": "location", + "optional": true, "type": { - "text": "number" + "text": "PromoLocation" } } ] }, { "kind": "method", - "name": "createPatch", - "privacy": "private" - }, + "name": "dispose", + "return": { + "type": { + "text": "void" + } + } + } + ] + }, + { + "kind": "variable", + "name": "promosContext" + } + ], + "exports": [ + { + "kind": "js", + "name": "PromosContext", + "declaration": { + "name": "PromosContext", + "module": "src/webviews/apps/shared/contexts/promos.ts" + } + }, + { + "kind": "js", + "name": "promosContext", + "declaration": { + "name": "promosContext", + "module": "src/webviews/apps/shared/contexts/promos.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/contexts/telemetry.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "TelemetryContext", + "members": [ { - "kind": "method", - "name": "onCreateAll", + "kind": "field", + "name": "ipc", + "type": { + "text": "HostIpc" + }, "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "Event" - } - } - ] + "readonly": true, + "default": "ipc" }, { - "kind": "method", - "name": "onSelectCreateOption", + "kind": "field", + "name": "disposables", + "type": { + "text": "Disposable[]" + }, "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "CustomEvent<{ target: MenuItem }>" - } - } - ] + "readonly": true, + "default": "[]" }, { "kind": "method", - "name": "getChangeForRepo", - "privacy": "private", + "name": "sendEvent", "return": { "type": { - "text": "Change | undefined" + "text": "void" } }, "parameters": [ { - "name": "repoUri", + "name": "detail", "type": { - "text": "string" + "text": "TelemetrySendEventParams" } } ] }, { "kind": "method", - "name": "onTitleInput", - "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "InputEvent" - } + "name": "dispose", + "return": { + "type": { + "text": "void" } - ] + } + } + ] + }, + { + "kind": "variable", + "name": "telemetryContext" + } + ], + "exports": [ + { + "kind": "js", + "name": "TelemetryContext", + "declaration": { + "name": "TelemetryContext", + "module": "src/webviews/apps/shared/contexts/telemetry.ts" + } + }, + { + "kind": "js", + "name": "telemetryContext", + "declaration": { + "name": "telemetryContext", + "module": "src/webviews/apps/shared/contexts/telemetry.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/composer/components/app.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "ComposerApp", + "members": [ + { + "kind": "field", + "name": "state", + "type": { + "text": "State" + } }, { "kind": "field", - "name": "onDebounceTitleInput", + "name": "_ipc", + "type": { + "text": "HostIpc" + }, "privacy": "private" }, { - "kind": "method", - "name": "onDescriptionInput", + "kind": "field", + "name": "history", + "type": { + "text": "ComposerHistory" + }, "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "InputEvent" - } - } - ] + "default": "{ resetState: null, undoStack: [], redoStack: [], }" }, { "kind": "field", - "name": "onDebounceDescriptionInput", + "name": "commitMessageDebounceTimer", + "type": { + "text": "number | undefined" + }, "privacy": "private" }, { - "kind": "method", - "name": "onInviteUsers", + "kind": "field", + "name": "commitMessageBeingEdited", + "type": { + "text": "string | null" + }, "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "Event" - } - } - ] + "default": "null" }, { - "kind": "method", - "name": "onChangeSelectionRole", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "MouseEvent" - } - }, - { - "name": "selection", - "type": { - "text": "DraftUserSelection" - } - }, - { - "name": "role", - "type": { - "text": "CreatePatchUpdateSelectionEventDetail['role']" - } - } - ] + "kind": "field", + "name": "commitsPanel", + "type": { + "text": "CommitsPanel" + } }, { - "kind": "method", - "name": "onVisibilityChange", - "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "Event" - } - } - ] + "kind": "field", + "name": "onboarding", + "type": { + "text": "Driver | undefined" + }, + "privacy": "private" }, { - "kind": "method", - "name": "onGenerateTitleClick", + "kind": "field", + "name": "selectedCommitId", + "type": { + "text": "string | null" + }, "privacy": "private", - "parameters": [ - { - "name": "_e", - "type": { - "text": "Event" - } - } - ] + "default": "null" }, { - "kind": "method", - "name": "fireMetadataUpdate", - "privacy": "private" + "kind": "field", + "name": "selectedUnassignedSection", + "type": { + "text": "'staged' | 'unstaged' | 'unassigned' | null" + }, + "privacy": "private", + "default": "null" }, { - "kind": "method", - "name": "onTreeItemActionClicked", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } + "kind": "field", + "name": "selectedCommitIds", + "type": { + "text": "Set" }, - "parameters": [ - { - "name": "e", - "type": { - "text": "CustomEvent" - } - } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + "privacy": "private", + "default": "new Set()" }, { - "kind": "method", - "name": "onOpenFile", + "kind": "field", + "name": "selectedHunkId", + "type": { + "text": "string | null" + }, "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "CustomEvent" - } - } - ] + "default": "null" }, { - "kind": "method", - "name": "onStageFile", + "kind": "field", + "name": "selectedHunkIds", + "type": { + "text": "Set" + }, "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "CustomEvent" - } - } - ] + "default": "new Set()" }, { - "kind": "method", - "name": "onUnstageFile", + "kind": "field", + "name": "customInstructions", + "type": { + "text": "string" + }, "privacy": "private", - "parameters": [ - { - "name": "e", - "type": { - "text": "CustomEvent" - } + "default": "''" + }, + { + "kind": "field", + "name": "compositionSummarySelected", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "field", + "name": "compositionFeedback", + "type": { + "text": "'helpful' | 'unhelpful' | null" + }, + "privacy": "private", + "default": "null" + }, + { + "kind": "field", + "name": "compositionSessionId", + "type": { + "text": "string | null" + }, + "privacy": "private", + "default": "null" + }, + { + "kind": "field", + "name": "currentDropTarget", + "type": { + "text": "HTMLElement | null" + }, + "privacy": "private", + "default": "null" + }, + { + "kind": "field", + "name": "lastSelectedHunkId", + "type": { + "text": "string | null" + }, + "privacy": "private", + "default": "null" + }, + { + "kind": "field", + "name": "showCommitsGeneratedModal", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "field", + "name": "onboardingStepNumber", + "type": { + "text": "number" + }, + "privacy": "private", + "default": "0" + }, + { + "kind": "field", + "name": "hunksSortable", + "type": { + "text": "Sortable | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "isDragging", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "field", + "name": "lastMouseEvent", + "type": { + "text": "MouseEvent | undefined" + }, + "privacy": "private" + }, + { + "kind": "method", + "name": "handleForcedUpdate", + "privacy": "private" + }, + { + "kind": "method", + "name": "initializeSortable", + "privacy": "private" + }, + { + "kind": "method", + "name": "initializeHunksSortable", + "privacy": "private" + }, + { + "kind": "method", + "name": "initializeAllDropZones", + "privacy": "private" + }, + { + "kind": "method", + "name": "initializeCommitDropZones", + "privacy": "private" + }, + { + "kind": "method", + "name": "createDataSnapshot", + "privacy": "private", + "return": { + "type": { + "text": "ComposerDataSnapshot" } - ] + } }, { "kind": "method", - "name": "onShowInGraph", + "name": "applyDataSnapshot", "privacy": "private", "parameters": [ { - "name": "_e", + "name": "snapshot", "type": { - "text": "CustomEvent" + "text": "ComposerDataSnapshot" } } ] }, { "kind": "method", - "name": "onCancel", + "name": "saveToHistory", "privacy": "private" }, { "kind": "method", - "name": "getFileActions", - "privacy": "protected", + "name": "initializeResetStateIfNeeded", + "privacy": "private" + }, + { + "kind": "method", + "name": "resetHistory", + "privacy": "private" + }, + { + "kind": "method", + "name": "canUndo", + "privacy": "private", "return": { "type": { - "text": "{ icon: string; label: string; action: string }[]" - } - }, - "parameters": [ - { - "name": "file", - "type": { - "text": "GitFileChangeShape" - } - }, - { - "name": "_options", - "optional": true, - "type": { - "text": "Partial" - } + "text": "boolean" } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" } }, { "kind": "method", - "name": "getRepoActions", - "privacy": "protected", + "name": "canRedo", + "privacy": "private", "return": { "type": { - "text": "{ icon: string; label: string; action: string }[]" + "text": "boolean" } - }, + } + }, + { + "kind": "method", + "name": "undo", + "privacy": "private" + }, + { + "kind": "method", + "name": "redo", + "privacy": "private" + }, + { + "kind": "method", + "name": "reset", + "privacy": "private" + }, + { + "kind": "method", + "name": "reorderCommits", + "privacy": "private", "parameters": [ { - "name": "_name", + "name": "oldIndex", "type": { - "text": "string" + "text": "number" } }, { - "name": "_path", + "name": "newIndex", "type": { - "text": "string" + "text": "number" } - }, + } + ] + }, + { + "kind": "method", + "name": "handleHunkDragStart", + "privacy": "private", + "parameters": [ { - "name": "_options", - "optional": true, + "name": "hunkIds", "type": { - "text": "Partial" + "text": "string[]" } } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "renderLoading", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult" - } - }, - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + "name": "handleHunkDragEnd", + "privacy": "private" }, { "kind": "method", - "name": "renderLayoutAction", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | typeof nothing" - } - }, + "name": "initializeDragTracking", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleHunkMove", + "privacy": "private", "parameters": [ { - "name": "layout", + "name": "hunkId", + "type": { + "text": "string" + } + }, + { + "name": "targetCommitId", "type": { "text": "string" } } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "renderTreeView", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult" - } - }, + "name": "createNewCommitWithHunks", + "privacy": "private", "parameters": [ { - "name": "treeModel", - "type": { - "text": "TreeModel[]" - } - }, - { - "name": "guides", - "default": "'none'", + "name": "hunkIds", "type": { - "text": "'none' | 'onHover' | 'always'" + "text": "string[]" } } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "renderFiles", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel[]" - } - }, + "name": "unassignHunks", + "privacy": "private", "parameters": [ { - "name": "files", + "name": "hunkIds", "type": { - "text": "GitFileChangeShape[]" + "text": "string[]" } - }, - { - "name": "isTree", - "default": "false" - }, - { - "name": "compact", - "default": "false" - }, - { - "name": "level", - "default": "2" } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "walkFileTree", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, + "name": "moveHunksToCommit", + "privacy": "private", "parameters": [ { - "name": "item", + "name": "hunkIds", "type": { - "text": "HierarchicalItem" + "text": "string[]" } }, { - "name": "options", - "default": "{ level: 1 }", + "name": "targetCommitId", "type": { - "text": "Partial" + "text": "string" } } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "folderToTreeModel", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, + "name": "moveHunkToCommit", + "privacy": "private", "parameters": [ { - "name": "name", + "name": "hunkId", "type": { "text": "string" } }, { - "name": "options", - "optional": true, + "name": "targetCommitId", "type": { - "text": "Partial" + "text": "string" } } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "emptyTreeModel", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, + "name": "createNewCommitWithHunk", + "privacy": "private", "parameters": [ { - "name": "name", + "name": "hunkId", "type": { "text": "string" } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Partial" - } } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "repoToTreeModel", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, + "name": "selectHunk", + "privacy": "private", "parameters": [ { - "name": "name", + "name": "hunkId", "type": { "text": "string" } }, { - "name": "path", + "name": "shiftKey", + "default": "false" + } + ] + }, + { + "kind": "method", + "name": "selectCommit", + "privacy": "private", + "parameters": [ + { + "name": "commitId", "type": { "text": "string" } }, { - "name": "options", - "optional": true, - "type": { - "text": "Partial" - } - }, + "name": "shiftKey", + "default": "false" + } + ] + }, + { + "kind": "method", + "name": "selectUnassignedSection", + "privacy": "private", + "parameters": [ { - "name": "description", - "optional": true, + "name": "section", "type": { - "text": "string" + "text": "'staged' | 'unstaged' | 'unassigned'" } } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "fileToTreeModel", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, + "name": "updateCommitMessage", + "privacy": "private", "parameters": [ { - "name": "file", + "name": "commitId", "type": { - "text": "GitFileChangeShape" + "text": "string" } }, { - "name": "options", - "optional": true, + "name": "message", "type": { - "text": "Partial" + "text": "string" } - }, - { - "name": "flat", - "default": "false" - }, - { - "name": "glue", - "default": "'/'" } - ], - "inheritedFrom": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" - } + ] }, { "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } + "name": "toggleCommitMessageExpanded", + "privacy": "private" + }, + { + "kind": "method", + "name": "toggleAiExplanationExpanded", + "privacy": "private" + }, + { + "kind": "method", + "name": "toggleFilesChangedExpanded", + "privacy": "private" + }, + { + "kind": "field", + "name": "autoScrollActive", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "field", + "name": "autoScrollTimer", + "type": { + "text": "number | undefined" }, + "privacy": "private" + }, + { + "kind": "field", + "name": "mouseTracker", + "privacy": "private" + }, + { + "kind": "method", + "name": "startAutoScroll", + "privacy": "private" + }, + { + "kind": "method", + "name": "stopAutoScroll", + "privacy": "private" + }, + { + "kind": "method", + "name": "performAutoScroll", + "privacy": "private", "parameters": [ { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, + "name": "mouseY", "type": { - "text": "Omit>, 'detail'>" + "text": "number" } } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } - } - ], - "attributes": [ + ] + }, { - "name": "state", + "kind": "method", + "name": "closeModal", + "privacy": "private" + }, + { + "kind": "field", + "name": "hunksWithAssignments", "type": { - "text": "Serialized | undefined" + "text": "ComposerHunk[]" }, - "fieldName": "state" + "privacy": "private", + "readonly": true }, { - "name": "review", + "kind": "field", + "name": "aiEnabled", "type": { "text": "boolean" }, - "default": "false", - "fieldName": "review" + "privacy": "private", + "readonly": true }, { - "name": "generate", + "kind": "field", + "name": "aiDisabledReason", "type": { - "text": "GenerateState | undefined" + "text": "string | null" }, - "fieldName": "generate" - } - ], - "superclass": { - "name": "GlTreeBase", - "module": "/src/webviews/apps/plus/patchDetails/components/gl-tree-base" - }, - "tagName": "gl-patch-create", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "GlPatchCreate", - "declaration": { - "name": "GlPatchCreate", - "module": "src/webviews/apps/plus/patchDetails/components/gl-patch-create.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-patch-create", - "declaration": { - "name": "GlPatchCreate", - "module": "src/webviews/apps/plus/patchDetails/components/gl-patch-create.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlTreeBase", - "members": [ + "privacy": "private", + "readonly": true + }, { - "kind": "method", - "name": "onTreeItemActionClicked", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } + "kind": "field", + "name": "canFinishAndCommit", + "type": { + "text": "boolean" }, - "parameters": [ - { - "name": "_e", - "type": { - "text": "CustomEvent" - } - } - ] + "privacy": "private", + "readonly": true }, { - "kind": "method", - "name": "onTreeItemChecked", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } + "kind": "field", + "name": "isPreviewMode", + "type": { + "text": "boolean" }, - "parameters": [ - { - "name": "_e", - "type": { - "text": "CustomEvent" - } - } - ] + "privacy": "private", + "readonly": true }, { - "kind": "method", - "name": "onTreeItemSelected", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } + "kind": "field", + "name": "canCombineCommits", + "type": { + "text": "boolean" }, - "parameters": [ - { - "name": "_e", - "type": { - "text": "CustomEvent" - } - } - ] + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "showHistoryButtons", + "type": { + "text": "boolean" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "canMoveHunks", + "type": { + "text": "boolean" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "isReadyToFinishAndCommit", + "type": { + "text": "boolean" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "canGenerateCommitsWithAI", + "type": { + "text": "boolean" + }, + "privacy": "private", + "readonly": true }, { "kind": "method", - "name": "renderLoading", - "privacy": "protected", + "name": "getEligibleHunksForAI", + "privacy": "private", "return": { "type": { - "text": "TemplateResult" + "text": "typeof this.hunksWithAssignments" } } }, { - "kind": "method", - "name": "renderLayoutAction", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | typeof nothing" - } + "kind": "field", + "name": "canEditCommitMessages", + "type": { + "text": "boolean" }, + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "canGenerateCommitMessages", + "type": { + "text": "boolean" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "finishAndCommit", + "privacy": "private" + }, + { + "kind": "method", + "name": "closeComposer", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCloseSafetyError", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleReloadComposer", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCloseLoadingError", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCloseAIOperationError", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCancelGenerateCommits", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCancelGenerateCommitMessage", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderLoadingDialogs", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderLoadingDialog", + "privacy": "private", "parameters": [ { - "name": "layout", + "name": "title", "type": { "text": "string" } - } - ] - }, - { - "kind": "method", - "name": "renderTreeView", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult" - } - }, - "parameters": [ + }, { - "name": "treeModel", + "name": "bodyText", "type": { - "text": "TreeModel[]" + "text": "string" } }, { - "name": "guides", - "default": "'none'", + "name": "onCancel", + "optional": true, "type": { - "text": "'none' | 'onHover' | 'always'" + "text": "() => void" } } ] }, { "kind": "method", - "name": "renderFiles", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel[]" - } - }, + "name": "handleGenerateCommitsWithAI", + "privacy": "private", "parameters": [ { - "name": "files", + "name": "e", "type": { - "text": "GitFileChangeShape[]" + "text": "CustomEvent" } - }, - { - "name": "isTree", - "default": "false" - }, - { - "name": "compact", - "default": "false" - }, - { - "name": "level", - "default": "2" } ] }, { "kind": "method", - "name": "walkFileTree", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, + "name": "handleAddHunksToCommit", + "privacy": "private", "parameters": [ { - "name": "item", - "type": { - "text": "HierarchicalItem" - } - }, - { - "name": "options", - "default": "{ level: 1 }", + "name": "e", "type": { - "text": "Partial" + "text": "CustomEvent" } } ] }, { "kind": "method", - "name": "folderToTreeModel", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, + "name": "handleCloseComposer", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleSelectAIModel", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleSelectCompositionSummary", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCompositionFeedbackHelpful", + "privacy": "private", "parameters": [ { - "name": "name", - "type": { - "text": "string" - } - }, - { - "name": "options", - "optional": true, + "name": "e", "type": { - "text": "Partial" + "text": "CustomEvent" } } ] }, { "kind": "method", - "name": "getRepoActions", - "privacy": "protected", - "return": { - "type": { - "text": "TreeItemAction[]" - } - }, + "name": "handleCompositionFeedbackUnhelpful", + "privacy": "private", "parameters": [ { - "name": "_name", - "type": { - "text": "string" - } - }, - { - "name": "_path", - "type": { - "text": "string" - } - }, - { - "name": "_options", - "optional": true, + "name": "e", "type": { - "text": "Partial" + "text": "CustomEvent" } } ] }, { "kind": "method", - "name": "emptyTreeModel", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, + "name": "handleCustomInstructionsChange", + "privacy": "private", "parameters": [ { - "name": "name", - "type": { - "text": "string" - } - }, - { - "name": "options", - "optional": true, + "name": "e", "type": { - "text": "Partial" + "text": "CustomEvent" } } ] }, { - "kind": "method", - "name": "repoToTreeModel", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } + "kind": "field", + "name": "detailsPanel", + "type": { + "text": "DetailsPanel" }, + "privacy": "private" + }, + { + "kind": "method", + "name": "handleFocusCommitMessage", + "privacy": "private", "parameters": [ { - "name": "name", - "type": { - "text": "string" - } - }, - { - "name": "path", - "type": { - "text": "string" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Partial" - } - }, - { - "name": "description", - "optional": true, + "name": "e", "type": { - "text": "string" + "text": "CustomEvent<{ commitId: string; checkValidity: boolean }>" } } ] }, { "kind": "method", - "name": "getFileActions", - "privacy": "protected", - "return": { - "type": { - "text": "TreeItemAction[]" - } - }, + "name": "generateCommitsWithAI", + "privacy": "private", "parameters": [ { - "name": "_file", - "type": { - "text": "GitFileChangeShape" - } - }, - { - "name": "_options", - "optional": true, + "name": "customInstructions", + "default": "''", "type": { - "text": "Partial" + "text": "string" } } ] }, { "kind": "method", - "name": "fileToTreeModel", - "privacy": "protected", - "return": { - "type": { - "text": "TreeModel" - } - }, + "name": "generateCommitMessage", + "privacy": "private", "parameters": [ { - "name": "file", - "type": { - "text": "GitFileChangeShape" - } - }, - { - "name": "options", - "optional": true, + "name": "commitId", "type": { - "text": "Partial" + "text": "string" } - }, - { - "name": "flat", - "default": "false" - }, - { - "name": "glue", - "default": "'/'" } ] }, { "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } - }, + "name": "combineSelectedCommits", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderWorkingDirectoryWarning", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderActions", + "privacy": "private" + }, + { + "kind": "method", + "name": "onRepositorySelectorClicked", + "privacy": "private", "parameters": [ { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, + "name": "e", "type": { - "text": "Omit>, 'detail'>" + "text": "CustomEvent" } } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } + ] + }, + { + "kind": "field", + "name": "onboardingSteps", + "type": { + "text": "KeyedDriveStep[]" + }, + "privacy": "private", + "default": "[ { key: `${onboardingKey}-welcome`, popover: { title: 'Welcome to Commit Composer', description: `Compose your changes into organized, meaningful commits before committing them. Use AI to automatically structure your work into draft commits with clear messages and descriptions, or commit manually.

Learn More`, }, }, { key: `${onboardingKey}-compose`, element: () => this.commitsPanel.autoComposeSection!, popover: { title: 'Auto Compose Commits with AI', description: 'Allow AI to organize your working changes into well-formed commits with clear messages and descriptions that help reviewers.

You can change which model to use and add custom instructions.', }, }, { key: `${onboardingKey}-changes`, element: () => this.commitsPanel.changesSection, popover: { title: 'Review and Compose Working Changes', description: \"Draft Commits represent what will be committed when you're finished. You can inspect changes to add commit messages and review diffs.

Coming soon: add draft commits and easily move hunks and lines between them.\", }, }, { key: `${onboardingKey}-finish`, element: () => this.commitsPanel.finishSection, popover: { title: 'Finish & Commit', description: \"Draft commits and messages will be committed when you're finished.\", }, }, ]" + }, + { + "kind": "method", + "name": "openOnboarding", + "privacy": "private" + }, + { + "kind": "method", + "name": "dismissOnboarding" + }, + { + "kind": "method", + "name": "advanceOnboardingStep" + }, + { + "kind": "method", + "name": "reduceOnboardingStep" } ], "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" - } + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-composer-app", + "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlTreeBase", + "name": "ComposerApp", "declaration": { - "name": "GlTreeBase", - "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + "name": "ComposerApp", + "module": "src/webviews/apps/plus/composer/components/app.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-composer-app", + "declaration": { + "name": "ComposerApp", + "module": "src/webviews/apps/plus/composer/components/app.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/patchDetails/components/patch-details-app.ts", + "path": "src/webviews/apps/plus/composer/components/commit-item.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlPatchDetailsApp", + "name": "CommitItem", "members": [ { "kind": "field", - "name": "state", + "name": "commitId", "type": { - "text": "State" + "text": "string" }, - "attribute": "state" + "attribute": "commitId" }, { "kind": "field", - "name": "explain", + "name": "message", "type": { - "text": "ExplainState | undefined" + "text": "string" }, - "attribute": "explain" + "attribute": "message" }, { "kind": "field", - "name": "generate", + "name": "fileCount", "type": { - "text": "GenerateState | undefined" + "text": "number" }, - "attribute": "generate" + "attribute": "fileCount" }, { "kind": "field", - "name": "app", + "name": "additions", "type": { - "text": "PatchDetailsApp | undefined" - } + "text": "number" + }, + "attribute": "additions" }, { "kind": "field", - "name": "wipChangesCount", + "name": "deletions", "type": { "text": "number" }, - "readonly": true + "attribute": "deletions" }, { "kind": "field", - "name": "wipChangeState", - "readonly": true + "name": "selected", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "selected" }, { "kind": "field", - "name": "mode", + "name": "multiSelected", "type": { - "text": "Mode" + "text": "boolean" }, - "readonly": true + "default": "false", + "attribute": "multiSelected" }, { "kind": "field", - "name": "indentPreference", + "name": "isPreviewMode", "type": { - "text": "number" + "text": "boolean" }, - "privacy": "private", - "default": "16" + "default": "false", + "attribute": "isPreviewMode" }, { - "kind": "method", - "name": "updateDocumentProperties", - "privacy": "private" + "kind": "field", + "name": "first", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "first" }, { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } + "kind": "field", + "name": "last", + "type": { + "text": "boolean" }, + "default": "false", + "attribute": "last" + }, + { + "kind": "method", + "name": "handleClick", + "privacy": "private", "parameters": [ { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, + "name": "e", "type": { - "text": "Omit>, 'detail'>" + "text": "MouseEvent | KeyboardEvent" } } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" + ] + } + ], + "events": [ + { + "name": "commit-selected", + "type": { + "text": "CustomEvent" } } ], "attributes": [ { - "name": "state", + "name": "commitId", "type": { - "text": "State" + "text": "string" }, - "fieldName": "state" + "fieldName": "commitId" }, { - "name": "explain", + "name": "message", "type": { - "text": "ExplainState | undefined" + "text": "string" }, - "fieldName": "explain" + "fieldName": "message" }, { - "name": "generate", + "name": "fileCount", "type": { - "text": "GenerateState | undefined" + "text": "number" }, - "fieldName": "generate" + "fieldName": "fileCount" + }, + { + "name": "additions", + "type": { + "text": "number" + }, + "fieldName": "additions" + }, + { + "name": "deletions", + "type": { + "text": "number" + }, + "fieldName": "deletions" + }, + { + "name": "selected", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "selected" + }, + { + "name": "multiSelected", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "multiSelected" + }, + { + "name": "isPreviewMode", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "isPreviewMode" + }, + { + "name": "first", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "first" + }, + { + "name": "last", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "last" } ], "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" + "name": "LitElement", + "package": "lit" }, - "tagName": "gl-patch-details-app", + "tagName": "gl-commit-item", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlPatchDetailsApp", + "name": "CommitItem", "declaration": { - "name": "GlPatchDetailsApp", - "module": "src/webviews/apps/plus/patchDetails/components/patch-details-app.ts" + "name": "CommitItem", + "module": "src/webviews/apps/plus/composer/components/commit-item.ts" } }, { "kind": "custom-element-definition", - "name": "gl-patch-details-app", + "name": "gl-commit-item", "declaration": { - "name": "GlPatchDetailsApp", - "module": "src/webviews/apps/plus/patchDetails/components/patch-details-app.ts" + "name": "CommitItem", + "module": "src/webviews/apps/plus/composer/components/commit-item.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/home/components/active-work.ts", + "path": "src/webviews/apps/plus/composer/components/commit-message.ts", "declarations": [ - { - "kind": "variable", - "name": "activeWorkTagName", - "type": { - "text": "string" - }, - "default": "'gl-active-work'" - }, { "kind": "class", "description": "", - "name": "GlActiveWork", + "name": "CommitMessage", "members": [ { "kind": "field", - "name": "_homeState", + "name": "shadowRootOptions", "type": { - "text": "State" + "text": "ShadowRootInit" }, - "privacy": "private" + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" }, { "kind": "field", - "name": "_activeOverviewState", + "name": "commitId", "type": { - "text": "ActiveOverviewState" + "text": "string | undefined" }, - "privacy": "private" + "attribute": "commit-id", + "reflects": true }, { "kind": "field", - "name": "repoCollapsed", + "name": "message", + "type": { + "text": "string | undefined" + }, + "attribute": "message" + }, + { + "kind": "field", + "name": "explanation", + "type": { + "text": "string | undefined" + }, + "attribute": "explanation" + }, + { + "kind": "field", + "name": "explanationLabel", + "type": { + "text": "string | undefined" + }, + "default": "'Auto-composition Summary:'", + "attribute": "explanation-label" + }, + { + "kind": "field", + "name": "placeholder", + "type": { + "text": "string" + }, + "default": "'Enter commit message...'", + "attribute": "placeholder" + }, + { + "kind": "field", + "name": "editable", "type": { "text": "boolean" }, - "privacy": "private", - "default": "true" + "default": "false", + "attribute": "editable", + "reflects": true }, { "kind": "field", - "name": "isPro", - "readonly": true + "name": "aiEnabled", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "ai-enabled", + "reflects": true + }, + { + "kind": "field", + "name": "aiDisabledReason", + "type": { + "text": "string | null" + }, + "default": "null", + "attribute": "aiDisabledReason" + }, + { + "kind": "field", + "name": "generating", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "generating", + "reflects": true + }, + { + "kind": "field", + "name": "focusableElement", + "type": { + "text": "HTMLTextAreaElement | HTMLParagraphElement" + } + }, + { + "kind": "field", + "name": "validityMessage", + "type": { + "text": "string | undefined" + } }, { "kind": "method", - "name": "renderLoader", + "name": "renderEditable", "privacy": "private" }, { "kind": "method", - "name": "renderPending", + "name": "renderHelpText", "privacy": "private" }, { "kind": "method", - "name": "renderComplete", + "name": "renderReadOnly", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderExplanation", + "privacy": "private" + }, + { + "kind": "method", + "name": "onGenerateCommitMessageClick", + "privacy": "private" + }, + { + "kind": "method", + "name": "onMessageInput", "privacy": "private", "parameters": [ { - "name": "overview", + "name": "event", "type": { - "text": "GetActiveOverviewResponse" + "text": "InputEvent" } - }, - { - "name": "isFetching", - "default": "false" } ] }, { "kind": "method", - "name": "renderRepoBranchCard", + "name": "disapatchMessageChange", "privacy": "private", "parameters": [ { - "name": "branch", - "type": { - "text": "GetOverviewBranch" - } - }, - { - "name": "repo", + "name": "message", "type": { "text": "string" } - }, - { - "name": "isFetching", - "type": { - "text": "boolean" - } } ] }, + { + "kind": "field", + "name": "dispatchMessageChangeDebounced" + }, { "kind": "method", - "name": "onRepositorySelectorClicked", - "privacy": "private", + "name": "focus", "parameters": [ { - "name": "e", + "name": "options", + "optional": true, "type": { - "text": "CustomEvent" + "text": "FocusOptions" } } ] - } - ], - "mixins": [ - { - "name": "SignalWatcher", - "package": "@lit-labs/signals" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "customElement": true - }, - { - "kind": "class", - "description": "", - "name": "GlActiveBranchCard", - "members": [ - { - "kind": "method", - "name": "renderActionsMenu", - "privacy": "private" }, { "kind": "method", - "name": "renderBranchStateActions", - "privacy": "private" + "name": "checkValidity", + "parameters": [ + { + "name": "reportErrors", + "default": "false" + } + ] }, { "kind": "method", - "name": "renderBranchIndicator", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | undefined" + "name": "select", + "parameters": [ + { + "name": "checkValidity", + "default": "false" } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + ] + } + ], + "events": [ + { + "name": "generate-commit-message", + "type": { + "text": "CustomEvent" } }, { - "kind": "method", - "name": "getBranchActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult[]" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "message-change", + "type": { + "text": "CustomEvent" } - }, + } + ], + "attributes": [ { - "kind": "method", - "name": "getPrActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult[]" - } + "name": "commit-id", + "type": { + "text": "string | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "commitId" }, { - "kind": "method", - "name": "getCollapsedActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult[]" - } + "name": "message", + "type": { + "text": "string | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "message" }, { - "kind": "method", - "name": "renderIssuesItem", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "name": "explanation", + "type": { + "text": "string | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "explanation" }, { - "kind": "field", - "name": "_homeState", + "name": "explanation-label", "type": { - "text": "State" + "text": "string | undefined" }, - "privacy": "protected", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "'Auto-composition Summary:'", + "fieldName": "explanationLabel" }, { - "kind": "field", - "name": "repo", + "name": "placeholder", "type": { "text": "string" }, - "attribute": "repo", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "'Enter commit message...'", + "fieldName": "placeholder" }, { - "kind": "field", - "name": "showUpgrade", + "name": "editable", "type": { "text": "boolean" }, "default": "false", - "attribute": "showUpgrade", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "editable" }, { - "kind": "field", - "name": "_branch", + "name": "ai-enabled", "type": { - "text": "GetOverviewBranch" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "fieldName": "aiEnabled" }, { - "kind": "field", - "name": "branch", + "name": "aiDisabledReason", "type": { - "text": "GetOverviewBranch" + "text": "string | null" }, - "attribute": "branch", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "fieldName": "aiDisabledReason" }, { - "kind": "field", - "name": "_autolinks", + "name": "generating", "type": { - "text": "Awaited" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, + "default": "false", + "fieldName": "generating" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-commit-message", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "CommitMessage", + "declaration": { + "name": "CommitMessage", + "module": "src/webviews/apps/plus/composer/components/commit-message.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-commit-message", + "declaration": { + "name": "CommitMessage", + "module": "src/webviews/apps/plus/composer/components/commit-message.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/composer/components/commits-panel.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "CommitsPanel", + "members": [ { "kind": "field", - "name": "autolinks", + "name": "commits", "type": { - "text": "Awaited" + "text": "ComposerCommit[]" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "[]", + "attribute": "commits" }, { "kind": "field", - "name": "_autolinksPromise", + "name": "hunks", "type": { - "text": "GetOverviewBranch['autolinks']" + "text": "ComposerHunk[]" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "[]", + "attribute": "hunks" }, { "kind": "field", - "name": "autolinksPromise", + "name": "selectedCommitId", "type": { - "text": "GetOverviewBranch['autolinks']" + "text": "string | null" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "attribute": "selectedCommitId" }, { "kind": "field", - "name": "_contributors", + "name": "selectedCommitIds", "type": { - "text": "Awaited" + "text": "Set" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "new Set()", + "attribute": "selectedCommitIds" }, { "kind": "field", - "name": "contributors", + "name": "selectedUnassignedSection", "type": { - "text": "Awaited" + "text": "string | null" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "attribute": "selectedUnassignedSection" }, { "kind": "field", - "name": "_contributorsPromise", + "name": "canFinishAndCommit", "type": { - "text": "GetOverviewBranch['contributors']" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "true", + "attribute": "canFinishAndCommit" }, { "kind": "field", - "name": "contributorsPromise", + "name": "generating", "type": { - "text": "GetOverviewBranch['contributors']" + "text": "boolean" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "generating" }, { "kind": "field", - "name": "_issues", + "name": "committing", "type": { - "text": "Awaited" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "committing" }, { "kind": "field", - "name": "issues", + "name": "aiEnabled", "type": { - "text": "Awaited" + "text": "boolean" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "aiEnabled" }, { "kind": "field", - "name": "_issuesPromise", + "name": "aiDisabledReason", "type": { - "text": "GetOverviewBranch['issues']" + "text": "string | null" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "attribute": "aiDisabledReason" }, { "kind": "field", - "name": "issuesPromise", + "name": "isPreviewMode", "type": { - "text": "GetOverviewBranch['issues']" + "text": "boolean" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "isPreviewMode" }, { "kind": "field", - "name": "_pr", + "name": "baseCommit", "type": { - "text": "Awaited" + "text": "ComposerBaseCommit | null" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "attribute": "baseCommit" }, { "kind": "field", - "name": "pr", + "name": "repoName", "type": { - "text": "Awaited" + "text": "string | null" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "attribute": "repoName" }, { "kind": "field", - "name": "_prPromise", + "name": "customInstructions", "type": { - "text": "GetOverviewBranch['pr']" + "text": "string" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "''", + "attribute": "customInstructions" }, { "kind": "field", - "name": "prPromise", + "name": "hasUsedAutoCompose", "type": { - "text": "GetOverviewBranch['pr']" + "text": "boolean" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "hasUsedAutoCompose" }, { "kind": "field", - "name": "_launchpadItem", + "name": "hasChanges", "type": { - "text": "Awaited>['launchpad']>" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "true", + "attribute": "hasChanges" }, { "kind": "field", - "name": "launchpadItem", + "name": "aiModel", "type": { - "text": "Awaited>['launchpad']>" + "text": "AIModel | undefined" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "undefined", + "attribute": "aiModel" }, { "kind": "field", - "name": "_launchpadItemPromise", + "name": "compositionSummarySelected", "type": { - "text": "NonNullable>['launchpad']" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "compositionSummarySelected" }, { "kind": "field", - "name": "launchpadItemPromise", + "name": "compositionFeedback", "type": { - "text": "NonNullable>['launchpad']" + "text": "'helpful' | 'unhelpful' | null" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "attribute": "compositionFeedback" }, { "kind": "field", - "name": "_mergeTarget", + "name": "compositionSessionId", "type": { - "text": "Awaited" + "text": "string | null" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "attribute": "compositionSessionId" }, { "kind": "field", - "name": "mergeTarget", + "name": "isReadyToCommit", "type": { - "text": "Awaited" + "text": "boolean" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "isReadyToCommit" }, { "kind": "field", - "name": "_mergeTargetPromise", + "name": "changesSection", "type": { - "text": "GetOverviewBranch['mergeTarget']" - }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "text": "HTMLElement" } }, { "kind": "field", - "name": "mergeTargetPromise", + "name": "autoComposeSection", "type": { - "text": "GetOverviewBranch['mergeTarget']" - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "text": "HTMLElement | undefined" } }, { "kind": "field", - "name": "_remote", + "name": "finishSection", "type": { - "text": "Awaited" - }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "text": "HTMLElement" } }, { "kind": "field", - "name": "remote", + "name": "commitsSortable", "type": { - "text": "Awaited" + "text": "Sortable | undefined" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "privacy": "private" }, { "kind": "field", - "name": "_remotePromise", + "name": "isDraggingHunks", "type": { - "text": "GetOverviewBranch['remote']" + "text": "boolean" }, "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false" }, { "kind": "field", - "name": "remotePromise", + "name": "draggedHunkIds", "type": { - "text": "GetOverviewBranch['remote']" + "text": "string[]" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "privacy": "private", + "default": "[]" }, { - "kind": "field", - "name": "_wip", - "type": { - "text": "Awaited" - }, + "kind": "method", + "name": "initializeSortable", + "privacy": "private" + }, + { + "kind": "method", + "name": "initializeDropZones", + "privacy": "private" + }, + { + "kind": "method", + "name": "initializeCommitDropZones", + "privacy": "private" + }, + { + "kind": "method", + "name": "setupNativeDropZone", "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "parameters": [ + { + "name": "element", + "type": { + "text": "HTMLElement" + } + }, + { + "name": "type", + "type": { + "text": "'new-commit' | 'unassign' | 'commit'" + } + } + ] }, { - "kind": "field", - "name": "wip", - "type": { - "text": "Awaited" - }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "kind": "method", + "name": "dispatchCommitReorder", + "privacy": "private", + "parameters": [ + { + "name": "oldIndex", + "type": { + "text": "number" + } + }, + { + "name": "newIndex", + "type": { + "text": "number" + } + } + ] }, { - "kind": "field", - "name": "_wipPromise", - "type": { - "text": "GetOverviewBranch['wip']" - }, + "kind": "method", + "name": "dispatchCreateNewCommit", "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "parameters": [ + { + "name": "hunkIds", + "type": { + "text": "string[]" + } + } + ] }, { - "kind": "field", - "name": "wipPromise", - "type": { - "text": "GetOverviewBranch['wip']" - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "kind": "method", + "name": "dispatchUnassignHunks", + "privacy": "private", + "parameters": [ + { + "name": "hunkIds", + "type": { + "text": "string[]" + } + } + ] }, { - "kind": "field", - "name": "busy", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "busy", - "reflects": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "kind": "method", + "name": "dispatchMoveHunksToCommit", + "privacy": "private", + "parameters": [ + { + "name": "hunkIds", + "type": { + "text": "string[]" + } + }, + { + "name": "targetCommitId", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "method", + "name": "handleHunkDragStart", + "privacy": "private", + "parameters": [ + { + "name": "event", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "addDropZoneHoverEffects", + "privacy": "private" + }, + { + "kind": "method", + "name": "removeDropZoneHoverEffects", + "privacy": "private" }, { "kind": "field", - "name": "expanded", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "expanded", - "reflects": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "name": "handleDragEnter", + "privacy": "private" }, { "kind": "field", - "name": "expandable", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "expandable", - "reflects": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "name": "handleDragLeave", + "privacy": "private" }, { "kind": "field", - "name": "eventController", + "name": "shouldShowUnassignZone", "type": { - "text": "AbortController | undefined" + "text": "boolean" }, "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, - { - "kind": "method", - "name": "onExpandableChanged", - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "readonly": true }, { "kind": "field", - "name": "branchRef", + "name": "shouldShowNewCommitZone", "type": { - "text": "BranchRef" + "text": "boolean" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "isWorktree", + "name": "firstCommitWithoutMessage", "type": { - "text": "boolean" + "text": "ComposerCommit | null" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "cardIndicator", + "name": "shouldShowAddToDraftButton", "type": { - "text": "GlCard['indicator']" + "text": "boolean" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "branchCardIndicator", + "name": "aiModelDisplayName", "type": { - "text": "GlCard['indicator']" + "text": "string" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "privacy": "private", + "readonly": true }, { "kind": "method", - "name": "attachFocusListener", - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "name": "handleHunkDragEnd", + "privacy": "private" }, { - "kind": "field", - "name": "onFocus", + "kind": "method", + "name": "dispatchCommitSelect", "privacy": "private", - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "parameters": [ + { + "name": "commitId", + "type": { + "text": "string" + } + }, + { + "name": "e", + "optional": true, + "type": { + "text": "MouseEvent | KeyboardEvent" + } + } + ] }, { "kind": "method", - "name": "renderIssues", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" + "name": "dispatchUnassignedSelect", + "privacy": "private", + "parameters": [ + { + "name": "section", + "type": { + "text": "string" + } + }, + { + "name": "e", + "optional": true, + "type": { + "text": "MouseEvent | KeyboardEvent" + } } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + ] }, { "kind": "method", - "name": "renderWip", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "name": "dispatchCombineCommits", + "privacy": "private" }, { "kind": "method", - "name": "renderAvatars", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "name": "dispatchFinishAndCommit", + "privacy": "private" }, { "kind": "method", - "name": "renderTracking", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, + "name": "dispatchFocusCommitMessage", + "privacy": "private", "parameters": [ { - "name": "showWip", - "default": "false" + "name": "commitId", + "optional": true, + "type": { + "text": "string" + } } - ], - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + ] }, { "kind": "method", - "name": "renderBranchActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "name": "dispatchGenerateCommitsWithAI", + "privacy": "private" }, { "kind": "method", - "name": "renderPrActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" + "name": "handleAddAllToDraftCommit", + "privacy": "private", + "parameters": [ + { + "name": "sectionKey", + "type": { + "text": "string" + } } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + ] }, { "kind": "method", - "name": "renderCollapsedActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "name": "handleGenerateCommitMessageWithAI", + "privacy": "private" }, { "kind": "method", - "name": "createWebviewCommandLink", - "privacy": "protected", - "return": { - "type": { - "text": "string" - } - }, + "name": "handleAIModelPickerClick", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCompositionSummaryClick", + "privacy": "private", "parameters": [ { - "name": "command", + "name": "e", "type": { - "text": "WebviewCommands | WebviewViewCommands | PlusCommands" + "text": "MouseEvent | KeyboardEvent" } - }, + } + ] + }, + { + "kind": "method", + "name": "handleCompositionFeedbackHelpful", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCompositionFeedbackUnhelpful", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCreateCommitsClick", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCancel", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleCustomInstructionsChange", + "privacy": "private", + "parameters": [ { - "name": "args", - "optional": true, + "name": "e", "type": { - "text": "T | any" + "text": "Event" } } - ], - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + ] }, { "kind": "method", - "name": "createCommandLink", - "privacy": "protected", + "name": "getIncludeButtonText", + "privacy": "private", "return": { "type": { "text": "string" @@ -17626,3229 +18456,2422 @@ }, "parameters": [ { - "name": "command", - "type": { - "text": "GlCommands" - } - }, - { - "name": "args", - "optional": true, + "name": "sectionKey", "type": { - "text": "T | any" + "text": "string" } } - ], - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + ] }, { "kind": "method", - "name": "renderTimestamp", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "name": "renderUnassignedSection", + "privacy": "private" }, { "kind": "method", - "name": "renderBranchItem", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, + "name": "renderCompositionSummarySection", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderAutoComposeContainer", + "privacy": "private", "parameters": [ { - "name": "actionsSection", - "optional": true, - "type": { - "text": "TemplateResult | NothingType" - } + "name": "disabled", + "default": "false" } - ], - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + ] }, { "kind": "method", - "name": "renderBranchIcon", + "name": "renderFinishCommitSection", "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "parameters": [ + { + "name": "disabled", + "default": "false" + } + ] + } + ], + "events": [ + { + "name": "commit-reorder", + "type": { + "text": "CustomEvent" } }, { - "kind": "method", - "name": "renderPrItem", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "create-new-commit", + "type": { + "text": "CustomEvent" } }, { - "kind": "method", - "name": "renderLaunchpadItem", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "unassign-hunks", + "type": { + "text": "CustomEvent" } }, { - "kind": "method", - "name": "renderMergeTargetStatus", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "move-hunks-to-commit", + "type": { + "text": "CustomEvent" } }, { - "kind": "method", - "name": "toggleExpanded", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "expanded", - "default": "!this.expanded" - } - ], - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "commit-select", + "type": { + "text": "CustomEvent" } }, { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" + "name": "unassigned-select", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "combine-commits", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "finish-and-commit", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "focus-commit-message", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "generate-commits-with-ai", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "add-hunks-to-commit", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "generate-commit-message", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "select-ai-model", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "select-composition-summary", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "composition-feedback-helpful", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "composition-feedback-unhelpful", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "cancel-composer", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "custom-instructions-change", + "type": { + "text": "CustomEvent" } } ], - "superclass": { - "name": "GlBranchCardBase", - "module": "/src/webviews/apps/plus/home/components/branch-card" - }, - "tagName": "gl-active-branch-card", - "customElement": true, "attributes": [ { - "name": "repo", + "name": "commits", "type": { - "text": "string" + "text": "ComposerCommit[]" }, - "fieldName": "repo", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "[]", + "fieldName": "commits" }, { - "name": "showUpgrade", + "name": "hunks", + "type": { + "text": "ComposerHunk[]" + }, + "default": "[]", + "fieldName": "hunks" + }, + { + "name": "selectedCommitId", + "type": { + "text": "string | null" + }, + "default": "null", + "fieldName": "selectedCommitId" + }, + { + "name": "selectedCommitIds", + "type": { + "text": "Set" + }, + "default": "new Set()", + "fieldName": "selectedCommitIds" + }, + { + "name": "selectedUnassignedSection", + "type": { + "text": "string | null" + }, + "default": "null", + "fieldName": "selectedUnassignedSection" + }, + { + "name": "canFinishAndCommit", + "type": { + "text": "boolean" + }, + "default": "true", + "fieldName": "canFinishAndCommit" + }, + { + "name": "generating", "type": { "text": "boolean" }, "default": "false", - "fieldName": "showUpgrade", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "generating" }, { - "name": "branch", + "name": "committing", "type": { - "text": "GetOverviewBranch" + "text": "boolean" }, - "fieldName": "branch", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "fieldName": "committing" }, { - "name": "busy", + "name": "aiEnabled", "type": { "text": "boolean" }, "default": "false", - "fieldName": "busy", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "aiEnabled" }, { - "name": "expanded", + "name": "aiDisabledReason", + "type": { + "text": "string | null" + }, + "default": "null", + "fieldName": "aiDisabledReason" + }, + { + "name": "isPreviewMode", "type": { "text": "boolean" }, "default": "false", - "fieldName": "expanded", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "isPreviewMode" }, { - "name": "expandable", + "name": "baseCommit", + "type": { + "text": "ComposerBaseCommit | null" + }, + "default": "null", + "fieldName": "baseCommit" + }, + { + "name": "repoName", + "type": { + "text": "string | null" + }, + "default": "null", + "fieldName": "repoName" + }, + { + "name": "customInstructions", + "type": { + "text": "string" + }, + "default": "''", + "fieldName": "customInstructions" + }, + { + "name": "hasUsedAutoCompose", "type": { "text": "boolean" }, "default": "false", - "fieldName": "expandable", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "hasUsedAutoCompose" + }, + { + "name": "hasChanges", + "type": { + "text": "boolean" + }, + "default": "true", + "fieldName": "hasChanges" + }, + { + "name": "aiModel", + "type": { + "text": "AIModel | undefined" + }, + "default": "undefined", + "fieldName": "aiModel" + }, + { + "name": "compositionSummarySelected", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "compositionSummarySelected" + }, + { + "name": "compositionFeedback", + "type": { + "text": "'helpful' | 'unhelpful' | null" + }, + "default": "null", + "fieldName": "compositionFeedback" + }, + { + "name": "compositionSessionId", + "type": { + "text": "string | null" + }, + "default": "null", + "fieldName": "compositionSessionId" + }, + { + "name": "isReadyToCommit", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "isReadyToCommit" } - ] + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-commits-panel", + "customElement": true } ], "exports": [ { "kind": "js", - "name": "activeWorkTagName", + "name": "CommitsPanel", "declaration": { - "name": "activeWorkTagName", - "module": "src/webviews/apps/plus/home/components/active-work.ts" + "name": "CommitsPanel", + "module": "src/webviews/apps/plus/composer/components/commits-panel.ts" } }, { - "kind": "js", - "name": "GlActiveWork", + "kind": "custom-element-definition", + "name": "gl-commits-panel", "declaration": { - "name": "GlActiveWork", - "module": "src/webviews/apps/plus/home/components/active-work.ts" + "name": "CommitsPanel", + "module": "src/webviews/apps/plus/composer/components/commits-panel.ts" } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/composer/components/composer.css.ts", + "declarations": [ + { + "kind": "variable", + "name": "composerItemStyles", + "default": "css` .composer-item { --composer-item-background: var(--composer-background-05); --composer-item-border: transparent; --composer-item-radius: 1.2rem; --composer-item-color: var(--vscode-foreground); --composer-item-icon-color: var(--vscode-icon-foreground); display: flex; flex-direction: row; align-items: center; /* gap: 0.8rem; */ border: 1px solid var(--composer-item-border); border-radius: var(--composer-item-radius); color: var(--composer-item-color); background: var(--composer-item-background); transition: background-color 0.2s ease; cursor: pointer; } .composer-item:not(.is-selected):is(:focus-visible, :hover) { --composer-item-background: var(--vscode-list-hoverBackground); } .composer-item.is-selected { --composer-item-background: var(--vscode-list-activeSelectionBackground, var(--color-background)); --composer-item-icon-color: var(--vscode-list-activeSelectionForeground, var(--vscode-foreground)); --composer-item-color: var(--vscode-list-activeSelectionForeground); } :host-context(.vscode-high-contrast) .composer-item.is-selected { --composer-item-border: var( --vscode-list-focusAndSelectionOutline, var(--vscode-contrastActiveBorder, var(--vscode-list-focusOutline)) ); } .composer-item.is-summary { --composer-item-border: var(--vscode-panel-border); --composer-item-radius: 0.4rem; } .composer-item.is-uncommitted { --composer-item-background: color-mix( in srgb, var(--vscode-notificationsWarningIcon-foreground) 8%, transparent ); --composer-item-border: color-mix(in srgb, var(--vscode-notificationsWarningIcon-foreground) 20%, transparent); --composer-item-radius: 0.4rem; border-style: dashed; } .composer-item.is-uncommitted:not(.is-selected):is(:focus-visible, :hover) { --composer-item-background: color-mix( in srgb, var(--vscode-notificationsWarningIcon-foreground) 12%, transparent ); } .composer-item.is-uncommitted.is-selected { --composer-item-background: color-mix( in srgb, var(--vscode-notificationsWarningIcon-foreground) 18%, transparent ); --composer-item-border: color-mix(in srgb, var(--vscode-notificationsWarningIcon-foreground) 25%, transparent); --composer-item-color: var(--vscode-foreground); } .composer-item.is-base, .composer-item.is-base:focus-visible, .composer-item.is-base:hover { --composer-item-background: var(--color-background); --composer-item-icon-color: var(--color-foreground--65); --composer-item-color: var(--color-foreground--65); } .composer-item__content { flex: 1; display: flex; min-width: 0; flex-direction: column; gap: 0.4rem; padding: 0.8rem 1.2rem; } .composer-item__header { font-size: 1.4rem; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .composer-item__header.is-placeholder, .composer-item__header.is-empty-state { font-style: italic; opacity: 0.65; } .composer-item__header.is-empty-state { white-space: normal; text-overflow: initial; text-wrap: pretty; } .composer-item__body { font-size: 1.2rem; } .composer-item.is-base .composer-item__body { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; } `" }, { - "kind": "custom-element-definition", + "kind": "variable", + "name": "composerItemCommitStyles", + "default": "css` .composer-item__commit { flex: none; position: relative; width: 2.2rem; align-self: stretch; margin-inline-start: 0.8rem; } .composer-item__commit::before { content: ''; position: absolute; top: 0; left: 50%; width: 0; height: 100%; border-left: 2px dashed var(--composer-item-icon-color); transform: translateX(-50%); } .composer-item.is-first .composer-item__commit::before { top: 50%; height: 50%; } .composer-item.is-last .composer-item__commit::before { display: none; } .composer-item__commit::after { content: ''; position: absolute; top: 50%; left: 0; width: 1.8rem; aspect-ratio: 1; transform: translateY(-50%); border-radius: 50%; background: var(--composer-item-background); border: 2px dashed var(--composer-item-icon-color); z-index: 1; } .composer-item.is-base .composer-item__commit::after { border-style: solid; } .composer-item.is-base .composer-item__commit::before { border-left-style: solid; } .composer-item__commit.is-empty::before, .composer-item__commit.is-empty::after { display: none; } `" + }, + { + "kind": "variable", + "name": "composerItemContentStyles", + "default": "css` .change-stats { display: flex; align-items: center; gap: 0.8rem; } .file-count { } .diff-stats { display: inline-flex; align-items: center; gap: 0.5rem; /* font-size: 0.8rem; */ font-weight: 500; } .diff-stats__additions { color: var(--vscode-gitDecoration-addedResourceForeground); color: light-dark( color-mix(in srgb, #fff 40%, var(--vscode-gitDecoration-addedResourceForeground)), var(--vscode-gitDecoration-addedResourceForeground) ); } .diff-stats__deletions { color: var(--vscode-gitDecoration-deletedResourceForeground); color: light-dark( color-mix(in srgb, #fff 40%, var(--vscode-gitDecoration-deletedResourceForeground)), var(--vscode-gitDecoration-deletedResourceForeground) ); } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "composerItemStyles", "declaration": { - "name": "GlActiveWork", - "module": "src/webviews/apps/plus/home/components/active-work.ts" + "name": "composerItemStyles", + "module": "src/webviews/apps/plus/composer/components/composer.css.ts" } }, { "kind": "js", - "name": "GlActiveBranchCard", + "name": "composerItemCommitStyles", "declaration": { - "name": "GlActiveBranchCard", - "module": "src/webviews/apps/plus/home/components/active-work.ts" + "name": "composerItemCommitStyles", + "module": "src/webviews/apps/plus/composer/components/composer.css.ts" } }, { - "kind": "custom-element-definition", - "name": "gl-active-branch-card", + "kind": "js", + "name": "composerItemContentStyles", "declaration": { - "name": "GlActiveBranchCard", - "module": "src/webviews/apps/plus/home/components/active-work.ts" + "name": "composerItemContentStyles", + "module": "src/webviews/apps/plus/composer/components/composer.css.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/home/components/branch-card.ts", + "path": "src/webviews/apps/plus/composer/components/details-panel.ts", "declarations": [ - { - "kind": "variable", - "name": "branchCardStyles", - "default": "css` * { box-sizing: border-box; } gl-avatar-list { --gl-avatar-size: 2.4rem; margin-block: -0.4rem; } .branch-item { position: relative; } .branch-item__container { display: flex; flex-direction: column; gap: 0.6rem; } .branch-item__container > * { margin-block: 0; } .branch-item__section { display: flex; flex-direction: column; gap: 0.4rem; } .branch-item__section > * { margin-block: 0; } .branch-item__section--details { font-size: 0.9em; color: var(--vscode-descriptionForeground); } .branch-item__actions { display: flex; align-items: center; gap: 0.8rem; flex-direction: row; justify-content: flex-end; font-size: 0.9em; } /* :empty selector doesn't work with lit */ .branch-item__actions:not(:has(*)) { display: none; } .branch-item__icon { color: var(--vscode-descriptionForeground); flex: none; } .branch-item__name { flex-grow: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: bold; } .branch-item__name--secondary { font-weight: normal; } .branch-item__identifier { color: var(--vscode-descriptionForeground); text-decoration: none; } .branch-item__grouping { display: inline-flex; align-items: center; gap: 0.6rem; max-width: 100%; margin-block: 0; } .branch-item__changes { display: flex; align-items: center; gap: 1rem; justify-content: flex-end; flex-wrap: wrap; white-space: nowrap; } .branch-item__changes formatted-date { margin-inline-end: auto; } .branch-item__summary { display: flex; align-items: center; gap: 0.6rem; } .branch-item__collapsed-actions { position: absolute; z-index: var(--gl-branch-card-actions-zindex, 2); right: 0.4rem; bottom: 0.3rem; padding: 0.4rem 0.6rem; background-color: var(--gl-card-hover-background); } .branch-item:not(:focus-within):not(:hover) .branch-item__collapsed-actions { ${srOnlyStyles} } .pill { --gl-pill-border: color-mix(in srgb, transparent 80%, var(--color-foreground)); } .work-item { --gl-card-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #fff 3%); --gl-card-hover-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #fff 1.5%); } .work-item::part(base) { margin-block-end: 0; } .branch-item__section.mb-1 { margin-block: 0.4rem; } .branch-item__merge-target { margin-inline-end: auto; } .branch-item__row { display: flex; gap: 0.8rem; } .branch-item__row [full] { flex-grow: 1; } .branch-item__missing { --button-foreground: inherit; } :host-context(.vscode-dark) .branch-item__missing, :host-context(.vscode-high-contrast) .branch-item__missing { --button-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #fff 3%); --button-hover-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #fff 1.5%); --button-border: color-mix(in lab, var(--vscode-sideBar-background) 100%, #fff 12%); } :host-context(.vscode-light) .branch-item__missing, :host-context(.vscode-high-contrast-light) .branch-item__missing { --button-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #000 8%); --button-hover-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #000 10%); --button-border: color-mix(in lab, var(--vscode-sideBar-background) 100%, #000 14%); } .branch-item__category { margin-inline-start: 0.6rem; } .launchpad-grouping--mergeable { color: var(--vscode-gitlens-launchpadIndicatorMergeableColor); } .launchpad-grouping--blocked { color: var(--vscode-gitlens-launchpadIndicatorBlockedColor); } .launchpad-grouping--attention { color: var(--vscode-gitlens-launchpadIndicatorAttentionColor); } .tracking__pill, .wip__pill { display: flex; flex-direction: row; gap: 1rem; } .tracking__tooltip, .wip__tooltip { display: contents; vertical-align: middle; } .tracking__tooltip p, .wip__tooltip p { margin-block: 0; } p.tracking__tooltip--wip { margin-block-start: 1rem; } `" - }, { "kind": "class", "description": "", - "name": "GlBranchCardBase", + "name": "DetailsPanel", "members": [ { "kind": "field", - "name": "_homeState", + "name": "commits", "type": { - "text": "State" + "text": "ComposerCommit[]" }, - "privacy": "protected" + "default": "[]", + "attribute": "commits" }, { "kind": "field", - "name": "repo", + "name": "selectedCommits", "type": { - "text": "string" + "text": "ComposerCommit[]" }, - "attribute": "repo" + "default": "[]", + "attribute": "selectedCommits" }, { "kind": "field", - "name": "showUpgrade", + "name": "hunks", "type": { - "text": "boolean" + "text": "ComposerHunk[]" }, - "default": "false", - "attribute": "showUpgrade" + "default": "[]", + "attribute": "hunks" }, { "kind": "field", - "name": "_branch", + "name": "selectedUnassignedSection", "type": { - "text": "GetOverviewBranch" + "text": "'staged' | 'unstaged' | 'unassigned' | null" }, - "privacy": "private" + "default": "null", + "attribute": "selectedUnassignedSection" }, { "kind": "field", - "name": "branch", + "name": "commitMessageExpanded", "type": { - "text": "GetOverviewBranch" + "text": "boolean" }, - "attribute": "branch" + "default": "true", + "attribute": "commitMessageExpanded" }, { "kind": "field", - "name": "_autolinks", + "name": "aiExplanationExpanded", "type": { - "text": "Awaited" + "text": "boolean" }, - "privacy": "private" + "default": "true", + "attribute": "aiExplanationExpanded" }, { "kind": "field", - "name": "autolinks", + "name": "filesChangedExpanded", "type": { - "text": "Awaited" + "text": "boolean" }, - "readonly": true + "default": "true", + "attribute": "filesChangedExpanded" }, { "kind": "field", - "name": "_autolinksPromise", + "name": "selectedHunkIds", "type": { - "text": "GetOverviewBranch['autolinks']" + "text": "Set" }, - "privacy": "private" + "default": "new Set()", + "attribute": "selectedHunkIds" }, { "kind": "field", - "name": "autolinksPromise", + "name": "generatingCommitMessage", "type": { - "text": "GetOverviewBranch['autolinks']" - } + "text": "string | null" + }, + "default": "null", + "attribute": "generatingCommitMessage" }, { "kind": "field", - "name": "_contributors", + "name": "committing", "type": { - "text": "Awaited" + "text": "boolean" }, - "privacy": "private" + "default": "false", + "attribute": "committing" }, { "kind": "field", - "name": "contributors", + "name": "aiEnabled", "type": { - "text": "Awaited" + "text": "boolean" }, - "readonly": true + "default": "false", + "attribute": "aiEnabled" }, { "kind": "field", - "name": "_contributorsPromise", + "name": "aiDisabledReason", "type": { - "text": "GetOverviewBranch['contributors']" + "text": "string | null" }, - "privacy": "private" + "default": "null", + "attribute": "aiDisabledReason" }, { "kind": "field", - "name": "contributorsPromise", + "name": "isPreviewMode", "type": { - "text": "GetOverviewBranch['contributors']" - } + "text": "boolean" + }, + "default": "false", + "attribute": "isPreviewMode" }, { "kind": "field", - "name": "_issues", + "name": "compositionSummarySelected", "type": { - "text": "Awaited" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "issues", - "type": { - "text": "Awaited" - }, - "readonly": true - }, - { - "kind": "field", - "name": "_issuesPromise", - "type": { - "text": "GetOverviewBranch['issues']" + "text": "boolean" }, - "privacy": "private" - }, - { - "kind": "field", - "name": "issuesPromise", - "type": { - "text": "GetOverviewBranch['issues']" - } + "default": "false", + "attribute": "compositionSummarySelected" }, { "kind": "field", - "name": "_pr", + "name": "hasChanges", "type": { - "text": "Awaited" + "text": "boolean" }, - "privacy": "private" + "default": "true", + "attribute": "hasChanges" }, { "kind": "field", - "name": "pr", + "name": "defaultFilesExpanded", "type": { - "text": "Awaited" + "text": "boolean" }, - "readonly": true + "privacy": "private", + "default": "true" }, { "kind": "field", - "name": "_prPromise", + "name": "hunksSortables", "type": { - "text": "GetOverviewBranch['pr']" + "text": "Sortable[]" }, - "privacy": "private" - }, - { - "kind": "field", - "name": "prPromise", - "type": { - "text": "GetOverviewBranch['pr']" - } + "privacy": "private", + "default": "[]" }, { "kind": "field", - "name": "_launchpadItem", + "name": "isDraggingHunks", "type": { - "text": "Awaited>['launchpad']>" + "text": "boolean" }, - "privacy": "private" + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "launchpadItem", + "name": "draggedHunkIds", "type": { - "text": "Awaited>['launchpad']>" + "text": "string[]" }, - "readonly": true + "privacy": "private", + "default": "[]" }, { "kind": "field", - "name": "_launchpadItemPromise", + "name": "autoScrollInterval", "type": { - "text": "NonNullable>['launchpad']" + "text": "number | undefined" }, "privacy": "private" }, { "kind": "field", - "name": "launchpadItemPromise", - "type": { - "text": "NonNullable>['launchpad']" - } - }, - { - "kind": "field", - "name": "_mergeTarget", + "name": "dragOverCleanupTimeout", "type": { - "text": "Awaited" + "text": "number | undefined" }, "privacy": "private" }, { "kind": "field", - "name": "mergeTarget", - "type": { - "text": "Awaited" - }, - "readonly": true - }, - { - "kind": "field", - "name": "_mergeTargetPromise", + "name": "detailsPanel", "type": { - "text": "GetOverviewBranch['mergeTarget']" + "text": "HTMLDivElement" }, "privacy": "private" }, { - "kind": "field", - "name": "mergeTargetPromise", - "type": { - "text": "GetOverviewBranch['mergeTarget']" - } - }, - { - "kind": "field", - "name": "_remote", - "type": { - "text": "Awaited" - }, + "kind": "method", + "name": "destroyHunksSortables", "privacy": "private" }, { - "kind": "field", - "name": "remote", - "type": { - "text": "Awaited" - }, - "readonly": true - }, - { - "kind": "field", - "name": "_remotePromise", - "type": { - "text": "GetOverviewBranch['remote']" - }, + "kind": "method", + "name": "initializeHunksSortable", "privacy": "private" }, { "kind": "field", - "name": "remotePromise", - "type": { - "text": "GetOverviewBranch['remote']" - } - }, - { - "kind": "field", - "name": "_wip", - "type": { - "text": "Awaited" - }, + "name": "handleFilesListDragOver", "privacy": "private" }, { "kind": "field", - "name": "wip", - "type": { - "text": "Awaited" - }, - "readonly": true - }, - { - "kind": "field", - "name": "_wipPromise", - "type": { - "text": "GetOverviewBranch['wip']" - }, + "name": "handleFilesListDrop", "privacy": "private" }, { - "kind": "field", - "name": "wipPromise", - "type": { - "text": "GetOverviewBranch['wip']" - } - }, - { - "kind": "field", - "name": "busy", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "busy", - "reflects": true - }, - { - "kind": "field", - "name": "expanded", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "expanded", - "reflects": true - }, - { - "kind": "field", - "name": "expandable", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "expandable", - "reflects": true - }, - { - "kind": "field", - "name": "eventController", - "type": { - "text": "AbortController | undefined" - }, + "kind": "method", + "name": "setupAutoScroll", "privacy": "private" }, { "kind": "method", - "name": "onExpandableChanged", + "name": "cleanupAutoScroll", "privacy": "private" }, { "kind": "field", - "name": "branchRef", - "type": { - "text": "BranchRef" - }, - "readonly": true - }, - { - "kind": "field", - "name": "isWorktree", - "type": { - "text": "boolean" - }, - "readonly": true - }, - { - "kind": "field", - "name": "cardIndicator", - "type": { - "text": "GlCard['indicator']" - }, - "readonly": true - }, - { - "kind": "field", - "name": "branchCardIndicator", - "type": { - "text": "GlCard['indicator']" - }, - "readonly": true - }, - { - "kind": "method", - "name": "attachFocusListener", + "name": "handleGlobalDragEnd", "privacy": "private" }, { "kind": "field", - "name": "onFocus", - "privacy": "private", - "readonly": true - }, - { - "kind": "method", - "name": "renderIssues", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - } + "name": "handleDragOverForAutoScroll", + "privacy": "private" }, { "kind": "method", - "name": "renderWip", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" + "name": "dispatchHunkDragStart", + "privacy": "private", + "parameters": [ + { + "name": "hunkIds", + "type": { + "text": "string[]" + } } - } + ] }, { "kind": "method", - "name": "renderAvatars", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - } + "name": "dispatchHunkDragEnd", + "privacy": "private" }, { "kind": "method", - "name": "renderTracking", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - }, + "name": "handleCommitMessageChange", + "privacy": "private", "parameters": [ { - "name": "showWip", - "default": "false" + "name": "commitId", + "type": { + "text": "string" + } + }, + { + "name": "message", + "type": { + "text": "string" + } } ] }, { "kind": "method", - "name": "getBranchActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult[]" + "name": "handleGenerateCommitMessage", + "privacy": "private", + "parameters": [ + { + "name": "commitId", + "type": { + "text": "string" + } + }, + { + "name": "e", + "optional": true, + "type": { + "text": "CustomEvent" + } } - } + ] }, { "kind": "method", - "name": "renderBranchActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - } + "name": "handleCollapseAllFiles", + "privacy": "private" }, { "kind": "method", - "name": "getPrActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult[]" - } - } + "name": "handleExpandAllFiles", + "privacy": "private" }, { "kind": "method", - "name": "renderPrActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" + "name": "renderFilesChangedHeader", + "privacy": "private", + "parameters": [ + { + "name": "fileCount", + "type": { + "text": "number | string" + } } - } + ] }, { "kind": "method", - "name": "getCollapsedActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult[]" + "name": "renderFileHierarchy", + "privacy": "private", + "parameters": [ + { + "name": "hunks", + "type": { + "text": "ComposerHunk[]" + } } - } + ] }, { "kind": "method", - "name": "renderCollapsedActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" + "name": "renderFile", + "privacy": "private", + "parameters": [ + { + "name": "fileName", + "type": { + "text": "string" + } + }, + { + "name": "fileHunks", + "type": { + "text": "ComposerHunk[]" + } } - } + ] }, { "kind": "method", - "name": "createWebviewCommandLink", - "privacy": "protected", - "return": { - "type": { - "text": "string" - } - }, + "name": "dispatchHunkSelect", + "privacy": "private", "parameters": [ { - "name": "command", + "name": "hunkId", "type": { - "text": "WebviewCommands | WebviewViewCommands | PlusCommands" + "text": "string" } }, { - "name": "args", - "optional": true, + "name": "shiftKey", + "default": "false", "type": { - "text": "T | any" + "text": "boolean" } } ] }, { "kind": "method", - "name": "createCommandLink", - "privacy": "protected", - "return": { - "type": { - "text": "string" - } - }, + "name": "focusCommitMessageInput", + "privacy": "public", "parameters": [ { - "name": "command", + "name": "commitId", "type": { - "text": "GlCommands" + "text": "string" } }, { - "name": "args", - "optional": true, - "type": { - "text": "T | any" - } + "name": "checkValidity", + "default": "false" } ] }, { "kind": "method", - "name": "renderTimestamp", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - } + "name": "renderUnassignedSectionDetails", + "privacy": "private" }, { "kind": "method", - "name": "renderBranchIndicator", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | undefined" + "name": "renderCommitDetails", + "privacy": "private", + "parameters": [ + { + "name": "commit", + "type": { + "text": "ComposerCommit" + } } - } + ] }, { "kind": "method", - "name": "renderBranchItem", - "privacy": "protected", + "name": "getHunksForSection", + "privacy": "private", "return": { "type": { - "text": "TemplateResult | NothingType" + "text": "ComposerHunk[]" } }, "parameters": [ { - "name": "actionsSection", - "optional": true, + "name": "section", "type": { - "text": "TemplateResult | NothingType" + "text": "'staged' | 'unstaged' | 'unassigned'" } } ] }, { "kind": "method", - "name": "renderBranchIcon", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderPrItem", - "privacy": "protected", + "name": "getSectionTitle", + "privacy": "private", "return": { "type": { - "text": "TemplateResult | NothingType" + "text": "string" } - } + }, + "parameters": [ + { + "name": "section", + "type": { + "text": "'staged' | 'unstaged' | 'unassigned'" + } + } + ] }, { "kind": "method", - "name": "renderLaunchpadItem", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - } + "name": "renderCompositionSummary", + "privacy": "private" }, { "kind": "method", - "name": "renderMergeTargetStatus", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - } + "name": "renderNoChangesState", + "privacy": "private" }, { "kind": "method", - "name": "renderIssuesItem", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } - } + "name": "handleClose", + "privacy": "private" }, { "kind": "method", - "name": "toggleExpanded", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "expanded", - "default": "!this.expanded" - } - ] + "name": "handleReload", + "privacy": "private" }, { "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } + "name": "renderDetails", + "privacy": "private" } ], - "attributes": [ + "events": [ { - "name": "repo", + "name": "hunk-drag-start", "type": { - "text": "string" - }, - "fieldName": "repo" + "text": "CustomEvent" + } }, { - "name": "showUpgrade", + "name": "hunk-drag-end", "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "showUpgrade" + "text": "CustomEvent" + } }, { - "name": "branch", + "name": "update-commit-message", "type": { - "text": "GetOverviewBranch" - }, - "fieldName": "branch" - }, - { - "name": "busy", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "busy" - }, - { - "name": "expanded", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "expanded" - }, - { - "name": "expandable", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "expandable" - } - ], - "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" - } - }, - { - "kind": "class", - "description": "", - "name": "GlBranchCard", - "members": [ - { - "kind": "method", - "name": "getCollapsedActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult[]" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "text": "CustomEvent" } }, { - "kind": "method", - "name": "getBranchActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult[]" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "generate-commit-message", + "type": { + "text": "CustomEvent" } }, { - "kind": "method", - "name": "getPrActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult[]" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "hunk-selected", + "type": { + "text": "CustomEvent" } }, { - "kind": "method", - "name": "renderBranchIndicator", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | undefined" - } - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "close-composer", + "type": { + "text": "CustomEvent" } }, { - "kind": "field", - "name": "_homeState", + "name": "reload-composer", "type": { - "text": "State" - }, - "privacy": "protected", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "text": "CustomEvent" } - }, + } + ], + "attributes": [ { - "kind": "field", - "name": "repo", + "name": "commits", "type": { - "text": "string" + "text": "ComposerCommit[]" }, - "attribute": "repo", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "[]", + "fieldName": "commits" }, { - "kind": "field", - "name": "showUpgrade", + "name": "selectedCommits", "type": { - "text": "boolean" + "text": "ComposerCommit[]" }, - "default": "false", - "attribute": "showUpgrade", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "[]", + "fieldName": "selectedCommits" }, { - "kind": "field", - "name": "_branch", + "name": "hunks", "type": { - "text": "GetOverviewBranch" + "text": "ComposerHunk[]" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "[]", + "fieldName": "hunks" }, { - "kind": "field", - "name": "branch", + "name": "selectedUnassignedSection", "type": { - "text": "GetOverviewBranch" + "text": "'staged' | 'unstaged' | 'unassigned' | null" }, - "attribute": "branch", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "fieldName": "selectedUnassignedSection" }, { - "kind": "field", - "name": "_autolinks", + "name": "commitMessageExpanded", "type": { - "text": "Awaited" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "true", + "fieldName": "commitMessageExpanded" }, { - "kind": "field", - "name": "autolinks", + "name": "aiExplanationExpanded", "type": { - "text": "Awaited" + "text": "boolean" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "true", + "fieldName": "aiExplanationExpanded" }, { - "kind": "field", - "name": "_autolinksPromise", + "name": "filesChangedExpanded", "type": { - "text": "GetOverviewBranch['autolinks']" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "true", + "fieldName": "filesChangedExpanded" }, { - "kind": "field", - "name": "autolinksPromise", + "name": "selectedHunkIds", "type": { - "text": "GetOverviewBranch['autolinks']" + "text": "Set" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "new Set()", + "fieldName": "selectedHunkIds" }, { - "kind": "field", - "name": "_contributors", + "name": "generatingCommitMessage", "type": { - "text": "Awaited" + "text": "string | null" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "fieldName": "generatingCommitMessage" }, { - "kind": "field", - "name": "contributors", + "name": "committing", "type": { - "text": "Awaited" + "text": "boolean" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "fieldName": "committing" }, { - "kind": "field", - "name": "_contributorsPromise", + "name": "aiEnabled", "type": { - "text": "GetOverviewBranch['contributors']" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "fieldName": "aiEnabled" }, { - "kind": "field", - "name": "contributorsPromise", + "name": "aiDisabledReason", "type": { - "text": "GetOverviewBranch['contributors']" + "text": "string | null" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "null", + "fieldName": "aiDisabledReason" }, { - "kind": "field", - "name": "_issues", + "name": "isPreviewMode", "type": { - "text": "Awaited" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "fieldName": "isPreviewMode" }, { - "kind": "field", - "name": "issues", + "name": "compositionSummarySelected", "type": { - "text": "Awaited" + "text": "boolean" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "fieldName": "compositionSummarySelected" }, { - "kind": "field", - "name": "_issuesPromise", + "name": "hasChanges", "type": { - "text": "GetOverviewBranch['issues']" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, + "default": "true", + "fieldName": "hasChanges" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-details-panel", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "DetailsPanel", + "declaration": { + "name": "DetailsPanel", + "module": "src/webviews/apps/plus/composer/components/details-panel.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-details-panel", + "declaration": { + "name": "DetailsPanel", + "module": "src/webviews/apps/plus/composer/components/details-panel.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/composer/components/hunk-item.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "HunkItem", + "members": [ { "kind": "field", - "name": "issuesPromise", + "name": "hunkId", "type": { - "text": "GetOverviewBranch['issues']" + "text": "string" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "hunkId" }, { "kind": "field", - "name": "_pr", + "name": "fileName", "type": { - "text": "Awaited" + "text": "string" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "fileName" }, { "kind": "field", - "name": "pr", + "name": "hunkHeader", "type": { - "text": "Awaited" + "text": "string | undefined" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "hunkHeader" }, { "kind": "field", - "name": "_prPromise", + "name": "content", "type": { - "text": "GetOverviewBranch['pr']" + "text": "string" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "content" }, { "kind": "field", - "name": "prPromise", + "name": "additions", "type": { - "text": "GetOverviewBranch['pr']" + "text": "number" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "additions" }, { "kind": "field", - "name": "_launchpadItem", + "name": "deletions", "type": { - "text": "Awaited>['launchpad']>" + "text": "number" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "deletions" }, { "kind": "field", - "name": "launchpadItem", + "name": "selected", "type": { - "text": "Awaited>['launchpad']>" + "text": "boolean" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "selected" }, { "kind": "field", - "name": "_launchpadItemPromise", + "name": "multiSelected", "type": { - "text": "NonNullable>['launchpad']" + "text": "boolean" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "multiSelected" }, { "kind": "field", - "name": "launchpadItemPromise", + "name": "isRename", "type": { - "text": "NonNullable>['launchpad']" + "text": "boolean" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "isRename" }, { "kind": "field", - "name": "_mergeTarget", + "name": "originalFileName", "type": { - "text": "Awaited" + "text": "string | undefined" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "originalFileName" }, { "kind": "field", - "name": "mergeTarget", + "name": "isPreviewMode", "type": { - "text": "Awaited" + "text": "boolean" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "default": "false", + "attribute": "isPreviewMode" }, { - "kind": "field", - "name": "_mergeTargetPromise", - "type": { - "text": "GetOverviewBranch['mergeTarget']" - }, + "kind": "method", + "name": "handleClick", "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "parameters": [ + { + "name": "e", + "type": { + "text": "MouseEvent" + } + } + ] }, { - "kind": "field", - "name": "mergeTargetPromise", - "type": { - "text": "GetOverviewBranch['mergeTarget']" - }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "kind": "method", + "name": "renderHunkHeader", + "privacy": "private" }, { - "kind": "field", - "name": "_remote", - "type": { - "text": "Awaited" - }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, + "kind": "method", + "name": "renderDiffContent", + "privacy": "private" + } + ], + "events": [ { - "kind": "field", - "name": "remote", + "name": "hunk-selected", "type": { - "text": "Awaited" - }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "text": "CustomEvent" } - }, + } + ], + "attributes": [ { - "kind": "field", - "name": "_remotePromise", + "name": "hunkId", "type": { - "text": "GetOverviewBranch['remote']" + "text": "string" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "hunkId" }, { - "kind": "field", - "name": "remotePromise", + "name": "fileName", "type": { - "text": "GetOverviewBranch['remote']" + "text": "string" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "fileName" }, { - "kind": "field", - "name": "_wip", + "name": "hunkHeader", "type": { - "text": "Awaited" + "text": "string | undefined" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "hunkHeader" }, { - "kind": "field", - "name": "wip", + "name": "content", "type": { - "text": "Awaited" + "text": "string" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "content" }, { - "kind": "field", - "name": "_wipPromise", + "name": "additions", "type": { - "text": "GetOverviewBranch['wip']" + "text": "number" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "additions" }, { - "kind": "field", - "name": "wipPromise", + "name": "deletions", "type": { - "text": "GetOverviewBranch['wip']" + "text": "number" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "deletions" }, { - "kind": "field", - "name": "busy", + "name": "selected", "type": { "text": "boolean" }, "default": "false", - "attribute": "busy", - "reflects": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "selected" }, { - "kind": "field", - "name": "expanded", + "name": "multiSelected", "type": { "text": "boolean" }, "default": "false", - "attribute": "expanded", - "reflects": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "multiSelected" }, { - "kind": "field", - "name": "expandable", + "name": "isRename", "type": { "text": "boolean" }, "default": "false", - "attribute": "expandable", - "reflects": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "isRename" }, { - "kind": "field", - "name": "eventController", + "name": "originalFileName", "type": { - "text": "AbortController | undefined" + "text": "string | undefined" }, - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "originalFileName" }, { - "kind": "method", - "name": "onExpandableChanged", - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, + "name": "isPreviewMode", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "isPreviewMode" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-hunk-item", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "HunkItem", + "declaration": { + "name": "HunkItem", + "module": "src/webviews/apps/plus/composer/components/hunk-item.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-hunk-item", + "declaration": { + "name": "HunkItem", + "module": "src/webviews/apps/plus/composer/components/hunk-item.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GitActionsButtons", + "members": [ { "kind": "field", - "name": "branchRef", + "name": "branchState", "type": { - "text": "BranchRef" + "text": "BranchState | undefined" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "branchState" }, { "kind": "field", - "name": "isWorktree", + "name": "branchName", "type": { - "text": "boolean" + "text": "string | undefined" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "branchName" }, { "kind": "field", - "name": "cardIndicator", + "name": "lastFetched", "type": { - "text": "GlCard['indicator']" + "text": "Date | undefined" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "lastFetched" }, { "kind": "field", - "name": "branchCardIndicator", + "name": "state", "type": { - "text": "GlCard['indicator']" + "text": "State" }, - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, - { - "kind": "method", - "name": "attachFocusListener", - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "state" }, { "kind": "field", - "name": "onFocus", + "name": "fetchedText", "privacy": "private", - "readonly": true, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, + "readonly": true + } + ], + "attributes": [ { - "kind": "method", - "name": "renderIssues", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "name": "branchState", + "type": { + "text": "BranchState | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "branchState" }, { - "kind": "method", - "name": "renderWip", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "name": "branchName", + "type": { + "text": "string | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "branchName" }, { - "kind": "method", - "name": "renderAvatars", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "name": "lastFetched", + "type": { + "text": "Date | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "lastFetched" }, { - "kind": "method", - "name": "renderTracking", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "name": "state", + "type": { + "text": "State" }, - "parameters": [ - { - "name": "showWip", - "default": "false" - } - ], - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, + "fieldName": "state" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-git-actions-buttons", + "customElement": true + }, + { + "kind": "class", + "description": "", + "name": "GlFetchButton", + "members": [ { - "kind": "method", - "name": "renderBranchActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "kind": "field", + "name": "state", + "type": { + "text": "State" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "state" }, { - "kind": "method", - "name": "renderPrActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "kind": "field", + "name": "fetchedText", + "type": { + "text": "string | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "fetchedText" }, { - "kind": "method", - "name": "renderCollapsedActions", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "kind": "field", + "name": "branchState", + "type": { + "text": "BranchState | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "branchState" }, { - "kind": "method", - "name": "createWebviewCommandLink", - "privacy": "protected", - "return": { - "type": { - "text": "string" - } + "kind": "field", + "name": "upstream", + "privacy": "private", + "readonly": true + } + ], + "attributes": [ + { + "name": "state", + "type": { + "text": "State" }, - "parameters": [ - { - "name": "command", - "type": { - "text": "WebviewCommands | WebviewViewCommands | PlusCommands" - } - }, - { - "name": "args", - "optional": true, - "type": { - "text": "T | any" - } - } - ], - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "state" }, { - "kind": "method", - "name": "createCommandLink", - "privacy": "protected", - "return": { - "type": { - "text": "string" - } + "name": "fetchedText", + "type": { + "text": "string | undefined" }, - "parameters": [ - { - "name": "command", - "type": { - "text": "GlCommands" - } - }, - { - "name": "args", - "optional": true, - "type": { - "text": "T | any" - } - } - ], - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "fetchedText" }, { - "kind": "method", - "name": "renderTimestamp", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "name": "branchState", + "type": { + "text": "BranchState | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, + "fieldName": "branchState" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-fetch-button", + "customElement": true + }, + { + "kind": "class", + "description": "", + "name": "PushPullButton", + "members": [ { - "kind": "method", - "name": "renderBranchItem", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "kind": "field", + "name": "branchState", + "type": { + "text": "BranchState | undefined" }, - "parameters": [ - { - "name": "actionsSection", - "optional": true, - "type": { - "text": "TemplateResult | NothingType" - } - } - ], - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "branchState" }, { - "kind": "method", - "name": "renderBranchIcon", - "privacy": "private", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "kind": "field", + "name": "state", + "type": { + "text": "State" + }, + "attribute": "state" }, { - "kind": "method", - "name": "renderPrItem", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "kind": "field", + "name": "fetchedText", + "type": { + "text": "string | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "fetchedText" }, { - "kind": "method", - "name": "renderLaunchpadItem", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "kind": "field", + "name": "branchName", + "type": { + "text": "string | undefined" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "attribute": "branchName" }, { - "kind": "method", - "name": "renderMergeTargetStatus", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "kind": "field", + "name": "isBehind", + "type": { + "text": "boolean" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "privacy": "private", + "readonly": true }, { - "kind": "method", - "name": "renderIssuesItem", - "privacy": "protected", - "return": { - "type": { - "text": "TemplateResult | NothingType" - } + "kind": "field", + "name": "isAhead", + "type": { + "text": "boolean" }, - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "upstream", + "privacy": "private", + "readonly": true }, { "kind": "method", - "name": "toggleExpanded", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "expanded", - "default": "!this.expanded" - } - ], - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "name": "renderBranchPrefix", + "privacy": "private" }, { "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } - }, + "name": "renderTooltipContent", + "privacy": "private", "parameters": [ { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, + "name": "action", "type": { - "text": "Omit>, 'detail'>" + "text": "'pull' | 'push'" } } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } + ] } ], - "superclass": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - }, - "tagName": "gl-branch-card", - "customElement": true, "attributes": [ { - "name": "repo", + "name": "branchState", "type": { - "text": "string" + "text": "BranchState | undefined" }, - "fieldName": "repo", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } + "fieldName": "branchState" }, { - "name": "showUpgrade", + "name": "state", "type": { - "text": "boolean" + "text": "State" }, - "default": "false", - "fieldName": "showUpgrade", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, - { - "name": "branch", - "type": { - "text": "GetOverviewBranch" - }, - "fieldName": "branch", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, - { - "name": "busy", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "busy", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, - { - "name": "expanded", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "expanded", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - }, - { - "name": "expandable", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "expandable", - "inheritedFrom": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" - } - } - ] - }, - { - "kind": "class", - "description": "", - "name": "GlWorkUnit", - "members": [ - { - "kind": "field", - "name": "primary", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "primary", - "reflects": true - }, - { - "kind": "field", - "name": "nested", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "nested", - "reflects": true - }, - { - "kind": "field", - "name": "indicator", - "type": { - "text": "GlCard['indicator'] | undefined" - }, - "attribute": "indicator", - "reflects": true - }, - { - "kind": "field", - "name": "expanded", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "expanded", - "reflects": true - }, - { - "kind": "method", - "name": "renderContent", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderSummary", - "privacy": "private" - } - ], - "attributes": [ - { - "name": "primary", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "primary" - }, - { - "name": "nested", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "nested" + "fieldName": "state" }, { - "name": "indicator", + "name": "fetchedText", "type": { - "text": "GlCard['indicator'] | undefined" + "text": "string | undefined" }, - "fieldName": "indicator" + "fieldName": "fetchedText" }, { - "name": "expanded", + "name": "branchName", "type": { - "text": "boolean" + "text": "string | undefined" }, - "default": "false", - "fieldName": "expanded" + "fieldName": "branchName" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-work-item", + "tagName": "gl-push-pull-button", "customElement": true } ], "exports": [ { "kind": "js", - "name": "branchCardStyles", + "name": "GitActionsButtons", "declaration": { - "name": "branchCardStyles", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "GitActionsButtons", + "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" } }, { - "kind": "js", - "name": "GlBranchCardBase", + "kind": "custom-element-definition", + "name": "gl-git-actions-buttons", "declaration": { - "name": "GlBranchCardBase", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "GitActionsButtons", + "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" } }, { "kind": "js", - "name": "GlBranchCard", + "name": "GlFetchButton", "declaration": { - "name": "GlBranchCard", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "GlFetchButton", + "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" } }, { "kind": "custom-element-definition", - "name": "gl-branch-card", + "name": "gl-fetch-button", "declaration": { - "name": "GlBranchCard", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "GlFetchButton", + "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" } }, { "kind": "js", - "name": "GlWorkUnit", + "name": "PushPullButton", "declaration": { - "name": "GlWorkUnit", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "PushPullButton", + "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" } }, { "kind": "custom-element-definition", - "name": "gl-work-item", + "name": "gl-push-pull-button", "declaration": { - "name": "GlWorkUnit", - "module": "src/webviews/apps/plus/home/components/branch-card.ts" + "name": "PushPullButton", + "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/home/components/branch-section.ts", + "path": "src/webviews/apps/plus/graph/graph-wrapper/gl-graph.ts", "declarations": [ { "kind": "class", - "description": "", - "name": "GlSection", + "description": "A LitElement web component that encapsulates the GraphWrapperReact component.\nThis component mounts the React component once and then updates its state\nwithout remounting on subsequent property changes.", + "name": "GlGraph", "members": [ { "kind": "field", - "name": "loading", + "name": "reactRoot", "type": { - "text": "boolean" + "text": "ReturnType | null" }, - "default": "false", - "attribute": "loading" + "privacy": "private", + "default": "null" }, { "kind": "field", - "name": "headingLevel", + "name": "provideReactState", "type": { - "text": "ARIAMixin['ariaLevel']" + "text": "((props: Partial) => void) | null" }, - "default": "'3'", - "attribute": "heading-level" - } - ], - "attributes": [ + "privacy": "private", + "default": "null" + }, { - "name": "loading", + "kind": "field", + "name": "setReactStateProvider", + "privacy": "private" + }, + { + "kind": "field", + "name": "activeRow", "type": { - "text": "boolean" + "text": "GraphWrapperProps['activeRow'] | undefined" }, - "default": "false", - "fieldName": "loading" + "attribute": "activeRow" }, { - "name": "heading-level", + "kind": "field", + "name": "avatars", "type": { - "text": "ARIAMixin['ariaLevel']" + "text": "GraphWrapperProps['avatars'] | undefined" }, - "default": "'3'", - "fieldName": "headingLevel" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-section", - "customElement": true - }, - { - "kind": "class", - "description": "", - "name": "GlBranchSection", - "members": [ + "attribute": "avatars" + }, { "kind": "field", - "name": "label", + "name": "columns", "type": { - "text": "string" + "text": "GraphWrapperProps['columns'] | undefined" }, - "attribute": "label" + "attribute": "columns" }, { "kind": "field", - "name": "repo", + "name": "context", "type": { - "text": "string" + "text": "GraphWrapperProps['context'] | undefined" }, - "attribute": "repo" + "attribute": "context" }, { "kind": "field", - "name": "branches", + "name": "config", "type": { - "text": "GetOverviewBranch[]" + "text": "GraphWrapperProps['config'] | undefined" }, - "attribute": "branches" + "attribute": "config" }, { "kind": "field", - "name": "isFetching", + "name": "downstreams", "type": { - "text": "boolean" + "text": "GraphWrapperProps['downstreams'] | undefined" }, - "default": "false", - "attribute": "isFetching" + "attribute": "downstreams" }, { "kind": "field", - "name": "branchCards", + "name": "rows", "type": { - "text": "GlBranchCardBase[]" + "text": "GraphWrapperProps['rows'] | undefined" }, - "privacy": "private" + "attribute": "rows" }, { "kind": "field", - "name": "onCardExpanded", - "privacy": "private", - "readonly": true + "name": "excludeRefs", + "type": { + "text": "GraphWrapperProps['excludeRefs'] | undefined" + }, + "attribute": "excludeRefs" }, { - "kind": "method", - "name": "toggleSiblingCards", - "privacy": "private", - "parameters": [ - { - "name": "card", - "optional": true, - "type": { - "text": "GlBranchCardBase" - } - } - ] + "kind": "field", + "name": "excludeTypes", + "type": { + "text": "GraphWrapperProps['excludeTypes'] | undefined" + }, + "attribute": "excludeTypes" }, { "kind": "field", - "name": "toggleSiblingCardsDebounced", - "privacy": "private" + "name": "paging", + "type": { + "text": "GraphWrapperProps['paging'] | undefined" + }, + "attribute": "paging" }, { - "kind": "method", - "name": "renderSectionLabel", - "privacy": "private" - } - ], - "attributes": [ + "kind": "field", + "name": "loading", + "type": { + "text": "GraphWrapperProps['loading'] | undefined" + }, + "attribute": "loading" + }, { - "name": "label", + "kind": "field", + "name": "selectedRows", "type": { - "text": "string" + "text": "GraphWrapperProps['selectedRows'] | undefined" }, - "fieldName": "label" + "attribute": "selectedRows" }, { - "name": "repo", + "kind": "field", + "name": "windowFocused", "type": { - "text": "string" + "text": "GraphWrapperProps['windowFocused'] | undefined" }, - "fieldName": "repo" + "attribute": "windowFocused" }, { - "name": "branches", + "kind": "field", + "name": "refsMetadata", "type": { - "text": "GetOverviewBranch[]" + "text": "GraphWrapperProps['refsMetadata'] | undefined" }, - "fieldName": "branches" + "attribute": "refsMetadata" }, { - "name": "isFetching", + "kind": "field", + "name": "includeOnlyRefs", "type": { - "text": "boolean" + "text": "GraphWrapperProps['includeOnlyRefs'] | undefined" }, - "default": "false", - "fieldName": "isFetching" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-branch-section", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "GlSection", - "declaration": { - "name": "GlSection", - "module": "src/webviews/apps/plus/home/components/branch-section.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-section", - "declaration": { - "name": "GlSection", - "module": "src/webviews/apps/plus/home/components/branch-section.ts" - } - }, - { - "kind": "js", - "name": "GlBranchSection", - "declaration": { - "name": "GlBranchSection", - "module": "src/webviews/apps/plus/home/components/branch-section.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-branch-section", - "declaration": { - "name": "GlBranchSection", - "module": "src/webviews/apps/plus/home/components/branch-section.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts", - "declarations": [ - { - "kind": "variable", - "name": "selectStyles", - "default": "css` .select { background: none; outline: none; border: none; text-decoration: none !important; font-weight: 500; color: var(--color-foreground--25); } .select option { color: var(--vscode-foreground); background-color: var(--vscode-dropdown-background); } .select:not(:disabled) { cursor: pointer; color: var(--color-foreground--50); } .select:not(:disabled):focus { outline: 1px solid var(--color-focus-border); } .select:not(:disabled):hover { color: var(--vscode-foreground); text-decoration: underline !important; } `" - }, - { - "kind": "class", - "description": "", - "name": "GlObjectSelect", - "members": [ + "attribute": "includeOnlyRefs" + }, { "kind": "field", - "name": "disabled", + "name": "rowsStats", "type": { - "text": "boolean" + "text": "GraphWrapperProps['rowsStats'] | undefined" }, - "default": "false", - "attribute": "disabled" + "attribute": "rowsStats" }, { "kind": "field", - "name": "value", + "name": "rowsStatsLoading", "type": { - "text": "V | undefined" + "text": "GraphWrapperProps['rowsStatsLoading'] | undefined" }, - "attribute": "value" + "attribute": "rowsStatsLoading" }, { "kind": "field", - "name": "options", + "name": "workingTreeStats", "type": { - "text": "T[] | undefined" + "text": "GraphWrapperProps['workingTreeStats'] | undefined" }, - "attribute": "options" + "attribute": "workingTreeStats" }, { - "kind": "method", - "name": "getValue", - "privacy": "protected", - "return": { - "type": { - "text": "V" - } + "kind": "field", + "name": "theming", + "type": { + "text": "GraphWrapperProps['theming'] | undefined" }, - "parameters": [ - { - "name": "option", - "type": { - "text": "T" - } - } - ] + "attribute": "theming" }, { - "kind": "method", - "name": "getLabel", - "privacy": "protected", - "return": { - "type": { - "text": "L" - } + "kind": "field", + "name": "searchResults", + "type": { + "text": "GraphWrapperProps['searchResults'] | undefined" }, - "parameters": [ - { - "name": "option", - "type": { - "text": "T" - } - } - ] + "attribute": "searchResults" }, { - "kind": "method", - "name": "onChange", - "privacy": "protected", - "return": { - "type": { - "text": "unknown" - } + "kind": "field", + "name": "filter", + "type": { + "text": "SearchQuery" }, - "parameters": [ - { - "name": "e", - "type": { - "text": "InputEvent" - } - } - ] + "attribute": "filter" }, { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } + "kind": "field", + "name": "setRef", + "type": { + "text": "(ref: GraphContainer) => void" + } + }, + { + "kind": "field", + "name": "changedProps", + "type": { + "text": "Map" }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } - } - ], - "attributes": [ + "privacy": "private", + "default": "new Map()" + }, { - "name": "disabled", + "kind": "field", + "name": "updateScheduled", "type": { "text": "boolean" }, - "default": "false", - "fieldName": "disabled" + "privacy": "private", + "default": "false" }, { - "name": "value", - "type": { - "text": "V | undefined" - }, - "fieldName": "value" + "kind": "field", + "name": "handleChangeColumns", + "privacy": "private" }, { - "name": "options", - "type": { - "text": "T[] | undefined" - }, - "fieldName": "options" + "kind": "field", + "name": "handleChangeRefsVisibility", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleChangeSelection", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleChangeVisibleDays", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleMissingAvatars", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleMissingRefsMetadata", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleMoreRows", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleMouseLeave", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleRefDoubleClick", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleRowContextMenu", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleRowDoubleClick", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleRowHover", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleRowUnhover", + "privacy": "private" } ], - "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" - } - }, - { - "kind": "class", - "description": "", - "name": "GlBranchThresholdFilter", - "members": [ + "attributes": [ { - "kind": "method", - "name": "getValue", - "privacy": "protected", - "return": { - "type": { - "text": "OverviewRecentThreshold | 'OneYear'" - } + "name": "activeRow", + "type": { + "text": "GraphWrapperProps['activeRow'] | undefined" }, - "parameters": [ - { - "name": "option", - "type": { - "text": "{\n\t\tvalue: OverviewRecentThreshold | OverviewStaleThreshold;\n\t}" - } - } - ], - "inheritedFrom": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } + "fieldName": "activeRow" }, { - "kind": "method", - "name": "getLabel", - "privacy": "protected", - "return": { - "type": { - "text": "string" - } + "name": "avatars", + "type": { + "text": "GraphWrapperProps['avatars'] | undefined" }, - "parameters": [ - { - "name": "option", - "type": { - "text": "{ label: string }" - } - } - ], - "inheritedFrom": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } + "fieldName": "avatars" }, { - "kind": "method", - "name": "onChange", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } + "name": "columns", + "type": { + "text": "GraphWrapperProps['columns'] | undefined" }, - "parameters": [ - { - "name": "e", - "type": { - "text": "InputEvent" - } - } - ], - "inheritedFrom": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } + "fieldName": "columns" }, { - "kind": "field", - "name": "disabled", + "name": "context", "type": { - "text": "boolean" + "text": "GraphWrapperProps['context'] | undefined" }, - "default": "false", - "attribute": "disabled", - "inheritedFrom": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } + "fieldName": "context" }, { - "kind": "field", - "name": "value", + "name": "config", "type": { - "text": "V | undefined" + "text": "GraphWrapperProps['config'] | undefined" }, - "attribute": "value", - "inheritedFrom": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } + "fieldName": "config" }, { - "kind": "field", - "name": "options", + "name": "downstreams", "type": { - "text": "T[] | undefined" + "text": "GraphWrapperProps['downstreams'] | undefined" }, - "attribute": "options", - "inheritedFrom": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } + "fieldName": "downstreams" }, { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } + "name": "rows", + "type": { + "text": "GraphWrapperProps['rows'] | undefined" }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } - } - ], - "superclass": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - }, - "tagName": "gl-branch-threshold-filter", - "customElement": true, - "attributes": [ + "fieldName": "rows" + }, { - "name": "disabled", + "name": "excludeRefs", "type": { - "text": "boolean" + "text": "GraphWrapperProps['excludeRefs'] | undefined" }, - "default": "false", - "fieldName": "disabled", - "inheritedFrom": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } + "fieldName": "excludeRefs" }, { - "name": "value", + "name": "excludeTypes", "type": { - "text": "V | undefined" + "text": "GraphWrapperProps['excludeTypes'] | undefined" }, - "fieldName": "value", - "inheritedFrom": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } + "fieldName": "excludeTypes" }, { - "name": "options", + "name": "paging", "type": { - "text": "T[] | undefined" + "text": "GraphWrapperProps['paging'] | undefined" }, - "fieldName": "options", - "inheritedFrom": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } - } - ] - } - ], - "exports": [ - { - "kind": "js", - "name": "selectStyles", - "declaration": { - "name": "selectStyles", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } - }, - { - "kind": "js", - "name": "GlObjectSelect", - "declaration": { - "name": "GlObjectSelect", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } - }, - { - "kind": "js", - "name": "GlBranchThresholdFilter", - "declaration": { - "name": "GlBranchThresholdFilter", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-branch-threshold-filter", - "declaration": { - "name": "GlBranchThresholdFilter", - "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/home/components/launchpad.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlLaunchpad", - "members": [ + "fieldName": "paging" + }, { - "kind": "field", - "name": "shadowRootOptions", + "name": "loading", "type": { - "text": "ShadowRootInit" + "text": "GraphWrapperProps['loading'] | undefined" }, - "static": true, - "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + "fieldName": "loading" }, { - "kind": "field", - "name": "_homeState", + "name": "selectedRows", "type": { - "text": "State" + "text": "GraphWrapperProps['selectedRows'] | undefined" }, - "privacy": "private" + "fieldName": "selectedRows" }, { - "kind": "field", - "name": "_ipc", + "name": "windowFocused", "type": { - "text": "HostIpc" + "text": "GraphWrapperProps['windowFocused'] | undefined" }, - "privacy": "private" + "fieldName": "windowFocused" }, { - "kind": "field", - "name": "_disposable", + "name": "refsMetadata", "type": { - "text": "Disposable[]" + "text": "GraphWrapperProps['refsMetadata'] | undefined" }, - "privacy": "private", - "default": "[]" + "fieldName": "refsMetadata" }, { - "kind": "field", - "name": "_summary", - "privacy": "private" + "name": "includeOnlyRefs", + "type": { + "text": "GraphWrapperProps['includeOnlyRefs'] | undefined" + }, + "fieldName": "includeOnlyRefs" }, { - "kind": "field", - "name": "_summaryState", - "privacy": "private", - "default": "new AsyncComputedState(async _abortSignal => { const rsp = await this._ipc.sendRequest(GetLaunchpadSummary, {}); return rsp; })" + "name": "rowsStats", + "type": { + "text": "GraphWrapperProps['rowsStats'] | undefined" + }, + "fieldName": "rowsStats" }, { - "kind": "field", - "name": "startWorkCommand", + "name": "rowsStatsLoading", "type": { - "text": "string" + "text": "GraphWrapperProps['rowsStatsLoading'] | undefined" }, - "readonly": true + "fieldName": "rowsStatsLoading" }, { - "kind": "field", - "name": "createBranchCommand", + "name": "workingTreeStats", "type": { - "text": "string" + "text": "GraphWrapperProps['workingTreeStats'] | undefined" }, - "readonly": true + "fieldName": "workingTreeStats" }, { - "kind": "method", - "name": "renderSummaryResult", - "privacy": "private" + "name": "theming", + "type": { + "text": "GraphWrapperProps['theming'] | undefined" + }, + "fieldName": "theming" }, { - "kind": "method", - "name": "renderPending", - "privacy": "private" + "name": "searchResults", + "type": { + "text": "GraphWrapperProps['searchResults'] | undefined" + }, + "fieldName": "searchResults" }, { - "kind": "method", - "name": "renderSummary", - "privacy": "private", - "parameters": [ - { - "name": "summary", - "type": { - "text": "LaunchpadSummary | undefined" - } - } - ] - } - ], - "mixins": [ - { - "name": "SignalWatcher", - "package": "@lit-labs/signals" + "name": "filter", + "type": { + "text": "SearchQuery" + }, + "fieldName": "filter" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-launchpad", + "tagName": "gl-graph", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlLaunchpad", + "name": "GlGraph", "declaration": { - "name": "GlLaunchpad", - "module": "src/webviews/apps/plus/home/components/launchpad.ts" + "name": "GlGraph", + "module": "src/webviews/apps/plus/graph/graph-wrapper/gl-graph.ts" } }, { "kind": "custom-element-definition", - "name": "gl-launchpad", + "name": "gl-graph", "declaration": { - "name": "GlLaunchpad", - "module": "src/webviews/apps/plus/home/components/launchpad.ts" + "name": "GlGraph", + "module": "src/webviews/apps/plus/graph/graph-wrapper/gl-graph.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/home/components/merge-target-status.ts", + "path": "src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlMergeTargetStatus", + "name": "GlGraphWrapper", "members": [ { "kind": "field", - "name": "shadowRootOptions", + "name": "disposables", "type": { - "text": "ShadowRootInit" + "text": "Disposable[]" }, - "static": true, - "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + "privacy": "private", + "default": "[]" }, { "kind": "field", - "name": "branch", + "name": "graphState", "type": { - "text": "Pick" + "text": "typeof graphStateContext.__context__" }, - "attribute": "branch" + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "_target", + "name": "_ipc", "type": { - "text": "Awaited" + "text": "typeof ipcContext.__context__" }, - "privacy": "private" + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "target", + "name": "_telemetry", "type": { - "text": "Awaited" + "text": "TelemetryContext" }, + "privacy": "private", "readonly": true }, { "kind": "field", - "name": "_targetPromise", + "name": "graph", "type": { - "text": "GetOverviewBranch['mergeTarget']" - }, - "privacy": "private" + "text": "typeof GlGraph" + } }, { "kind": "field", - "name": "targetPromise", + "name": "ref", "type": { - "text": "GetOverviewBranch['mergeTarget']" + "text": "GraphContainer | undefined" }, - "attribute": "targetPromise" - }, - { - "kind": "field", - "name": "conflicts", - "privacy": "private", - "readonly": true - }, - { - "kind": "field", - "name": "mergedStatus", - "privacy": "private", - "readonly": true + "privacy": "private" }, { "kind": "field", - "name": "status", - "privacy": "private", - "readonly": true + "name": "onSetRef", + "privacy": "private" }, { "kind": "field", - "name": "branchRef", + "name": "theming", "type": { - "text": "BranchRef | undefined" + "text": "GraphWrapperTheming | undefined" }, - "privacy": "private", - "readonly": true - }, - { - "kind": "field", - "name": "targetBranchRef", - "type": { - "text": "BranchRef | undefined" - }, - "privacy": "private", - "readonly": true - }, - { - "kind": "method", - "name": "renderContent", "privacy": "private" }, { "kind": "method", - "name": "renderHeader", - "privacy": "private", + "name": "selectCommits", "parameters": [ { - "name": "title", + "name": "shaList", "type": { - "text": "string" + "text": "string[]" } }, { - "name": "icon", + "name": "includeToPrevSel", "type": { - "text": "string" + "text": "boolean" } }, { - "name": "status", - "optional": true, + "name": "isAutoOrKeyScroll", "type": { - "text": "string" + "text": "boolean" } } ] }, { "kind": "method", - "name": "renderHeaderActions", - "privacy": "private" + "name": "onColumnsChanged", + "privacy": "private", + "parameters": [ + { + "name": "event", + "type": { + "text": "CustomEventType<'graph-changecolumns'>" + } + } + ] }, { "kind": "method", - "name": "renderInlineTargetEdit", + "name": "onGetMoreRows", "privacy": "private", "parameters": [ { - "name": "target", + "name": "{ detail: sha }", "type": { - "text": "Awaited" + "text": "CustomEventType<'graph-morerows'>" } } ] }, { "kind": "method", - "name": "renderFiles", + "name": "onMouseLeave", + "privacy": "private" + }, + { + "kind": "method", + "name": "onMissingAvatars", "privacy": "private", "parameters": [ { - "name": "files", + "name": "{ detail: emails }", "type": { - "text": "{ path: string }[]" + "text": "CustomEventType<'graph-missingavatars'>" } } ] }, { "kind": "method", - "name": "renderFile", + "name": "onMissingRefsMetadata", "privacy": "private", "parameters": [ { - "name": "path", + "name": "{ detail: metadata }", "type": { - "text": "string" + "text": "CustomEventType<'graph-missingrefsmetadata'>" } } ] - } - ], - "attributes": [ + }, { - "name": "branch", - "type": { - "text": "Pick" - }, - "fieldName": "branch" + "kind": "method", + "name": "onRefDoubleClick", + "privacy": "private", + "parameters": [ + { + "name": "{ detail: { ref, metadata } }", + "type": { + "text": "CustomEventType<'graph-doubleclickref'>" + } + } + ] }, { - "name": "targetPromise", - "type": { - "text": "GetOverviewBranch['mergeTarget']" - }, - "fieldName": "targetPromise" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-merge-target-status", - "customElement": true - }, - { - "kind": "class", - "description": "", - "name": "GlMergeTargetUpgrade", - "members": [ + "kind": "method", + "name": "onRefsVisibilityChanged", + "privacy": "private", + "parameters": [ + { + "name": "{ detail }", + "type": { + "text": "CustomEventType<'graph-changerefsvisibility'>" + } + } + ] + }, { - "kind": "field", - "name": "shadowRootOptions", - "type": { - "text": "ShadowRootInit" - }, - "static": true, - "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-merge-target-upgrade", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "GlMergeTargetStatus", - "declaration": { - "name": "GlMergeTargetStatus", - "module": "src/webviews/apps/plus/home/components/merge-target-status.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-merge-target-status", - "declaration": { - "name": "GlMergeTargetStatus", - "module": "src/webviews/apps/plus/home/components/merge-target-status.ts" - } - }, - { - "kind": "js", - "name": "GlMergeTargetUpgrade", - "declaration": { - "name": "GlMergeTargetUpgrade", - "module": "src/webviews/apps/plus/home/components/merge-target-status.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-merge-target-upgrade", - "declaration": { - "name": "GlMergeTargetUpgrade", - "module": "src/webviews/apps/plus/home/components/merge-target-status.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/home/components/overview.ts", - "declarations": [ - { - "kind": "variable", - "name": "overviewTagName", - "type": { - "text": "string" - }, - "default": "'gl-overview'" - }, - { - "kind": "class", - "description": "", - "name": "GlOverview", - "members": [ + "kind": "method", + "name": "onRowContextMenu", + "privacy": "private", + "parameters": [ + { + "name": "{ detail: { graphRow, graphZoneType } }", + "type": { + "text": "CustomEventType<'graph-rowcontextmenu'>" + } + } + ] + }, { - "kind": "field", - "name": "_homeState", - "type": { - "text": "State" - }, - "privacy": "private" + "kind": "method", + "name": "onRowDoubleClick", + "privacy": "private", + "parameters": [ + { + "name": "{ detail: { row, preserveFocus } }", + "type": { + "text": "CustomEventType<'graph-doubleclickrow'>" + } + } + ] }, { - "kind": "field", - "name": "_inactiveOverviewState", - "type": { - "text": "InactiveOverviewState" - }, - "privacy": "private" + "kind": "method", + "name": "onRowHover", + "privacy": "private", + "parameters": [ + { + "name": "{ detail }", + "type": { + "text": "CustomEventType<'graph-graphrowhovered'>" + } + } + ] }, { "kind": "method", - "name": "renderLoader", - "privacy": "private" + "name": "onRowUnhover", + "privacy": "private", + "parameters": [ + { + "name": "{ detail }", + "type": { + "text": "CustomEventType<'graph-graphrowunhovered'>" + } + } + ] }, { "kind": "method", - "name": "renderPending", - "privacy": "private" + "name": "onSelectionChanged", + "privacy": "private", + "parameters": [ + { + "name": "{ detail: rows }", + "type": { + "text": "CustomEventType<'graph-changeselection'>" + } + } + ] }, { - "kind": "field", - "name": "_ipc", - "type": { - "text": "HostIpc" - }, + "kind": "method", + "name": "onVisibleDaysChanged", "privacy": "private", - "readonly": true + "parameters": [ + { + "name": "{ detail }", + "type": { + "text": "CustomEventType<'graph-changevisibledays'>" + } + } + ] }, { "kind": "field", - "name": "onChangeRecentThresholdFilter", + "name": "themingDefaults", + "type": { + "text": "{ cssVariables: CssVariables; themeOpacityFactor: number }" + }, "privacy": "private", - "readonly": true + "readonly": true, + "default": "{ cssVariables: (() => { const bgColor = getCssVariableValue('--color-background'); const mixedGraphColors: CssVariables = {}; let i = 0; let color; for (const [colorVar, colorDefault] of graphLaneThemeColors) { color = getCssVariableValue(colorVar, { fallbackValue: colorDefault }); mixedGraphColors[`--graph-color-${i}`] = color; for (const mixInt of [15, 25, 45, 50]) { mixedGraphColors[`--graph-color-${i}-bg${mixInt}`] = getCssMixedColorValue(bgColor, color, mixInt); } for (const mixInt of [10, 50]) { mixedGraphColors[`--graph-color-${i}-f${mixInt}`] = getCssOpacityColorValue(color, mixInt); } i++; } return { '--app__bg0': getCssVariableValue('--color-background'), '--panel__bg0': getCssVariableValue('--color-graph-background'), '--panel__bg1': getCssVariableValue('--color-graph-background2'), '--section-border': getCssVariableValue('--color-graph-background2'), '--selected-row': getCssVariableValue('--color-graph-selected-row'), '--selected-row-border': 'none', '--hover-row': getCssVariableValue('--color-graph-hover-row'), '--hover-row-border': 'none', '--scrollable-scrollbar-thickness': getCssVariableValue('--graph-column-scrollbar-thickness'), '--scroll-thumb-bg': getCssVariableValue('--vscode-scrollbarSlider-background'), '--scroll-marker-head-color': getCssVariableValue('--color-graph-scroll-marker-head'), '--scroll-marker-upstream-color': getCssVariableValue('--color-graph-scroll-marker-upstream'), '--scroll-marker-highlights-color': getCssVariableValue('--color-graph-scroll-marker-highlights'), '--scroll-marker-local-branches-color': getCssVariableValue( '--color-graph-scroll-marker-local-branches', ), '--scroll-marker-remote-branches-color': getCssVariableValue( '--color-graph-scroll-marker-remote-branches', ), '--scroll-marker-stashes-color': getCssVariableValue('--color-graph-scroll-marker-stashes'), '--scroll-marker-tags-color': getCssVariableValue('--color-graph-scroll-marker-tags'), '--scroll-marker-selection-color': getCssVariableValue('--color-graph-scroll-marker-selection'), '--scroll-marker-pull-requests-color': getCssVariableValue('--color-graph-scroll-marker-pull-requests'), '--stats-added-color': getCssVariableValue('--color-graph-stats-added'), '--stats-deleted-color': getCssVariableValue('--color-graph-stats-deleted'), '--stats-files-color': getCssVariableValue('--color-graph-stats-files'), '--stats-bar-border-radius': getCssVariableValue('--graph-stats-bar-border-radius'), '--stats-bar-height': getCssVariableValue('--graph-stats-bar-height'), '--text-selected': getCssVariableValue('--color-graph-text-selected'), '--text-selected-row': getCssVariableValue('--color-graph-text-selected-row'), '--text-hovered': getCssVariableValue('--color-graph-text-hovered'), '--text-dimmed-selected': getCssVariableValue('--color-graph-text-dimmed-selected'), '--text-dimmed': getCssVariableValue('--color-graph-text-dimmed'), '--text-normal': getCssVariableValue('--color-graph-text-normal'), '--text-secondary': getCssVariableValue('--color-graph-text-secondary'), '--text-disabled': getCssVariableValue('--color-graph-text-disabled'), '--text-accent': getCssVariableValue('--color-link-foreground'), '--text-inverse': getCssVariableValue('--vscode-input-background'), '--text-bright': getCssVariableValue('--vscode-input-background'), ...mixedGraphColors, }; })(), themeOpacityFactor: 1, }" }, { "kind": "method", - "name": "renderComplete", + "name": "getGraphTheming", "privacy": "private", + "return": { + "type": { + "text": "GraphWrapperTheming" + } + }, "parameters": [ { - "name": "overview", + "name": "e", + "optional": true, "type": { - "text": "GetInactiveOverviewResponse" + "text": "ThemeChangeEvent" } - }, - { - "name": "isFetching", - "default": "false" } ] } ], + "events": [ + { + "name": "gl-graph-mouse-leave", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "gl-graph-row-context-menu", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "gl-graph-row-hover", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "gl-graph-row-unhover", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "gl-graph-change-selection", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "gl-graph-change-visible-days", + "type": { + "text": "CustomEvent" + } + } + ], "mixins": [ { "name": "SignalWatcher", @@ -20859,983 +20882,1179 @@ "name": "LitElement", "package": "lit" }, + "tagName": "gl-graph-wrapper", "customElement": true } ], "exports": [ { "kind": "js", - "name": "overviewTagName", - "declaration": { - "name": "overviewTagName", - "module": "src/webviews/apps/plus/home/components/overview.ts" - } - }, - { - "kind": "js", - "name": "GlOverview", + "name": "GlGraphWrapper", "declaration": { - "name": "GlOverview", - "module": "src/webviews/apps/plus/home/components/overview.ts" + "name": "GlGraphWrapper", + "module": "src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper.ts" } }, { "kind": "custom-element-definition", + "name": "gl-graph-wrapper", "declaration": { - "name": "GlOverview", - "module": "src/webviews/apps/plus/home/components/overview.ts" + "name": "GlGraphWrapper", + "module": "src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/home/components/overviewState.ts", + "path": "src/webviews/apps/plus/graph/hover/graphHover.ts", "declarations": [ { "kind": "class", "description": "", - "name": "ActiveOverviewState", + "name": "GlGraphHover", "members": [ { "kind": "field", - "name": "_disposable", + "name": "anchor", "type": { - "text": "Disposable | undefined" + "text": "Anchor | undefined" }, - "privacy": "private", - "readonly": true + "attribute": "anchor" }, { - "kind": "method", - "name": "dispose" + "kind": "field", + "name": "distance", + "type": { + "text": "number | undefined | undefined" + }, + "attribute": "distance", + "reflects": true }, { - "kind": "method", - "name": "changeRepository", - "return": { - "type": { - "text": "void" - } - } + "kind": "field", + "name": "open", + "type": { + "text": "boolean | undefined" + }, + "default": "false", + "attribute": "open", + "reflects": true }, { "kind": "field", - "name": "_debounce", + "name": "placement", "type": { - "text": "number" + "text": "GlPopover['placement'] | undefined" }, - "privacy": "private", - "default": "500", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "default": "'bottom-start'", + "attribute": "placement", + "reflects": true }, { "kind": "field", - "name": "_invalidate", - "privacy": "private", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "name": "markdown", + "type": { + "text": "Promise> | string | undefined" + }, + "attribute": "markdown" }, { "kind": "field", - "name": "_computed", + "name": "skidding", "type": { - "text": "AsyncComputed | undefined" + "text": "number | undefined | undefined" }, - "privacy": "private", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" + "attribute": "skidding", + "reflects": true + }, + { + "kind": "field", + "name": "requestMarkdown", + "type": { + "text": "((row: GraphRow) => Promise) | undefined" + }, + "attribute": "requestMarkdown" + }, + { + "kind": "field", + "name": "popup", + "type": { + "text": "GlPopover" } }, { "kind": "field", - "name": "_state", + "name": "hoverMarkdownCache", "privacy": "private", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "default": "new Map< string, Promise> | PromiseSettledResult | string >()" }, { "kind": "field", - "name": "state", + "name": "shaHovering", "type": { - "text": "T | undefined" + "text": "string | undefined" }, - "readonly": true, - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "privacy": "private" }, { "kind": "field", - "name": "computed", + "name": "unhoverTimer", "type": { - "text": "AsyncComputed" + "text": "ReturnType | undefined" }, - "readonly": true, - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "privacy": "private" }, { - "kind": "method", - "name": "_runCore", - "privacy": "private", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "kind": "field", + "name": "previousSkidding", + "type": { + "text": "number | undefined" + }, + "privacy": "private" }, { "kind": "field", - "name": "_runDebounced", + "name": "recalculated", "type": { - "text": "Deferrable<() => void> | undefined" + "text": "boolean" }, "privacy": "private", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "default": "false" }, { "kind": "method", - "name": "_run", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "immediate", - "default": "false" - } - ], - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "name": "onReposition", + "privacy": "private" }, { "kind": "method", - "name": "run", + "name": "reset", "return": { "type": { "text": "void" } - }, - "parameters": [ - { - "name": "force", - "default": "false" - } - ], - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" } }, { - "kind": "method", - "name": "invalidate", - "return": { - "type": { - "text": "void" - } - }, - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } - } - ], - "superclass": { - "name": "AsyncComputedState", - "module": "/src/webviews/apps/shared/components/signal-utils" - } - }, - { - "kind": "class", - "description": "", - "name": "InactiveOverviewState", - "members": [ + "kind": "field", + "name": "onParentMouseLeave", + "privacy": "private" + }, { "kind": "field", - "name": "_disposable", + "name": "onPopoverMouseLeave", + "privacy": "private" + }, + { + "kind": "field", + "name": "_showCoreDebounced", "type": { - "text": "Disposable | undefined" + "text": "Deferrable | undefined" }, "privacy": "private", - "readonly": true + "default": "undefined" }, { - "kind": "field", - "name": "filter" + "kind": "method", + "name": "onRowHovered", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "row", + "type": { + "text": "GraphRow" + } + }, + { + "name": "anchor", + "type": { + "text": "Anchor" + } + } + ] }, { "kind": "method", - "name": "dispose", + "name": "onRowUnhovered", "return": { "type": { "text": "void" } - } + }, + "parameters": [ + { + "name": "_row", + "type": { + "text": "GraphRow" + } + }, + { + "name": "relatedTarget", + "type": { + "text": "EventTarget | null" + } + } + ] }, { "kind": "field", - "name": "_debounce", - "type": { - "text": "number" - }, - "privacy": "private", - "default": "500", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "name": "onWindowKeydown", + "privacy": "private" }, { - "kind": "field", - "name": "_invalidate", + "kind": "method", + "name": "showCore", "privacy": "private", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "parameters": [ + { + "name": "anchor", + "type": { + "text": "string | HTMLElement | { getBoundingClientRect: () => Omit }" + } + }, + { + "name": "markdown", + "type": { + "text": "Promise> | PromiseSettledResult | string" + } + } + ] }, { "kind": "field", - "name": "_computed", + "name": "_lastUnhoveredTimestamp", "type": { - "text": "AsyncComputed | undefined" + "text": "number" }, "privacy": "private", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" + "default": "0" + }, + { + "kind": "method", + "name": "hide", + "return": { + "type": { + "text": "void" + } } }, { - "kind": "field", - "name": "_state", + "kind": "method", + "name": "resetUnhoverTimer", "privacy": "private", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" + "return": { + "type": { + "text": "void" + } } }, { - "kind": "field", - "name": "state", - "type": { - "text": "T | undefined" + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } }, - "readonly": true, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" } + } + ], + "attributes": [ + { + "name": "anchor", + "type": { + "text": "Anchor | undefined" + }, + "fieldName": "anchor" }, { - "kind": "field", - "name": "computed", + "name": "distance", "type": { - "text": "AsyncComputed" + "text": "number | undefined | undefined" }, - "readonly": true, - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "fieldName": "distance" }, { - "kind": "method", - "name": "_runCore", - "privacy": "private", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "name": "open", + "type": { + "text": "boolean | undefined" + }, + "default": "false", + "fieldName": "open" }, { - "kind": "field", - "name": "_runDebounced", + "name": "placement", "type": { - "text": "Deferrable<() => void> | undefined" + "text": "GlPopover['placement'] | undefined" }, - "privacy": "private", - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "default": "'bottom-start'", + "fieldName": "placement" }, { - "kind": "method", - "name": "_run", - "privacy": "protected", - "return": { - "type": { - "text": "void" - } + "name": "markdown", + "type": { + "text": "Promise> | string | undefined" }, - "parameters": [ - { - "name": "immediate", - "default": "false" - } - ], - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "fieldName": "markdown" }, { - "kind": "method", - "name": "run", - "return": { - "type": { - "text": "void" - } + "name": "skidding", + "type": { + "text": "number | undefined | undefined" }, - "parameters": [ - { - "name": "force", - "default": "false" - } - ], - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "fieldName": "skidding" }, { - "kind": "method", - "name": "invalidate", - "return": { - "type": { - "text": "void" - } + "name": "requestMarkdown", + "type": { + "text": "((row: GraphRow) => Promise) | undefined" }, - "inheritedFrom": { - "name": "AsyncComputedState", - "module": "src/webviews/apps/shared/components/signal-utils.ts" - } + "fieldName": "requestMarkdown" } ], "superclass": { - "name": "AsyncComputedState", - "module": "/src/webviews/apps/shared/components/signal-utils" - } - }, - { - "kind": "variable", - "name": "activeOverviewStateContext" - }, - { - "kind": "variable", - "name": "inactiveOverviewStateContext" + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" + }, + "tagName": "gl-graph-hover", + "customElement": true } ], "exports": [ { "kind": "js", - "name": "ActiveOverviewState", - "declaration": { - "name": "ActiveOverviewState", - "module": "src/webviews/apps/plus/home/components/overviewState.ts" - } - }, - { - "kind": "js", - "name": "InactiveOverviewState", - "declaration": { - "name": "InactiveOverviewState", - "module": "src/webviews/apps/plus/home/components/overviewState.ts" - } - }, - { - "kind": "js", - "name": "activeOverviewStateContext", + "name": "GlGraphHover", "declaration": { - "name": "activeOverviewStateContext", - "module": "src/webviews/apps/plus/home/components/overviewState.ts" + "name": "GlGraphHover", + "module": "src/webviews/apps/plus/graph/hover/graphHover.ts" } }, { - "kind": "js", - "name": "inactiveOverviewStateContext", + "kind": "custom-element-definition", + "name": "gl-graph-hover", "declaration": { - "name": "inactiveOverviewStateContext", - "module": "src/webviews/apps/plus/home/components/overviewState.ts" + "name": "GlGraphHover", + "module": "src/webviews/apps/plus/graph/hover/graphHover.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/shared/components/account-chip.ts", + "path": "src/webviews/apps/plus/graph/minimap/minimap-container.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlAccountChip", + "name": "GlGraphMinimapContainer", "members": [ { "kind": "field", - "name": "shadowRootOptions", + "name": "activeDay", "type": { - "text": "ShadowRootInit" + "text": "number | undefined" }, - "static": true, - "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + "attribute": "activeDay" }, { "kind": "field", - "name": "_showUpgrade", + "name": "disabled", "type": { "text": "boolean" }, - "privacy": "private", - "default": "false" + "default": "false", + "attribute": "disabled" }, { - "kind": "field", - "name": "showUpgrade", - "privacy": "private", - "attribute": "show-upgrade", - "reflects": true + "kind": "method", + "name": "onDisabledChanged", + "privacy": "private" }, { "kind": "field", - "name": "_chip", + "name": "dataType", "type": { - "text": "HTMLElement" + "text": "'commits' | 'lines'" }, - "privacy": "private" + "default": "'commits'", + "attribute": "dataType" }, { "kind": "field", - "name": "_popover", + "name": "downstreams", "type": { - "text": "GlPopover" + "text": "GraphDownstreams | undefined" }, - "privacy": "private" + "attribute": "downstreams" }, { "kind": "field", - "name": "_state", + "name": "markerTypes", "type": { - "text": "State" + "text": "GraphMinimapMarkerTypes[]" }, - "privacy": "private" - }, - { - "kind": "field", - "name": "accountAvatar", - "privacy": "private", - "readonly": true + "default": "[]", + "attribute": "markerTypes" }, { "kind": "field", - "name": "accountName", - "privacy": "private", - "readonly": true + "name": "refMetadata", + "type": { + "text": "GraphRefsMetadata | null | undefined" + }, + "attribute": "refMetadata" }, { "kind": "field", - "name": "accountEmail", - "privacy": "private", - "readonly": true + "name": "rows", + "type": { + "text": "GraphRow[]" + }, + "default": "[]", + "attribute": "rows" }, { "kind": "field", - "name": "hasAccount", - "privacy": "private", - "readonly": true + "name": "rowsStats", + "type": { + "text": "Record | undefined" + }, + "attribute": "rowsStats" }, { "kind": "field", - "name": "isReactivatedTrial", + "name": "searchResults", "type": { - "text": "boolean" + "text": "GraphSearchResults | GraphSearchResultsError | undefined" }, - "readonly": true + "attribute": "searchResults" }, { "kind": "field", - "name": "planId", - "privacy": "private", - "readonly": true + "name": "visibleDays", + "type": { + "text": "{ top: number; bottom: number } | undefined" + }, + "attribute": "visibleDays" }, { "kind": "field", - "name": "effectivePlanId", + "name": "markersByDay", "privacy": "private", - "readonly": true + "default": "new Map()" }, { "kind": "field", - "name": "planName", + "name": "searchResultsByDay", "privacy": "private", - "readonly": true + "default": "new Map()" }, { "kind": "field", - "name": "planTier", + "name": "statsByDay", "privacy": "private", - "readonly": true + "default": "new Map()" }, { "kind": "field", - "name": "promos", + "name": "pendingDataChange", "type": { - "text": "PromosContext" + "text": "boolean" }, - "privacy": "private" + "privacy": "private", + "default": "false" }, { - "kind": "field", - "name": "subscription", + "kind": "method", + "name": "handleDataChanged", "privacy": "private", - "readonly": true + "parameters": [ + { + "name": "changedKeys", + "type": { + "text": "PropertyKey[]" + } + } + ] }, { "kind": "field", - "name": "subscriptionState", + "name": "pendingSearchResultsChange", + "type": { + "text": "boolean" + }, "privacy": "private", - "readonly": true + "default": "false" + }, + { + "kind": "method", + "name": "handleSearchResultsChanged", + "privacy": "private" }, { "kind": "field", - "name": "trialDaysRemaining", - "privacy": "private", - "readonly": true + "name": "minimap", + "type": { + "text": "GlGraphMinimap | undefined" + }, + "privacy": "private" }, { "kind": "method", - "name": "focus", + "name": "select", "return": { "type": { "text": "void" } - } + }, + "parameters": [ + { + "name": "date", + "type": { + "text": "number | Date | undefined" + } + }, + { + "name": "trackOnly", + "default": "false", + "type": { + "text": "boolean" + } + } + ] }, { "kind": "method", - "name": "show", + "name": "unselect", "return": { "type": { "text": "void" } - } - }, - { - "kind": "method", - "name": "renderAccountInfo", - "privacy": "private" + }, + "parameters": [ + { + "name": "date", + "optional": true, + "type": { + "text": "number | Date" + } + }, + { + "name": "focus", + "default": "false", + "type": { + "text": "boolean" + } + } + ] }, { "kind": "method", - "name": "renderAccountState", + "name": "processRows", "privacy": "private" }, { "kind": "method", - "name": "renderIncludesDevEx", + "name": "processSearchResults", "privacy": "private" }, { "kind": "method", - "name": "renderReferFriend", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderUpgradeContent", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderPromo", - "privacy": "private", + "name": "emit", "return": { "type": { - "text": "unknown" + "text": "CustomEventType" } }, "parameters": [ { - "name": "plan", + "name": "name", "type": { - "text": "PromoPlans" + "text": "T" } }, { - "name": "type", - "default": "'info'", + "name": "detail", "type": { - "text": "GlPromo['type']" + "text": "CustomEventDetailType" } }, { - "name": "slot", + "name": "options", "optional": true, "type": { - "text": "string" + "text": "Omit>, 'detail'>" } } - ] + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } } ], "attributes": [ { - "name": "show-upgrade", - "fieldName": "showUpgrade" + "name": "activeDay", + "type": { + "text": "number | undefined" + }, + "fieldName": "activeDay" + }, + { + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "disabled" + }, + { + "name": "dataType", + "type": { + "text": "'commits' | 'lines'" + }, + "default": "'commits'", + "fieldName": "dataType" + }, + { + "name": "downstreams", + "type": { + "text": "GraphDownstreams | undefined" + }, + "fieldName": "downstreams" + }, + { + "name": "markerTypes", + "type": { + "text": "GraphMinimapMarkerTypes[]" + }, + "default": "[]", + "fieldName": "markerTypes" + }, + { + "name": "refMetadata", + "type": { + "text": "GraphRefsMetadata | null | undefined" + }, + "fieldName": "refMetadata" + }, + { + "name": "rows", + "type": { + "text": "GraphRow[]" + }, + "default": "[]", + "fieldName": "rows" + }, + { + "name": "rowsStats", + "type": { + "text": "Record | undefined" + }, + "fieldName": "rowsStats" + }, + { + "name": "searchResults", + "type": { + "text": "GraphSearchResults | GraphSearchResultsError | undefined" + }, + "fieldName": "searchResults" + }, + { + "name": "visibleDays", + "type": { + "text": "{ top: number; bottom: number } | undefined" + }, + "fieldName": "visibleDays" } ], "superclass": { - "name": "LitElement", - "package": "lit" + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" }, - "tagName": "gl-account-chip", + "tagName": "gl-graph-minimap-container", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlAccountChip", + "name": "GlGraphMinimapContainer", "declaration": { - "name": "GlAccountChip", - "module": "src/webviews/apps/plus/shared/components/account-chip.ts" + "name": "GlGraphMinimapContainer", + "module": "src/webviews/apps/plus/graph/minimap/minimap-container.ts" } }, { "kind": "custom-element-definition", - "name": "gl-account-chip", - "declaration": { - "name": "GlAccountChip", - "module": "src/webviews/apps/plus/shared/components/account-chip.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/shared/components/chipStyles.ts", - "declarations": [ - { - "kind": "variable", - "name": "chipStyles", - "default": "css` :host { display: flex; } .chip { display: flex; gap: 0.6rem; align-items: center; border-radius: 0.3rem; padding: 0.2rem 0.4rem; cursor: pointer; } .chip:focus-visible { ${focusOutline} } .content { display: flex; flex-direction: column; gap: 0.4rem; padding-bottom: 0.4rem; } .header { display: flex; align-items: center; gap: 0.6rem; width: 100%; padding-bottom: 0.4rem; } .header__actions { flex: none; display: flex; gap: 0.2rem; flex-direction: row; align-items: center; justify-content: center; } .header__title { flex: 1; font-size: 1.5rem; line-height: 1.7; font-weight: 600; margin: 0; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } `" - } - ], - "exports": [ - { - "kind": "js", - "name": "chipStyles", + "name": "gl-graph-minimap-container", "declaration": { - "name": "chipStyles", - "module": "src/webviews/apps/plus/shared/components/chipStyles.ts" + "name": "GlGraphMinimapContainer", + "module": "src/webviews/apps/plus/graph/minimap/minimap-container.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/shared/components/feature-gate-plus-state.ts", + "path": "src/webviews/apps/plus/graph/minimap/minimap.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlFeatureGatePlusState", + "name": "GlGraphMinimap", "members": [ { "kind": "field", - "name": "button", + "name": "chartContainer", "type": { - "text": "GlButton" + "text": "HTMLDivElement" + } + }, + { + "kind": "field", + "name": "_chart", + "type": { + "text": "Chart" }, - "privacy": "private", - "readonly": true + "privacy": "private" }, { "kind": "field", - "name": "featurePreview", + "name": "spinner", "type": { - "text": "FeaturePreview | undefined" + "text": "HTMLDivElement" + } + }, + { + "kind": "field", + "name": "_loadTimer", + "type": { + "text": "ReturnType | undefined" }, - "attribute": "featurePreview" + "privacy": "private" }, { "kind": "field", - "name": "featurePreviewCommandLink", + "name": "_markerRegions", "type": { - "text": "string | undefined" + "text": "Iterable | undefined" }, - "attribute": "featurePreviewCommandLink" + "privacy": "private" }, { "kind": "field", - "name": "appearance", + "name": "_regions", "type": { - "text": "'alert' | 'welcome' | undefined" + "text": "RegionOptions[] | undefined" }, - "attribute": "appearance" + "privacy": "private" }, { "kind": "field", - "name": "featureWithArticleIfNeeded", + "name": "activeDay", "type": { - "text": "string | undefined" + "text": "number | undefined" }, - "attribute": "featureWithArticleIfNeeded" + "attribute": "activeDay" + }, + { + "kind": "method", + "name": "onActiveDayChanged", + "privacy": "private" }, { "kind": "field", - "name": "promos", + "name": "data", "type": { - "text": "PromosContext" + "text": "Map | undefined" + }, + "attribute": "data" + }, + { + "kind": "field", + "name": "dataType", + "type": { + "text": "'commits' | 'lines'" }, + "default": "'commits'", + "attribute": "dataType" + }, + { + "kind": "method", + "name": "onDataChanged", "privacy": "private" }, { "kind": "field", - "name": "source", + "name": "markers", "type": { - "text": "Source | undefined" + "text": "Map | undefined" }, - "attribute": "source" + "attribute": "markers" + }, + { + "kind": "method", + "name": "onMarkersChanged", + "privacy": "private" }, { "kind": "field", - "name": "state", + "name": "searchResults", "type": { - "text": "SubscriptionState | undefined" - } + "text": "Map | undefined" + }, + "attribute": "searchResults" + }, + { + "kind": "method", + "name": "onSearchResultsChanged", + "privacy": "private" }, { "kind": "field", - "name": "webroot", + "name": "visibleDays", "type": { - "text": "string | undefined" + "text": "{ top: number; bottom: number } | undefined" }, - "attribute": "webroot" + "attribute": "visibleDays" }, { "kind": "method", - "name": "renderFeaturePreview", + "name": "onVisibleDaysChanged", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleDataChanged", "privacy": "private", "parameters": [ { - "name": "featurePreview", + "name": "markerChanged", "type": { - "text": "FeaturePreview" + "text": "boolean" } } ] }, { "kind": "method", - "name": "renderFeaturePreviewStep", + "name": "getInternalChart", "privacy": "private", + "return": { + "type": { + "text": "ChartInternal | undefined" + } + } + }, + { + "kind": "method", + "name": "select", + "return": { + "type": { + "text": "void" + } + }, "parameters": [ { - "name": "featurePreview", + "name": "date", "type": { - "text": "FeaturePreview" + "text": "number | Date | undefined" } }, { - "name": "used", + "name": "trackOnly", + "default": "false", "type": { - "text": "number" + "text": "boolean" } } ] }, { "kind": "method", - "name": "renderPromo", + "name": "unselect", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "date", + "optional": true, + "type": { + "text": "number | Date" + } + }, + { + "name": "focus", + "default": "false", + "type": { + "text": "boolean" + } + } + ] + }, + { + "kind": "method", + "name": "getDataPoint", + "privacy": "private", + "return": { + "type": { + "text": "DataItem | undefined" + } + }, + "parameters": [ + { + "name": "date", + "type": { + "text": "number | Date" + } + } + ] + }, + { + "kind": "method", + "name": "getIndex", + "privacy": "private", + "return": { + "type": { + "text": "number | undefined" + } + }, + "parameters": [ + { + "name": "date", + "type": { + "text": "number | Date" + } + } + ] + }, + { + "kind": "method", + "name": "getMarkerRegions", + "privacy": "private" + }, + { + "kind": "method", + "name": "getAllRegions", + "privacy": "private" + }, + { + "kind": "method", + "name": "getSearchResultsRegions", + "privacy": "private", + "return": { + "type": { + "text": "Iterable" + } + }, + "parameters": [ + { + "name": "searchResults", + "type": { + "text": "NonNullable" + } + } + ] + }, + { + "kind": "method", + "name": "getVisibleAreaRegion", + "privacy": "private", + "return": { + "type": { + "text": "RegionOptions" + } + }, + "parameters": [ + { + "name": "visibleDays", + "type": { + "text": "NonNullable" + } + } + ] + }, + { + "kind": "field", + "name": "_loading", + "type": { + "text": "Promise | undefined" + }, + "privacy": "private" + }, + { + "kind": "method", + "name": "loadChart", + "privacy": "private" + }, + { + "kind": "method", + "name": "loadChartCore", "privacy": "private" + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } } ], "attributes": [ { - "name": "featurePreview", + "name": "activeDay", "type": { - "text": "FeaturePreview | undefined" + "text": "number | undefined" }, - "fieldName": "featurePreview" + "fieldName": "activeDay" }, { - "name": "featurePreviewCommandLink", + "name": "data", "type": { - "text": "string | undefined" + "text": "Map | undefined" }, - "fieldName": "featurePreviewCommandLink" + "fieldName": "data" }, { - "name": "appearance", + "name": "dataType", "type": { - "text": "'alert' | 'welcome' | undefined" + "text": "'commits' | 'lines'" }, - "fieldName": "appearance" + "default": "'commits'", + "fieldName": "dataType" }, { - "name": "featureWithArticleIfNeeded", + "name": "markers", "type": { - "text": "string | undefined" + "text": "Map | undefined" }, - "fieldName": "featureWithArticleIfNeeded" + "fieldName": "markers" }, { - "name": "source", + "name": "searchResults", "type": { - "text": "Source | undefined" + "text": "Map | undefined" }, - "fieldName": "source" + "fieldName": "searchResults" }, { - "name": "webroot", + "name": "visibleDays", "type": { - "text": "string | undefined" + "text": "{ top: number; bottom: number } | undefined" }, - "fieldName": "webroot" + "fieldName": "visibleDays" } ], "superclass": { - "name": "LitElement", - "package": "lit" + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" }, - "tagName": "gl-feature-gate-plus-state", + "tagName": "gl-graph-minimap", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlFeatureGatePlusState", + "name": "GlGraphMinimap", "declaration": { - "name": "GlFeatureGatePlusState", - "module": "src/webviews/apps/plus/shared/components/feature-gate-plus-state.ts" + "name": "GlGraphMinimap", + "module": "src/webviews/apps/plus/graph/minimap/minimap.ts" } }, { "kind": "custom-element-definition", - "name": "gl-feature-gate-plus-state", + "name": "gl-graph-minimap", "declaration": { - "name": "GlFeatureGatePlusState", - "module": "src/webviews/apps/plus/shared/components/feature-gate-plus-state.ts" + "name": "GlGraphMinimap", + "module": "src/webviews/apps/plus/graph/minimap/minimap.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/shared/components/home-header.ts", + "path": "src/webviews/apps/plus/graph/sidebar/sidebar.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlHomeHeader", + "name": "GlGraphSideBar", "members": [ { "kind": "field", - "name": "accountChip", + "name": "include", "type": { - "text": "GlAccountChip" + "text": "undefined | IconTypes[]" }, - "privacy": "private" + "readonly": true }, { "kind": "field", - "name": "promoBanner", + "name": "_ipc", "type": { - "text": "GlPromoBanner" - }, - "privacy": "private" - }, - { - "kind": "method", - "name": "show", - "return": { - "type": { - "text": "void" - } - } - }, - { - "kind": "method", - "name": "refreshPromo", - "return": { - "type": { - "text": "void" - } - } - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-home-header", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "GlHomeHeader", - "declaration": { - "name": "GlHomeHeader", - "module": "src/webviews/apps/plus/shared/components/home-header.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-home-header", - "declaration": { - "name": "GlHomeHeader", - "module": "src/webviews/apps/plus/shared/components/home-header.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/shared/components/integrations-chip.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlIntegrationsChip", - "members": [ - { - "kind": "field", - "name": "shadowRootOptions", - "type": { - "text": "ShadowRootInit" - }, - "static": true, - "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" - }, - { - "kind": "field", - "name": "_chip", - "type": { - "text": "HTMLElement" + "text": "HostIpc" }, "privacy": "private" }, @@ -21843,2074 +22062,6960 @@ "kind": "field", "name": "_state", "type": { - "text": "State" + "text": "typeof graphStateContext.__context__" }, - "privacy": "private" - }, - { - "kind": "field", - "name": "hasAccount", - "privacy": "private", - "readonly": true - }, - { - "kind": "field", - "name": "isPaidAccount", - "privacy": "private", - "readonly": true - }, - { - "kind": "field", - "name": "isProAccount", - "privacy": "private", - "readonly": true - }, - { - "kind": "field", - "name": "hasConnectedIntegrations", - "privacy": "private", - "readonly": true - }, - { - "kind": "field", - "name": "ai", - "privacy": "private", - "readonly": true - }, - { - "kind": "field", - "name": "aiSettingEnabled", "privacy": "private", "readonly": true }, { "kind": "field", - "name": "aiOrgEnabled", - "privacy": "private", - "readonly": true + "name": "_disposable", + "type": { + "text": "Disposable | undefined" + }, + "privacy": "private" }, { "kind": "field", - "name": "aiEnabled", + "name": "_countsTask", "privacy": "private", - "readonly": true + "default": "new Task(this, { args: () => [this.fetchCounts()], task: ([counts]) => counts, autoRun: false, })" }, { "kind": "field", - "name": "integrations", - "privacy": "private", - "readonly": true + "name": "_counts", + "type": { + "text": "Promise | undefined" + }, + "privacy": "private" }, { "kind": "method", - "name": "focus", - "return": { - "type": { - "text": "void" - } - } + "name": "fetchCounts", + "privacy": "private" }, { "kind": "method", - "name": "renderIntegrationStatus", + "name": "renderIcon", "privacy": "private", "parameters": [ { - "name": "integration", + "name": "icon", "type": { - "text": "IntegrationState" + "text": "Icon" } } ] }, { "kind": "method", - "name": "renderIntegrationRow", + "name": "sendTelemetry", "privacy": "private", "parameters": [ { - "name": "integration", + "name": "command", "type": { - "text": "IntegrationState" + "text": "string" } } ] - }, - { - "kind": "method", - "name": "renderAIStatus", - "privacy": "private" - }, + } + ], + "mixins": [ { - "kind": "method", - "name": "renderAIRow", - "privacy": "private" + "name": "SignalWatcher", + "package": "@lit-labs/signals" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-integrations-chip", + "tagName": "gl-graph-sidebar", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlIntegrationsChip", + "name": "GlGraphSideBar", "declaration": { - "name": "GlIntegrationsChip", - "module": "src/webviews/apps/plus/shared/components/integrations-chip.ts" + "name": "GlGraphSideBar", + "module": "src/webviews/apps/plus/graph/sidebar/sidebar.ts" } }, { "kind": "custom-element-definition", - "name": "gl-integrations-chip", + "name": "gl-graph-sidebar", "declaration": { - "name": "GlIntegrationsChip", - "module": "src/webviews/apps/plus/shared/components/integrations-chip.ts" + "name": "GlGraphSideBar", + "module": "src/webviews/apps/plus/graph/sidebar/sidebar.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/shared/components/merge-rebase-status.ts", + "path": "src/webviews/apps/plus/graph/styles/graph.css.ts", + "declarations": [ + { + "kind": "variable", + "name": "linkBase", + "default": "css` a { text-decoration: none; } a:focus { ${focusOutline} } a:hover { text-decoration: underline; } `" + }, + { + "kind": "variable", + "name": "actionButton", + "default": "css` .action-button { position: relative; appearance: none; font-family: inherit; font-size: 1.2rem; line-height: 2.2rem; // background-color: var(--color-graph-actionbar-background); background-color: transparent; border: none; color: inherit; color: var(--color-foreground); padding: 0 0.75rem; cursor: pointer; border-radius: 3px; height: auto; display: grid; grid-auto-flow: column; grid-gap: 0.5rem; gap: 0.5rem; max-width: fit-content; } .action-button[disabled] { pointer-events: none; cursor: default; opacity: 1; } .action-button:hover { background-color: var(--color-graph-actionbar-selectedBackground); color: var(--color-foreground); text-decoration: none; } .action-button[aria-checked] { border: 1px solid transparent; } .action-button[aria-checked='true'] { background-color: var(--vscode-inputOption-activeBackground); color: var(--vscode-inputOption-activeForeground); border-color: var(--vscode-inputOption-activeBorder); } .action-button code-icon { line-height: 2.2rem; vertical-align: bottom; } .action-button code-icon[icon='graph-line'] { transform: translateY(1px); } .is-ahead .action-button__pill { background-color: var(--branch-status-ahead-pill-background); } .is-behind .action-button__pill { background-color: var(--branch-status-behind-pill-background); } .is-ahead.is-behind .action-button__pill { background-color: var(--branch-status-both-pill-background); } .action-button__more, .action-button__more.codicon[class*='codicon-'] { font-size: 1rem; margin-right: -0.25rem; } code-icon.action-button__more::before { margin-left: -0.25rem; } .action-button__indicator { margin-left: -0.2rem; --gl-indicator-color: green; --gl-indicator-size: 0.4rem; } .action-button__small { font-size: smaller; opacity: 0.6; text-overflow: ellipsis; overflow: hidden; } .action-button.is-ahead { background-color: var(--branch-status-ahead-background); } .action-button.is-ahead:hover { background-color: var(--branch-status-ahead-hover-background); } .action-button.is-behind { background-color: var(--branch-status-behind-background); } .action-button.is-behind:hover { background-color: var(--branch-status-behind-hover-background); } .action-button.is-ahead.is-behind { background-color: var(--branch-status-both-background); } .action-button.is-ahead.is-behind:hover { background-color: var(--branch-status-both-hover-background); } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "linkBase", + "declaration": { + "name": "linkBase", + "module": "src/webviews/apps/plus/graph/styles/graph.css.ts" + } + }, + { + "kind": "js", + "name": "actionButton", + "declaration": { + "name": "actionButton", + "module": "src/webviews/apps/plus/graph/styles/graph.css.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/graph/styles/header.css.ts", + "declarations": [ + { + "kind": "variable", + "name": "repoHeaderStyles", + "default": "css` .jump-to-ref { --button-foreground: var(--color-foreground); } .merge-conflict-warning { flex: 0 0 100%; min-width: 0; } `" + }, + { + "kind": "variable", + "name": "progressStyles", + "default": "css` .progress-container { position: absolute; left: 0; bottom: 0; z-index: 5; height: 2px; width: 100%; overflow: hidden; } .progress-container .progress-bar { background-color: var(--vscode-progressBar-background); display: none; position: absolute; left: 0; width: 2%; height: 2px; } .progress-container.active .progress-bar { display: inherit; } .progress-container.discrete .progress-bar { left: 0; transition: width 0.1s linear; } .progress-container.discrete.done .progress-bar { width: 100%; } .progress-container.infinite .progress-bar { animation-name: progress; animation-duration: 4s; animation-iteration-count: infinite; animation-timing-function: steps(100); transform: translateZ(0); } @keyframes progress { 0% { transform: translateX(0) scaleX(1); } 50% { transform: translateX(2500%) scaleX(3); } to { transform: translateX(4900%) scaleX(1); } } `" + }, + { + "kind": "variable", + "name": "titlebarStyles", + "default": "css` .titlebar { background: var(--titlebar-bg); color: var(--titlebar-fg); padding: 0.6rem 0.8rem; font-size: 1.3rem; flex-wrap: wrap; } .titlebar, .titlebar__row, .titlebar__group { display: flex; flex-direction: row; align-items: center; gap: 0.5rem; } .titlebar > *, .titlebar__row > *, .titlebar__group > * { margin: 0; } .titlebar, .titlebar__row { justify-content: space-between; } .titlebar__row { flex: 0 0 100%; } .titlebar__row--wrap { display: grid; grid-auto-flow: column; justify-content: start; grid-template-columns: 1fr min-content; } .titlebar__group { flex: auto 1 1; } .titlebar__row--wrap .titlebar__group { white-space: nowrap; } .titlebar__row--wrap .titlebar__group:nth-child(odd) { min-width: 0; } .titlebar__debugging > * { display: inline-block; } .titlebar gl-feature-badge { color: var(--color-foreground); } `" + }, + { + "kind": "variable", + "name": "graphHeaderControlStyles", + "default": "css` .popover::part(body) { padding: 0; font-size: var(--vscode-font-size); background-color: var(--vscode-menu-background); } .titlebar__group gl-repo-button-group, .titlebar__group gl-ref-button { font-size: 1.2rem; } .shrink { max-width: fit-content; transition: all 0.2s; } .shrink.hidden { max-width: 0; overflow: hidden; } .titlebar__group .shrink.hidden:not(:first-child) { // compensate the parent gap margin-left: -0.5rem; } .branch-menu { display: flex; gap: 0.5em; align-items: center; } .branch-menu__avatar { width: 1.4rem; aspect-ratio: 1; vertical-align: text-bottom; } .action-divider { display: inline-block; width: 0.1rem; height: 2.2rem; vertical-align: middle; background-color: var(--titlebar-fg); opacity: 0.4; margin: { // left: 0.2rem; right: 0.2rem; } } .button-group { display: flex; flex-direction: row; align-items: stretch; } .button-group:hover, .button-group:focus-within { background-color: var(--color-graph-actionbar-selectedBackground); border-radius: 3px; } .button-group > *:not(:first-child), .button-group > *:not(:first-child) .action-button { display: flex; border-top-left-radius: 0; border-bottom-left-radius: 0; } .button-group > *:not(:first-child) .action-button { padding-left: 0.5rem; padding-right: 0.5rem; height: 100%; } .button-group:hover > *:not(:last-child), .button-group:active > *:not(:last-child), .button-group:focus-within > *:not(:last-child), .button-group:hover > *:not(:last-child) .action-button, .button-group:active > *:not(:last-child) .action-button, .button-group:focus-within > *:not(:last-child) .action-button { border-top-right-radius: 0; border-bottom-right-radius: 0; } .minimap-marker-swatch { display: inline-block; width: 1rem; height: 1rem; border-radius: 2px; transform: scale(1.6); margin-left: 0.3rem; margin-right: 1rem; } .minimap-marker-swatch[data-marker='localBranches'] { background-color: var(--color-graph-minimap-marker-local-branches); } .minimap-marker-swatch[data-marker='pullRequests'] { background-color: var(--color-graph-minimap-marker-pull-requests); } .minimap-marker-swatch[data-marker='remoteBranches'] { background-color: var(--color-graph-minimap-marker-remote-branches); } .minimap-marker-swatch[data-marker='stashes'] { background-color: var(--color-graph-minimap-marker-stashes); } .minimap-marker-swatch[data-marker='tags'] { background-color: var(--color-graph-minimap-marker-tags); } gl-search-box::part(search) { --gl-search-input-background: var(--color-graph-actionbar-background); --gl-search-input-border: var(--sl-input-border-color); } sl-option::part(base) { padding: 0.2rem 0.4rem; } sl-option[aria-selected='true']::part(base), sl-option:not([aria-selected='true']):hover::part(base), sl-option:not([aria-selected='true']):focus::part(base) { background-color: var(--vscode-list-activeSelectionBackground); color: var(--vscode-list-activeSelectionForeground); } sl-option::part(checked-icon) { display: none; } sl-select::part(listbox) { padding-block: 0.2rem 0; width: max-content; } sl-select::part(combobox) { --sl-input-background-color: var(--color-graph-actionbar-background); --sl-input-color: var(--color-foreground); --sl-input-color-hover: var(--color-foreground); padding: 0 0.75rem; color: var(--color-foreground); border-radius: var(--sl-border-radius-small); } sl-select::part(display-input) { field-sizing: content; } sl-select::part(expand-icon) { margin-inline-start: var(--sl-spacing-x-small); } sl-select[open]::part(combobox) { background-color: var(--color-graph-actionbar-background); } sl-select:hover::part(combobox), sl-select:focus::part(combobox) { background-color: var(--color-graph-actionbar-selectedBackground); } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "repoHeaderStyles", + "declaration": { + "name": "repoHeaderStyles", + "module": "src/webviews/apps/plus/graph/styles/header.css.ts" + } + }, + { + "kind": "js", + "name": "progressStyles", + "declaration": { + "name": "progressStyles", + "module": "src/webviews/apps/plus/graph/styles/header.css.ts" + } + }, + { + "kind": "js", + "name": "titlebarStyles", + "declaration": { + "name": "titlebarStyles", + "module": "src/webviews/apps/plus/graph/styles/header.css.ts" + } + }, + { + "kind": "js", + "name": "graphHeaderControlStyles", + "declaration": { + "name": "graphHeaderControlStyles", + "module": "src/webviews/apps/plus/graph/styles/header.css.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/home/components/active-work.ts", "declarations": [ + { + "kind": "variable", + "name": "activeWorkTagName", + "type": { + "text": "string" + }, + "default": "'gl-active-work'" + }, { "kind": "class", "description": "", - "name": "GlMergeConflictWarning", + "name": "GlActiveWork", "members": [ { "kind": "field", - "name": "conflicts", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "conflicts", - "reflects": true - }, - { - "kind": "field", - "name": "pausedOpStatus", - "type": { - "text": "GitPausedOperationStatus | undefined" - }, - "attribute": "pausedOpStatus" - }, - { - "kind": "field", - "name": "skipCommand", + "name": "_homeState", "type": { - "text": "string" + "text": "State" }, - "default": "'gitlens.home.skipPausedOperation'", - "attribute": "skipCommand" + "privacy": "private" }, { "kind": "field", - "name": "continueCommand", + "name": "_activeOverviewState", "type": { - "text": "string" + "text": "ActiveOverviewState" }, - "default": "'gitlens.home.continuePausedOperation'", - "attribute": "continueCommand" + "privacy": "private" }, { "kind": "field", - "name": "abortCommand", + "name": "_ipc", "type": { - "text": "string" + "text": "typeof ipcContext.__context__" }, - "default": "'gitlens.home.abortPausedOperation'", - "attribute": "abortCommand" + "privacy": "private" }, { "kind": "field", - "name": "openEditorCommand", + "name": "repoCollapsed", "type": { - "text": "string" + "text": "boolean" }, - "default": "'gitlens.home.openRebaseEditor'", - "attribute": "openEditorCommand" + "privacy": "private", + "default": "true" }, { "kind": "field", - "name": "webviewCommandContext", - "type": { - "text": "{ webview: string; webviewInstance: string | undefined } | undefined" - }, - "attribute": "webviewCommandContext" + "name": "isPro", + "readonly": true }, { - "kind": "field", - "name": "onSkipUrl", - "privacy": "private", - "readonly": true + "kind": "method", + "name": "onBranchSelectorClicked", + "privacy": "private" }, { - "kind": "field", - "name": "onContinueUrl", - "privacy": "private", - "readonly": true + "kind": "method", + "name": "renderLoader", + "privacy": "private" }, { - "kind": "field", - "name": "onAbortUrl", - "privacy": "private", - "readonly": true + "kind": "method", + "name": "renderPending", + "privacy": "private" }, { - "kind": "field", - "name": "onOpenEditorUrl", + "kind": "method", + "name": "renderComplete", "privacy": "private", - "readonly": true + "parameters": [ + { + "name": "overview", + "type": { + "text": "GetActiveOverviewResponse" + } + }, + { + "name": "isFetching", + "default": "false" + } + ] }, { "kind": "method", - "name": "createCommandLink", + "name": "renderRepoBranchCard", "privacy": "private", "parameters": [ { - "name": "command", + "name": "branch", + "type": { + "text": "GetOverviewBranch" + } + }, + { + "name": "repo", "type": { "text": "string" } }, { - "name": "args", - "optional": true, + "name": "isFetching", "type": { - "text": "any" + "text": "boolean" } } ] }, { "kind": "method", - "name": "renderStatus", + "name": "onRepositorySelectorClicked", "privacy": "private", "parameters": [ { - "name": "pausedOpStatus", + "name": "e", "type": { - "text": "GitPausedOperationStatus" + "text": "CustomEvent" } } ] + } + ], + "mixins": [ + { + "name": "SignalWatcher", + "package": "@lit-labs/signals" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "customElement": true + }, + { + "kind": "class", + "description": "", + "name": "GlActiveBranchCard", + "members": [ + { + "kind": "method", + "name": "renderActionsMenu", + "privacy": "private" }, { "kind": "method", - "name": "renderActions", + "name": "renderBranchStateActions", "privacy": "private" - } - ], - "attributes": [ + }, { - "name": "conflicts", - "type": { - "text": "boolean" + "kind": "method", + "name": "renderBranchIndicator", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | undefined" + } }, - "default": "false", - "fieldName": "conflicts" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "pausedOpStatus", - "type": { - "text": "GitPausedOperationStatus | undefined" + "kind": "method", + "name": "getBranchActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult[]" + } }, - "fieldName": "pausedOpStatus" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "skipCommand", - "type": { - "text": "string" + "kind": "method", + "name": "getPrActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult[]" + } }, - "default": "'gitlens.home.skipPausedOperation'", - "fieldName": "skipCommand" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "continueCommand", - "type": { - "text": "string" + "kind": "method", + "name": "getCollapsedActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult[]" + } }, - "default": "'gitlens.home.continuePausedOperation'", - "fieldName": "continueCommand" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "abortCommand", - "type": { - "text": "string" + "kind": "method", + "name": "renderIssuesItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "default": "'gitlens.home.abortPausedOperation'", - "fieldName": "abortCommand" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "openEditorCommand", + "kind": "field", + "name": "_homeState", "type": { - "text": "string" + "text": "State" }, - "default": "'gitlens.home.openRebaseEditor'", - "fieldName": "openEditorCommand" + "privacy": "protected", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, - { - "name": "webviewCommandContext", - "type": { - "text": "{ webview: string; webviewInstance: string | undefined } | undefined" - }, - "fieldName": "webviewCommandContext" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-merge-rebase-status", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "GlMergeConflictWarning", - "declaration": { - "name": "GlMergeConflictWarning", - "module": "src/webviews/apps/plus/shared/components/merge-rebase-status.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-merge-rebase-status", - "declaration": { - "name": "GlMergeConflictWarning", - "module": "src/webviews/apps/plus/shared/components/merge-rebase-status.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/shared/components/vscode.css.ts", - "declarations": [ - { - "kind": "variable", - "name": "linkStyles", - "default": "css` a { border: 0; color: var(--link-foreground); font-weight: 400; outline: none; text-decoration: var(--link-decoration-default, none); } a:focus-visible { outline: 1px solid var(--color-focus-border); border-radius: 0.2rem; } a:hover { color: var(--link-foreground-active); text-decoration: underline; } `" - }, - { - "kind": "variable", - "name": "ruleStyles", - "default": "css` hr { border: none; border-top: 1px solid var(--color-foreground--25); } `" - } - ], - "exports": [ - { - "kind": "js", - "name": "linkStyles", - "declaration": { - "name": "linkStyles", - "module": "src/webviews/apps/plus/shared/components/vscode.css.ts" - } - }, - { - "kind": "js", - "name": "ruleStyles", - "declaration": { - "name": "ruleStyles", - "module": "src/webviews/apps/plus/shared/components/vscode.css.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GitActionsButtons", - "members": [ { "kind": "field", - "name": "branchState", + "name": "repo", "type": { - "text": "BranchState | undefined" + "text": "string" }, - "attribute": "branchState" + "attribute": "repo", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "branchName", + "name": "showUpgrade", "type": { - "text": "string | undefined" + "text": "boolean" }, - "attribute": "branchName" + "default": "false", + "attribute": "showUpgrade", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "lastFetched", + "name": "_branch", "type": { - "text": "Date | undefined" + "text": "GetOverviewBranch" }, - "attribute": "lastFetched" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "state", + "name": "branch", "type": { - "text": "State" + "text": "GetOverviewBranch" }, - "attribute": "state" + "attribute": "branch", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "fetchedText", - "privacy": "private", - "readonly": true - } - ], - "attributes": [ - { - "name": "branchState", + "name": "_autolinks", "type": { - "text": "BranchState | undefined" + "text": "Awaited" }, - "fieldName": "branchState" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "branchName", + "kind": "field", + "name": "autolinks", "type": { - "text": "string | undefined" + "text": "Awaited" }, - "fieldName": "branchName" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "lastFetched", + "kind": "field", + "name": "_autolinksPromise", "type": { - "text": "Date | undefined" + "text": "GetOverviewBranch['autolinks']" }, - "fieldName": "lastFetched" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, - { - "name": "state", - "type": { - "text": "State" - }, - "fieldName": "state" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-git-actions-buttons", - "customElement": true - }, - { - "kind": "class", - "description": "", - "name": "GlFetchButton", - "members": [ { "kind": "field", - "name": "state", + "name": "autolinksPromise", "type": { - "text": "State" + "text": "GetOverviewBranch['autolinks']" }, - "attribute": "state" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "fetchedText", + "name": "_contributors", "type": { - "text": "string | undefined" + "text": "Awaited" }, - "attribute": "fetchedText" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "branchState", + "name": "contributors", "type": { - "text": "BranchState | undefined" + "text": "Awaited" }, - "attribute": "branchState" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "upstream", - "privacy": "private", - "readonly": true - } - ], - "attributes": [ - { - "name": "state", + "name": "_contributorsPromise", "type": { - "text": "State" + "text": "GetOverviewBranch['contributors']" }, - "fieldName": "state" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "fetchedText", + "kind": "field", + "name": "contributorsPromise", "type": { - "text": "string | undefined" + "text": "GetOverviewBranch['contributors']" }, - "fieldName": "fetchedText" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, - { - "name": "branchState", - "type": { - "text": "BranchState | undefined" - }, - "fieldName": "branchState" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-fetch-button", - "customElement": true - }, - { - "kind": "class", - "description": "", - "name": "PushPullButton", - "members": [ { "kind": "field", - "name": "branchState", + "name": "_issues", "type": { - "text": "BranchState | undefined" + "text": "Awaited" }, - "attribute": "branchState" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "state", + "name": "issues", "type": { - "text": "State" + "text": "Awaited" }, - "attribute": "state" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "fetchedText", + "name": "_issuesPromise", "type": { - "text": "string | undefined" + "text": "GetOverviewBranch['issues']" }, - "attribute": "fetchedText" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "branchName", + "name": "issuesPromise", "type": { - "text": "string | undefined" + "text": "GetOverviewBranch['issues']" }, - "attribute": "branchName" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "isBehind", + "name": "_pr", "type": { - "text": "boolean" + "text": "Awaited" }, "privacy": "private", - "readonly": true + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "isAhead", + "name": "pr", "type": { - "text": "boolean" + "text": "Awaited" }, - "privacy": "private", - "readonly": true + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "upstream", - "privacy": "private", - "readonly": true - }, - { - "kind": "method", - "name": "renderBranchPrefix", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderTooltipContent", - "privacy": "private", - "parameters": [ - { - "name": "action", - "type": { - "text": "'pull' | 'push'" - } - } - ] - } - ], - "attributes": [ - { - "name": "branchState", + "name": "_prPromise", "type": { - "text": "BranchState | undefined" + "text": "GetOverviewBranch['pr']" }, - "fieldName": "branchState" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "state", + "kind": "field", + "name": "prPromise", "type": { - "text": "State" + "text": "GetOverviewBranch['pr']" }, - "fieldName": "state" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "fetchedText", + "kind": "field", + "name": "_launchpadItem", "type": { - "text": "string | undefined" + "text": "Awaited>['launchpad']>" }, - "fieldName": "fetchedText" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, - { - "name": "branchName", - "type": { - "text": "string | undefined" - }, - "fieldName": "branchName" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-push-pull-button", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "GitActionsButtons", - "declaration": { - "name": "GitActionsButtons", - "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-git-actions-buttons", - "declaration": { - "name": "GitActionsButtons", - "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" - } - }, - { - "kind": "js", - "name": "GlFetchButton", - "declaration": { - "name": "GlFetchButton", - "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-fetch-button", - "declaration": { - "name": "GlFetchButton", - "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" - } - }, - { - "kind": "js", - "name": "PushPullButton", - "declaration": { - "name": "PushPullButton", - "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-push-pull-button", - "declaration": { - "name": "PushPullButton", - "module": "src/webviews/apps/plus/graph/actions/gitActionsButtons.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper-element.ts", - "declarations": [ - { - "kind": "class", - "description": "A LitElement web component that encapsulates the GraphWrapperReact component.\nThis component mounts the React component once and then updates its state\nwithout remounting on subsequent property changes.", - "name": "GlGraph", - "members": [ { "kind": "field", - "name": "reactRoot", + "name": "launchpadItem", "type": { - "text": "ReturnType | null" + "text": "Awaited>['launchpad']>" }, - "privacy": "private", - "default": "null" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "provideReactState", + "name": "_launchpadItemPromise", "type": { - "text": "((props: Partial) => void) | null" + "text": "NonNullable>['launchpad']" }, "privacy": "private", - "default": "null" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "setReactStateProvider", - "privacy": "private" + "name": "launchpadItemPromise", + "type": { + "text": "NonNullable>['launchpad']" + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "activeRow", + "name": "_mergeTarget", "type": { - "text": "GraphWrapperProps['activeRow'] | undefined" + "text": "Awaited" }, - "attribute": "activeRow" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "avatars", + "name": "mergeTarget", "type": { - "text": "GraphWrapperProps['avatars'] | undefined" + "text": "Awaited" }, - "attribute": "avatars" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "columns", + "name": "_mergeTargetPromise", "type": { - "text": "GraphWrapperProps['columns'] | undefined" + "text": "GetOverviewBranch['mergeTarget']" }, - "attribute": "columns" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "context", + "name": "mergeTargetPromise", "type": { - "text": "GraphWrapperProps['context'] | undefined" + "text": "GetOverviewBranch['mergeTarget']" }, - "attribute": "context" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "config", + "name": "_remote", "type": { - "text": "GraphWrapperProps['config'] | undefined" + "text": "Awaited" }, - "attribute": "config" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "downstreams", + "name": "remote", "type": { - "text": "GraphWrapperProps['downstreams'] | undefined" + "text": "Awaited" }, - "attribute": "downstreams" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "rows", + "name": "_remotePromise", "type": { - "text": "GraphWrapperProps['rows'] | undefined" + "text": "GetOverviewBranch['remote']" }, - "attribute": "rows" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "excludeRefs", + "name": "remotePromise", "type": { - "text": "GraphWrapperProps['excludeRefs'] | undefined" + "text": "GetOverviewBranch['remote']" }, - "attribute": "excludeRefs" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "excludeTypes", + "name": "_wip", "type": { - "text": "GraphWrapperProps['excludeTypes'] | undefined" + "text": "Awaited" }, - "attribute": "excludeTypes" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "paging", + "name": "wip", "type": { - "text": "GraphWrapperProps['paging'] | undefined" + "text": "Awaited" }, - "attribute": "paging" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "loading", + "name": "_wipPromise", "type": { - "text": "GraphWrapperProps['loading'] | undefined" + "text": "GetOverviewBranch['wip']" }, - "attribute": "loading" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "selectedRows", + "name": "wipPromise", "type": { - "text": "GraphWrapperProps['selectedRows'] | undefined" + "text": "GetOverviewBranch['wip']" }, - "attribute": "selectedRows" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "windowFocused", + "name": "busy", "type": { - "text": "GraphWrapperProps['windowFocused'] | undefined" + "text": "boolean" }, - "attribute": "windowFocused" + "default": "false", + "attribute": "busy", + "reflects": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "refsMetadata", + "name": "expanded", "type": { - "text": "GraphWrapperProps['refsMetadata'] | undefined" + "text": "boolean" }, - "attribute": "refsMetadata" + "default": "false", + "attribute": "expanded", + "reflects": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "includeOnlyRefs", + "name": "expandable", "type": { - "text": "GraphWrapperProps['includeOnlyRefs'] | undefined" + "text": "boolean" }, - "attribute": "includeOnlyRefs" + "default": "false", + "attribute": "expandable", + "reflects": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "rowsStats", + "name": "eventController", "type": { - "text": "GraphWrapperProps['rowsStats'] | undefined" + "text": "AbortController | undefined" }, - "attribute": "rowsStats" + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "kind": "field", - "name": "rowsStatsLoading", - "type": { - "text": "GraphWrapperProps['rowsStatsLoading'] | undefined" - }, - "attribute": "rowsStatsLoading" + "kind": "method", + "name": "onExpandableChanged", + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "workingTreeStats", + "name": "branchRef", "type": { - "text": "GraphWrapperProps['workingTreeStats'] | undefined" + "text": "BranchRef" }, - "attribute": "workingTreeStats" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "theming", + "name": "isWorktree", "type": { - "text": "GraphWrapperProps['theming'] | undefined" + "text": "boolean" }, - "attribute": "theming" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "searchResults", + "name": "cardIndicator", "type": { - "text": "GraphWrapperProps['searchResults'] | undefined" + "text": "GlCard['indicator']" }, - "attribute": "searchResults" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "filter", + "name": "branchCardIndicator", "type": { - "text": "SearchQuery" + "text": "GlCard['indicator']" }, - "attribute": "filter" - }, - { - "kind": "field", - "name": "setRef", - "type": { - "text": "(ref: GraphContainer) => void" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" } }, { - "kind": "field", - "name": "changedProps", - "type": { - "text": "Map" - }, + "kind": "method", + "name": "attachFocusListener", "privacy": "private", - "default": "new Map()" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { "kind": "field", - "name": "updateScheduled", - "type": { - "text": "boolean" - }, + "name": "onFocus", "privacy": "private", - "default": "false" - }, - { - "kind": "field", - "name": "handleChangeColumns", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleChangeRefsVisibility", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleChangeSelection", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleChangeVisibleDays", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleMissingAvatars", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleMissingRefsMetadata", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleMoreRows", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleMouseLeave", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleRefDoubleClick", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleRowContextMenu", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleRowDoubleClick", - "privacy": "private" - }, - { - "kind": "field", - "name": "handleRowHover", - "privacy": "private" + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "kind": "field", - "name": "handleRowUnhover", - "privacy": "private" - } - ], - "attributes": [ - { - "name": "activeRow", - "type": { - "text": "GraphWrapperProps['activeRow'] | undefined" + "kind": "method", + "name": "renderIssues", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "activeRow" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "avatars", - "type": { - "text": "GraphWrapperProps['avatars'] | undefined" + "kind": "method", + "name": "renderWip", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "avatars" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "columns", - "type": { - "text": "GraphWrapperProps['columns'] | undefined" + "kind": "method", + "name": "renderAvatars", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "columns" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "context", - "type": { - "text": "GraphWrapperProps['context'] | undefined" + "kind": "method", + "name": "renderTracking", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "context" + "parameters": [ + { + "name": "showWip", + "default": "false" + } + ], + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "config", - "type": { - "text": "GraphWrapperProps['config'] | undefined" + "kind": "method", + "name": "renderBranchActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "config" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "downstreams", - "type": { - "text": "GraphWrapperProps['downstreams'] | undefined" + "kind": "method", + "name": "renderPrActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "downstreams" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "rows", - "type": { - "text": "GraphWrapperProps['rows'] | undefined" + "kind": "method", + "name": "renderCollapsedActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "rows" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "excludeRefs", - "type": { - "text": "GraphWrapperProps['excludeRefs'] | undefined" + "kind": "method", + "name": "createWebviewCommandLink", + "privacy": "protected", + "return": { + "type": { + "text": "string" + } }, - "fieldName": "excludeRefs" + "parameters": [ + { + "name": "command", + "type": { + "text": "WebviewCommands | WebviewViewCommands | PlusCommands" + } + }, + { + "name": "args", + "optional": true, + "type": { + "text": "T | any" + } + } + ], + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "excludeTypes", - "type": { - "text": "GraphWrapperProps['excludeTypes'] | undefined" + "kind": "method", + "name": "createCommandLink", + "privacy": "protected", + "return": { + "type": { + "text": "string" + } }, - "fieldName": "excludeTypes" + "parameters": [ + { + "name": "command", + "type": { + "text": "GlCommands" + } + }, + { + "name": "args", + "optional": true, + "type": { + "text": "T | any" + } + } + ], + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "paging", - "type": { - "text": "GraphWrapperProps['paging'] | undefined" + "kind": "method", + "name": "renderTimestamp", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "paging" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "loading", - "type": { - "text": "GraphWrapperProps['loading'] | undefined" + "kind": "method", + "name": "renderBranchItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "loading" + "parameters": [ + { + "name": "actionsSection", + "optional": true, + "type": { + "text": "TemplateResult | NothingType" + } + } + ], + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "selectedRows", - "type": { - "text": "GraphWrapperProps['selectedRows'] | undefined" - }, - "fieldName": "selectedRows" + "kind": "method", + "name": "renderBranchIcon", + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "windowFocused", - "type": { - "text": "GraphWrapperProps['windowFocused'] | undefined" + "kind": "method", + "name": "renderPrItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "windowFocused" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "refsMetadata", - "type": { - "text": "GraphWrapperProps['refsMetadata'] | undefined" - }, - "fieldName": "refsMetadata" + "kind": "method", + "name": "renderLaunchpadItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "includeOnlyRefs", - "type": { - "text": "GraphWrapperProps['includeOnlyRefs'] | undefined" + "kind": "method", + "name": "renderMergeTargetStatus", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } }, - "fieldName": "includeOnlyRefs" + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "rowsStats", + "kind": "method", + "name": "toggleExpanded", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "expanded", + "default": "!this.expanded" + } + ], + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "superclass": { + "name": "GlBranchCardBase", + "module": "/src/webviews/apps/plus/home/components/branch-card" + }, + "tagName": "gl-active-branch-card", + "customElement": true, + "attributes": [ + { + "name": "repo", "type": { - "text": "GraphWrapperProps['rowsStats'] | undefined" + "text": "string" }, - "fieldName": "rowsStats" + "fieldName": "repo", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "rowsStatsLoading", + "name": "showUpgrade", "type": { - "text": "GraphWrapperProps['rowsStatsLoading'] | undefined" + "text": "boolean" }, - "fieldName": "rowsStatsLoading" + "default": "false", + "fieldName": "showUpgrade", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "workingTreeStats", + "name": "branch", "type": { - "text": "GraphWrapperProps['workingTreeStats'] | undefined" + "text": "GetOverviewBranch" }, - "fieldName": "workingTreeStats" + "fieldName": "branch", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "theming", + "name": "busy", "type": { - "text": "GraphWrapperProps['theming'] | undefined" + "text": "boolean" }, - "fieldName": "theming" + "default": "false", + "fieldName": "busy", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "searchResults", + "name": "expanded", "type": { - "text": "GraphWrapperProps['searchResults'] | undefined" + "text": "boolean" }, - "fieldName": "searchResults" + "default": "false", + "fieldName": "expanded", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } }, { - "name": "filter", + "name": "expandable", "type": { - "text": "SearchQuery" + "text": "boolean" }, - "fieldName": "filter" + "default": "false", + "fieldName": "expandable", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-graph", - "customElement": true + ] } ], "exports": [ { "kind": "js", - "name": "GlGraph", + "name": "activeWorkTagName", "declaration": { - "name": "GlGraph", - "module": "src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper-element.ts" + "name": "activeWorkTagName", + "module": "src/webviews/apps/plus/home/components/active-work.ts" + } + }, + { + "kind": "js", + "name": "GlActiveWork", + "declaration": { + "name": "GlActiveWork", + "module": "src/webviews/apps/plus/home/components/active-work.ts" } }, { "kind": "custom-element-definition", - "name": "gl-graph", "declaration": { - "name": "GlGraph", - "module": "src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper-element.ts" + "name": "GlActiveWork", + "module": "src/webviews/apps/plus/home/components/active-work.ts" + } + }, + { + "kind": "js", + "name": "GlActiveBranchCard", + "declaration": { + "name": "GlActiveBranchCard", + "module": "src/webviews/apps/plus/home/components/active-work.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-active-branch-card", + "declaration": { + "name": "GlActiveBranchCard", + "module": "src/webviews/apps/plus/home/components/active-work.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper.ts", + "path": "src/webviews/apps/plus/home/components/branch-card.ts", "declarations": [ + { + "kind": "variable", + "name": "branchCardStyles", + "default": "css` * { box-sizing: border-box; } gl-avatar-list { --gl-avatar-size: 2.4rem; margin-block: -0.4rem; } .branch-item { position: relative; } .branch-item__container { display: flex; flex-direction: column; gap: 0.6rem; } .branch-item__container > * { margin-block: 0; } .branch-item__section { display: flex; flex-direction: column; gap: 0.4rem; } .branch-item__section > * { margin-block: 0; } .branch-item__section--details { font-size: 0.9em; color: var(--vscode-descriptionForeground); } .branch-item__actions { display: flex; align-items: center; gap: 0.8rem; flex-direction: row; justify-content: flex-end; font-size: 0.9em; } /* :empty selector doesn't work with lit */ .branch-item__actions:not(:has(*)) { display: none; } .branch-item__icon { color: var(--vscode-descriptionForeground); flex: none; } .branch-item__name { flex-grow: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: bold; } .branch-item__name--secondary { font-weight: normal; } .branch-item__identifier { color: var(--vscode-descriptionForeground); text-decoration: none; } .branch-item__grouping { display: inline-flex; align-items: center; gap: 0.6rem; max-width: 100%; margin-block: 0; } .branch-item__changes { display: flex; align-items: center; gap: 1rem; justify-content: flex-end; flex-wrap: wrap; white-space: nowrap; } .branch-item__changes formatted-date { margin-inline-end: auto; } .branch-item__summary { display: flex; align-items: center; gap: 0.6rem; } .branch-item__collapsed-actions { position: absolute; z-index: var(--gl-branch-card-actions-zindex, 2); right: 0.4rem; bottom: 0.3rem; padding: 0.4rem 0.6rem; background-color: var(--gl-card-hover-background); } .branch-item:not(:focus-within):not(:hover) .branch-item__collapsed-actions { ${srOnlyStyles} } .pill { --gl-pill-border: color-mix(in srgb, transparent 80%, var(--color-foreground)); } .work-item { --gl-card-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #fff 3%); --gl-card-hover-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #fff 1.5%); } .work-item::part(base) { margin-block-end: 0; } .branch-item__section.mb-1 { margin-block: 0.4rem; } .branch-item__merge-target { margin-inline-end: auto; } .branch-item__row { display: flex; gap: 0.8rem; } .branch-item__row [full] { flex-grow: 1; } .branch-item__missing { --button-foreground: inherit; } :host-context(.vscode-dark) .branch-item__missing, :host-context(.vscode-high-contrast) .branch-item__missing { --button-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #fff 3%); --button-hover-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #fff 1.5%); --button-border: color-mix(in lab, var(--vscode-sideBar-background) 100%, #fff 12%); } :host-context(.vscode-light) .branch-item__missing, :host-context(.vscode-high-contrast-light) .branch-item__missing { --button-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #000 8%); --button-hover-background: color-mix(in lab, var(--vscode-sideBar-background) 100%, #000 10%); --button-border: color-mix(in lab, var(--vscode-sideBar-background) 100%, #000 14%); } .branch-item__category { margin-inline-start: 0.6rem; } .launchpad-grouping--mergeable { color: var(--vscode-gitlens-launchpadIndicatorMergeableColor); } .launchpad-grouping--blocked { color: var(--vscode-gitlens-launchpadIndicatorBlockedColor); } .launchpad-grouping--attention { color: var(--vscode-gitlens-launchpadIndicatorAttentionColor); } .tracking__pill, .wip__pill { display: flex; flex-direction: row; gap: 1rem; } .tracking__tooltip, .wip__tooltip { display: contents; vertical-align: middle; } .tracking__tooltip p, .wip__tooltip p { margin-block: 0; } p.tracking__tooltip--wip { margin-block-start: 1rem; } `" + }, { "kind": "class", "description": "", - "name": "GlGraphWrapper", + "name": "GlBranchCardBase", "members": [ { "kind": "field", - "name": "graphAppState", + "name": "_homeState", "type": { - "text": "typeof graphStateContext.__context__" + "text": "State" + }, + "privacy": "protected" + }, + { + "kind": "field", + "name": "repo", + "type": { + "text": "string" + }, + "attribute": "repo" + }, + { + "kind": "field", + "name": "showUpgrade", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "showUpgrade" + }, + { + "kind": "field", + "name": "_branch", + "type": { + "text": "GetOverviewBranch" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "branch", + "type": { + "text": "GetOverviewBranch" + }, + "attribute": "branch" + }, + { + "kind": "field", + "name": "_autolinks", + "type": { + "text": "Awaited" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "autolinks", + "type": { + "text": "Awaited" }, - "privacy": "private", "readonly": true }, { "kind": "field", - "name": "hostState", + "name": "_autolinksPromise", "type": { - "text": "typeof stateContext.__context__" + "text": "GetOverviewBranch['autolinks']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "autolinksPromise", + "type": { + "text": "GetOverviewBranch['autolinks']" + } + }, + { + "kind": "field", + "name": "_contributors", + "type": { + "text": "Awaited" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "contributors", + "type": { + "text": "Awaited" }, - "privacy": "private", "readonly": true }, { "kind": "field", - "name": "_ipc", + "name": "_contributorsPromise", "type": { - "text": "typeof ipcContext.__context__" + "text": "GetOverviewBranch['contributors']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "contributorsPromise", + "type": { + "text": "GetOverviewBranch['contributors']" + } + }, + { + "kind": "field", + "name": "_issues", + "type": { + "text": "Awaited" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "issues", + "type": { + "text": "Awaited" }, - "privacy": "private", "readonly": true }, { "kind": "field", - "name": "_telemetry", + "name": "_issuesPromise", "type": { - "text": "TelemetryContext" + "text": "GetOverviewBranch['issues']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "issuesPromise", + "type": { + "text": "GetOverviewBranch['issues']" + } + }, + { + "kind": "field", + "name": "_pr", + "type": { + "text": "Awaited" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "pr", + "type": { + "text": "Awaited" }, - "privacy": "private", "readonly": true }, { "kind": "field", - "name": "graph", + "name": "_prPromise", "type": { - "text": "typeof GlGraph" + "text": "GetOverviewBranch['pr']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "prPromise", + "type": { + "text": "GetOverviewBranch['pr']" } }, { "kind": "field", - "name": "ref", + "name": "_launchpadItem", "type": { - "text": "GraphContainer | undefined" + "text": "Awaited>['launchpad']>" }, "privacy": "private" }, { "kind": "field", - "name": "onSetRef", + "name": "launchpadItem", + "type": { + "text": "Awaited>['launchpad']>" + }, + "readonly": true + }, + { + "kind": "field", + "name": "_launchpadItemPromise", + "type": { + "text": "NonNullable>['launchpad']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "launchpadItemPromise", + "type": { + "text": "NonNullable>['launchpad']" + } + }, + { + "kind": "field", + "name": "_mergeTarget", + "type": { + "text": "Awaited" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "mergeTarget", + "type": { + "text": "Awaited" + }, + "readonly": true + }, + { + "kind": "field", + "name": "_mergeTargetPromise", + "type": { + "text": "GetOverviewBranch['mergeTarget']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "mergeTargetPromise", + "type": { + "text": "GetOverviewBranch['mergeTarget']" + } + }, + { + "kind": "field", + "name": "_remote", + "type": { + "text": "Awaited" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "remote", + "type": { + "text": "Awaited" + }, + "readonly": true + }, + { + "kind": "field", + "name": "_remotePromise", + "type": { + "text": "GetOverviewBranch['remote']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "remotePromise", + "type": { + "text": "GetOverviewBranch['remote']" + } + }, + { + "kind": "field", + "name": "_wip", + "type": { + "text": "Awaited" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "wip", + "type": { + "text": "Awaited" + }, + "readonly": true + }, + { + "kind": "field", + "name": "_wipPromise", + "type": { + "text": "GetOverviewBranch['wip']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "wipPromise", + "type": { + "text": "GetOverviewBranch['wip']" + } + }, + { + "kind": "field", + "name": "busy", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "busy", + "reflects": true + }, + { + "kind": "field", + "name": "expanded", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "expanded", + "reflects": true + }, + { + "kind": "field", + "name": "expandable", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "expandable", + "reflects": true + }, + { + "kind": "field", + "name": "eventController", + "type": { + "text": "AbortController | undefined" + }, + "privacy": "private" + }, + { + "kind": "method", + "name": "onExpandableChanged", "privacy": "private" }, + { + "kind": "field", + "name": "branchRef", + "type": { + "text": "BranchRef" + }, + "readonly": true + }, + { + "kind": "field", + "name": "isWorktree", + "type": { + "text": "boolean" + }, + "readonly": true + }, + { + "kind": "field", + "name": "cardIndicator", + "type": { + "text": "GlCard['indicator']" + }, + "readonly": true + }, + { + "kind": "field", + "name": "branchCardIndicator", + "type": { + "text": "GlCard['indicator']" + }, + "readonly": true + }, + { + "kind": "method", + "name": "attachFocusListener", + "privacy": "private" + }, + { + "kind": "field", + "name": "onFocus", + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "renderIssues", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "renderWip", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "renderAvatars", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "renderTracking", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "parameters": [ + { + "name": "showWip", + "default": "false" + } + ] + }, + { + "kind": "method", + "name": "getBranchActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult[]" + } + } + }, + { + "kind": "method", + "name": "renderBranchActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "getPrActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult[]" + } + } + }, + { + "kind": "method", + "name": "renderPrActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "getCollapsedActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult[]" + } + } + }, + { + "kind": "method", + "name": "renderCollapsedActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "createWebviewCommandLink", + "privacy": "protected", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "command", + "type": { + "text": "WebviewCommands | WebviewViewCommands | PlusCommands" + } + }, + { + "name": "args", + "optional": true, + "type": { + "text": "T | any" + } + } + ] + }, + { + "kind": "method", + "name": "createCommandLink", + "privacy": "protected", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "command", + "type": { + "text": "GlCommands" + } + }, + { + "name": "args", + "optional": true, + "type": { + "text": "T | any" + } + } + ] + }, + { + "kind": "method", + "name": "renderTimestamp", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "renderBranchIndicator", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | undefined" + } + } + }, + { + "kind": "method", + "name": "renderBranchItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "parameters": [ + { + "name": "actionsSection", + "optional": true, + "type": { + "text": "TemplateResult | NothingType" + } + } + ] + }, + { + "kind": "method", + "name": "renderBranchIcon", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderPrItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "renderLaunchpadItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "renderMergeTargetStatus", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "renderIssuesItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + } + }, + { + "kind": "method", + "name": "toggleExpanded", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "expanded", + "default": "!this.expanded" + } + ] + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "attributes": [ + { + "name": "repo", + "type": { + "text": "string" + }, + "fieldName": "repo" + }, + { + "name": "showUpgrade", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "showUpgrade" + }, + { + "name": "branch", + "type": { + "text": "GetOverviewBranch" + }, + "fieldName": "branch" + }, + { + "name": "busy", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "busy" + }, + { + "name": "expanded", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "expanded" + }, + { + "name": "expandable", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "expandable" + } + ], + "superclass": { + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" + } + }, + { + "kind": "class", + "description": "", + "name": "GlBranchCard", + "members": [ + { + "kind": "method", + "name": "getCollapsedActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult[]" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "getBranchActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult[]" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "getPrActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult[]" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderBranchIndicator", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | undefined" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_homeState", + "type": { + "text": "State" + }, + "privacy": "protected", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "repo", + "type": { + "text": "string" + }, + "attribute": "repo", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "showUpgrade", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "showUpgrade", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_branch", + "type": { + "text": "GetOverviewBranch" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "branch", + "type": { + "text": "GetOverviewBranch" + }, + "attribute": "branch", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_autolinks", + "type": { + "text": "Awaited" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "autolinks", + "type": { + "text": "Awaited" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_autolinksPromise", + "type": { + "text": "GetOverviewBranch['autolinks']" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "autolinksPromise", + "type": { + "text": "GetOverviewBranch['autolinks']" + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_contributors", + "type": { + "text": "Awaited" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "contributors", + "type": { + "text": "Awaited" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_contributorsPromise", + "type": { + "text": "GetOverviewBranch['contributors']" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "contributorsPromise", + "type": { + "text": "GetOverviewBranch['contributors']" + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_issues", + "type": { + "text": "Awaited" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "issues", + "type": { + "text": "Awaited" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_issuesPromise", + "type": { + "text": "GetOverviewBranch['issues']" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "issuesPromise", + "type": { + "text": "GetOverviewBranch['issues']" + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_pr", + "type": { + "text": "Awaited" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "pr", + "type": { + "text": "Awaited" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_prPromise", + "type": { + "text": "GetOverviewBranch['pr']" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "prPromise", + "type": { + "text": "GetOverviewBranch['pr']" + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_launchpadItem", + "type": { + "text": "Awaited>['launchpad']>" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "launchpadItem", + "type": { + "text": "Awaited>['launchpad']>" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_launchpadItemPromise", + "type": { + "text": "NonNullable>['launchpad']" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "launchpadItemPromise", + "type": { + "text": "NonNullable>['launchpad']" + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_mergeTarget", + "type": { + "text": "Awaited" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "mergeTarget", + "type": { + "text": "Awaited" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_mergeTargetPromise", + "type": { + "text": "GetOverviewBranch['mergeTarget']" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "mergeTargetPromise", + "type": { + "text": "GetOverviewBranch['mergeTarget']" + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_remote", + "type": { + "text": "Awaited" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "remote", + "type": { + "text": "Awaited" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_remotePromise", + "type": { + "text": "GetOverviewBranch['remote']" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "remotePromise", + "type": { + "text": "GetOverviewBranch['remote']" + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_wip", + "type": { + "text": "Awaited" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "wip", + "type": { + "text": "Awaited" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "_wipPromise", + "type": { + "text": "GetOverviewBranch['wip']" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "wipPromise", + "type": { + "text": "GetOverviewBranch['wip']" + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "busy", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "busy", + "reflects": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "expanded", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "expanded", + "reflects": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "expandable", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "expandable", + "reflects": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "eventController", + "type": { + "text": "AbortController | undefined" + }, + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "onExpandableChanged", + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "branchRef", + "type": { + "text": "BranchRef" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "isWorktree", + "type": { + "text": "boolean" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "cardIndicator", + "type": { + "text": "GlCard['indicator']" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "branchCardIndicator", + "type": { + "text": "GlCard['indicator']" + }, + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "attachFocusListener", + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "field", + "name": "onFocus", + "privacy": "private", + "readonly": true, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderIssues", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderWip", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderAvatars", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderTracking", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "parameters": [ + { + "name": "showWip", + "default": "false" + } + ], + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderBranchActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderPrActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderCollapsedActions", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "createWebviewCommandLink", + "privacy": "protected", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "command", + "type": { + "text": "WebviewCommands | WebviewViewCommands | PlusCommands" + } + }, + { + "name": "args", + "optional": true, + "type": { + "text": "T | any" + } + } + ], + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "createCommandLink", + "privacy": "protected", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "command", + "type": { + "text": "GlCommands" + } + }, + { + "name": "args", + "optional": true, + "type": { + "text": "T | any" + } + } + ], + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderTimestamp", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderBranchItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "parameters": [ + { + "name": "actionsSection", + "optional": true, + "type": { + "text": "TemplateResult | NothingType" + } + } + ], + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderBranchIcon", + "privacy": "private", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderPrItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderLaunchpadItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderMergeTargetStatus", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "renderIssuesItem", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | NothingType" + } + }, + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "toggleExpanded", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "expanded", + "default": "!this.expanded" + } + ], + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "superclass": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + }, + "tagName": "gl-branch-card", + "customElement": true, + "attributes": [ + { + "name": "repo", + "type": { + "text": "string" + }, + "fieldName": "repo", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "name": "showUpgrade", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "showUpgrade", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "name": "branch", + "type": { + "text": "GetOverviewBranch" + }, + "fieldName": "branch", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "name": "busy", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "busy", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "name": "expanded", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "expanded", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "name": "expandable", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "expandable", + "inheritedFrom": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + } + ] + }, + { + "kind": "class", + "description": "", + "name": "GlWorkUnit", + "members": [ + { + "kind": "field", + "name": "primary", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "primary", + "reflects": true + }, + { + "kind": "field", + "name": "nested", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "nested", + "reflects": true + }, + { + "kind": "field", + "name": "indicator", + "type": { + "text": "GlCard['indicator'] | undefined" + }, + "attribute": "indicator", + "reflects": true + }, + { + "kind": "field", + "name": "expanded", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "expanded", + "reflects": true + }, + { + "kind": "method", + "name": "renderContent", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderSummary", + "privacy": "private" + } + ], + "attributes": [ + { + "name": "primary", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "primary" + }, + { + "name": "nested", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "nested" + }, + { + "name": "indicator", + "type": { + "text": "GlCard['indicator'] | undefined" + }, + "fieldName": "indicator" + }, + { + "name": "expanded", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "expanded" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-work-item", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "branchCardStyles", + "declaration": { + "name": "branchCardStyles", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "js", + "name": "GlBranchCardBase", + "declaration": { + "name": "GlBranchCardBase", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "js", + "name": "GlBranchCard", + "declaration": { + "name": "GlBranchCard", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-branch-card", + "declaration": { + "name": "GlBranchCard", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "js", + "name": "GlWorkUnit", + "declaration": { + "name": "GlWorkUnit", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-work-item", + "declaration": { + "name": "GlWorkUnit", + "module": "src/webviews/apps/plus/home/components/branch-card.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/home/components/branch-section.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlSection", + "members": [ + { + "kind": "field", + "name": "loading", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "loading" + }, + { + "kind": "field", + "name": "headingLevel", + "type": { + "text": "ARIAMixin['ariaLevel']" + }, + "default": "'3'", + "attribute": "heading-level" + } + ], + "attributes": [ + { + "name": "loading", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "loading" + }, + { + "name": "heading-level", + "type": { + "text": "ARIAMixin['ariaLevel']" + }, + "default": "'3'", + "fieldName": "headingLevel" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-section", + "customElement": true + }, + { + "kind": "class", + "description": "", + "name": "GlBranchSection", + "members": [ + { + "kind": "field", + "name": "label", + "type": { + "text": "string" + }, + "attribute": "label" + }, + { + "kind": "field", + "name": "repo", + "type": { + "text": "string" + }, + "attribute": "repo" + }, + { + "kind": "field", + "name": "branches", + "type": { + "text": "GetOverviewBranch[]" + }, + "attribute": "branches" + }, + { + "kind": "field", + "name": "isFetching", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "isFetching" + }, + { + "kind": "field", + "name": "branchCards", + "type": { + "text": "GlBranchCardBase[]" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "onCardExpanded", + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "toggleSiblingCards", + "privacy": "private", + "parameters": [ + { + "name": "card", + "optional": true, + "type": { + "text": "GlBranchCardBase" + } + } + ] + }, + { + "kind": "field", + "name": "toggleSiblingCardsDebounced", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderSectionLabel", + "privacy": "private" + } + ], + "attributes": [ + { + "name": "label", + "type": { + "text": "string" + }, + "fieldName": "label" + }, + { + "name": "repo", + "type": { + "text": "string" + }, + "fieldName": "repo" + }, + { + "name": "branches", + "type": { + "text": "GetOverviewBranch[]" + }, + "fieldName": "branches" + }, + { + "name": "isFetching", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "isFetching" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-branch-section", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlSection", + "declaration": { + "name": "GlSection", + "module": "src/webviews/apps/plus/home/components/branch-section.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-section", + "declaration": { + "name": "GlSection", + "module": "src/webviews/apps/plus/home/components/branch-section.ts" + } + }, + { + "kind": "js", + "name": "GlBranchSection", + "declaration": { + "name": "GlBranchSection", + "module": "src/webviews/apps/plus/home/components/branch-section.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-branch-section", + "declaration": { + "name": "GlBranchSection", + "module": "src/webviews/apps/plus/home/components/branch-section.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts", + "declarations": [ + { + "kind": "variable", + "name": "selectStyles", + "default": "css` .select { background: none; outline: none; border: none; text-decoration: none !important; font-weight: 500; color: var(--color-foreground--25); } .select option { color: var(--vscode-foreground); background-color: var(--vscode-dropdown-background); } .select:not(:disabled) { cursor: pointer; color: var(--color-foreground--50); } .select:not(:disabled):focus { outline: 1px solid var(--color-focus-border); } .select:not(:disabled):hover { color: var(--vscode-foreground); text-decoration: underline !important; } `" + }, + { + "kind": "class", + "description": "", + "name": "GlObjectSelect", + "members": [ + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "disabled" + }, + { + "kind": "field", + "name": "value", + "type": { + "text": "V | undefined" + }, + "attribute": "value" + }, + { + "kind": "field", + "name": "options", + "type": { + "text": "T[] | undefined" + }, + "attribute": "options" + }, + { + "kind": "method", + "name": "getValue", + "privacy": "protected", + "return": { + "type": { + "text": "V" + } + }, + "parameters": [ + { + "name": "option", + "type": { + "text": "T" + } + } + ] + }, + { + "kind": "method", + "name": "getLabel", + "privacy": "protected", + "return": { + "type": { + "text": "L" + } + }, + "parameters": [ + { + "name": "option", + "type": { + "text": "T" + } + } + ] + }, + { + "kind": "method", + "name": "onChange", + "privacy": "protected", + "return": { + "type": { + "text": "unknown" + } + }, + "parameters": [ + { + "name": "e", + "type": { + "text": "InputEvent" + } + } + ] + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "attributes": [ + { + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "disabled" + }, + { + "name": "value", + "type": { + "text": "V | undefined" + }, + "fieldName": "value" + }, + { + "name": "options", + "type": { + "text": "T[] | undefined" + }, + "fieldName": "options" + } + ], + "superclass": { + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" + } + }, + { + "kind": "class", + "description": "", + "name": "GlBranchThresholdFilter", + "members": [ + { + "kind": "method", + "name": "getValue", + "privacy": "protected", + "return": { + "type": { + "text": "OverviewRecentThreshold | 'OneYear'" + } + }, + "parameters": [ + { + "name": "option", + "type": { + "text": "{\n\t\tvalue: OverviewRecentThreshold | OverviewStaleThreshold;\n\t}" + } + } + ], + "inheritedFrom": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "kind": "method", + "name": "getLabel", + "privacy": "protected", + "return": { + "type": { + "text": "string" + } + }, + "parameters": [ + { + "name": "option", + "type": { + "text": "{ label: string }" + } + } + ], + "inheritedFrom": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "kind": "method", + "name": "onChange", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "e", + "type": { + "text": "InputEvent" + } + } + ], + "inheritedFrom": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "disabled", + "inheritedFrom": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "kind": "field", + "name": "value", + "type": { + "text": "V | undefined" + }, + "attribute": "value", + "inheritedFrom": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "kind": "field", + "name": "options", + "type": { + "text": "T[] | undefined" + }, + "attribute": "options", + "inheritedFrom": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "superclass": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + }, + "tagName": "gl-branch-threshold-filter", + "customElement": true, + "attributes": [ + { + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "disabled", + "inheritedFrom": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "name": "value", + "type": { + "text": "V | undefined" + }, + "fieldName": "value", + "inheritedFrom": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "name": "options", + "type": { + "text": "T[] | undefined" + }, + "fieldName": "options", + "inheritedFrom": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + } + ] + } + ], + "exports": [ + { + "kind": "js", + "name": "selectStyles", + "declaration": { + "name": "selectStyles", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "kind": "js", + "name": "GlObjectSelect", + "declaration": { + "name": "GlObjectSelect", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "kind": "js", + "name": "GlBranchThresholdFilter", + "declaration": { + "name": "GlBranchThresholdFilter", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-branch-threshold-filter", + "declaration": { + "name": "GlBranchThresholdFilter", + "module": "src/webviews/apps/plus/home/components/branch-threshold-filter.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/home/components/launchpad.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlLaunchpad", + "members": [ + { + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + }, + { + "kind": "field", + "name": "_homeState", + "type": { + "text": "State" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_ipc", + "type": { + "text": "HostIpc" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_disposable", + "type": { + "text": "Disposable[]" + }, + "privacy": "private", + "default": "[]" + }, + { + "kind": "field", + "name": "_summary", + "privacy": "private" + }, + { + "kind": "field", + "name": "_summaryState", + "privacy": "private", + "default": "new AsyncComputedState(async _abortSignal => { const rsp = await this._ipc.sendRequest(GetLaunchpadSummary, {}); return rsp; })" + }, + { + "kind": "field", + "name": "startWorkCommand", + "type": { + "text": "string" + }, + "readonly": true + }, + { + "kind": "field", + "name": "createBranchCommand", + "type": { + "text": "string" + }, + "readonly": true + }, + { + "kind": "method", + "name": "renderSummaryResult", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderPending", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderSummary", + "privacy": "private", + "parameters": [ + { + "name": "summary", + "type": { + "text": "LaunchpadSummary | undefined" + } + } + ] + } + ], + "mixins": [ + { + "name": "SignalWatcher", + "package": "@lit-labs/signals" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-launchpad", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlLaunchpad", + "declaration": { + "name": "GlLaunchpad", + "module": "src/webviews/apps/plus/home/components/launchpad.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-launchpad", + "declaration": { + "name": "GlLaunchpad", + "module": "src/webviews/apps/plus/home/components/launchpad.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/home/components/merge-target-status.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlMergeTargetStatus", + "members": [ + { + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + }, + { + "kind": "field", + "name": "branch", + "type": { + "text": "Pick" + }, + "attribute": "branch" + }, + { + "kind": "field", + "name": "_target", + "type": { + "text": "Awaited" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "target", + "type": { + "text": "Awaited" + }, + "readonly": true + }, + { + "kind": "field", + "name": "_targetPromise", + "type": { + "text": "GetOverviewBranch['mergeTarget']" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "targetPromise", + "type": { + "text": "GetOverviewBranch['mergeTarget']" + }, + "attribute": "targetPromise" + }, + { + "kind": "field", + "name": "conflicts", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "mergedStatus", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "status", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "branchRef", + "type": { + "text": "BranchRef | undefined" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "targetBranchRef", + "type": { + "text": "BranchRef | undefined" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "renderContent", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderHeader", + "privacy": "private", + "parameters": [ + { + "name": "title", + "type": { + "text": "string" + } + }, + { + "name": "icon", + "type": { + "text": "string" + } + }, + { + "name": "status", + "optional": true, + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "method", + "name": "renderHeaderActions", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderInlineTargetEdit", + "privacy": "private", + "parameters": [ + { + "name": "target", + "type": { + "text": "Awaited" + } + } + ] + }, + { + "kind": "method", + "name": "renderFiles", + "privacy": "private", + "parameters": [ + { + "name": "files", + "type": { + "text": "{ path: string }[]" + } + } + ] + }, + { + "kind": "method", + "name": "renderFile", + "privacy": "private", + "parameters": [ + { + "name": "path", + "type": { + "text": "string" + } + } + ] + } + ], + "attributes": [ + { + "name": "branch", + "type": { + "text": "Pick" + }, + "fieldName": "branch" + }, + { + "name": "targetPromise", + "type": { + "text": "GetOverviewBranch['mergeTarget']" + }, + "fieldName": "targetPromise" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-merge-target-status", + "customElement": true + }, + { + "kind": "class", + "description": "", + "name": "GlMergeTargetUpgrade", + "members": [ + { + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-merge-target-upgrade", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlMergeTargetStatus", + "declaration": { + "name": "GlMergeTargetStatus", + "module": "src/webviews/apps/plus/home/components/merge-target-status.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-merge-target-status", + "declaration": { + "name": "GlMergeTargetStatus", + "module": "src/webviews/apps/plus/home/components/merge-target-status.ts" + } + }, + { + "kind": "js", + "name": "GlMergeTargetUpgrade", + "declaration": { + "name": "GlMergeTargetUpgrade", + "module": "src/webviews/apps/plus/home/components/merge-target-status.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-merge-target-upgrade", + "declaration": { + "name": "GlMergeTargetUpgrade", + "module": "src/webviews/apps/plus/home/components/merge-target-status.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/home/components/overview.ts", + "declarations": [ + { + "kind": "variable", + "name": "overviewTagName", + "type": { + "text": "string" + }, + "default": "'gl-overview'" + }, + { + "kind": "class", + "description": "", + "name": "GlOverview", + "members": [ + { + "kind": "field", + "name": "_homeState", + "type": { + "text": "State" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_inactiveOverviewState", + "type": { + "text": "InactiveOverviewState" + }, + "privacy": "private" + }, + { + "kind": "method", + "name": "renderLoader", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderPending", + "privacy": "private" + }, + { + "kind": "field", + "name": "_ipc", + "type": { + "text": "HostIpc" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "onChangeRecentThresholdFilter", + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "renderComplete", + "privacy": "private", + "parameters": [ + { + "name": "overview", + "type": { + "text": "GetInactiveOverviewResponse" + } + }, + { + "name": "isFetching", + "default": "false" + } + ] + } + ], + "mixins": [ + { + "name": "SignalWatcher", + "package": "@lit-labs/signals" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "overviewTagName", + "declaration": { + "name": "overviewTagName", + "module": "src/webviews/apps/plus/home/components/overview.ts" + } + }, + { + "kind": "js", + "name": "GlOverview", + "declaration": { + "name": "GlOverview", + "module": "src/webviews/apps/plus/home/components/overview.ts" + } + }, + { + "kind": "custom-element-definition", + "declaration": { + "name": "GlOverview", + "module": "src/webviews/apps/plus/home/components/overview.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/home/components/overviewState.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "ActiveOverviewState", + "members": [ + { + "kind": "field", + "name": "_disposable", + "type": { + "text": "Disposable | undefined" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "dispose" + }, + { + "kind": "method", + "name": "changeRepository", + "return": { + "type": { + "text": "void" + } + } + }, + { + "kind": "field", + "name": "_debounce", + "type": { + "text": "number" + }, + "privacy": "private", + "default": "500", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "_invalidate", + "privacy": "private", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "_computed", + "type": { + "text": "AsyncComputed | undefined" + }, + "privacy": "private", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "_state", + "privacy": "private", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "state", + "type": { + "text": "T | undefined" + }, + "readonly": true, + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "computed", + "type": { + "text": "AsyncComputed" + }, + "readonly": true, + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "method", + "name": "_runCore", + "privacy": "private", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "_runDebounced", + "type": { + "text": "Deferrable<() => void> | undefined" + }, + "privacy": "private", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "method", + "name": "_run", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "immediate", + "default": "false" + } + ], + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "method", + "name": "run", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "force", + "default": "false" + } + ], + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "method", + "name": "invalidate", + "return": { + "type": { + "text": "void" + } + }, + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + } + ], + "superclass": { + "name": "AsyncComputedState", + "module": "/src/webviews/apps/shared/components/signal-utils" + } + }, + { + "kind": "class", + "description": "", + "name": "InactiveOverviewState", + "members": [ + { + "kind": "field", + "name": "_disposable", + "type": { + "text": "Disposable | undefined" + }, + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "filter" + }, + { + "kind": "method", + "name": "dispose", + "return": { + "type": { + "text": "void" + } + } + }, + { + "kind": "field", + "name": "_debounce", + "type": { + "text": "number" + }, + "privacy": "private", + "default": "500", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "_invalidate", + "privacy": "private", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "_computed", + "type": { + "text": "AsyncComputed | undefined" + }, + "privacy": "private", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "_state", + "privacy": "private", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "state", + "type": { + "text": "T | undefined" + }, + "readonly": true, + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "computed", + "type": { + "text": "AsyncComputed" + }, + "readonly": true, + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "method", + "name": "_runCore", + "privacy": "private", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "field", + "name": "_runDebounced", + "type": { + "text": "Deferrable<() => void> | undefined" + }, + "privacy": "private", + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "method", + "name": "_run", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "immediate", + "default": "false" + } + ], + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "method", + "name": "run", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "force", + "default": "false" + } + ], + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + }, + { + "kind": "method", + "name": "invalidate", + "return": { + "type": { + "text": "void" + } + }, + "inheritedFrom": { + "name": "AsyncComputedState", + "module": "src/webviews/apps/shared/components/signal-utils.ts" + } + } + ], + "superclass": { + "name": "AsyncComputedState", + "module": "/src/webviews/apps/shared/components/signal-utils" + } + }, + { + "kind": "variable", + "name": "activeOverviewStateContext" + }, + { + "kind": "variable", + "name": "inactiveOverviewStateContext" + } + ], + "exports": [ + { + "kind": "js", + "name": "ActiveOverviewState", + "declaration": { + "name": "ActiveOverviewState", + "module": "src/webviews/apps/plus/home/components/overviewState.ts" + } + }, + { + "kind": "js", + "name": "InactiveOverviewState", + "declaration": { + "name": "InactiveOverviewState", + "module": "src/webviews/apps/plus/home/components/overviewState.ts" + } + }, + { + "kind": "js", + "name": "activeOverviewStateContext", + "declaration": { + "name": "activeOverviewStateContext", + "module": "src/webviews/apps/plus/home/components/overviewState.ts" + } + }, + { + "kind": "js", + "name": "inactiveOverviewStateContext", + "declaration": { + "name": "inactiveOverviewStateContext", + "module": "src/webviews/apps/plus/home/components/overviewState.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/patchDetails/components/gl-draft-details.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlDraftDetails", + "members": [ + { + "kind": "field", + "name": "state", + "type": { + "text": "State" + }, + "attribute": "state" + }, + { + "kind": "field", + "name": "explainBusy", + "type": { + "text": "boolean" + }, + "default": "false" + }, + { + "kind": "field", + "name": "explain", + "type": { + "text": "ExplainState | undefined" + }, + "attribute": "explain" + }, + { + "kind": "field", + "name": "selectedPatches", + "type": { + "text": "string[]" + }, + "default": "[]" + }, + { + "kind": "field", + "name": "validityMessage", + "type": { + "text": "string | undefined" + } + }, + { + "kind": "field", + "name": "_copiedLink", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "field", + "name": "cloudDraft", + "readonly": true + }, + { + "kind": "field", + "name": "isCodeSuggestion", + "type": { + "text": "boolean" + }, + "readonly": true + }, + { + "kind": "field", + "name": "canSubmit", + "type": { + "text": "boolean" + }, + "readonly": true + }, + { + "kind": "method", + "name": "renderEmptyContent", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderPatchMessage", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderExplainAi", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderChangedFiles", + "privacy": "private" + }, + { + "kind": "field", + "name": "treeModel", + "type": { + "text": "TreeModel[]" + }, + "readonly": true + }, + { + "kind": "method", + "name": "renderUserSelection", + "privacy": "private", + "parameters": [ + { + "name": "userSelection", + "type": { + "text": "DraftUserSelection" + } + }, + { + "name": "role", + "type": { + "text": "DraftRole" + } + } + ] + }, + { + "kind": "method", + "name": "renderUserSelectionList", + "privacy": "private", + "parameters": [ + { + "name": "draft", + "type": { + "text": "CloudDraftDetails" + } + }, + { + "name": "includeOwner", + "default": "false" + } + ] + }, + { + "kind": "method", + "name": "renderPatchPermissions", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderCodeSuggectionActions", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderPatches", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderActionbar", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderDraftInfo", + "privacy": "private" + }, + { + "kind": "method", + "name": "onInviteUsers", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "onChangeSelectionRole", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "MouseEvent" + } + }, + { + "name": "selection", + "type": { + "text": "DraftUserSelection" + } + }, + { + "name": "role", + "type": { + "text": "PatchDetailsUpdateSelectionEventDetail['role']" + } + } + ] + }, + { + "kind": "method", + "name": "onVisibilityChange", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "onUpdatePatch", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "onExplainChanges", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "MouseEvent | KeyboardEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onTreeItemActionClicked", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "fireFileEvent", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "string" + } + }, + { + "name": "file", + "type": { + "text": "DraftPatchFileChange" + } + }, + { + "name": "showOptions", + "optional": true, + "type": { + "text": "TextDocumentShowOptions" + } + } + ] + }, + { + "kind": "method", + "name": "onCompareWorking", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onOpenFile", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onTreeItemChecked", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "onTreeItemSelected", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "onApplyPatch", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "optional": true, + "type": { + "text": "MouseEvent | KeyboardEvent" + } + }, + { + "name": "target", + "default": "'current'", + "type": { + "text": "'current' | 'branch' | 'worktree'" + } + } + ] + }, + { + "kind": "method", + "name": "onArchiveDraft", + "privacy": "private", + "parameters": [ + { + "name": "reason", + "type": { + "text": "DraftReasonEventDetail['reason']" + } + } + ] + }, + { + "kind": "method", + "name": "onSelectApplyOption", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent<{ target: MenuItem }>" + } + } + ] + }, + { + "kind": "method", + "name": "onChangePatchBase", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "optional": true, + "type": { + "text": "MouseEvent | KeyboardEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onSelectPatchRepo", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "optional": true, + "type": { + "text": "MouseEvent | KeyboardEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onShowInGraph", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "optional": true, + "type": { + "text": "MouseEvent | KeyboardEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onCopyCloudLink", + "privacy": "private" + }, + { + "kind": "method", + "name": "onShareLocalPatch", + "privacy": "private" + }, + { + "kind": "method", + "name": "draftPatchToTreeModel", + "return": { + "type": { + "text": "TreeModel" + } + }, + "parameters": [ + { + "name": "patch", + "type": { + "text": "NonNullable[0]" + } + }, + { + "name": "isTree", + "default": "false" + }, + { + "name": "compact", + "default": "true" + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Partial" + } + } + ] + }, + { + "kind": "method", + "name": "getFileActions", + "privacy": "protected", + "return": { + "type": { + "text": "{ icon: string; label: string; action: string }[]" + } + }, + "parameters": [ + { + "name": "_file", + "type": { + "text": "DraftPatchFileChange" + } + }, + { + "name": "_options", + "optional": true, + "type": { + "text": "Partial" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "renderLoading", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult" + } + }, + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "renderLayoutAction", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | typeof nothing" + } + }, + "parameters": [ + { + "name": "layout", + "type": { + "text": "string" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "renderTreeView", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult" + } + }, + "parameters": [ + { + "name": "treeModel", + "type": { + "text": "TreeModel[]" + } + }, + { + "name": "guides", + "default": "'none'", + "type": { + "text": "'none' | 'onHover' | 'always'" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "renderFiles", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel[]" + } + }, + "parameters": [ + { + "name": "files", + "type": { + "text": "GitFileChangeShape[]" + } + }, + { + "name": "isTree", + "default": "false" + }, + { + "name": "compact", + "default": "false" + }, + { + "name": "level", + "default": "2" + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "walkFileTree", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, + "parameters": [ + { + "name": "item", + "type": { + "text": "HierarchicalItem" + } + }, + { + "name": "options", + "default": "{ level: 1 }", + "type": { + "text": "Partial" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "folderToTreeModel", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "string" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Partial" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "getRepoActions", + "privacy": "protected", + "return": { + "type": { + "text": "TreeItemAction[]" + } + }, + "parameters": [ + { + "name": "_name", + "type": { + "text": "string" + } + }, + { + "name": "_path", + "type": { + "text": "string" + } + }, + { + "name": "_options", + "optional": true, + "type": { + "text": "Partial" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "emptyTreeModel", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "string" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Partial" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "repoToTreeModel", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "string" + } + }, + { + "name": "path", + "type": { + "text": "string" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Partial" + } + }, + { + "name": "description", + "optional": true, + "type": { + "text": "string" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "fileToTreeModel", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, + "parameters": [ + { + "name": "file", + "type": { + "text": "GitFileChangeShape" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Partial" + } + }, + { + "name": "flat", + "default": "false" + }, + { + "name": "glue", + "default": "'/'" + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "attributes": [ + { + "name": "state", + "type": { + "text": "State" + }, + "fieldName": "state" + }, + { + "name": "explain", + "type": { + "text": "ExplainState | undefined" + }, + "fieldName": "explain" + } + ], + "superclass": { + "name": "GlTreeBase", + "module": "/src/webviews/apps/plus/patchDetails/components/gl-tree-base" + }, + "tagName": "gl-draft-details", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlDraftDetails", + "declaration": { + "name": "GlDraftDetails", + "module": "src/webviews/apps/plus/patchDetails/components/gl-draft-details.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-draft-details", + "declaration": { + "name": "GlDraftDetails", + "module": "src/webviews/apps/plus/patchDetails/components/gl-draft-details.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/patchDetails/components/gl-patch-create.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlPatchCreate", + "members": [ + { + "kind": "field", + "name": "state", + "type": { + "text": "Serialized | undefined" + }, + "attribute": "state" + }, + { + "kind": "field", + "name": "review", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "review" + }, + { + "kind": "field", + "name": "generate", + "type": { + "text": "GenerateState | undefined" + }, + "attribute": "generate" + }, + { + "kind": "field", + "name": "generateBusy", + "type": { + "text": "boolean" + }, + "default": "false" + }, + { + "kind": "field", + "name": "creationBusy", + "type": { + "text": "boolean" + }, + "default": "false" + }, + { + "kind": "field", + "name": "titleInput", + "type": { + "text": "HTMLInputElement" + } + }, + { + "kind": "field", + "name": "descInput", + "type": { + "text": "HTMLInputElement" + } + }, + { + "kind": "field", + "name": "generateAiButton", + "type": { + "text": "HTMLElement" + } + }, + { + "kind": "field", + "name": "validityMessage", + "type": { + "text": "string | undefined" + } + }, + { + "kind": "field", + "name": "create", + "type": { + "text": "NonNullable" + }, + "readonly": true + }, + { + "kind": "field", + "name": "createChanges", + "type": { + "text": "Change[]" + }, + "readonly": true + }, + { + "kind": "field", + "name": "createEntries", + "type": { + "text": "[string, Change][]" + }, + "readonly": true + }, + { + "kind": "field", + "name": "hasWipChanges", + "type": { + "text": "boolean" + }, + "readonly": true + }, + { + "kind": "field", + "name": "selectedChanges", + "type": { + "text": "[string, Change][]" + }, + "readonly": true + }, + { + "kind": "field", + "name": "canSubmit", + "type": { + "text": "boolean" + }, + "readonly": true + }, + { + "kind": "field", + "name": "fileLayout", + "type": { + "text": "ViewFilesLayout" + }, + "readonly": true + }, + { + "kind": "field", + "name": "isCompact", + "type": { + "text": "boolean" + }, + "readonly": true + }, + { + "kind": "field", + "name": "filesModified", + "type": { + "text": "number" + }, + "readonly": true + }, + { + "kind": "field", + "name": "draftVisibility", + "type": { + "text": "DraftVisibility" + }, + "readonly": true + }, + { + "kind": "method", + "name": "renderUserSelection", + "privacy": "private", + "parameters": [ + { + "name": "userSelection", + "type": { + "text": "DraftUserSelection" + } + } + ] + }, + { + "kind": "method", + "name": "renderUserSelectionList", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderForm", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderChangedFiles", + "privacy": "private" + }, + { + "kind": "method", + "name": "onTreeItemChecked", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "onTreeItemSelected", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "renderTreeViewWithModel", + "privacy": "private" + }, + { + "kind": "method", + "name": "getTreeForChange", + "privacy": "private", + "return": { + "type": { + "text": "TreeModel[] | undefined" + } + }, + "parameters": [ + { + "name": "change", + "type": { + "text": "Change" + } + }, + { + "name": "isMulti", + "default": "false" + }, + { + "name": "isTree", + "default": "false" + }, + { + "name": "compact", + "default": "true" + } + ] + }, + { + "kind": "method", + "name": "isTree", + "privacy": "private", + "parameters": [ + { + "name": "count", + "type": { + "text": "number" + } + } + ] + }, + { + "kind": "method", + "name": "createPatch", + "privacy": "private" + }, + { + "kind": "method", + "name": "onCreateAll", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "onSelectCreateOption", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "CustomEvent<{ target: MenuItem }>" + } + } + ] + }, + { + "kind": "method", + "name": "getChangeForRepo", + "privacy": "private", + "return": { + "type": { + "text": "Change | undefined" + } + }, + "parameters": [ + { + "name": "repoUri", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "method", + "name": "onTitleInput", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "InputEvent" + } + } + ] + }, + { + "kind": "field", + "name": "onDebounceTitleInput", + "privacy": "private" + }, + { + "kind": "method", + "name": "onDescriptionInput", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "InputEvent" + } + } + ] + }, + { + "kind": "field", + "name": "onDebounceDescriptionInput", + "privacy": "private" + }, + { + "kind": "method", + "name": "onInviteUsers", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "onChangeSelectionRole", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "MouseEvent" + } + }, + { + "name": "selection", + "type": { + "text": "DraftUserSelection" + } + }, + { + "name": "role", + "type": { + "text": "CreatePatchUpdateSelectionEventDetail['role']" + } + } + ] + }, + { + "kind": "method", + "name": "onVisibilityChange", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "onGenerateTitleClick", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "fireMetadataUpdate", + "privacy": "private" + }, + { + "kind": "method", + "name": "onTreeItemActionClicked", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "onOpenFile", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onStageFile", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onUnstageFile", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "CustomEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onShowInGraph", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "CustomEvent" + } + } + ] + }, + { + "kind": "method", + "name": "onCancel", + "privacy": "private" + }, + { + "kind": "method", + "name": "getFileActions", + "privacy": "protected", + "return": { + "type": { + "text": "{ icon: string; label: string; action: string }[]" + } + }, + "parameters": [ + { + "name": "file", + "type": { + "text": "GitFileChangeShape" + } + }, + { + "name": "_options", + "optional": true, + "type": { + "text": "Partial" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "getRepoActions", + "privacy": "protected", + "return": { + "type": { + "text": "{ icon: string; label: string; action: string }[]" + } + }, + "parameters": [ + { + "name": "_name", + "type": { + "text": "string" + } + }, + { + "name": "_path", + "type": { + "text": "string" + } + }, + { + "name": "_options", + "optional": true, + "type": { + "text": "Partial" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "renderLoading", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult" + } + }, + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "renderLayoutAction", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | typeof nothing" + } + }, + "parameters": [ + { + "name": "layout", + "type": { + "text": "string" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "renderTreeView", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult" + } + }, + "parameters": [ + { + "name": "treeModel", + "type": { + "text": "TreeModel[]" + } + }, + { + "name": "guides", + "default": "'none'", + "type": { + "text": "'none' | 'onHover' | 'always'" + } + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, + { + "kind": "method", + "name": "renderFiles", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel[]" + } + }, + "parameters": [ + { + "name": "files", + "type": { + "text": "GitFileChangeShape[]" + } + }, + { + "name": "isTree", + "default": "false" + }, + { + "name": "compact", + "default": "false" + }, + { + "name": "level", + "default": "2" + } + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + }, { "kind": "method", - "name": "selectCommits", + "name": "walkFileTree", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, "parameters": [ { - "name": "shaList", - "type": { - "text": "string[]" - } - }, - { - "name": "includeToPrevSel", + "name": "item", "type": { - "text": "boolean" + "text": "HierarchicalItem" } }, { - "name": "isAutoOrKeyScroll", + "name": "options", + "default": "{ level: 1 }", "type": { - "text": "boolean" + "text": "Partial" } } - ] + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } }, { "kind": "method", - "name": "onColumnsChanged", - "privacy": "private", + "name": "folderToTreeModel", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, "parameters": [ { - "name": "event", + "name": "name", "type": { - "text": "CustomEventType<'graph-changecolumns'>" + "text": "string" } - } - ] - }, - { - "kind": "method", - "name": "onGetMoreRows", - "privacy": "private", - "parameters": [ + }, { - "name": "{ detail: sha }", + "name": "options", + "optional": true, "type": { - "text": "CustomEventType<'graph-morerows'>" + "text": "Partial" } } - ] - }, - { - "kind": "method", - "name": "onMouseLeave", - "privacy": "private" + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } }, { "kind": "method", - "name": "onMissingAvatars", - "privacy": "private", + "name": "emptyTreeModel", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, "parameters": [ { - "name": "{ detail: emails }", + "name": "name", "type": { - "text": "CustomEventType<'graph-missingavatars'>" + "text": "string" } - } - ] - }, - { - "kind": "method", - "name": "onMissingRefsMetadata", - "privacy": "private", - "parameters": [ + }, { - "name": "{ detail: metadata }", + "name": "options", + "optional": true, "type": { - "text": "CustomEventType<'graph-missingrefsmetadata'>" + "text": "Partial" } } - ] + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } }, { "kind": "method", - "name": "onRefDoubleClick", - "privacy": "private", + "name": "repoToTreeModel", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, "parameters": [ { - "name": "{ detail: { ref, metadata } }", + "name": "name", "type": { - "text": "CustomEventType<'graph-doubleclickref'>" + "text": "string" } - } - ] - }, - { - "kind": "method", - "name": "onRefsVisibilityChanged", - "privacy": "private", - "parameters": [ + }, { - "name": "{ detail }", + "name": "path", "type": { - "text": "CustomEventType<'graph-changerefsvisibility'>" + "text": "string" } - } - ] - }, - { - "kind": "method", - "name": "onRowContextMenu", - "privacy": "private", - "parameters": [ + }, { - "name": "{ detail: { graphRow, graphZoneType } }", + "name": "options", + "optional": true, "type": { - "text": "CustomEventType<'graph-rowcontextmenu'>" + "text": "Partial" } - } - ] - }, - { - "kind": "method", - "name": "onRowDoubleClick", - "privacy": "private", - "parameters": [ + }, { - "name": "{ detail: { row, preserveFocus } }", + "name": "description", + "optional": true, "type": { - "text": "CustomEventType<'graph-doubleclickrow'>" + "text": "string" } } - ] + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } }, { "kind": "method", - "name": "onRowHover", - "privacy": "private", + "name": "fileToTreeModel", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, "parameters": [ { - "name": "{ detail }", + "name": "file", "type": { - "text": "CustomEventType<'graph-graphrowhovered'>" + "text": "GitFileChangeShape" } - } - ] - }, - { - "kind": "method", - "name": "onRowUnhover", - "privacy": "private", - "parameters": [ + }, { - "name": "{ detail }", + "name": "options", + "optional": true, "type": { - "text": "CustomEventType<'graph-graphrowunhovered'>" + "text": "Partial" } + }, + { + "name": "flat", + "default": "false" + }, + { + "name": "glue", + "default": "'/'" } - ] + ], + "inheritedFrom": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } }, { "kind": "method", - "name": "onSelectionChanged", - "privacy": "private", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, "parameters": [ { - "name": "{ detail: rows }", + "name": "name", "type": { - "text": "CustomEventType<'graph-changeselection'>" + "text": "T" } - } - ] - }, - { - "kind": "method", - "name": "onVisibleDaysChanged", - "privacy": "private", - "parameters": [ + }, { - "name": "{ detail }", + "name": "detail", "type": { - "text": "CustomEventType<'graph-changevisibledays'>" + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" } } - ] + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } } ], - "events": [ - { - "name": "gl-graph-mouse-leave", - "type": { - "text": "CustomEvent" - } - }, - { - "name": "gl-graph-row-context-menu", - "type": { - "text": "CustomEvent" - } - }, - { - "name": "gl-graph-row-hover", - "type": { - "text": "CustomEvent" - } - }, + "attributes": [ { - "name": "gl-graph-row-unhover", + "name": "state", "type": { - "text": "CustomEvent" - } + "text": "Serialized | undefined" + }, + "fieldName": "state" }, { - "name": "gl-graph-change-selection", + "name": "review", "type": { - "text": "CustomEvent" - } + "text": "boolean" + }, + "default": "false", + "fieldName": "review" }, { - "name": "gl-graph-change-visible-days", + "name": "generate", "type": { - "text": "CustomEvent" - } - } - ], - "mixins": [ - { - "name": "SignalWatcher", - "package": "@lit-labs/signals" + "text": "GenerateState | undefined" + }, + "fieldName": "generate" } ], "superclass": { - "name": "LitElement", - "package": "lit" + "name": "GlTreeBase", + "module": "/src/webviews/apps/plus/patchDetails/components/gl-tree-base" }, - "tagName": "gl-graph-wrapper", + "tagName": "gl-patch-create", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlGraphWrapper", + "name": "GlPatchCreate", "declaration": { - "name": "GlGraphWrapper", - "module": "src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper.ts" + "name": "GlPatchCreate", + "module": "src/webviews/apps/plus/patchDetails/components/gl-patch-create.ts" } }, { "kind": "custom-element-definition", - "name": "gl-graph-wrapper", + "name": "gl-patch-create", "declaration": { - "name": "GlGraphWrapper", - "module": "src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper.ts" + "name": "GlPatchCreate", + "module": "src/webviews/apps/plus/patchDetails/components/gl-patch-create.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/hover/graphHover.ts", + "path": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlGraphHover", + "name": "GlTreeBase", "members": [ { - "kind": "field", - "name": "anchor", - "type": { - "text": "Anchor | undefined" - }, - "attribute": "anchor" - }, - { - "kind": "field", - "name": "distance", - "type": { - "text": "number | undefined | undefined" - }, - "attribute": "distance", - "reflects": true - }, - { - "kind": "field", - "name": "open", - "type": { - "text": "boolean | undefined" - }, - "default": "false", - "attribute": "open", - "reflects": true - }, - { - "kind": "field", - "name": "placement", - "type": { - "text": "GlPopover['placement'] | undefined" - }, - "default": "'bottom-start'", - "attribute": "placement", - "reflects": true - }, - { - "kind": "field", - "name": "markdown", - "type": { - "text": "Promise> | string | undefined" + "kind": "method", + "name": "onTreeItemActionClicked", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "attribute": "markdown" + "parameters": [ + { + "name": "_e", + "type": { + "text": "CustomEvent" + } + } + ] }, { - "kind": "field", - "name": "skidding", - "type": { - "text": "number | undefined | undefined" + "kind": "method", + "name": "onTreeItemChecked", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "attribute": "skidding", - "reflects": true + "parameters": [ + { + "name": "_e", + "type": { + "text": "CustomEvent" + } + } + ] }, { - "kind": "field", - "name": "requestMarkdown", - "type": { - "text": "((row: GraphRow) => Promise) | undefined" + "kind": "method", + "name": "onTreeItemSelected", + "privacy": "protected", + "return": { + "type": { + "text": "void" + } }, - "attribute": "requestMarkdown" + "parameters": [ + { + "name": "_e", + "type": { + "text": "CustomEvent" + } + } + ] }, { - "kind": "field", - "name": "popup", - "type": { - "text": "GlPopover" + "kind": "method", + "name": "renderLoading", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult" + } } }, - { - "kind": "field", - "name": "hoverMarkdownCache", - "privacy": "private", - "default": "new Map< string, Promise> | PromiseSettledResult | string >()" - }, - { - "kind": "field", - "name": "shaHovering", - "type": { - "text": "string | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "unhoverTimer", - "type": { - "text": "ReturnType | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "previousSkidding", - "type": { - "text": "number | undefined" - }, - "privacy": "private" - }, - { - "kind": "field", - "name": "recalculated", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" - }, { "kind": "method", - "name": "onReposition", - "privacy": "private" + "name": "renderLayoutAction", + "privacy": "protected", + "return": { + "type": { + "text": "TemplateResult | typeof nothing" + } + }, + "parameters": [ + { + "name": "layout", + "type": { + "text": "string" + } + } + ] }, { "kind": "method", - "name": "reset", + "name": "renderTreeView", + "privacy": "protected", "return": { "type": { - "text": "void" + "text": "TemplateResult" } - } - }, - { - "kind": "field", - "name": "onParentMouseLeave", - "privacy": "private" - }, - { - "kind": "field", - "name": "_showCoreDebounced", - "type": { - "text": "Deferrable | undefined" }, - "privacy": "private", - "default": "undefined" + "parameters": [ + { + "name": "treeModel", + "type": { + "text": "TreeModel[]" + } + }, + { + "name": "guides", + "default": "'none'", + "type": { + "text": "'none' | 'onHover' | 'always'" + } + } + ] }, { "kind": "method", - "name": "onRowHovered", + "name": "renderFiles", + "privacy": "protected", "return": { "type": { - "text": "void" + "text": "TreeModel[]" } }, "parameters": [ { - "name": "row", + "name": "files", "type": { - "text": "GraphRow" + "text": "GitFileChangeShape[]" } }, { - "name": "anchor", - "type": { - "text": "Anchor" - } + "name": "isTree", + "default": "false" + }, + { + "name": "compact", + "default": "false" + }, + { + "name": "level", + "default": "2" } ] }, { "kind": "method", - "name": "onRowUnhovered", + "name": "walkFileTree", + "privacy": "protected", "return": { "type": { - "text": "void" + "text": "TreeModel" } }, "parameters": [ { - "name": "_row", + "name": "item", "type": { - "text": "GraphRow" + "text": "HierarchicalItem" } }, { - "name": "relatedTarget", + "name": "options", + "default": "{ level: 1 }", "type": { - "text": "EventTarget | null" + "text": "Partial" } } ] }, - { - "kind": "field", - "name": "onWindowKeydown", - "privacy": "private" - }, { "kind": "method", - "name": "showCore", - "privacy": "private", + "name": "folderToTreeModel", + "privacy": "protected", + "return": { + "type": { + "text": "TreeModel" + } + }, "parameters": [ { - "name": "anchor", + "name": "name", "type": { - "text": "string | HTMLElement | { getBoundingClientRect: () => Omit }" + "text": "string" } }, { - "name": "markdown", + "name": "options", + "optional": true, "type": { - "text": "Promise> | PromiseSettledResult | string" + "text": "Partial" } } ] }, - { - "kind": "field", - "name": "_lastUnhoveredTimestamp", - "type": { - "text": "number" - }, - "privacy": "private", - "default": "0" - }, { "kind": "method", - "name": "hide", + "name": "getRepoActions", + "privacy": "protected", "return": { "type": { - "text": "void" + "text": "TreeItemAction[]" } - } + }, + "parameters": [ + { + "name": "_name", + "type": { + "text": "string" + } + }, + { + "name": "_path", + "type": { + "text": "string" + } + }, + { + "name": "_options", + "optional": true, + "type": { + "text": "Partial" + } + } + ] }, { "kind": "method", - "name": "resetUnhoverTimer", - "privacy": "private", + "name": "emptyTreeModel", + "privacy": "protected", "return": { "type": { - "text": "void" + "text": "TreeModel" } - } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "string" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Partial" + } + } + ] }, { "kind": "method", - "name": "emit", + "name": "repoToTreeModel", + "privacy": "protected", "return": { "type": { - "text": "CustomEventType" + "text": "TreeModel" } }, "parameters": [ { "name": "name", "type": { - "text": "T" + "text": "string" } }, { - "name": "detail", + "name": "path", "type": { - "text": "CustomEventDetailType" + "text": "string" } }, { "name": "options", "optional": true, "type": { - "text": "Omit>, 'detail'>" + "text": "Partial" } - } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } - } - ], - "attributes": [ - { - "name": "anchor", - "type": { - "text": "Anchor | undefined" - }, - "fieldName": "anchor" - }, - { - "name": "distance", - "type": { - "text": "number | undefined | undefined" - }, - "fieldName": "distance" - }, - { - "name": "open", - "type": { - "text": "boolean | undefined" - }, - "default": "false", - "fieldName": "open" - }, - { - "name": "placement", - "type": { - "text": "GlPopover['placement'] | undefined" - }, - "default": "'bottom-start'", - "fieldName": "placement" - }, - { - "name": "markdown", - "type": { - "text": "Promise> | string | undefined" - }, - "fieldName": "markdown" - }, - { - "name": "skidding", - "type": { - "text": "number | undefined | undefined" - }, - "fieldName": "skidding" - }, - { - "name": "requestMarkdown", - "type": { - "text": "((row: GraphRow) => Promise) | undefined" - }, - "fieldName": "requestMarkdown" - } - ], - "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" - }, - "tagName": "gl-graph-hover", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "GlGraphHover", - "declaration": { - "name": "GlGraphHover", - "module": "src/webviews/apps/plus/graph/hover/graphHover.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "gl-graph-hover", - "declaration": { - "name": "GlGraphHover", - "module": "src/webviews/apps/plus/graph/hover/graphHover.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/minimap/minimap-container.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlGraphMinimapContainer", - "members": [ - { - "kind": "field", - "name": "activeDay", - "type": { - "text": "number | undefined" - }, - "attribute": "activeDay" - }, - { - "kind": "field", - "name": "disabled", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "disabled" - }, - { - "kind": "method", - "name": "onDisabledChanged", - "privacy": "private" - }, - { - "kind": "field", - "name": "dataType", - "type": { - "text": "'commits' | 'lines'" - }, - "default": "'commits'", - "attribute": "dataType" - }, - { - "kind": "field", - "name": "downstreams", - "type": { - "text": "GraphDownstreams | undefined" - }, - "attribute": "downstreams" - }, - { - "kind": "field", - "name": "markerTypes", - "type": { - "text": "GraphMinimapMarkerTypes[]" - }, - "default": "[]", - "attribute": "markerTypes" - }, - { - "kind": "field", - "name": "refMetadata", - "type": { - "text": "GraphRefsMetadata | null | undefined" - }, - "attribute": "refMetadata" - }, - { - "kind": "field", - "name": "rows", - "type": { - "text": "GraphRow[]" - }, - "default": "[]", - "attribute": "rows" - }, - { - "kind": "field", - "name": "rowsStats", - "type": { - "text": "Record | undefined" - }, - "attribute": "rowsStats" - }, - { - "kind": "field", - "name": "searchResults", - "type": { - "text": "GraphSearchResults | GraphSearchResultsError | undefined" - }, - "attribute": "searchResults" - }, - { - "kind": "field", - "name": "visibleDays", - "type": { - "text": "{ top: number; bottom: number } | undefined" - }, - "attribute": "visibleDays" - }, - { - "kind": "field", - "name": "markersByDay", - "privacy": "private", - "default": "new Map()" - }, - { - "kind": "field", - "name": "searchResultsByDay", - "privacy": "private", - "default": "new Map()" - }, - { - "kind": "field", - "name": "statsByDay", - "privacy": "private", - "default": "new Map()" - }, - { - "kind": "field", - "name": "pendingDataChange", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" - }, - { - "kind": "method", - "name": "handleDataChanged", - "privacy": "private", - "parameters": [ + }, { - "name": "changedKeys", + "name": "description", + "optional": true, "type": { - "text": "PropertyKey[]" + "text": "string" } } ] }, - { - "kind": "field", - "name": "pendingSearchResultsChange", - "type": { - "text": "boolean" - }, - "privacy": "private", - "default": "false" - }, - { - "kind": "method", - "name": "handleSearchResultsChanged", - "privacy": "private" - }, - { - "kind": "field", - "name": "minimap", - "type": { - "text": "GlGraphMinimap | undefined" - }, - "privacy": "private" - }, { "kind": "method", - "name": "select", + "name": "getFileActions", + "privacy": "protected", "return": { "type": { - "text": "void" + "text": "TreeItemAction[]" } }, "parameters": [ { - "name": "date", + "name": "_file", "type": { - "text": "number | Date | undefined" + "text": "GitFileChangeShape" } }, { - "name": "trackOnly", - "default": "false", + "name": "_options", + "optional": true, "type": { - "text": "boolean" + "text": "Partial" } } ] }, { "kind": "method", - "name": "unselect", + "name": "fileToTreeModel", + "privacy": "protected", "return": { "type": { - "text": "void" + "text": "TreeModel" } }, "parameters": [ { - "name": "date", - "optional": true, + "name": "file", "type": { - "text": "number | Date" + "text": "GitFileChangeShape" } }, { - "name": "focus", - "default": "false", + "name": "options", + "optional": true, "type": { - "text": "boolean" + "text": "Partial" } + }, + { + "name": "flat", + "default": "false" + }, + { + "name": "glue", + "default": "'/'" } ] }, - { - "kind": "method", - "name": "processRows", - "privacy": "private" - }, - { - "kind": "method", - "name": "processSearchResults", - "privacy": "private" - }, { "kind": "method", "name": "emit", @@ -23946,539 +29051,737 @@ } } ], - "attributes": [ + "superclass": { + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" + } + } + ], + "exports": [ + { + "kind": "js", + "name": "GlTreeBase", + "declaration": { + "name": "GlTreeBase", + "module": "src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/patchDetails/components/patch-details-app.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlPatchDetailsApp", + "members": [ { - "name": "activeDay", + "kind": "field", + "name": "state", "type": { - "text": "number | undefined" + "text": "State" }, - "fieldName": "activeDay" + "attribute": "state" }, { - "name": "disabled", + "kind": "field", + "name": "explain", "type": { - "text": "boolean" + "text": "ExplainState | undefined" }, - "default": "false", - "fieldName": "disabled" + "attribute": "explain" }, { - "name": "dataType", + "kind": "field", + "name": "generate", "type": { - "text": "'commits' | 'lines'" + "text": "GenerateState | undefined" }, - "default": "'commits'", - "fieldName": "dataType" + "attribute": "generate" }, { - "name": "downstreams", + "kind": "field", + "name": "app", "type": { - "text": "GraphDownstreams | undefined" - }, - "fieldName": "downstreams" + "text": "PatchDetailsApp | undefined" + } }, { - "name": "markerTypes", + "kind": "field", + "name": "wipChangesCount", "type": { - "text": "GraphMinimapMarkerTypes[]" + "text": "number" }, - "default": "[]", - "fieldName": "markerTypes" + "readonly": true }, { - "name": "refMetadata", + "kind": "field", + "name": "wipChangeState", + "readonly": true + }, + { + "kind": "field", + "name": "mode", "type": { - "text": "GraphRefsMetadata | null | undefined" + "text": "Mode" }, - "fieldName": "refMetadata" + "readonly": true }, { - "name": "rows", + "kind": "field", + "name": "indentPreference", "type": { - "text": "GraphRow[]" + "text": "number" }, - "default": "[]", - "fieldName": "rows" + "privacy": "private", + "default": "16" }, { - "name": "rowsStats", + "kind": "method", + "name": "updateDocumentProperties", + "privacy": "private" + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "attributes": [ + { + "name": "state", "type": { - "text": "Record | undefined" + "text": "State" }, - "fieldName": "rowsStats" + "fieldName": "state" }, { - "name": "searchResults", + "name": "explain", "type": { - "text": "GraphSearchResults | GraphSearchResultsError | undefined" + "text": "ExplainState | undefined" }, - "fieldName": "searchResults" + "fieldName": "explain" }, { - "name": "visibleDays", + "name": "generate", "type": { - "text": "{ top: number; bottom: number } | undefined" + "text": "GenerateState | undefined" }, - "fieldName": "visibleDays" + "fieldName": "generate" } ], "superclass": { "name": "GlElement", "module": "/src/webviews/apps/shared/components/element" }, - "tagName": "gl-graph-minimap-container", + "tagName": "gl-patch-details-app", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlGraphMinimapContainer", + "name": "GlPatchDetailsApp", "declaration": { - "name": "GlGraphMinimapContainer", - "module": "src/webviews/apps/plus/graph/minimap/minimap-container.ts" + "name": "GlPatchDetailsApp", + "module": "src/webviews/apps/plus/patchDetails/components/patch-details-app.ts" } }, { "kind": "custom-element-definition", - "name": "gl-graph-minimap-container", + "name": "gl-patch-details-app", "declaration": { - "name": "GlGraphMinimapContainer", - "module": "src/webviews/apps/plus/graph/minimap/minimap-container.ts" + "name": "GlPatchDetailsApp", + "module": "src/webviews/apps/plus/patchDetails/components/patch-details-app.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/minimap/minimap.ts", + "path": "src/webviews/apps/plus/shared/components/account-chip.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlGraphMinimap", + "name": "GlAccountChip", "members": [ { "kind": "field", - "name": "chartContainer", + "name": "shadowRootOptions", "type": { - "text": "HTMLDivElement" - } + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" }, { "kind": "field", - "name": "_chart", + "name": "_showUpgrade", "type": { - "text": "Chart" + "text": "boolean" }, - "privacy": "private" + "privacy": "private", + "default": "false" }, { "kind": "field", - "name": "spinner", - "type": { - "text": "HTMLDivElement" - } + "name": "showUpgrade", + "privacy": "private", + "attribute": "show-upgrade", + "reflects": true }, { "kind": "field", - "name": "_loadTimer", + "name": "_chip", "type": { - "text": "ReturnType | undefined" + "text": "HTMLElement" }, "privacy": "private" }, { "kind": "field", - "name": "_markerRegions", + "name": "_popover", "type": { - "text": "Iterable | undefined" + "text": "GlPopover" }, "privacy": "private" }, { "kind": "field", - "name": "_regions", + "name": "_state", "type": { - "text": "RegionOptions[] | undefined" + "text": "State" }, "privacy": "private" }, { "kind": "field", - "name": "activeDay", - "type": { - "text": "number | undefined" - }, - "attribute": "activeDay" + "name": "accountAvatar", + "privacy": "private", + "readonly": true }, { - "kind": "method", - "name": "onActiveDayChanged", - "privacy": "private" + "kind": "field", + "name": "accountName", + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "data", - "type": { - "text": "Map | undefined" - }, - "attribute": "data" + "name": "accountEmail", + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "dataType", + "name": "hasAccount", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "isReactivatedTrial", "type": { - "text": "'commits' | 'lines'" + "text": "boolean" }, - "default": "'commits'", - "attribute": "dataType" + "readonly": true }, { - "kind": "method", - "name": "onDataChanged", - "privacy": "private" + "kind": "field", + "name": "planId", + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "markers", - "type": { - "text": "Map | undefined" - }, - "attribute": "markers" + "name": "effectivePlanId", + "privacy": "private", + "readonly": true }, { - "kind": "method", - "name": "onMarkersChanged", - "privacy": "private" + "kind": "field", + "name": "planName", + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "searchResults", - "type": { - "text": "Map | undefined" - }, - "attribute": "searchResults" + "name": "planTier", + "privacy": "private", + "readonly": true }, { - "kind": "method", - "name": "onSearchResultsChanged", + "kind": "field", + "name": "promos", + "type": { + "text": "PromosContext" + }, "privacy": "private" }, { "kind": "field", - "name": "visibleDays", - "type": { - "text": "{ top: number; bottom: number } | undefined" - }, - "attribute": "visibleDays" + "name": "subscription", + "privacy": "private", + "readonly": true }, { - "kind": "method", - "name": "onVisibleDaysChanged", - "privacy": "private" + "kind": "field", + "name": "subscriptionState", + "privacy": "private", + "readonly": true }, { - "kind": "method", - "name": "handleDataChanged", + "kind": "field", + "name": "trialDaysRemaining", "privacy": "private", - "parameters": [ - { - "name": "markerChanged", - "type": { - "text": "boolean" - } - } - ] + "readonly": true }, { "kind": "method", - "name": "getInternalChart", - "privacy": "private", + "name": "focus", "return": { "type": { - "text": "ChartInternal | undefined" + "text": "void" } } }, { "kind": "method", - "name": "select", + "name": "show", "return": { "type": { "text": "void" } - }, - "parameters": [ - { - "name": "date", - "type": { - "text": "number | Date | undefined" - } - }, - { - "name": "trackOnly", - "default": "false", - "type": { - "text": "boolean" - } - } - ] + } }, { "kind": "method", - "name": "unselect", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "date", - "optional": true, - "type": { - "text": "number | Date" - } - }, - { - "name": "focus", - "default": "false", - "type": { - "text": "boolean" - } - } - ] + "name": "renderAccountInfo", + "privacy": "private" }, { "kind": "method", - "name": "getDataPoint", - "privacy": "private", - "return": { - "type": { - "text": "DataItem | undefined" - } - }, - "parameters": [ - { - "name": "date", - "type": { - "text": "number | Date" - } - } - ] + "name": "renderAccountState", + "privacy": "private" }, { "kind": "method", - "name": "getIndex", - "privacy": "private", - "return": { - "type": { - "text": "number | undefined" - } - }, - "parameters": [ - { - "name": "date", - "type": { - "text": "number | Date" - } - } - ] + "name": "renderIncludesDevEx", + "privacy": "private" }, { "kind": "method", - "name": "getMarkerRegions", + "name": "renderReferFriend", "privacy": "private" }, { "kind": "method", - "name": "getAllRegions", + "name": "renderUpgradeContent", "privacy": "private" }, { "kind": "method", - "name": "getSearchResultsRegions", + "name": "renderPromo", "privacy": "private", "return": { "type": { - "text": "Iterable" + "text": "unknown" } }, "parameters": [ { - "name": "searchResults", + "name": "plan", "type": { - "text": "NonNullable" + "text": "PromoPlans" } - } - ] - }, - { - "kind": "method", - "name": "getVisibleAreaRegion", - "privacy": "private", - "return": { - "type": { - "text": "RegionOptions" - } - }, - "parameters": [ + }, { - "name": "visibleDays", + "name": "type", + "default": "'info'", "type": { - "text": "NonNullable" + "text": "GlPromo['type']" + } + }, + { + "name": "slot", + "optional": true, + "type": { + "text": "string" } } ] + } + ], + "attributes": [ + { + "name": "show-upgrade", + "fieldName": "showUpgrade" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-account-chip", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlAccountChip", + "declaration": { + "name": "GlAccountChip", + "module": "src/webviews/apps/plus/shared/components/account-chip.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-account-chip", + "declaration": { + "name": "GlAccountChip", + "module": "src/webviews/apps/plus/shared/components/account-chip.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/shared/components/chipStyles.ts", + "declarations": [ + { + "kind": "variable", + "name": "chipStyles", + "default": "css` :host { display: flex; } .chip { display: flex; gap: 0.6rem; align-items: center; border-radius: 0.3rem; padding: 0.2rem 0.4rem; cursor: pointer; } .chip:focus-visible { ${focusOutline} } .content { display: flex; flex-direction: column; gap: 0.4rem; padding-bottom: 0.4rem; } .header { display: flex; align-items: center; gap: 0.6rem; width: 100%; padding-bottom: 0.4rem; } .header__actions { flex: none; display: flex; gap: 0.2rem; flex-direction: row; align-items: center; justify-content: center; } .header__title { flex: 1; font-size: 1.5rem; line-height: 1.7; font-weight: 600; margin: 0; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "chipStyles", + "declaration": { + "name": "chipStyles", + "module": "src/webviews/apps/plus/shared/components/chipStyles.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/shared/components/feature-gate-plus-state.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlFeatureGatePlusState", + "members": [ + { + "kind": "field", + "name": "button", + "type": { + "text": "GlButton" + }, + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "_loading", + "name": "featurePreview", "type": { - "text": "Promise | undefined" + "text": "FeaturePreview | undefined" }, - "privacy": "private" + "attribute": "featurePreview" }, { - "kind": "method", - "name": "loadChart", - "privacy": "private" + "kind": "field", + "name": "featurePreviewCommandLink", + "type": { + "text": "string | undefined" + }, + "attribute": "featurePreviewCommandLink" }, { - "kind": "method", - "name": "loadChartCore", + "kind": "field", + "name": "appearance", + "type": { + "text": "'alert' | 'welcome' | undefined" + }, + "attribute": "appearance" + }, + { + "kind": "field", + "name": "featureWithArticleIfNeeded", + "type": { + "text": "string | undefined" + }, + "attribute": "featureWithArticleIfNeeded" + }, + { + "kind": "field", + "name": "promos", + "type": { + "text": "PromosContext" + }, "privacy": "private" }, { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } + "kind": "field", + "name": "source", + "type": { + "text": "Source | undefined" + }, + "attribute": "source" + }, + { + "kind": "field", + "name": "state", + "type": { + "text": "SubscriptionState | undefined" + } + }, + { + "kind": "field", + "name": "webroot", + "type": { + "text": "string | undefined" }, + "attribute": "webroot" + }, + { + "kind": "method", + "name": "renderFeaturePreview", + "privacy": "private", "parameters": [ { - "name": "name", + "name": "featurePreview", "type": { - "text": "T" + "text": "FeaturePreview" } - }, + } + ] + }, + { + "kind": "method", + "name": "renderFeaturePreviewStep", + "privacy": "private", + "parameters": [ { - "name": "detail", + "name": "featurePreview", "type": { - "text": "CustomEventDetailType" + "text": "FeaturePreview" } }, { - "name": "options", - "optional": true, + "name": "used", "type": { - "text": "Omit>, 'detail'>" + "text": "number" } } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } + ] + }, + { + "kind": "method", + "name": "renderPromo", + "privacy": "private" } ], "attributes": [ { - "name": "activeDay", + "name": "featurePreview", "type": { - "text": "number | undefined" + "text": "FeaturePreview | undefined" }, - "fieldName": "activeDay" + "fieldName": "featurePreview" }, { - "name": "data", + "name": "featurePreviewCommandLink", "type": { - "text": "Map | undefined" + "text": "string | undefined" }, - "fieldName": "data" + "fieldName": "featurePreviewCommandLink" }, { - "name": "dataType", + "name": "appearance", "type": { - "text": "'commits' | 'lines'" + "text": "'alert' | 'welcome' | undefined" }, - "default": "'commits'", - "fieldName": "dataType" + "fieldName": "appearance" }, { - "name": "markers", + "name": "featureWithArticleIfNeeded", "type": { - "text": "Map | undefined" + "text": "string | undefined" }, - "fieldName": "markers" + "fieldName": "featureWithArticleIfNeeded" }, { - "name": "searchResults", + "name": "source", "type": { - "text": "Map | undefined" + "text": "Source | undefined" }, - "fieldName": "searchResults" + "fieldName": "source" }, { - "name": "visibleDays", + "name": "webroot", "type": { - "text": "{ top: number; bottom: number } | undefined" + "text": "string | undefined" }, - "fieldName": "visibleDays" + "fieldName": "webroot" } ], "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" + "name": "LitElement", + "package": "lit" }, - "tagName": "gl-graph-minimap", + "tagName": "gl-feature-gate-plus-state", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlGraphMinimap", + "name": "GlFeatureGatePlusState", "declaration": { - "name": "GlGraphMinimap", - "module": "src/webviews/apps/plus/graph/minimap/minimap.ts" + "name": "GlFeatureGatePlusState", + "module": "src/webviews/apps/plus/shared/components/feature-gate-plus-state.ts" } }, { "kind": "custom-element-definition", - "name": "gl-graph-minimap", + "name": "gl-feature-gate-plus-state", "declaration": { - "name": "GlGraphMinimap", - "module": "src/webviews/apps/plus/graph/minimap/minimap.ts" + "name": "GlFeatureGatePlusState", + "module": "src/webviews/apps/plus/shared/components/feature-gate-plus-state.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/sidebar/sidebar.ts", + "path": "src/webviews/apps/plus/shared/components/home-header.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlGraphSideBar", + "name": "GlHomeHeader", "members": [ { "kind": "field", - "name": "include", + "name": "accountChip", "type": { - "text": "undefined | IconTypes[]" + "text": "GlAccountChip" }, - "readonly": true + "privacy": "private" }, { "kind": "field", - "name": "_ipc", + "name": "promoBanner", "type": { - "text": "HostIpc" + "text": "GlPromoBanner" + }, + "privacy": "private" + }, + { + "kind": "method", + "name": "show", + "return": { + "type": { + "text": "void" + } + } + }, + { + "kind": "method", + "name": "refreshPromo", + "return": { + "type": { + "text": "void" + } + } + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-home-header", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlHomeHeader", + "declaration": { + "name": "GlHomeHeader", + "module": "src/webviews/apps/plus/shared/components/home-header.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-home-header", + "declaration": { + "name": "GlHomeHeader", + "module": "src/webviews/apps/plus/shared/components/home-header.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/shared/components/integrations-chip.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlIntegrationsChip", + "members": [ + { + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + }, + { + "kind": "field", + "name": "_chip", + "type": { + "text": "HTMLElement" }, "privacy": "private" }, @@ -24488,180 +29791,382 @@ "type": { "text": "State" }, + "privacy": "private" + }, + { + "kind": "field", + "name": "hasAccount", "privacy": "private", "readonly": true }, { "kind": "field", - "name": "_disposable", - "type": { - "text": "Disposable | undefined" - }, - "privacy": "private" + "name": "isPaidAccount", + "privacy": "private", + "readonly": true }, { "kind": "field", - "name": "_countsTask", + "name": "isProAccount", "privacy": "private", - "default": "new Task(this, { args: () => [this.fetchCounts()], task: ([counts]) => counts, autoRun: false, })" + "readonly": true }, { "kind": "field", - "name": "_counts", - "type": { - "text": "Promise | undefined" - }, - "privacy": "private" + "name": "hasConnectedIntegrations", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "ai", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "aiSettingEnabled", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "aiOrgEnabled", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "aiEnabled", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "integrations", + "privacy": "private", + "readonly": true }, { "kind": "method", - "name": "fetchCounts", - "privacy": "private" + "name": "focus", + "return": { + "type": { + "text": "void" + } + } }, { "kind": "method", - "name": "renderIcon", + "name": "renderIntegrationStatus", "privacy": "private", "parameters": [ { - "name": "icon", + "name": "integration", "type": { - "text": "Icon" + "text": "IntegrationState" } } ] }, { "kind": "method", - "name": "sendTelemetry", + "name": "renderIntegrationRow", "privacy": "private", "parameters": [ { - "name": "command", + "name": "integration", "type": { - "text": "string" + "text": "IntegrationState" } } ] + }, + { + "kind": "method", + "name": "renderAIStatus", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderAIRow", + "privacy": "private" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-graph-sidebar", + "tagName": "gl-integrations-chip", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlGraphSideBar", + "name": "GlIntegrationsChip", "declaration": { - "name": "GlGraphSideBar", - "module": "src/webviews/apps/plus/graph/sidebar/sidebar.ts" + "name": "GlIntegrationsChip", + "module": "src/webviews/apps/plus/shared/components/integrations-chip.ts" } }, { "kind": "custom-element-definition", - "name": "gl-graph-sidebar", + "name": "gl-integrations-chip", "declaration": { - "name": "GlGraphSideBar", - "module": "src/webviews/apps/plus/graph/sidebar/sidebar.ts" + "name": "GlIntegrationsChip", + "module": "src/webviews/apps/plus/shared/components/integrations-chip.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/styles/graph.css.ts", + "path": "src/webviews/apps/plus/shared/components/merge-rebase-status.ts", "declarations": [ { - "kind": "variable", - "name": "linkBase", - "default": "css` a { text-decoration: none; } a:focus { ${focusOutline} } a:hover { text-decoration: underline; } `" - }, - { - "kind": "variable", - "name": "actionButton", - "default": "css` .action-button { position: relative; appearance: none; font-family: inherit; font-size: 1.2rem; line-height: 2.2rem; // background-color: var(--color-graph-actionbar-background); background-color: transparent; border: none; color: inherit; color: var(--color-foreground); padding: 0 0.75rem; cursor: pointer; border-radius: 3px; height: auto; display: grid; grid-auto-flow: column; grid-gap: 0.5rem; gap: 0.5rem; max-width: fit-content; } .action-button[disabled] { pointer-events: none; cursor: default; opacity: 1; } .action-button:hover { background-color: var(--color-graph-actionbar-selectedBackground); color: var(--color-foreground); text-decoration: none; } .action-button[aria-checked] { border: 1px solid transparent; } .action-button[aria-checked='true'] { background-color: var(--vscode-inputOption-activeBackground); color: var(--vscode-inputOption-activeForeground); border-color: var(--vscode-inputOption-activeBorder); } .action-button code-icon { line-height: 2.2rem; vertical-align: bottom; } .action-button code-icon[icon='graph-line'] { transform: translateY(1px); } .is-ahead .action-button__pill { background-color: var(--branch-status-ahead-pill-background); } .is-behind .action-button__pill { background-color: var(--branch-status-behind-pill-background); } .is-ahead.is-behind .action-button__pill { background-color: var(--branch-status-both-pill-background); } .action-button__more, .action-button__more.codicon[class*='codicon-'] { font-size: 1rem; margin-right: -0.25rem; } code-icon.action-button__more::before { margin-left: -0.25rem; } .action-button__indicator { margin-left: -0.2rem; --gl-indicator-color: green; --gl-indicator-size: 0.4rem; } .action-button__small { font-size: smaller; opacity: 0.6; text-overflow: ellipsis; overflow: hidden; } .action-button.is-ahead { background-color: var(--branch-status-ahead-background); } .action-button.is-ahead:hover { background-color: var(--branch-status-ahead-hover-background); } .action-button.is-behind { background-color: var(--branch-status-behind-background); } .action-button.is-behind:hover { background-color: var(--branch-status-behind-hover-background); } .action-button.is-ahead.is-behind { background-color: var(--branch-status-both-background); } .action-button.is-ahead.is-behind:hover { background-color: var(--branch-status-both-hover-background); } `" + "kind": "class", + "description": "", + "name": "GlMergeConflictWarning", + "members": [ + { + "kind": "field", + "name": "conflicts", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "conflicts", + "reflects": true + }, + { + "kind": "field", + "name": "pausedOpStatus", + "type": { + "text": "GitPausedOperationStatus | undefined" + }, + "attribute": "pausedOpStatus" + }, + { + "kind": "field", + "name": "skipCommand", + "type": { + "text": "string" + }, + "default": "'gitlens.home.skipPausedOperation'", + "attribute": "skipCommand" + }, + { + "kind": "field", + "name": "continueCommand", + "type": { + "text": "string" + }, + "default": "'gitlens.home.continuePausedOperation'", + "attribute": "continueCommand" + }, + { + "kind": "field", + "name": "abortCommand", + "type": { + "text": "string" + }, + "default": "'gitlens.home.abortPausedOperation'", + "attribute": "abortCommand" + }, + { + "kind": "field", + "name": "openEditorCommand", + "type": { + "text": "string" + }, + "default": "'gitlens.home.openRebaseEditor'", + "attribute": "openEditorCommand" + }, + { + "kind": "field", + "name": "webviewCommandContext", + "type": { + "text": "{ webview: string; webviewInstance: string | undefined } | undefined" + }, + "attribute": "webviewCommandContext" + }, + { + "kind": "field", + "name": "onSkipUrl", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "onContinueUrl", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "onAbortUrl", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "onOpenEditorUrl", + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "createCommandLink", + "privacy": "private", + "parameters": [ + { + "name": "command", + "type": { + "text": "string" + } + }, + { + "name": "args", + "optional": true, + "type": { + "text": "any" + } + } + ] + }, + { + "kind": "method", + "name": "renderStatus", + "privacy": "private", + "parameters": [ + { + "name": "pausedOpStatus", + "type": { + "text": "GitPausedOperationStatus" + } + } + ] + }, + { + "kind": "method", + "name": "renderActions", + "privacy": "private" + } + ], + "attributes": [ + { + "name": "conflicts", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "conflicts" + }, + { + "name": "pausedOpStatus", + "type": { + "text": "GitPausedOperationStatus | undefined" + }, + "fieldName": "pausedOpStatus" + }, + { + "name": "skipCommand", + "type": { + "text": "string" + }, + "default": "'gitlens.home.skipPausedOperation'", + "fieldName": "skipCommand" + }, + { + "name": "continueCommand", + "type": { + "text": "string" + }, + "default": "'gitlens.home.continuePausedOperation'", + "fieldName": "continueCommand" + }, + { + "name": "abortCommand", + "type": { + "text": "string" + }, + "default": "'gitlens.home.abortPausedOperation'", + "fieldName": "abortCommand" + }, + { + "name": "openEditorCommand", + "type": { + "text": "string" + }, + "default": "'gitlens.home.openRebaseEditor'", + "fieldName": "openEditorCommand" + }, + { + "name": "webviewCommandContext", + "type": { + "text": "{ webview: string; webviewInstance: string | undefined } | undefined" + }, + "fieldName": "webviewCommandContext" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-merge-rebase-status", + "customElement": true } ], "exports": [ { "kind": "js", - "name": "linkBase", + "name": "GlMergeConflictWarning", "declaration": { - "name": "linkBase", - "module": "src/webviews/apps/plus/graph/styles/graph.css.ts" + "name": "GlMergeConflictWarning", + "module": "src/webviews/apps/plus/shared/components/merge-rebase-status.ts" } }, { - "kind": "js", - "name": "actionButton", + "kind": "custom-element-definition", + "name": "gl-merge-rebase-status", "declaration": { - "name": "actionButton", - "module": "src/webviews/apps/plus/graph/styles/graph.css.ts" + "name": "GlMergeConflictWarning", + "module": "src/webviews/apps/plus/shared/components/merge-rebase-status.ts" } } ] }, { "kind": "javascript-module", - "path": "src/webviews/apps/plus/graph/styles/header.css.ts", + "path": "src/webviews/apps/plus/shared/components/vscode.css.ts", "declarations": [ { "kind": "variable", - "name": "repoHeaderStyles", - "default": "css` .jump-to-ref { --button-foreground: var(--color-foreground); } .merge-conflict-warning { flex: 0 0 100%; min-width: 0; } `" - }, - { - "kind": "variable", - "name": "progressStyles", - "default": "css` .progress-container { position: absolute; left: 0; bottom: 0; z-index: 5; height: 2px; width: 100%; overflow: hidden; } .progress-container .progress-bar { background-color: var(--vscode-progressBar-background); display: none; position: absolute; left: 0; width: 2%; height: 2px; } .progress-container.active .progress-bar { display: inherit; } .progress-container.discrete .progress-bar { left: 0; transition: width 0.1s linear; } .progress-container.discrete.done .progress-bar { width: 100%; } .progress-container.infinite .progress-bar { animation-name: progress; animation-duration: 4s; animation-iteration-count: infinite; animation-timing-function: steps(100); transform: translateZ(0); } @keyframes progress { 0% { transform: translateX(0) scaleX(1); } 50% { transform: translateX(2500%) scaleX(3); } to { transform: translateX(4900%) scaleX(1); } } `" - }, - { - "kind": "variable", - "name": "titlebarStyles", - "default": "css` .titlebar { background: var(--titlebar-bg); color: var(--titlebar-fg); padding: 0.6rem 0.8rem; font-size: 1.3rem; flex-wrap: wrap; } .titlebar, .titlebar__row, .titlebar__group { display: flex; flex-direction: row; align-items: center; gap: 0.5rem; } .titlebar > *, .titlebar__row > *, .titlebar__group > * { margin: 0; } .titlebar, .titlebar__row { justify-content: space-between; } .titlebar__row { flex: 0 0 100%; } .titlebar__row--wrap { display: grid; grid-auto-flow: column; justify-content: start; grid-template-columns: 1fr min-content; } .titlebar__group { flex: auto 1 1; } .titlebar__row--wrap .titlebar__group { white-space: nowrap; } .titlebar__row--wrap .titlebar__group:nth-child(odd) { min-width: 0; } .titlebar__debugging > * { display: inline-block; } .titlebar gl-feature-badge { color: var(--color-foreground); } `" + "name": "linkStyles", + "default": "css` a { border: 0; color: var(--link-foreground); font-weight: 400; outline: none; text-decoration: var(--link-decoration-default, none); } a:focus-visible { outline: 1px solid var(--color-focus-border); border-radius: 0.2rem; } a:hover { color: var(--link-foreground-active); text-decoration: underline; } `" }, { "kind": "variable", - "name": "graphHeaderControlStyles", - "default": "css` .popover::part(body) { padding: 0; font-size: var(--vscode-font-size); background-color: var(--vscode-menu-background); } .titlebar__group gl-repo-button-group, .titlebar__group gl-ref-button { font-size: 1.2rem; } .shrink { max-width: fit-content; transition: all 0.2s; } .shrink.hidden { max-width: 0; overflow: hidden; } .titlebar__group .shrink.hidden:not(:first-child) { // compensate the parent gap margin-left: -0.5rem; } .branch-menu { display: flex; gap: 0.5em; align-items: center; } .branch-menu__avatar { width: 1.4rem; aspect-ratio: 1; vertical-align: text-bottom; } .action-divider { display: inline-block; width: 0.1rem; height: 2.2rem; vertical-align: middle; background-color: var(--titlebar-fg); opacity: 0.4; margin: { // left: 0.2rem; right: 0.2rem; } } .button-group { display: flex; flex-direction: row; align-items: stretch; } .button-group:hover, .button-group:focus-within { background-color: var(--color-graph-actionbar-selectedBackground); border-radius: 3px; } .button-group > *:not(:first-child), .button-group > *:not(:first-child) .action-button { display: flex; border-top-left-radius: 0; border-bottom-left-radius: 0; } .button-group > *:not(:first-child) .action-button { padding-left: 0.5rem; padding-right: 0.5rem; height: 100%; } .button-group:hover > *:not(:last-child), .button-group:active > *:not(:last-child), .button-group:focus-within > *:not(:last-child), .button-group:hover > *:not(:last-child) .action-button, .button-group:active > *:not(:last-child) .action-button, .button-group:focus-within > *:not(:last-child) .action-button { border-top-right-radius: 0; border-bottom-right-radius: 0; } .minimap-marker-swatch { display: inline-block; width: 1rem; height: 1rem; border-radius: 2px; transform: scale(1.6); margin-left: 0.3rem; margin-right: 1rem; } .minimap-marker-swatch[data-marker='localBranches'] { background-color: var(--color-graph-minimap-marker-local-branches); } .minimap-marker-swatch[data-marker='pullRequests'] { background-color: var(--color-graph-minimap-marker-pull-requests); } .minimap-marker-swatch[data-marker='remoteBranches'] { background-color: var(--color-graph-minimap-marker-remote-branches); } .minimap-marker-swatch[data-marker='stashes'] { background-color: var(--color-graph-minimap-marker-stashes); } .minimap-marker-swatch[data-marker='tags'] { background-color: var(--color-graph-minimap-marker-tags); } gl-search-box::part(search) { --gl-search-input-background: var(--color-graph-actionbar-background); --gl-search-input-border: var(--sl-input-border-color); } sl-option::part(base) { padding: 0.2rem 0.4rem; } sl-option[aria-selected='true']::part(base), sl-option:not([aria-selected='true']):hover::part(base), sl-option:not([aria-selected='true']):focus::part(base) { background-color: var(--vscode-list-activeSelectionBackground); color: var(--vscode-list-activeSelectionForeground); } sl-option::part(checked-icon) { display: none; } sl-select::part(listbox) { padding-block: 0.2rem 0; width: max-content; } sl-select::part(combobox) { --sl-input-background-color: var(--color-graph-actionbar-background); --sl-input-color: var(--color-foreground); --sl-input-color-hover: var(--color-foreground); padding: 0 0.75rem; color: var(--color-foreground); border-radius: var(--sl-border-radius-small); } sl-select::part(display-input) { field-sizing: content; } sl-select::part(expand-icon) { margin-inline-start: var(--sl-spacing-x-small); } sl-select[open]::part(combobox) { background-color: var(--color-graph-actionbar-background); } sl-select:hover::part(combobox), sl-select:focus::part(combobox) { background-color: var(--color-graph-actionbar-selectedBackground); } `" + "name": "ruleStyles", + "default": "css` hr { border: none; border-top: 1px solid var(--color-foreground--25); } `" } ], "exports": [ { "kind": "js", - "name": "repoHeaderStyles", - "declaration": { - "name": "repoHeaderStyles", - "module": "src/webviews/apps/plus/graph/styles/header.css.ts" - } - }, - { - "kind": "js", - "name": "progressStyles", - "declaration": { - "name": "progressStyles", - "module": "src/webviews/apps/plus/graph/styles/header.css.ts" - } - }, - { - "kind": "js", - "name": "titlebarStyles", + "name": "linkStyles", "declaration": { - "name": "titlebarStyles", - "module": "src/webviews/apps/plus/graph/styles/header.css.ts" + "name": "linkStyles", + "module": "src/webviews/apps/plus/shared/components/vscode.css.ts" } }, { "kind": "js", - "name": "graphHeaderControlStyles", + "name": "ruleStyles", "declaration": { - "name": "graphHeaderControlStyles", - "module": "src/webviews/apps/plus/graph/styles/header.css.ts" + "name": "ruleStyles", + "module": "src/webviews/apps/plus/shared/components/vscode.css.ts" } } ] @@ -26129,6 +31634,11 @@ } ] }, + { + "kind": "field", + "name": "handleLinkKeydown", + "privacy": "private" + }, { "kind": "method", "name": "focus", @@ -26564,6 +32074,404 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/banner/banner.css.ts", + "declarations": [ + { + "kind": "variable", + "name": "bannerStyles", + "default": "css` :host { /* Banner color custom properties */ --gl-banner-primary-background: var(--vscode-sideBar-background); --gl-banner-secondary-background: var(--vscode-editor-background); --gl-banner-primary-emphasis-background: var(--vscode-button-background); --gl-banner-secondary-emphasis-background: var(--vscode-button-secondaryBackground); --gl-banner-text-color: var(--vscode-foreground); --gl-banner-dim-text-color: var(--vscode-descriptionForeground); --gl-banner-transparency: 0.5; /* Layout properties */ --gl-banner-padding: 1.2rem; --gl-banner-gap: 0.8rem; --gl-banner-border-radius: 0.4rem; /* Button customization - use 8px horizontal padding, keep original vertical padding */ --gl-banner-button-padding: 0.4rem 0.8rem; display: block; margin-block-end: 1.2rem; } .banner { display: flex; flex-direction: column; padding: var(--gl-banner-padding); border-radius: var(--gl-banner-border-radius); position: relative; overflow: hidden; container-type: inline-size; } /* Solid display mode - same as card background */ .banner--solid { background-color: var(--gl-banner-primary-background); border: 1px solid color-mix(in lab, var(--gl-banner-primary-background) 100%, var(--vscode-foreground) 12%); } /* Outline display mode - emphasis color outline with secondary background */ .banner--outline { background-color: var(--gl-banner-secondary-background); border: 2px solid var(--gl-banner-primary-emphasis-background); } /* Gradient display mode - horizontal gradient from primary to secondary emphasis */ .banner--gradient { background: linear-gradient( to right, var(--gl-banner-primary-emphasis-background) 0%, var(--gl-banner-secondary-emphasis-background) 100% ); border: 1px solid color-mix( in lab, var(--gl-banner-primary-emphasis-background) 50%, var(--gl-banner-secondary-emphasis-background) 50% ); } /* Gradient transparent display mode - same gradient but with transparency */ .banner--gradient-transparent { background: linear-gradient( to right, color-mix( in lab, var(--gl-banner-primary-emphasis-background) calc(100% * (1 - var(--gl-banner-transparency))), transparent ) 0%, color-mix( in lab, var(--gl-banner-secondary-emphasis-background) calc(100% * (1 - var(--gl-banner-transparency))), transparent ) 100% ); border: 1px solid color-mix( in lab, color-mix( in lab, var(--gl-banner-primary-emphasis-background) 50%, var(--gl-banner-secondary-emphasis-background) 50% ) calc(100% * (1 - var(--gl-banner-transparency))), transparent ); } /* Gradient purple display mode - matches the auto-composer container styling */ .banner--gradient-purple { border: 1px solid var(--vscode-panel-border); border-radius: 6px; background: linear-gradient(135deg, #a100ff1a 0%, #255ed11a 100%); } .banner--gradient-purple .banner__title { font-size: 1.3rem; color: var(--vscode-foreground); font-weight: normal; } .banner--gradient-purple .banner__body { font-size: 1.2rem; color: var(--vscode-descriptionForeground); line-height: 1.4; } .banner--gradient-purple .banner__body a { color: var(--vscode-textLink-foreground); text-decoration: none; } .banner--gradient-purple .banner__body a:hover { color: var(--vscode-textLink-activeForeground); text-decoration: underline; } .banner__content { display: flex; flex-direction: column; gap: var(--gl-banner-gap); align-items: center; text-align: center; } /* Responsive layout */ .banner--responsive .banner__content { display: flex; flex-direction: column; align-items: stretch; text-align: left; gap: var(--gl-banner-gap); } .banner--responsive .banner__text { display: flex; flex-direction: column; gap: 0.4rem; } .banner--responsive .banner__title, .banner--responsive .banner__body { text-align: left; } /* < 500px: Stack vertically with full-width buttons */ .banner--responsive .banner__buttons { display: flex; flex-direction: column; gap: 0.8rem; margin-top: 0.8rem; width: 100%; } .banner--responsive .banner__button { grid-column: unset; justify-self: unset; width: 100% !important; min-width: 100% !important; max-width: 100% !important; justify-content: center; flex: 1; } /* >= 500px: Three-group horizontal layout */ @container (min-width: 500px) { .banner--responsive .banner__content { flex-direction: row; align-items: center; gap: 1.6rem; } /* Group 1: Text content (left-aligned) */ .banner--responsive .banner__text { flex: 1; min-width: 0; align-self: center; } /* Group 2: Buttons (content-sized) */ .banner--responsive .banner__buttons { display: flex; flex-direction: column; gap: 0.8rem; margin-top: 0; width: auto; flex-shrink: 0; align-self: center; } .banner--responsive .banner__button { width: auto; white-space: nowrap; } /* Group 3: Dismiss button (to the right of buttons) */ .banner--responsive .banner__dismiss { position: static !important; top: auto !important; right: auto !important; align-self: center; flex-shrink: 0; } } .banner__title { font-size: 1.2em; font-weight: bold; color: var(--gl-banner-text-color); margin: 0; text-wrap: pretty; } .banner__body { font-size: 1em; color: var(--gl-banner-text-color); margin: 0; line-height: 1.4; text-wrap: pretty; } .banner__buttons { display: grid; grid-template-columns: 1fr auto 1fr; gap: 0.8rem; margin-top: 0.8rem; align-items: center; width: 100%; } .banner:not(.banner--gradient-purple) .banner__button--primary { grid-column: 2; justify-self: center; white-space: nowrap; --button-background: color-mix(in lab, var(--gl-banner-primary-background) 10%, #fff 20%); --button-foreground: var(--gl-banner-text-color); --button-hover-background: color-mix(in lab, var(--gl-banner-primary-background) 20%, #fff 30%); --button-padding: var(--gl-banner-button-padding); } .banner--gradient-purple .banner__button--primary { grid-column: 2; justify-self: center; white-space: nowrap; --button-padding: var(--gl-banner-button-padding); } .banner__button--secondary { grid-column: 3; justify-self: end; white-space: nowrap; --button-background: transparent; --button-foreground: var(--gl-banner-dim-text-color); --button-hover-background: color-mix(in lab, var(--gl-banner-dim-text-color) 10%, transparent); } /* When only primary button exists, center it across the full width */ .banner__buttons:has(.banner__button--primary):not(:has(.banner__button--secondary)) .banner__button--primary { grid-column: 1 / -1; justify-self: center; } /* Dismiss button */ .banner__dismiss { position: absolute; top: 0.8rem; right: 0.8rem; --button-background: transparent; --button-foreground: var(--gl-banner-dim-text-color); --button-hover-background: color-mix(in lab, var(--gl-banner-dim-text-color) 15%, transparent); --button-padding: 0.4rem; z-index: 1; } /* Responsive layout dismiss button */ .banner--responsive .banner__dismiss { /* < 500px: Upper right corner (default positioning) */ position: absolute; top: 0.8rem; right: 0.8rem; } /* Theme-specific adjustments */ /* Light theme: Brighten gradient colors for better contrast with dark text */ :host-context(.vscode-light), :host-context(.vscode-high-contrast-light) { --gl-banner-primary-emphasis-background: color-mix(in lab, var(--vscode-button-background) 40%, #fff 60%); --gl-banner-secondary-emphasis-background: color-mix( in lab, var(--vscode-button-secondaryBackground) 40%, #fff 60% ); } /* Override text color for high contrast light theme specifically */ :host-context(.vscode-high-contrast-light) { --gl-banner-text-color: #000; } :host-context(.vscode-dark) .banner:not(.banner--gradient-purple) .banner__button--primary, :host-context(.vscode-high-contrast:not(.vscode-high-contrast-light)) .banner:not(.banner--gradient-purple) .banner__button--primary { --button-background: color-mix(in lab, var(--gl-banner-primary-background) 10%, #fff 20%); --button-hover-background: color-mix(in lab, var(--gl-banner-primary-background) 20%, #fff 30%); --button-foreground: #fff; } :host-context(.vscode-light) .banner:not(.banner--gradient-purple) .banner__button--primary, :host-context(.vscode-high-contrast-light) .banner:not(.banner--gradient-purple) .banner__button--primary { --button-background: color-mix(in lab, var(--gl-banner-primary-background) 8%, #fff 25%); --button-hover-background: color-mix(in lab, var(--gl-banner-primary-background) 15%, #fff 35%); --button-foreground: #000; } /* Make banner text darker in light themes */ :host-context(.vscode-light) .banner__body, :host-context(.vscode-high-contrast-light) .banner__body { color: color-mix(in lab, var(--gl-banner-text-color) 20%, #000 80%); } /* Strong colors for banner title - pure black/white for maximum contrast */ :host-context(.vscode-light) .banner__title, :host-context(.vscode-high-contrast-light) .banner__title { color: #000 !important; } :host-context(.vscode-dark) .banner__title, :host-context(.vscode-high-contrast:not(.vscode-high-contrast-light)) .banner__title { color: #fff !important; } /* Responsive adjustments */ @media (max-width: 640px) { .banner__buttons { flex-direction: column; width: 100%; } .banner__button { width: 100%; } } /* More aggressive responsive layout for narrow sidebars */ @media (max-width: 400px) { .banner__buttons { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.8rem; align-items: center; width: 100%; } .banner__button--primary, .banner__button--secondary { grid-column: unset; justify-self: unset; width: 100%; max-width: 200px; } .banner__button--primary { order: 1; } .banner__button--secondary { order: 2; } } /* Support for custom banner buttons layout */ :host([data-banner-buttons-layout='column']) .banner__buttons, .banner__buttons[data-layout='column'] { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.8rem; align-items: center; width: 100%; } :host([data-banner-buttons-layout='column']) .banner__button--primary, :host([data-banner-buttons-layout='column']) .banner__button--secondary, .banner__buttons[data-layout='column'] .banner__button--primary, .banner__buttons[data-layout='column'] .banner__button--secondary { grid-column: unset; justify-self: unset; width: 100%; max-width: 200px; } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "bannerStyles", + "declaration": { + "name": "bannerStyles", + "module": "src/webviews/apps/shared/components/banner/banner.css.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/banner/banner.ts", + "declarations": [ + { + "kind": "variable", + "name": "bannerTagName", + "type": { + "text": "string" + }, + "default": "'gl-banner'" + }, + { + "kind": "class", + "description": "", + "name": "GlBanner", + "members": [ + { + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }" + }, + { + "kind": "field", + "name": "display", + "type": { + "text": "BannerDisplay" + }, + "default": "'solid'", + "attribute": "display", + "reflects": true + }, + { + "kind": "field", + "name": "bannerTitle", + "type": { + "text": "string | undefined" + }, + "attribute": "banner-title" + }, + { + "kind": "field", + "name": "body", + "type": { + "text": "string | undefined" + }, + "attribute": "body" + }, + { + "kind": "field", + "name": "primaryButton", + "type": { + "text": "string | undefined" + }, + "attribute": "primary-button" + }, + { + "kind": "field", + "name": "primaryButtonHref", + "type": { + "text": "string | undefined" + }, + "attribute": "primary-button-href" + }, + { + "kind": "field", + "name": "primaryButtonCommand", + "type": { + "text": "string | undefined" + }, + "attribute": "primary-button-command" + }, + { + "kind": "field", + "name": "secondaryButton", + "type": { + "text": "string | undefined" + }, + "attribute": "secondary-button" + }, + { + "kind": "field", + "name": "secondaryButtonHref", + "type": { + "text": "string | undefined" + }, + "attribute": "secondary-button-href" + }, + { + "kind": "field", + "name": "secondaryButtonCommand", + "type": { + "text": "string | undefined" + }, + "attribute": "secondary-button-command" + }, + { + "kind": "field", + "name": "dismissible", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "dismissible" + }, + { + "kind": "field", + "name": "dismissHref", + "type": { + "text": "string | undefined" + }, + "attribute": "dismiss-href" + }, + { + "kind": "field", + "name": "layout", + "type": { + "text": "'default' | 'responsive'" + }, + "default": "'default'", + "attribute": "layout" + }, + { + "kind": "field", + "name": "classNames", + "privacy": "private", + "readonly": true + }, + { + "kind": "method", + "name": "renderDefaultContent", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderResponsiveContent", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderTitle", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderBody", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderButtons", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderPrimaryButton", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderSecondaryButton", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderDismissButton", + "privacy": "private" + }, + { + "kind": "method", + "name": "onPrimaryButtonClick", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "onSecondaryButtonClick", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "onDismissClick", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "Event" + } + } + ] + } + ], + "events": [ + { + "name": "gl-banner-primary-click", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "gl-banner-secondary-click", + "type": { + "text": "CustomEvent" + } + }, + { + "name": "gl-banner-dismiss", + "type": { + "text": "CustomEvent" + } + } + ], + "attributes": [ + { + "name": "display", + "type": { + "text": "BannerDisplay" + }, + "default": "'solid'", + "fieldName": "display" + }, + { + "name": "banner-title", + "type": { + "text": "string | undefined" + }, + "fieldName": "bannerTitle" + }, + { + "name": "body", + "type": { + "text": "string | undefined" + }, + "fieldName": "body" + }, + { + "name": "primary-button", + "type": { + "text": "string | undefined" + }, + "fieldName": "primaryButton" + }, + { + "name": "primary-button-href", + "type": { + "text": "string | undefined" + }, + "fieldName": "primaryButtonHref" + }, + { + "name": "primary-button-command", + "type": { + "text": "string | undefined" + }, + "fieldName": "primaryButtonCommand" + }, + { + "name": "secondary-button", + "type": { + "text": "string | undefined" + }, + "fieldName": "secondaryButton" + }, + { + "name": "secondary-button-href", + "type": { + "text": "string | undefined" + }, + "fieldName": "secondaryButtonHref" + }, + { + "name": "secondary-button-command", + "type": { + "text": "string | undefined" + }, + "fieldName": "secondaryButtonCommand" + }, + { + "name": "dismissible", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "dismissible" + }, + { + "name": "dismiss-href", + "type": { + "text": "string | undefined" + }, + "fieldName": "dismissHref" + }, + { + "name": "layout", + "type": { + "text": "'default' | 'responsive'" + }, + "default": "'default'", + "fieldName": "layout" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "bannerTagName", + "declaration": { + "name": "bannerTagName", + "module": "src/webviews/apps/shared/components/banner/banner.ts" + } + }, + { + "kind": "js", + "name": "GlBanner", + "declaration": { + "name": "GlBanner", + "module": "src/webviews/apps/shared/components/banner/banner.ts" + } + }, + { + "kind": "custom-element-definition", + "declaration": { + "name": "GlBanner", + "module": "src/webviews/apps/shared/components/banner/banner.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/banner/index.ts", + "declarations": [], + "exports": [ + { + "kind": "js", + "name": "*", + "declaration": { + "name": "*", + "module": "src/webviews/apps/shared/components/banner/banner" + } + }, + { + "kind": "js", + "name": "bannerStyles", + "declaration": { + "name": "bannerStyles", + "module": "./banner.css" + } + } + ] + }, { "kind": "javascript-module", "path": "src/webviews/apps/shared/components/card/card.css.ts", @@ -28518,6 +34426,94 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/markdown/markdown.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlMarkdown", + "members": [ + { + "kind": "field", + "name": "markdown", + "type": { + "text": "string" + }, + "privacy": "private", + "default": "''", + "attribute": "markdown" + }, + { + "kind": "field", + "name": "density", + "type": { + "text": "'compact' | 'document'" + }, + "default": "'compact'", + "attribute": "density", + "reflects": true + }, + { + "kind": "method", + "name": "renderMarkdown", + "privacy": "private", + "parameters": [ + { + "name": "markdown", + "type": { + "text": "string" + } + } + ] + } + ], + "attributes": [ + { + "name": "markdown", + "type": { + "text": "string" + }, + "default": "''", + "fieldName": "markdown" + }, + { + "name": "density", + "type": { + "text": "'compact' | 'document'" + }, + "default": "'compact'", + "fieldName": "density" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-markdown", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlMarkdown", + "declaration": { + "name": "GlMarkdown", + "module": "src/webviews/apps/shared/components/markdown/markdown.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-markdown", + "declaration": { + "name": "GlMarkdown", + "module": "src/webviews/apps/shared/components/markdown/markdown.ts" + } + } + ] + }, { "kind": "javascript-module", "path": "src/webviews/apps/shared/components/menu/menu-divider.ts", @@ -28728,70 +34724,110 @@ }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/markdown/markdown.ts", + "path": "src/webviews/apps/shared/components/overlays/dialog.ts", "declarations": [ { "kind": "class", "description": "", - "name": "GlMarkdown", + "name": "GlDialog", "members": [ { "kind": "field", - "name": "markdown", + "name": "open", "type": { - "text": "string" + "text": "boolean" }, - "privacy": "private", - "default": "''", - "attribute": "markdown" + "default": "false", + "attribute": "open", + "reflects": true + }, + { + "kind": "field", + "name": "modal", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "modal", + "reflects": true + }, + { + "kind": "field", + "name": "closedby", + "type": { + "text": "'any' | 'closerequest' | 'none' | undefined" + }, + "attribute": "closedby" + }, + { + "kind": "field", + "name": "dialog", + "type": { + "text": "HTMLDialogElement" + } }, { "kind": "method", - "name": "renderMarkdown", - "privacy": "private", - "parameters": [ - { - "name": "markdown", - "type": { - "text": "string" - } - } - ] + "name": "toggleVisibility", + "privacy": "private" + }, + { + "kind": "method", + "name": "close" + }, + { + "kind": "method", + "name": "show" } ], "attributes": [ { - "name": "markdown", + "name": "open", "type": { - "text": "string" + "text": "boolean" }, - "default": "''", - "fieldName": "markdown" + "default": "false", + "fieldName": "open" + }, + { + "name": "modal", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "modal" + }, + { + "name": "closedby", + "type": { + "text": "'any' | 'closerequest' | 'none' | undefined" + }, + "fieldName": "closedby" } ], "superclass": { "name": "LitElement", "package": "lit" }, - "tagName": "gl-markdown", + "tagName": "gl-dialog", "customElement": true } ], "exports": [ { "kind": "js", - "name": "GlMarkdown", + "name": "GlDialog", "declaration": { - "name": "GlMarkdown", - "module": "src/webviews/apps/shared/components/markdown/markdown.ts" + "name": "GlDialog", + "module": "src/webviews/apps/shared/components/overlays/dialog.ts" } }, { "kind": "custom-element-definition", - "name": "gl-markdown", + "name": "gl-dialog", "declaration": { - "name": "GlMarkdown", - "module": "src/webviews/apps/shared/components/markdown/markdown.ts" + "name": "GlDialog", + "module": "src/webviews/apps/shared/components/overlays/dialog.ts" } } ] @@ -29648,41 +35684,410 @@ "type": { "text": "boolean" }, - "default": "false", - "fieldName": "colorized" + "default": "false", + "fieldName": "colorized" + }, + { + "name": "missingUpstream", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "missingUpstream" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-tracking-pill", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlTrackingPill", + "declaration": { + "name": "GlTrackingPill", + "module": "src/webviews/apps/shared/components/pills/tracking.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-tracking-pill", + "declaration": { + "name": "GlTrackingPill", + "module": "src/webviews/apps/shared/components/pills/tracking.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/radio/radio-group.ts", + "declarations": [ + { + "kind": "variable", + "name": "tagName", + "type": { + "text": "string" + }, + "default": "'gl-radio-group'" + }, + { + "kind": "class", + "description": "", + "name": "RadioGroup", + "members": [ + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "disabled", + "reflects": true + }, + { + "kind": "field", + "name": "value", + "type": { + "text": "string | undefined" + }, + "attribute": "value" + }, + { + "kind": "method", + "name": "handleValueChange", + "privacy": "private" + }, + { + "kind": "field", + "name": "radioEls", + "type": { + "text": "Radio[]" + }, + "privacy": "private" + }, + { + "kind": "method", + "name": "updateRadioElements", + "privacy": "private", + "parameters": [ + { + "name": "updateParentGroup", + "default": "false" + } + ] + }, + { + "kind": "method", + "name": "setValue", + "return": { + "type": { + "text": "void" + } + }, + "parameters": [ + { + "name": "value", + "type": { + "text": "string" + } + } + ] + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "attributes": [ + { + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "disabled" + }, + { + "name": "value", + "type": { + "text": "string | undefined" + }, + "fieldName": "value" + } + ], + "superclass": { + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" + } + } + ], + "exports": [ + { + "kind": "js", + "name": "tagName", + "declaration": { + "name": "tagName", + "module": "src/webviews/apps/shared/components/radio/radio-group.ts" + } + }, + { + "kind": "js", + "name": "RadioGroup", + "declaration": { + "name": "RadioGroup", + "module": "src/webviews/apps/shared/components/radio/radio-group.ts" + } + }, + { + "kind": "custom-element-definition", + "declaration": { + "name": "RadioGroup", + "module": "src/webviews/apps/shared/components/radio/radio-group.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/radio/radio.css.ts", + "declarations": [ + { + "kind": "variable", + "name": "radioStyles", + "default": "css` :host { --checkbox-radius: 50%; --checkbox-foreground: var(--vscode-radio-inactiveForeground); --checkbox-background: var(--vscode-radio-inactiveBackground); --checkbox-border: var(--vscode-radio-inactiveBorder); --checkbox-checked-foreground: var(--vscode-radio-activeForeground); --checkbox-checked-background: var(--vscode-radio-activeBackground); --checkbox-checked-border: var(--vscode-radio-activeBorder); --checkbox-hover-background: var(--vscode-radio-inactiveHoverBackground); } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "radioStyles", + "declaration": { + "name": "radioStyles", + "module": "src/webviews/apps/shared/components/radio/radio.css.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/shared/components/radio/radio.ts", + "declarations": [ + { + "kind": "variable", + "name": "tagName", + "type": { + "text": "string" + }, + "default": "'gl-radio'" + }, + { + "kind": "class", + "description": "", + "name": "Radio", + "members": [ + { + "kind": "field", + "name": "shadowRootOptions", + "type": { + "text": "ShadowRootInit" + }, + "static": true, + "default": "{ ...GlElement.shadowRootOptions, delegatesFocus: true, }" + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "disabled", + "reflects": true + }, + { + "kind": "field", + "name": "value", + "type": { + "text": "string | undefined" + }, + "attribute": "value" + }, + { + "kind": "field", + "name": "name", + "type": { + "text": "string | undefined" + }, + "attribute": "name", + "reflects": true + }, + { + "kind": "field", + "name": "checked", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "checked", + "reflects": true + }, + { + "kind": "field", + "name": "_parentGroup", + "type": { + "text": "RadioGroup | undefined" + }, + "privacy": "private", + "default": "undefined" + }, + { + "kind": "field", + "name": "parentGroup", + "type": { + "text": "RadioGroup | undefined" + } + }, + { + "kind": "method", + "name": "handleClick", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderCircle", + "privacy": "private" + }, + { + "kind": "method", + "name": "emit", + "return": { + "type": { + "text": "CustomEventType" + } + }, + "parameters": [ + { + "name": "name", + "type": { + "text": "T" + } + }, + { + "name": "detail", + "type": { + "text": "CustomEventDetailType" + } + }, + { + "name": "options", + "optional": true, + "type": { + "text": "Omit>, 'detail'>" + } + } + ], + "inheritedFrom": { + "name": "GlElement", + "module": "src/webviews/apps/shared/components/element.ts" + } + } + ], + "attributes": [ + { + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "disabled" + }, + { + "name": "value", + "type": { + "text": "string | undefined" + }, + "fieldName": "value" + }, + { + "name": "name", + "type": { + "text": "string | undefined" + }, + "fieldName": "name" }, { - "name": "missingUpstream", + "name": "checked", "type": { "text": "boolean" }, "default": "false", - "fieldName": "missingUpstream" + "fieldName": "checked" } ], "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "gl-tracking-pill", - "customElement": true + "name": "GlElement", + "module": "/src/webviews/apps/shared/components/element" + } } ], "exports": [ { "kind": "js", - "name": "GlTrackingPill", + "name": "tagName", "declaration": { - "name": "GlTrackingPill", - "module": "src/webviews/apps/shared/components/pills/tracking.ts" + "name": "tagName", + "module": "src/webviews/apps/shared/components/radio/radio.ts" + } + }, + { + "kind": "js", + "name": "Radio", + "declaration": { + "name": "Radio", + "module": "src/webviews/apps/shared/components/radio/radio.ts" } }, { "kind": "custom-element-definition", - "name": "gl-tracking-pill", "declaration": { - "name": "GlTrackingPill", - "module": "src/webviews/apps/shared/components/pills/tracking.ts" + "name": "Radio", + "module": "src/webviews/apps/shared/components/radio/radio.ts" } } ] @@ -30221,447 +36626,136 @@ }, { "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/radio/radio-group.ts", + "path": "src/webviews/apps/shared/components/search/search-box.ts", "declarations": [ - { - "kind": "variable", - "name": "tagName", - "type": { - "text": "string" - }, - "default": "'gl-radio-group'" - }, { "kind": "class", "description": "", - "name": "RadioGroup", + "name": "GlSearchBox", "members": [ { "kind": "field", - "name": "disabled", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "disabled", - "reflects": true - }, - { - "kind": "field", - "name": "value", + "name": "searchInput", "type": { - "text": "string | undefined" - }, - "attribute": "value" - }, - { - "kind": "method", - "name": "handleValueChange", - "privacy": "private" + "text": "GlSearchInput" + } }, { "kind": "field", - "name": "radioEls", - "type": { - "text": "Radio[]" - }, - "privacy": "private" - }, - { - "kind": "method", - "name": "updateRadioElements", - "privacy": "private", - "parameters": [ - { - "name": "updateParentGroup", - "default": "false" - } - ] - }, - { - "kind": "method", - "name": "setValue", - "return": { - "type": { - "text": "void" - } - }, - "parameters": [ - { - "name": "value", - "type": { - "text": "string" - } - } - ] - }, - { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } - } - ], - "attributes": [ - { - "name": "disabled", + "name": "aiAllowed", "type": { "text": "boolean" }, - "default": "false", - "fieldName": "disabled" + "default": "true", + "attribute": "aiAllowed" }, - { - "name": "value", - "type": { - "text": "string | undefined" - }, - "fieldName": "value" - } - ], - "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" - } - } - ], - "exports": [ - { - "kind": "js", - "name": "tagName", - "declaration": { - "name": "tagName", - "module": "src/webviews/apps/shared/components/radio/radio-group.ts" - } - }, - { - "kind": "js", - "name": "RadioGroup", - "declaration": { - "name": "RadioGroup", - "module": "src/webviews/apps/shared/components/radio/radio-group.ts" - } - }, - { - "kind": "custom-element-definition", - "declaration": { - "name": "RadioGroup", - "module": "src/webviews/apps/shared/components/radio/radio-group.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/radio/radio.css.ts", - "declarations": [ - { - "kind": "variable", - "name": "radioStyles", - "default": "css` :host { --checkbox-radius: 50%; --checkbox-foreground: var(--vscode-radio-inactiveForeground); --checkbox-background: var(--vscode-radio-inactiveBackground); --checkbox-border: var(--vscode-radio-inactiveBorder); --checkbox-checked-foreground: var(--vscode-radio-activeForeground); --checkbox-checked-background: var(--vscode-radio-activeBackground); --checkbox-checked-border: var(--vscode-radio-activeBorder); --checkbox-hover-background: var(--vscode-radio-inactiveHoverBackground); } `" - } - ], - "exports": [ - { - "kind": "js", - "name": "radioStyles", - "declaration": { - "name": "radioStyles", - "module": "src/webviews/apps/shared/components/radio/radio.css.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/radio/radio.ts", - "declarations": [ - { - "kind": "variable", - "name": "tagName", - "type": { - "text": "string" - }, - "default": "'gl-radio'" - }, - { - "kind": "class", - "description": "", - "name": "Radio", - "members": [ { "kind": "field", - "name": "shadowRootOptions", + "name": "errorMessage", "type": { - "text": "ShadowRootInit" + "text": "string" }, - "static": true, - "default": "{ ...GlElement.shadowRootOptions, delegatesFocus: true, }" + "default": "''", + "attribute": "errorMessage" }, { "kind": "field", - "name": "disabled", + "name": "filter", "type": { "text": "boolean" }, "default": "false", - "attribute": "disabled", - "reflects": true - }, - { - "kind": "field", - "name": "value", - "type": { - "text": "string | undefined" - }, - "attribute": "value" + "attribute": "filter" }, { "kind": "field", - "name": "name", + "name": "matchAll", "type": { - "text": "string | undefined" + "text": "boolean" }, - "attribute": "name", - "reflects": true + "default": "false", + "attribute": "matchAll" }, { "kind": "field", - "name": "checked", + "name": "matchCase", "type": { "text": "boolean" }, "default": "false", - "attribute": "checked", - "reflects": true + "attribute": "matchCase" }, { "kind": "field", - "name": "_parentGroup", + "name": "matchRegex", "type": { - "text": "RadioGroup | undefined" + "text": "boolean" }, - "privacy": "private", - "default": "undefined" + "default": "true", + "attribute": "matchRegex" }, { "kind": "field", - "name": "parentGroup", - "type": { - "text": "RadioGroup | undefined" - } - }, - { - "kind": "method", - "name": "handleClick", - "privacy": "private" - }, - { - "kind": "method", - "name": "renderCircle", - "privacy": "private" - }, - { - "kind": "method", - "name": "emit", - "return": { - "type": { - "text": "CustomEventType" - } - }, - "parameters": [ - { - "name": "name", - "type": { - "text": "T" - } - }, - { - "name": "detail", - "type": { - "text": "CustomEventDetailType" - } - }, - { - "name": "options", - "optional": true, - "type": { - "text": "Omit>, 'detail'>" - } - } - ], - "inheritedFrom": { - "name": "GlElement", - "module": "src/webviews/apps/shared/components/element.ts" - } - } - ], - "attributes": [ - { - "name": "disabled", + "name": "matchWholeWord", "type": { "text": "boolean" }, "default": "false", - "fieldName": "disabled" - }, - { - "name": "value", - "type": { - "text": "string | undefined" - }, - "fieldName": "value" - }, - { - "name": "name", - "type": { - "text": "string | undefined" - }, - "fieldName": "name" + "attribute": "matchWholeWord" }, { - "name": "checked", + "kind": "field", + "name": "more", "type": { "text": "boolean" }, "default": "false", - "fieldName": "checked" - } - ], - "superclass": { - "name": "GlElement", - "module": "/src/webviews/apps/shared/components/element" - } - } - ], - "exports": [ - { - "kind": "js", - "name": "tagName", - "declaration": { - "name": "tagName", - "module": "src/webviews/apps/shared/components/radio/radio.ts" - } - }, - { - "kind": "js", - "name": "Radio", - "declaration": { - "name": "Radio", - "module": "src/webviews/apps/shared/components/radio/radio.ts" - } - }, - { - "kind": "custom-element-definition", - "declaration": { - "name": "Radio", - "module": "src/webviews/apps/shared/components/radio/radio.ts" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/webviews/apps/shared/components/search/search-box.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "GlSearchBox", - "members": [ - { - "kind": "field", - "name": "errorMessage", - "type": { - "text": "string" - }, - "default": "''", - "attribute": "errorMessage" - }, - { - "kind": "field", - "name": "_value", - "type": { - "text": "string" - } - }, - { - "kind": "field", - "name": "value", - "attribute": "value" + "attribute": "more" }, { "kind": "field", - "name": "matchAll", + "name": "naturalLanguage", "type": { "text": "boolean" }, "default": "false", - "attribute": "matchAll" + "attribute": "naturalLanguage" }, { "kind": "field", - "name": "matchCase", + "name": "resultsHidden", "type": { "text": "boolean" }, "default": "false", - "attribute": "matchCase" + "attribute": "resultsHidden" }, { "kind": "field", - "name": "matchRegex", + "name": "resultsLabel", "type": { - "text": "boolean" + "text": "string" }, - "default": "true", - "attribute": "matchRegex" + "default": "'result'", + "attribute": "resultsLabel" }, { "kind": "field", - "name": "filter", + "name": "resultsLoaded", "type": { "text": "boolean" }, "default": "false", - "attribute": "filter" + "attribute": "resultsLoaded" }, { "kind": "field", - "name": "total", + "name": "searching", "type": { - "text": "number" + "text": "boolean" }, - "default": "0", - "attribute": "total" + "default": "false", + "attribute": "searching" }, { "kind": "field", @@ -30674,21 +36768,12 @@ }, { "kind": "field", - "name": "more", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "more" - }, - { - "kind": "field", - "name": "searching", + "name": "total", "type": { - "text": "boolean" + "text": "number" }, - "default": "false", - "attribute": "searching" + "default": "0", + "attribute": "total" }, { "kind": "field", @@ -30701,30 +36786,16 @@ }, { "kind": "field", - "name": "resultsHidden", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "resultsHidden" + "name": "value", + "attribute": "value" }, { "kind": "field", - "name": "resultsLabel", + "name": "_value", "type": { "text": "string" }, - "default": "'result'", - "attribute": "resultsLabel" - }, - { - "kind": "field", - "name": "resultsLoaded", - "type": { - "text": "boolean" - }, - "default": "false", - "attribute": "resultsLoaded" + "privacy": "private" }, { "kind": "field", @@ -30732,15 +36803,9 @@ "type": { "text": "boolean" }, + "privacy": "private", "readonly": true }, - { - "kind": "field", - "name": "searchInput", - "type": { - "text": "GlSearchInput" - } - }, { "kind": "field", "name": "_disposable", @@ -30912,6 +36977,14 @@ } ], "attributes": [ + { + "name": "aiAllowed", + "type": { + "text": "boolean" + }, + "default": "true", + "fieldName": "aiAllowed" + }, { "name": "errorMessage", "type": { @@ -30921,8 +36994,12 @@ "fieldName": "errorMessage" }, { - "name": "value", - "fieldName": "value" + "name": "filter", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "filter" }, { "name": "matchAll", @@ -30949,28 +37026,12 @@ "fieldName": "matchRegex" }, { - "name": "filter", + "name": "matchWholeWord", "type": { "text": "boolean" }, "default": "false", - "fieldName": "filter" - }, - { - "name": "total", - "type": { - "text": "number" - }, - "default": "0", - "fieldName": "total" - }, - { - "name": "step", - "type": { - "text": "number" - }, - "default": "0", - "fieldName": "step" + "fieldName": "matchWholeWord" }, { "name": "more", @@ -30978,23 +37039,15 @@ "text": "boolean" }, "default": "false", - "fieldName": "more" - }, - { - "name": "searching", - "type": { - "text": "boolean" - }, - "default": "false", - "fieldName": "searching" + "fieldName": "more" }, { - "name": "valid", + "name": "naturalLanguage", "type": { "text": "boolean" }, "default": "false", - "fieldName": "valid" + "fieldName": "naturalLanguage" }, { "name": "resultsHidden", @@ -31019,6 +37072,42 @@ }, "default": "false", "fieldName": "resultsLoaded" + }, + { + "name": "searching", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "searching" + }, + { + "name": "step", + "type": { + "text": "number" + }, + "default": "0", + "fieldName": "step" + }, + { + "name": "total", + "type": { + "text": "number" + }, + "default": "0", + "fieldName": "total" + }, + { + "name": "valid", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "valid" + }, + { + "name": "value", + "fieldName": "value" } ], "superclass": { @@ -31089,78 +37178,119 @@ }, { "kind": "field", - "name": "errorMessage", + "name": "aiAllowed", "type": { - "text": "string" + "text": "boolean" }, - "default": "''" + "default": "true", + "attribute": "aiAllowed" }, { "kind": "field", - "name": "helpType", + "name": "filter", "type": { - "text": "SearchOperatorsLongForm | undefined" - } + "text": "boolean" + }, + "default": "false", + "attribute": "filter" }, { "kind": "field", - "name": "label", - "privacy": "private", - "readonly": true + "name": "matchAll", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "matchAll" }, { "kind": "field", - "name": "placeholder", - "privacy": "private", - "readonly": true + "name": "matchCase", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "matchCase" }, { "kind": "field", - "name": "_value", + "name": "matchRegex", "type": { - "text": "string" - } + "text": "boolean" + }, + "default": "true", + "attribute": "matchRegex" }, { "kind": "field", - "name": "value", - "attribute": "value" + "name": "matchWholeWord", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "matchWholeWord" }, { "kind": "field", - "name": "filter", + "name": "naturalLanguage", "type": { "text": "boolean" }, "default": "false", - "attribute": "filter" + "attribute": "naturalLanguage" }, { "kind": "field", - "name": "matchAll", + "name": "searching", "type": { "text": "boolean" }, "default": "false", - "attribute": "matchAll" + "attribute": "searching" }, { "kind": "field", - "name": "matchCase", + "name": "value", + "attribute": "value" + }, + { + "kind": "field", + "name": "errorMessage", "type": { - "text": "boolean" + "text": "string" }, - "default": "false", - "attribute": "matchCase" + "privacy": "private", + "default": "''" }, { "kind": "field", - "name": "matchRegex", + "name": "helpType", "type": { - "text": "boolean" + "text": "SearchOperatorsLongForm | undefined" }, - "default": "true", - "attribute": "matchRegex" + "privacy": "private" + }, + { + "kind": "field", + "name": "processedQuery", + "type": { + "text": "string | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_value", + "type": { + "text": "string" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "label", + "privacy": "private", + "readonly": true }, { "kind": "field", @@ -31170,6 +37300,29 @@ }, "readonly": true }, + { + "kind": "field", + "name": "matchWholeWordOverride", + "type": { + "text": "boolean" + }, + "readonly": true + }, + { + "kind": "field", + "name": "placeholder", + "privacy": "private", + "readonly": true + }, + { + "kind": "field", + "name": "showNaturalLanguageHelpText", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "true" + }, { "kind": "method", "name": "focus", @@ -31299,7 +37452,33 @@ }, { "kind": "method", - "name": "handleFilter", + "name": "handleMatchWholeWord", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "handleFilterClick", + "privacy": "private", + "parameters": [ + { + "name": "_e", + "type": { + "text": "Event" + } + } + ] + }, + { + "kind": "method", + "name": "handleNaturalLanguageClick", "privacy": "private", "parameters": [ { @@ -31310,6 +37489,19 @@ } ] }, + { + "kind": "method", + "name": "updateNaturalLanguage", + "privacy": "private", + "parameters": [ + { + "name": "useNaturalLanguage", + "type": { + "text": "boolean" + } + } + ] + }, { "kind": "method", "name": "handleKeyup", @@ -31427,6 +37619,35 @@ } ] }, + { + "kind": "method", + "name": "renderHelpText", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderSpecificHelpText", + "privacy": "private", + "parameters": [ + { + "name": "type", + "optional": true, + "type": { + "text": "SearchOperatorsLongForm" + } + } + ] + }, + { + "kind": "method", + "name": "renderSearchByPopover", + "privacy": "private" + }, + { + "kind": "method", + "name": "renderSearchOptions", + "privacy": "private" + }, { "kind": "method", "name": "emit", @@ -31464,8 +37685,12 @@ ], "attributes": [ { - "name": "value", - "fieldName": "value" + "name": "aiAllowed", + "type": { + "text": "boolean" + }, + "default": "true", + "fieldName": "aiAllowed" }, { "name": "filter", @@ -31498,6 +37723,34 @@ }, "default": "true", "fieldName": "matchRegex" + }, + { + "name": "matchWholeWord", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "matchWholeWord" + }, + { + "name": "naturalLanguage", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "naturalLanguage" + }, + { + "name": "searching", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "searching" + }, + { + "name": "value", + "fieldName": "value" } ], "superclass": { @@ -31666,12 +37919,129 @@ "attribute": "guides", "reflects": true }, + { + "kind": "field", + "name": "ariaLabel", + "type": { + "text": "string" + }, + "default": "'Tree'", + "attribute": "aria-label" + }, + { + "kind": "field", + "name": "_lastSelectedPath", + "type": { + "text": "string | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_focusedItemPath", + "type": { + "text": "string | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_focusedItemIndex", + "type": { + "text": "number" + }, + "privacy": "private", + "default": "-1" + }, + { + "kind": "field", + "name": "virtualizerRef", + "type": { + "text": "Ref" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "scrollableRef", + "type": { + "text": "Ref" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_containerHasFocus", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "field", + "name": "_actionButtonHasFocus", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "field", + "name": "_scrolling", + "type": { + "text": "boolean" + }, + "privacy": "private", + "default": "false" + }, + { + "kind": "field", + "name": "_typeAheadBuffer", + "type": { + "text": "string" + }, + "privacy": "private", + "default": "''" + }, + { + "kind": "field", + "name": "_typeAheadTimer", + "type": { + "text": "number | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "_typeAheadTimeout", + "type": { + "text": "number" + }, + "privacy": "private", + "readonly": true, + "default": "800" + }, + { + "kind": "field", + "name": "_nodeMap", + "privacy": "private", + "default": "new Map()" + }, + { + "kind": "field", + "name": "_pathToIndexMap", + "privacy": "private", + "default": "new Map()" + }, { "kind": "field", "name": "_model", "type": { "text": "TreeModel[] | undefined" - } + }, + "privacy": "private" }, { "kind": "field", @@ -31732,14 +38102,57 @@ }, { "kind": "method", - "name": "renderTree", + "name": "findTreeNode", "privacy": "private", + "return": { + "type": { + "text": "TreeModel | undefined" + } + }, "parameters": [ { - "name": "nodes", - "optional": true, + "name": "path", + "type": { + "text": "string" + } + } + ], + "description": "Find a tree node by path using O(1) map lookup" + }, + { + "kind": "method", + "name": "getItemIndex", + "privacy": "private", + "return": { + "type": { + "text": "number" + } + }, + "parameters": [ + { + "name": "path", + "type": { + "text": "string" + } + } + ], + "description": "Get the index of an item by path using O(1) map lookup" + }, + { + "kind": "method", + "name": "rebuildFlattenedTree", + "privacy": "private", + "description": "Rebuild the flattened tree from the hierarchical model\nThis is called when the tree structure changes (expand/collapse)" + }, + { + "kind": "method", + "name": "onBeforeTreeItemSelected", + "privacy": "private", + "parameters": [ + { + "name": "model", "type": { - "text": "TreeModelFlat[]" + "text": "TreeModelFlat" } } ] @@ -31804,34 +38217,181 @@ "type": { "text": "TreeItemAction" } + }, + { + "name": "dblClick", + "default": "false" + } + ] + }, + { + "kind": "field", + "name": "handleContainerFocus", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleContainerBlur", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleFocusIn", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleFocusOut", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleContextMenu", + "privacy": "private" + }, + { + "kind": "field", + "name": "handleKeydown", + "privacy": "private" + }, + { + "kind": "method", + "name": "getCurrentFocusedIndex", + "privacy": "private", + "return": { + "type": { + "text": "number" + } + } + }, + { + "kind": "field", + "name": "handleContainerKeydown", + "privacy": "private" + }, + { + "kind": "method", + "name": "handleItemActivation", + "privacy": "private", + "parameters": [ + { + "name": "item", + "type": { + "text": "TreeModelFlat" + } } ] }, { "kind": "method", - "name": "onTreeItemActionDblClicked", + "name": "handleBranchToggle", "privacy": "private", + "return": { + "type": { + "text": "boolean" + } + }, "parameters": [ { "name": "e", "type": { - "text": "MouseEvent" + "text": "KeyboardEvent" } }, { - "name": "model", + "name": "item", "type": { "text": "TreeModelFlat" } - }, + } + ] + }, + { + "kind": "method", + "name": "focusItemAtIndex", + "privacy": "private", + "parameters": [ { - "name": "action", + "name": "index", "type": { - "text": "TreeItemAction" + "text": "number" + } + } + ] + }, + { + "kind": "method", + "name": "scrollToItem", + "privacy": "private", + "parameters": [ + { + "name": "index", + "type": { + "text": "number" } } ] }, + { + "kind": "method", + "name": "handleTypeAhead", + "privacy": "private", + "parameters": [ + { + "name": "char", + "type": { + "text": "string" + }, + "description": "The character to add to the search buffer" + } + ], + "description": "Handles type-ahead search functionality" + }, + { + "kind": "method", + "name": "buildPathToIndexMap", + "privacy": "private" + }, + { + "kind": "method", + "name": "findNextMatchingItem", + "privacy": "private", + "return": { + "type": { + "text": "" + } + }, + "parameters": [ + { + "name": "searchText", + "type": { + "text": "string" + }, + "description": "The text to search for" + } + ], + "description": "Finds the next tree item that matches the search buffer" + }, + { + "kind": "method", + "name": "isPrintableCharacter", + "privacy": "private", + "return": { + "type": { + "text": "" + } + }, + "parameters": [ + { + "name": "char", + "type": { + "text": "string" + }, + "description": "The character to check" + } + ], + "description": "Checks if a character is printable (for type-ahead search)" + }, { "kind": "method", "name": "emit", @@ -31874,6 +38434,14 @@ "text": "'none' | 'onHover' | 'always' | undefined" }, "fieldName": "guides" + }, + { + "name": "aria-label", + "type": { + "text": "string" + }, + "default": "'Tree'", + "fieldName": "ariaLabel" } ], "superclass": { @@ -32018,6 +38586,23 @@ "default": "true", "attribute": "showIcon" }, + { + "kind": "field", + "name": "tabIndex", + "type": { + "text": "number" + }, + "default": "-1", + "attribute": "tabIndex" + }, + { + "kind": "field", + "name": "vscodeContext", + "type": { + "text": "string | undefined" + }, + "attribute": "vscode-context" + }, { "kind": "field", "name": "selected", @@ -32032,7 +38617,19 @@ "type": { "text": "boolean" }, - "default": "false" + "default": "false", + "attribute": "focused", + "reflects": true + }, + { + "kind": "field", + "name": "focusedInactive", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "focused-inactive", + "reflects": true }, { "kind": "field", @@ -32163,6 +38760,19 @@ } ] }, + { + "kind": "method", + "name": "onButtonContextMenu", + "privacy": "private", + "parameters": [ + { + "name": "e", + "type": { + "text": "MouseEvent" + } + } + ] + }, { "kind": "method", "name": "onCheckboxClick", @@ -32318,6 +38928,37 @@ }, "default": "true", "fieldName": "showIcon" + }, + { + "name": "tabIndex", + "type": { + "text": "number" + }, + "default": "-1", + "fieldName": "tabIndex" + }, + { + "name": "vscode-context", + "type": { + "text": "string | undefined" + }, + "fieldName": "vscodeContext" + }, + { + "name": "focused", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "focused" + }, + { + "name": "focused-inactive", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "focusedInactive" } ], "superclass": { @@ -32357,7 +38998,7 @@ "type": { "text": "array" }, - "default": "[elementBase, css``]" + "default": "[ elementBase, css` :host { display: block; height: 100%; } `, ]" }, { "kind": "variable", @@ -32365,7 +39006,7 @@ "type": { "text": "array" }, - "default": "[ elementBase, css` :host { --tree-connector-spacing: 0.6rem; --tree-connector-size: var(--gitlens-tree-indent, 1.6rem); box-sizing: border-box; padding-left: var(--gitlens-gutter-width); /* padding-right: var(--gitlens-scrollbar-gutter-width); */ padding-right: 0.5rem; padding-top: 0.1rem; padding-bottom: 0.1rem; line-height: 2.2rem; height: 2.2rem; display: flex; flex-direction: row; align-items: center; justify-content: space-between; font-size: var(--vscode-font-size); color: var(--gitlens-tree-foreground, var(--vscode-foreground)); content-visibility: auto; contain-intrinsic-size: auto 2.2rem; cursor: pointer; } :host(:hover), :host(:focus-within) { content-visibility: visible; } :host([aria-hidden='true']) { display: none; } :host(:hover) { color: var(--vscode-list-hoverForeground); background-color: var(--vscode-list-hoverBackground); } :host([aria-selected='true']) { color: var(--vscode-list-inactiveSelectionForeground); background-color: var(--vscode-list-inactiveSelectionBackground); } /* TODO: these should be :has(.input:focus) instead of :focus-within */ :host(:focus-within) { outline: 1px solid var(--vscode-list-focusOutline); outline-offset: -0.1rem; } :host([aria-selected='true']:focus-within) { color: var(--vscode-list-activeSelectionForeground); background-color: var(--vscode-list-activeSelectionBackground); } .item { appearance: none; display: flex; flex-direction: row; justify-content: flex-start; align-items: center; gap: 0.6rem; width: 100%; padding: 0; font-family: inherit; font-size: inherit; text-decoration: none; color: inherit; background: none; border: none; outline: none; cursor: pointer; min-width: 0; } /* FIXME: remove, this is for debugging .item:focus { outline: 1px solid var(--vscode-list-focusOutline); outline-offset: -0.1rem; } */ .icon { display: inline-block; width: 1.6rem; text-align: center; height: 2.2rem; line-height: 2.2rem; pointer-events: none; vertical-align: text-bottom; } slot[name='icon']::slotted(*) { width: 1.6rem; aspect-ratio: 1; vertical-align: text-bottom; } .node { display: inline-block; width: var(--tree-connector-size); text-align: center; flex: none; height: 2.2rem; line-height: 2.2rem; pointer-events: none; vertical-align: text-bottom; } .node:last-of-type { margin-right: 0.3rem; } .node--connector { position: relative; } .node--connector::before { content: ''; position: absolute; height: 2.2rem; border-left: 1px solid transparent; top: 50%; transform: translate(-1px, -50%); left: 0.8rem; width: 0.1rem; transition: border-color 0.1s linear; opacity: 0.4; } :host-context([guides='always']) .node--connector::before, :host-context([guides='onHover']:focus-within) .node--connector::before, :host-context([guides='onHover']:hover) .node--connector::before { border-color: var(--vscode-tree-indentGuidesStroke); } .branch { display: inline-block; margin-right: 0.6rem; height: 2.2rem; line-height: 2.2rem; vertical-align: text-bottom; } .text { line-height: 1.6rem; overflow: hidden; white-space: nowrap; text-align: left; text-overflow: ellipsis; flex: 1; } .main { display: inline; } .description { display: inline; opacity: 0.7; font-size: 0.9em; margin-left: 0.3rem; pointer-events: none; } .actions { flex: none; user-select: none; color: var(--vscode-icon-foreground); } :host(:focus-within) .actions { color: var(--vscode-list-activeSelectionIconForeground); } :host(:not(:hover):not(:focus-within)) .actions { display: none; } .checkbox { position: relative; display: inline-flex; width: 1.6rem; aspect-ratio: 1 / 1; text-align: center; color: var(--vscode-checkbox-foreground); background: var(--vscode-checkbox-background); border: 1px solid var(--vscode-checkbox-border); border-radius: 0.3rem; // overflow: hidden; margin-right: 0.6rem; } .checkbox:has(:checked) { color: var(--vscode-inputOption-activeForeground); border-color: var(--vscode-inputOption-activeBorder); background-color: var(--vscode-inputOption-activeBackground); } .checkbox:has(:disabled) { opacity: 0.4; } .checkbox__input { position: absolute; top: 0; left: 0; appearance: none; width: 1.4rem; aspect-ratio: 1 / 1; margin: 0; cursor: pointer; border-radius: 0.3rem; } .checkbox__input:disabled { cursor: default; } .checkbox__check { width: 1.6rem; aspect-ratio: 1 / 1; opacity: 0; transition: opacity 0.1s linear; color: var(--vscode-checkbox-foreground); pointer-events: none; } .checkbox__input:checked + .checkbox__check { opacity: 1; } slot[name='decorations'] { display: inline-block; margin-left: 0.4rem; } `, ]" + "default": "[ elementBase, css` :host { --tree-connector-spacing: 0.6rem; --tree-connector-size: var(--gitlens-tree-indent, 1.6rem); box-sizing: border-box; padding-left: var(--gitlens-gutter-width); padding-right: 0.5rem; padding-top: 0.1rem; padding-bottom: 0.1rem; line-height: 2.2rem; height: 2.2rem; display: flex; flex-direction: row; align-items: center; justify-content: space-between; font-size: var(--vscode-font-size); color: var(--gitlens-tree-foreground, var(--vscode-foreground)); cursor: pointer; /* Reduced containment to allow tooltips to escape */ contain: layout; } :host([aria-hidden='true']) { display: none; } :host(:hover) { color: var(--vscode-list-hoverForeground); background-color: var(--vscode-list-hoverBackground); } :host([aria-selected='true']) { color: var(--vscode-list-inactiveSelectionForeground); background-color: var(--vscode-list-inactiveSelectionBackground); } /* Focused state - when the item is the active descendant in the tree */ :host([focused]) { outline: 1px solid var(--vscode-list-focusOutline); outline-offset: -0.1rem; } :host([aria-selected='true'][focused]) { color: var(--vscode-list-activeSelectionForeground); background-color: var(--vscode-list-activeSelectionBackground); } /* Inactive focus state - when the item would be focused but container doesn't have focus */ /* In VS Code, inactive focus shows the selection background without the outline */ :host([focused-inactive]) { color: var(--vscode-list-inactiveSelectionForeground); background-color: var(--vscode-list-inactiveSelectionBackground); } /* TODO: these should be :has(.input:focus) instead of :focus-within */ :host(:focus-within) { outline: 1px solid var(--vscode-list-focusOutline); outline-offset: -0.1rem; } :host([aria-selected='true']:focus-within) { color: var(--vscode-list-activeSelectionForeground); background-color: var(--vscode-list-activeSelectionBackground); } .item { appearance: none; display: flex; flex-direction: row; justify-content: flex-start; align-items: center; gap: 0.6rem; width: 100%; padding: 0; font-family: inherit; font-size: inherit; text-decoration: none; color: inherit; background: none; border: none; outline: none; cursor: pointer; min-width: 0; } .icon { display: inline-block; width: 1.6rem; text-align: center; height: 2.2rem; line-height: 2.2rem; pointer-events: none; vertical-align: text-bottom; } slot[name='icon']::slotted(*) { width: 1.6rem; aspect-ratio: 1; vertical-align: text-bottom; } .node { display: inline-block; width: var(--tree-connector-size); text-align: center; flex: none; height: 2.2rem; line-height: 2.2rem; pointer-events: none; vertical-align: text-bottom; } .node:last-of-type { margin-right: 0.3rem; } .node--connector { position: relative; } .node--connector::before { content: ''; position: absolute; height: 2.2rem; border-left: 1px solid transparent; top: 50%; transform: translate(-1px, -50%); left: 0.8rem; width: 0.1rem; transition: border-color 0.1s linear; opacity: 0.4; } @media (prefers-reduced-motion: reduce) { .node--connector::before { transition: none; } } :host-context([guides='always']) .node--connector::before, :host-context([guides='onHover']:focus-within) .node--connector::before, :host-context([guides='onHover'][focused]) .node--connector::before, :host-context([guides='onHover'][focused-inactive]) .node--connector::before, :host-context([guides='onHover']:hover) .node--connector::before { border-color: var(--vscode-tree-indentGuidesStroke); } .branch { display: inline-block; margin-right: 0.6rem; height: 2.2rem; line-height: 2.2rem; vertical-align: text-bottom; } .text { line-height: 1.8rem; overflow: hidden; white-space: nowrap; text-align: left; text-overflow: ellipsis; flex: 1; } .main { display: inline; } .description { display: inline; opacity: 0.7; font-size: 0.9em; margin-left: 0.3rem; pointer-events: none; } .actions { flex: none; user-select: none; color: var(--vscode-icon-foreground); } :host(:focus-within) .actions, :host([focused]) .actions { color: var(--vscode-list-activeSelectionIconForeground); } :host([focused-inactive]) .actions { color: var(--vscode-list-inactiveSelectionIconForeground, var(--vscode-icon-foreground)); } :host(:not(:hover):not(:focus-within):not([focused]):not([focused-inactive])) .actions { display: none; } .checkbox { position: relative; display: inline-flex; width: 1.6rem; aspect-ratio: 1 / 1; text-align: center; color: var(--vscode-checkbox-foreground); background: var(--vscode-checkbox-background); border: 1px solid var(--vscode-checkbox-border); border-radius: 0.3rem; margin-right: 0.6rem; } .checkbox:has(:checked) { color: var(--vscode-inputOption-activeForeground); border-color: var(--vscode-inputOption-activeBorder); background-color: var(--vscode-inputOption-activeBackground); } .checkbox:has(:disabled) { opacity: 0.4; } .checkbox__input { position: absolute; top: 0; left: 0; appearance: none; width: 1.4rem; aspect-ratio: 1 / 1; margin: 0; cursor: pointer; border-radius: 0.3rem; } .checkbox__input:disabled { cursor: default; } .checkbox__check { width: 1.6rem; aspect-ratio: 1 / 1; opacity: 0; transition: opacity 0.1s linear; color: var(--vscode-checkbox-foreground); pointer-events: none; } .checkbox__input:checked + .checkbox__check { opacity: 1; } slot[name='decorations'] { display: inline-block; margin-left: 0.4rem; } /* High Contrast Mode Support */ @media (forced-colors: active) { :host { forced-color-adjust: none; } :host([focused]) { outline: 2px solid CanvasText; outline-offset: -2px; } :host([aria-selected='true']) { background-color: Highlight; color: HighlightText; } :host([aria-selected='true'][focused]) { outline: 2px solid CanvasText; outline-offset: -2px; } .checkbox { border: 1px solid CanvasText; } .checkbox:has(:checked) { background-color: Highlight; border-color: CanvasText; } .node--connector::before { border-color: CanvasText; opacity: 1; } } `, ]" } ], "exports": [ @@ -32510,6 +39151,409 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/composer/components/diff/diff-file.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlDiffFile", + "members": [ + { + "kind": "field", + "name": "filename", + "type": { + "text": "string | undefined" + }, + "attribute": "filename" + }, + { + "kind": "field", + "name": "hunks", + "type": { + "text": "ComposerHunk[] | undefined" + }, + "attribute": "hunks" + }, + { + "kind": "field", + "name": "sideBySide", + "type": { + "text": "boolean" + }, + "default": "false", + "attribute": "side-by-side" + }, + { + "kind": "field", + "name": "defaultExpanded", + "type": { + "text": "boolean" + }, + "default": "true", + "attribute": "default-expanded" + }, + { + "kind": "field", + "name": "targetElement", + "type": { + "text": "HTMLDivElement" + } + }, + { + "kind": "field", + "name": "diffText", + "type": { + "text": "string | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "parsedDiff", + "type": { + "text": "DiffFile[] | undefined" + }, + "privacy": "private" + }, + { + "kind": "field", + "name": "diffFile", + "type": { + "text": "DiffFile | undefined" + }, + "readonly": true + }, + { + "kind": "field", + "name": "diff2htmlUi", + "type": { + "text": "Diff2HtmlUI | undefined" + }, + "privacy": "private" + }, + { + "kind": "method", + "name": "renderDiff", + "privacy": "private" + }, + { + "kind": "method", + "name": "processDiff", + "privacy": "private" + } + ], + "attributes": [ + { + "name": "filename", + "type": { + "text": "string | undefined" + }, + "fieldName": "filename" + }, + { + "name": "hunks", + "type": { + "text": "ComposerHunk[] | undefined" + }, + "fieldName": "hunks" + }, + { + "name": "side-by-side", + "type": { + "text": "boolean" + }, + "default": "false", + "fieldName": "sideBySide" + }, + { + "name": "default-expanded", + "type": { + "text": "boolean" + }, + "default": "true", + "fieldName": "defaultExpanded" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-diff-file", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlDiffFile", + "declaration": { + "name": "GlDiffFile", + "module": "src/webviews/apps/plus/composer/components/diff/diff-file.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-diff-file", + "declaration": { + "name": "GlDiffFile", + "module": "src/webviews/apps/plus/composer/components/diff/diff-file.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/composer/components/diff/diff-templates.compiled.ts", + "declarations": [ + { + "kind": "variable", + "name": "compiledComposerTemplates", + "type": { + "text": "CompiledTemplates" + }, + "default": "{ \"generic-block-header\": new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
\");if(t.s(t.f(\"blockHeader\",c,p,1),c,p,0,156,173,\"{{ }}\")){t.rs(c,p,function(c,p,t){t.b(t.t(t.f(\"blockHeader\",c,p,0)));});c.pop();}if(!t.s(t.f(\"blockHeader\",c,p,1),c,p,1,0,0,\"\")){t.b(\" \");};t.b(\"
\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"\");return t.fl(); },partials: {}, subs: { }}), \"line-by-line-file-diff\": new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"
\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(t.t(t.f(\"filePath\",c,p,0)));t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(t.t(t.f(\"diffs\",c,p,0)));t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");return t.fl(); },partials: {}, subs: { }}), \"side-by-side-file-diff\": new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"
\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(t.t(t.f(\"filePath\",c,p,0)));t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(t.t(t.d(\"diffs.left\",c,p,0)));t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\" \");t.b(t.t(t.d(\"diffs.right\",c,p,0)));t.b(\"\\n\" + i);t.b(\" \");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");t.b(\"\\n\" + i);t.b(\"
\");return t.fl(); },partials: {}, subs: { }}), \"generic-file-path\": new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||\"\");t.b(\"\");t.b(\"\\n\" + i);t.b(\" \");t.b(t.v(t.f(\"fileDiffName\",c,p,0)));t.b(\"\");t.b(\"\\n\" + i);t.b(t.rp(\"\");t.b(\"\\n\" + i);t.b(\"\");return t.fl(); },partials: {\"
{{#blockHeader}}{{{blockHeader}}}{{/blockHeader}}{{^blockHeader}} {{/blockHeader}}
`" + }, + { + "kind": "variable", + "name": "lineByLineFileTemplate", + "default": "`
{{{filePath}}}
{{{diffs}}}
`" + }, + { + "kind": "variable", + "name": "sideBySideFileTemplate", + "default": "`
{{{filePath}}}
{{{diffs.left}}}
{{{diffs.right}}}
`" + }, + { + "kind": "variable", + "name": "genericFilePathTemplate", + "default": "` {{fileDiffName}} {{>fileTag}} `" + } + ], + "exports": [ + { + "kind": "js", + "name": "blockHeaderTemplate", + "declaration": { + "name": "blockHeaderTemplate", + "module": "src/webviews/apps/plus/composer/components/diff/diff-templates.ts" + } + }, + { + "kind": "js", + "name": "lineByLineFileTemplate", + "declaration": { + "name": "lineByLineFileTemplate", + "module": "src/webviews/apps/plus/composer/components/diff/diff-templates.ts" + } + }, + { + "kind": "js", + "name": "sideBySideFileTemplate", + "declaration": { + "name": "sideBySideFileTemplate", + "module": "src/webviews/apps/plus/composer/components/diff/diff-templates.ts" + } + }, + { + "kind": "js", + "name": "genericFilePathTemplate", + "declaration": { + "name": "genericFilePathTemplate", + "module": "src/webviews/apps/plus/composer/components/diff/diff-templates.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/composer/components/diff/diff.css.ts", + "declarations": [ + { + "kind": "variable", + "name": "hljsStyles", + "default": "css` .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hljs-comment, .hljs-quote { color: #998; font-style: italic; } .hljs-keyword, .hljs-selector-tag, .hljs-subst { color: #333; font-weight: 700; } .hljs-literal, .hljs-number, .hljs-tag .hljs-attr, .hljs-template-variable, .hljs-variable { color: teal; } .hljs-doctag, .hljs-string { color: #d14; } .hljs-section, .hljs-selector-id, .hljs-title { color: #900; font-weight: 700; } .hljs-subst { font-weight: 400; } .hljs-class .hljs-title, .hljs-type { color: #458; font-weight: 700; } .hljs-attribute, .hljs-name, .hljs-tag { color: navy; font-weight: 400; } .hljs-link, .hljs-regexp { color: #009926; } .hljs-bullet, .hljs-symbol { color: #990073; } .hljs-built_in, .hljs-builtin-name { color: #0086b3; } .hljs-meta { color: #999; font-weight: 700; } .hljs-deletion { background: #fdd; } .hljs-addition { background: #dfd; } .hljs-emphasis { font-style: italic; } .hljs-strong { font-weight: 700; } `" + }, + { + "kind": "variable", + "name": "diff2htmlStyles", + "default": "css` :host { --d2h-intrinsic-base-height: 3.5rem; --d2h-intrinsic-line-count: 50; --d2h-intrinsic-line-height: 1.8rem; --d2h-intrinsic-height: calc( var(--d2h-intrinsic-base-height) + (var(--d2h-intrinsic-line-height) * var(--d2h-intrinsic-line-count)) ); display: block; position: relative; } .d2h-file-wrapper { content-visibility: auto; contain-intrinsic-size: auto var(--d2h-intrinsic-base-height); } .d2h-file-wrapper[open] { contain-intrinsic-height: var(--d2h-intrinsic-height); } .d2h-wrapper { color: var(--d2h-color); text-align: left; } .d2h-file-header { background-color: var(--d2h-file-header-bg-color); border-bottom: 1px solid var(--d2h-file-header-border-color); display: flex; font-family: var(--vscode-font-family); height: 35px; padding: 4px 5px; } .d2h-file-header.d2h-sticky-header { position: sticky; top: 0; z-index: 1; } .d2h-file-stats { display: flex; font-size: 14px; margin-left: auto; } .d2h-lines-added { border: 1px solid var(--d2h-ins-border-color); border-radius: 5px 0 0 5px; color: var(--d2h-ins-label-color); padding: 2px; text-align: right; vertical-align: middle; } .d2h-lines-deleted { border: 1px solid var(--d2h-del-border-color); border-radius: 0 5px 5px 0; color: var(--d2h-del-label-color); margin-left: 1px; padding: 2px; text-align: left; vertical-align: middle; } .d2h-file-name-wrapper { display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; font-size: 1.4rem; width: 100%; } .d2h-file-name { overflow-x: hidden; text-overflow: ellipsis; white-space: nowrap; } .d2h-file-wrapper { border: 1px solid var(--d2h-border-color); border-radius: 3px; margin-bottom: 1em; } .d2h-file-collapse { -webkit-box-pack: end; -ms-flex-pack: end; cursor: pointer; display: none; font-size: 12px; justify-content: flex-end; -webkit-box-align: center; -ms-flex-align: center; align-items: center; border: 1px solid var(--d2h-border-color); border-radius: 3px; padding: 4px 8px; } .d2h-file-collapse.d2h-selected { background-color: var(--d2h-selected-color); } .d2h-file-collapse-input { margin: 0 4px 0 0; } .d2h-diff-table { border-collapse: collapse; font-family: var(--vscode-editor-font-family); font-size: var(--editor-font-size); width: 100%; } .d2h-files-diff { display: flex; width: 100%; } .d2h-file-diff { overflow-y: hidden; } .d2h-file-diff.d2h-d-none, .d2h-files-diff.d2h-d-none { display: none; } .d2h-file-side-diff { display: inline-block; overflow-x: scroll; overflow-y: hidden; width: 50%; } .d2h-code-line { padding: 0 8em; /* width: calc(100% - 16em); */ width: 100%; } .d2h-code-line, .d2h-code-side-line { display: inline-block; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; white-space: nowrap; } .d2h-code-side-line { padding: 0 4.5em; width: calc(100% - 9em); } .d2h-code-line-ctn { background: none; display: inline-block; padding: 0; word-wrap: normal; -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; vertical-align: middle; white-space: pre; width: 100%; } .d2h-code-line del, .d2h-code-side-line del { background-color: var(--d2h-del-highlight-bg-color); } .d2h-code-line del, .d2h-code-line ins, .d2h-code-side-line del, .d2h-code-side-line ins { border-radius: 0.2em; display: inline-block; margin-top: -1px; -webkit-text-decoration: none; text-decoration: none; } .d2h-code-line ins, .d2h-code-side-line ins { background-color: var(--d2h-ins-highlight-bg-color); text-align: left; } .d2h-code-line-prefix { background: none; display: inline; padding: 0; word-wrap: normal; white-space: pre; } .line-num1 { float: left; } .line-num1, .line-num2 { -webkit-box-sizing: border-box; box-sizing: border-box; overflow: hidden; padding: 0 0.5em; text-overflow: ellipsis; width: 3.5em; } .line-num2 { float: right; } .d2h-code-linenumber { background-color: var(--d2h-bg-color); border-style: solid; border-color: transparent var(--d2h-line-border-color); border-width: 1px; -webkit-box-sizing: border-box; box-sizing: border-box; color: var(--d2h-dim-color); cursor: pointer; display: inline-block; position: absolute; text-align: right; width: 7.5em; } .d2h-code-linenumber:after { content: '\\\\200b'; } .d2h-code-linenumber.d2h-ins { border-color: transparent var(--d2h-ins-border-color); } .d2h-code-linenumber.d2h-del { border-color: transparent var(--d2h-del-border-color); } .d2h-code-side-linenumber { background-color: var(--d2h-bg-color); border: solid var(--d2h-line-border-color); border-width: 0 1px; -webkit-box-sizing: border-box; box-sizing: border-box; color: var(--d2h-dim-color); cursor: pointer; display: inline-block; overflow: hidden; padding: 0 0.5em; position: absolute; text-align: right; text-overflow: ellipsis; width: 4em; } .d2h-code-side-linenumber:after { content: '\\\\200b'; } .d2h-code-side-emptyplaceholder, .d2h-emptyplaceholder { background-color: var(--d2h-empty-placeholder-bg-color); border-color: var(--d2h-empty-placeholder-border-color); } .d2h-code-line-prefix, .d2h-code-linenumber, .d2h-code-side-linenumber, .d2h-emptyplaceholder { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .d2h-code-linenumber, .d2h-code-side-linenumber { direction: rtl; } .d2h-del { background-color: var(--d2h-del-bg-color); border-color: var(--d2h-del-border-color); } .d2h-ins { background-color: var(--d2h-ins-bg-color); border-color: var(--d2h-ins-border-color); } .d2h-info { background-color: var(--d2h-info-bg-color); border-color: var(--d2h-info-border-color); color: var(--d2h-dim-color); } .d2h-file-diff .d2h-del.d2h-change { background-color: var(--d2h-change-del-color); } .d2h-file-diff .d2h-ins.d2h-change { background-color: var(--d2h-change-ins-color); } .d2h-file-list-wrapper { margin-bottom: 10px; } .d2h-file-list-wrapper a { -webkit-text-decoration: none; text-decoration: none; } .d2h-file-list-wrapper a, .d2h-file-list-wrapper a:visited { color: var(--d2h-moved-label-color); } .d2h-file-list-header { text-align: left; } .d2h-file-list-title { font-weight: 700; } .d2h-file-list-line { display: flex; text-align: left; } .d2h-file-list { display: block; list-style: none; margin: 0; padding: 0; } .d2h-file-list > li { border-bottom: 1px solid var(--d2h-border-color); margin: 0; padding: 5px 10px; } .d2h-file-list > li:last-child { border-bottom: none; } .d2h-file-switch { cursor: pointer; display: none; font-size: 10px; } .d2h-icon { margin-right: 10px; vertical-align: middle; fill: currentColor; } .d2h-deleted { color: var(--d2h-del-label-color); } .d2h-added { color: var(--d2h-ins-label-color); } .d2h-changed { color: var(--d2h-change-label-color); } .d2h-moved { color: var(--d2h-moved-label-color); } .d2h-tag { background-color: var(--d2h-bg-color); display: flex; font-size: 10px; margin-left: 6px; padding: 0px 3px; border-radius: 2px; } .d2h-deleted-tag { border: 1px solid var(--d2h-del-label-color); } .d2h-added-tag { border: 1px solid var(--d2h-ins-label-color); } .d2h-changed-tag { border: 1px solid var(--d2h-change-label-color); } .d2h-moved-tag { border: 1px solid var(--d2h-moved-label-color); } :host-context(.vscode-high-contrast) .d2h-ins .d2h-code-line { border: 1px dashed var(--d2h-ins-border-color); line-height: calc(var(--d2h-intrinsic-line-height) - 0.2rem); } :host-context(.vscode-high-contrast) .d2h-del .d2h-code-line { border: 1px dashed var(--d2h-del-border-color); line-height: calc(var(--d2h-intrinsic-line-height) - 0.2rem); } `" + }, + { + "kind": "variable", + "name": "diffStyles", + "default": "css` td { padding-block: 0; line-height: var(--d2h-intrinsic-line-height); } .d2h-file-wrapper { margin-block-end: 0; } tr:has(.d2h-code-linenumber) { position: relative; } .d2h-file-header { align-items: center; gap: 0.4rem; cursor: pointer; } .d2h-file-wrapper:not([open]) .d2h-file-header, .d2h-file-header:has(.d2h-file-collapse.d2h-selected) { border-bottom-color: transparent; } .d2h-code-linenumber { background-color: color-mix(in srgb, var(--d2h-bg-color) 100%, transparent 12%) !important; } .d2h-file-wrapper:not([open]) .file-icon--open, .d2h-file-wrapper[open] .file-icon--closed { display: none; } `" + } + ], + "exports": [ + { + "kind": "js", + "name": "hljsStyles", + "declaration": { + "name": "hljsStyles", + "module": "src/webviews/apps/plus/composer/components/diff/diff.css.ts" + } + }, + { + "kind": "js", + "name": "diff2htmlStyles", + "declaration": { + "name": "diff2htmlStyles", + "module": "src/webviews/apps/plus/composer/components/diff/diff.css.ts" + } + }, + { + "kind": "js", + "name": "diffStyles", + "declaration": { + "name": "diffStyles", + "module": "src/webviews/apps/plus/composer/components/diff/diff.css.ts" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/webviews/apps/plus/composer/components/diff/diff.ts", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "GlDiffHunk", + "members": [ + { + "kind": "field", + "name": "diffHeader", + "type": { + "text": "string" + }, + "default": "''", + "attribute": "diff-header" + }, + { + "kind": "field", + "name": "hunkHeader", + "type": { + "text": "string" + }, + "default": "''", + "attribute": "hunk-header" + }, + { + "kind": "field", + "name": "hunkContent", + "type": { + "text": "string" + }, + "default": "''", + "attribute": "hunk-content" + }, + { + "kind": "field", + "name": "targetElement", + "type": { + "text": "HTMLDivElement" + } + }, + { + "kind": "field", + "name": "isDarkMode", + "readonly": true + }, + { + "kind": "field", + "name": "rawTemplates", + "readonly": true + }, + { + "kind": "field", + "name": "diff2htmlUi", + "type": { + "text": "Diff2HtmlUI | undefined" + }, + "privacy": "private" + }, + { + "kind": "method", + "name": "renderDiff", + "privacy": "private" + } + ], + "attributes": [ + { + "name": "diff-header", + "type": { + "text": "string" + }, + "default": "''", + "fieldName": "diffHeader" + }, + { + "name": "hunk-header", + "type": { + "text": "string" + }, + "default": "''", + "fieldName": "hunkHeader" + }, + { + "name": "hunk-content", + "type": { + "text": "string" + }, + "default": "''", + "fieldName": "hunkContent" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "gl-diff-hunk", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "GlDiffHunk", + "declaration": { + "name": "GlDiffHunk", + "module": "src/webviews/apps/plus/composer/components/diff/diff.ts" + } + }, + { + "kind": "custom-element-definition", + "name": "gl-diff-hunk", + "declaration": { + "name": "GlDiffHunk", + "module": "src/webviews/apps/plus/composer/components/diff/diff.ts" + } + } + ] + }, { "kind": "javascript-module", "path": "src/webviews/apps/shared/components/styles/lit/a11y.css.ts", @@ -32592,6 +39636,11 @@ "name": "elementBase", "default": "css` :host { box-sizing: border-box; } :host *, :host *::before, :host *::after { box-sizing: inherit; } [hidden] { display: none !important; } `" }, + { + "kind": "variable", + "name": "boxSizingBase", + "default": "css` * { box-sizing: border-box; } `" + }, { "kind": "variable", "name": "linkBase", @@ -32617,6 +39666,14 @@ "module": "src/webviews/apps/shared/components/styles/lit/base.css.ts" } }, + { + "kind": "js", + "name": "boxSizingBase", + "declaration": { + "name": "boxSizingBase", + "module": "src/webviews/apps/shared/components/styles/lit/base.css.ts" + } + }, { "kind": "js", "name": "linkBase", diff --git a/docs/telemetry-events.md b/docs/telemetry-events.md index 01c2d66ca83a9..390c3575c10e0 100644 --- a/docs/telemetry-events.md +++ b/docs/telemetry-events.md @@ -2174,6 +2174,7 @@ or 'context.config.dimMergeCommits': boolean, 'context.config.experimental.renderer.enabled': boolean, 'context.config.highlightRowsOnRefHover': boolean, + 'context.config.initialRowSelection': 'wip' | 'head', 'context.config.issues.enabled': boolean, 'context.config.layout': 'editor' | 'panel', 'context.config.minimap.additionalTypes': string, @@ -2813,6 +2814,27 @@ void } ``` +### op/gate/deadlock + +```typescript +{ + 'key': string, + 'prop': string, + 'timeout': number +} +``` + +### op/git/aborted + +```typescript +{ + 'duration': number, + 'operation': string, + 'reason': 'unknown' | 'timeout' | 'cancellation', + 'timeout': number +} +``` + ### openReviewMode > Sent when a PR review was started in the inspect overview diff --git a/eslint.config.mjs b/eslint.config.mjs index cf6fa2f1dfb82..eb5eb15ca0f51 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -30,6 +30,7 @@ const filePatterns = { webviewsApps: ['src/webviews/apps/**/*'], webviewsShared: [ // Keep in sync with `src/webviews/apps/tsconfig.json` + 'src/webviews/ipc.ts', 'src/webviews/**/protocol.ts', 'src/**/models/**/*.ts', 'src/**/utils/**/*.ts', diff --git a/package.json b/package.json index f4d883efcff20..275ec536d2992 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "engines": { "node": ">= 22.12.0", "pnpm": ">= 10.0.0", - "vscode": "^1.92.0" + "vscode": "^1.95.0" }, "license": "SEE LICENSE IN LICENSE", "publisher": "eamodio", @@ -1117,6 +1117,23 @@ "scope": "window", "order": 500 }, + "gitlens.graph.initialRowSelection": { + "type": [ + "string" + ], + "default": "wip", + "enum": [ + "wip", + "head" + ], + "enumDescriptions": [ + "Selects the working changes (WIP) row when there are uncommitted changes, otherwise selects the HEAD row", + "Always selects the HEAD row" + ], + "markdownDescription": "Specifies whether to select the \"Work in progress\" (WIP) row instead of HEAD if there are uncommitted changes in the _Commit Graph_", + "scope": "window", + "order": 501 + }, "gitlens.graph.dateStyle": { "type": [ "string", @@ -6340,11 +6357,6 @@ "command": "gitlens.ai.switchProvider:scm", "title": "Switch GitLens AI Provider/Model..." }, - { - "command": "gitlens.ai.undoGenerateRebase", - "title": "Undo AI Generated Changes (Preview)...", - "icon": "$(discard)" - }, { "command": "gitlens.annotations.nextChange", "title": "Next Change", @@ -6492,6 +6504,16 @@ "title": "Copy Link to Commit", "icon": "$(copy)" }, + { + "command": "gitlens.copyDeepLinkToCommit:commitDetails", + "title": "Copy Link to Commit", + "icon": "$(copy)" + }, + { + "command": "gitlens.copyDeepLinkToCommit:graphDetails", + "title": "Copy Link to Commit", + "icon": "$(copy)" + }, { "command": "gitlens.copyDeepLinkToComparison", "title": "Copy Link to Comparison", @@ -6502,11 +6524,31 @@ "title": "Copy Link to File", "icon": "$(copy)" }, + { + "command": "gitlens.copyDeepLinkToFile:commitDetails", + "title": "Copy Link to File", + "icon": "$(copy)" + }, + { + "command": "gitlens.copyDeepLinkToFile:graphDetails", + "title": "Copy Link to File", + "icon": "$(copy)" + }, { "command": "gitlens.copyDeepLinkToFileAtRevision", "title": "Copy Link to File at Revision...", "icon": "$(copy)" }, + { + "command": "gitlens.copyDeepLinkToFileAtRevision:commitDetails", + "title": "Copy Link to File at Revision...", + "icon": "$(copy)" + }, + { + "command": "gitlens.copyDeepLinkToFileAtRevision:graphDetails", + "title": "Copy Link to File at Revision...", + "icon": "$(copy)" + }, { "command": "gitlens.copyDeepLinkToLines", "title": "Copy Link to Code", @@ -6539,10 +6581,18 @@ "title": "Copy Changes (Patch)", "category": "GitLens" }, + { + "command": "gitlens.copyPatchToClipboard:commitDetails", + "title": "Copy Changes (Patch)" + }, { "command": "gitlens.copyPatchToClipboard:graph", "title": "Copy Changes (Patch)" }, + { + "command": "gitlens.copyPatchToClipboard:graphDetails", + "title": "Copy Changes (Patch)" + }, { "command": "gitlens.copyPatchToClipboard:scm", "title": "Copy Changes (Patch)" @@ -6557,6 +6607,16 @@ "category": "GitLens", "icon": "$(copy)" }, + { + "command": "gitlens.copyRelativePathToClipboard:commitDetails", + "title": "Copy Relative Path", + "icon": "$(copy)" + }, + { + "command": "gitlens.copyRelativePathToClipboard:graphDetails", + "title": "Copy Relative Path", + "icon": "$(copy)" + }, { "command": "gitlens.copyRemoteBranchesUrl", "title": "Copy Remote Branches URL", @@ -6584,6 +6644,16 @@ "category": "GitLens", "icon": "$(copy)" }, + { + "command": "gitlens.copyRemoteFileUrlFrom:commitDetails", + "title": "Copy Remote File URL From...", + "icon": "$(copy)" + }, + { + "command": "gitlens.copyRemoteFileUrlFrom:graphDetails", + "title": "Copy Remote File URL From...", + "icon": "$(copy)" + }, { "command": "gitlens.copyRemoteFileUrlToClipboard", "title": "Copy Remote File URL", @@ -6595,6 +6665,16 @@ "title": "Copy Remote File URL", "icon": "$(copy)" }, + { + "command": "gitlens.copyRemoteFileUrlWithoutRange:commitDetails", + "title": "Copy Remote File URL", + "icon": "$(copy)" + }, + { + "command": "gitlens.copyRemoteFileUrlWithoutRange:graphDetails", + "title": "Copy Remote File URL", + "icon": "$(copy)" + }, { "command": "gitlens.copyRemotePullRequestUrl", "title": "Copy Pull Request URL", @@ -6717,11 +6797,29 @@ "category": "GitLens", "icon": "$(gitlens-prev-commit-menu)" }, + { + "command": "gitlens.diffWithRevision:commitDetails", + "title": "Open Changes with Revision...", + "icon": "$(gitlens-prev-commit-menu)" + }, + { + "command": "gitlens.diffWithRevision:graphDetails", + "title": "Open Changes with Revision...", + "icon": "$(gitlens-prev-commit-menu)" + }, { "command": "gitlens.diffWithRevisionFrom", "title": "Open Changes with Branch or Tag...", "category": "GitLens" }, + { + "command": "gitlens.diffWithRevisionFrom:commitDetails", + "title": "Open Changes with Branch or Tag..." + }, + { + "command": "gitlens.diffWithRevisionFrom:graphDetails", + "title": "Open Changes with Branch or Tag..." + }, { "command": "gitlens.diffWithWorking", "title": "Open Changes with Working File", @@ -6774,6 +6872,14 @@ "title": "Open Changes (difftool)", "category": "GitLens" }, + { + "command": "gitlens.externalDiff:commitDetails", + "title": "Open Changes (difftool)" + }, + { + "command": "gitlens.externalDiff:graphDetails", + "title": "Open Changes (difftool)" + }, { "command": "gitlens.externalDiffAll", "title": "Open All Changes (difftool)", @@ -7531,10 +7637,6 @@ "title": "Open Changed Files", "category": "GitLens" }, - { - "command": "gitlens.openCloudPatch", - "title": "Open Cloud Patch..." - }, { "command": "gitlens.openCommitOnRemote", "title": "Open Commit on Remote", @@ -7562,12 +7664,32 @@ "title": "Open File History", "category": "GitLens" }, + { + "command": "gitlens.openFileHistory:commitDetails", + "title": "Open File History", + "icon": "$(history)" + }, + { + "command": "gitlens.openFileHistory:graphDetails", + "title": "Open File History", + "icon": "$(history)" + }, { "command": "gitlens.openFileOnRemote", "title": "Open File on Remote", "category": "GitLens", "icon": "$(globe)" }, + { + "command": "gitlens.openFileOnRemote:commitDetails", + "title": "Open File on Remote", + "icon": "$(globe)" + }, + { + "command": "gitlens.openFileOnRemote:graphDetails", + "title": "Open File on Remote", + "icon": "$(globe)" + }, { "command": "gitlens.openFileOnRemoteFrom", "title": "Open File on Remote From...", @@ -7733,6 +7855,14 @@ "title": "Quick Open File History", "category": "GitLens" }, + { + "command": "gitlens.quickOpenFileHistory:commitDetails", + "title": "Quick Open File History" + }, + { + "command": "gitlens.quickOpenFileHistory:graphDetails", + "title": "Quick Open File History" + }, { "command": "gitlens.regenerateMarkdownDocument", "title": "Regenerate", @@ -7748,10 +7878,28 @@ "title": "Reset Views Layout", "category": "GitLens" }, + { + "command": "gitlens.restore.file:commitDetails", + "title": "Restore Changes (Checkout)", + "icon": "$(discard)" + }, + { + "command": "gitlens.restore.file:graphDetails", + "title": "Restore Changes (Checkout)", + "icon": "$(discard)" + }, { "command": "gitlens.restore.file:views", "title": "Restore Changes (Checkout)" }, + { + "command": "gitlens.restorePrevious.file:commitDetails", + "title": "Restore Previous Changes" + }, + { + "command": "gitlens.restorePrevious.file:graphDetails", + "title": "Restore Previous Changes" + }, { "command": "gitlens.restorePrevious.file:views", "title": "Restore Previous Changes" @@ -7778,6 +7926,14 @@ "title": "Share as Cloud Patch...", "category": "GitLens" }, + { + "command": "gitlens.shareAsCloudPatch:commitDetails", + "title": "Share as Cloud Patch..." + }, + { + "command": "gitlens.shareAsCloudPatch:graphDetails", + "title": "Share as Cloud Patch..." + }, { "command": "gitlens.showAccountView", "title": "Show Account on Home", @@ -7858,11 +8014,6 @@ "title": "Open in Commit Graph", "icon": "$(gitlens-graph)" }, - { - "command": "gitlens.showInCommitGraphView", - "title": "Open in Commit Graph", - "icon": "$(gitlens-graph)" - }, { "command": "gitlens.showInDetailsView", "title": "Inspect Details", @@ -7908,7 +8059,8 @@ }, { "command": "gitlens.showQuickCommitDetails", - "title": "Quick Show Commit" + "title": "Quick Show Commit", + "category": "GitLens" }, { "command": "gitlens.showQuickCommitFileDetails", @@ -8041,11 +8193,6 @@ "title": "Open View Settings", "icon": "$(gear)" }, - { - "command": "gitlens.showSettingsPage!views", - "title": "Open Settings", - "icon": "$(gear)" - }, { "command": "gitlens.showSettingsPage!worktrees-view", "title": "Open View Settings", @@ -8278,11 +8425,6 @@ "title": "Toggle File Changes", "icon": "$(gitlens-gitlens)" }, - { - "command": "gitlens.toggleFileChangesOnly", - "title": "Toggle File Changes", - "icon": "$(gitlens-gitlens)" - }, { "command": "gitlens.toggleFileHeatmap", "title": "Toggle File Heatmap", @@ -8381,12 +8523,6 @@ "title": "Add Co-authors...", "icon": "$(person-add)" }, - { - "command": "gitlens.views.addPullRequestRemote", - "title": "Add Pull Request Remote", - "icon": "$(add)", - "enablement": "!operationInProgress" - }, { "command": "gitlens.views.addRemote", "title": "Add Remote...", @@ -8398,6 +8534,16 @@ "title": "Apply Changes", "enablement": "!operationInProgress" }, + { + "command": "gitlens.views.applyChanges:commitDetails", + "title": "Apply Changes", + "enablement": "!operationInProgress" + }, + { + "command": "gitlens.views.applyChanges:graphDetails", + "title": "Apply Changes", + "enablement": "!operationInProgress" + }, { "command": "gitlens.views.associateIssueWithBranch", "title": "Associate Issue with Branch...", @@ -8644,6 +8790,14 @@ "command": "gitlens.views.compareFileWithSelected", "title": "Compare with Selected" }, + { + "command": "gitlens.views.compareFileWithSelected:commitDetails", + "title": "Compare with Selected" + }, + { + "command": "gitlens.views.compareFileWithSelected:graphDetails", + "title": "Compare with Selected" + }, { "command": "gitlens.views.compareWithHead", "title": "Compare to/from HEAD", @@ -8747,6 +8901,16 @@ "title": "Copy", "icon": "$(copy)" }, + { + "command": "gitlens.views.copy:commitDetails", + "title": "Copy", + "icon": "$(copy)" + }, + { + "command": "gitlens.views.copy:graphDetails", + "title": "Copy", + "icon": "$(copy)" + }, { "command": "gitlens.views.copyAsMarkdown", "title": "Copy as Markdown", @@ -8757,6 +8921,16 @@ "title": "Copy Remote Commit URL", "icon": "$(copy)" }, + { + "command": "gitlens.views.copyRemoteCommitUrl:commitDetails", + "title": "Copy Remote Commit URL", + "icon": "$(copy)" + }, + { + "command": "gitlens.views.copyRemoteCommitUrl:graphDetails", + "title": "Copy Remote Commit URL", + "icon": "$(copy)" + }, { "command": "gitlens.views.copyRemoteCommitUrl.multi", "title": "Copy Remote Commit URLs", @@ -9004,10 +9178,26 @@ "command": "gitlens.views.highlightChanges", "title": "Highlight All Changes Since Before this Commit" }, + { + "command": "gitlens.views.highlightChanges:commitDetails", + "title": "Highlight All Changes Since Before this Commit" + }, + { + "command": "gitlens.views.highlightChanges:graphDetails", + "title": "Highlight All Changes Since Before this Commit" + }, { "command": "gitlens.views.highlightRevisionChanges", "title": "Highlight Changes from this Commit" }, + { + "command": "gitlens.views.highlightRevisionChanges:commitDetails", + "title": "Highlight Changes from this Commit" + }, + { + "command": "gitlens.views.highlightRevisionChanges:graphDetails", + "title": "Highlight Changes from this Commit" + }, { "command": "gitlens.views.home.disablePreview", "title": "Revert to Old Home View", @@ -9140,10 +9330,6 @@ "title": "Load All", "icon": "$(gitlens-expand)" }, - { - "command": "gitlens.views.loadMoreChildren", - "title": "Load More" - }, { "command": "gitlens.views.mergeBranchInto", "title": "Merge Branch into Current Branch...", @@ -9153,6 +9339,14 @@ "command": "gitlens.views.mergeChangesWithWorking", "title": "Merge Changes (Manually)..." }, + { + "command": "gitlens.views.mergeChangesWithWorking:commitDetails", + "title": "Merge Changes (Manually)..." + }, + { + "command": "gitlens.views.mergeChangesWithWorking:graphDetails", + "title": "Merge Changes (Manually)..." + }, { "command": "gitlens.views.openBranchOnRemote", "title": "Open Branch on Remote", @@ -9199,6 +9393,16 @@ "title": "Open Changes", "icon": "$(compare-changes)" }, + { + "command": "gitlens.views.openChanges:commitDetails", + "title": "Open Changes", + "icon": "$(git-compare)" + }, + { + "command": "gitlens.views.openChanges:graphDetails", + "title": "Open Changes", + "icon": "$(git-compare)" + }, { "command": "gitlens.views.openChangesWithMergeBase", "title": "Open Changes with Common Base" @@ -9208,6 +9412,16 @@ "title": "Open Changes with Working File", "icon": "$(gitlens-compare-ref-working)" }, + { + "command": "gitlens.views.openChangesWithWorking:commitDetails", + "title": "Open Changes with Working File", + "icon": "$(gitlens-compare-ref-working)" + }, + { + "command": "gitlens.views.openChangesWithWorking:graphDetails", + "title": "Open Changes with Working File", + "icon": "$(gitlens-compare-ref-working)" + }, { "command": "gitlens.views.openCommitOnRemote", "title": "Open Commit on Remote", @@ -9231,11 +9445,31 @@ "title": "Open File", "icon": "$(go-to-file)" }, + { + "command": "gitlens.views.openFile:commitDetails", + "title": "Open File", + "icon": "$(go-to-file)" + }, + { + "command": "gitlens.views.openFile:graphDetails", + "title": "Open File", + "icon": "$(go-to-file)" + }, { "command": "gitlens.views.openFileRevision", "title": "Open File at Revision", "icon": "$(gitlens-open-revision)" }, + { + "command": "gitlens.views.openFileRevision:commitDetails", + "title": "Open File at Revision", + "icon": "$(gitlens-open-revision)" + }, + { + "command": "gitlens.views.openFileRevision:graphDetails", + "title": "Open File at Revision", + "icon": "$(gitlens-open-revision)" + }, { "command": "gitlens.views.openInIntegratedTerminal", "title": "Open in Integrated Terminal" @@ -9262,6 +9496,14 @@ "command": "gitlens.views.openPreviousChangesWithWorking", "title": "Open Previous Changes with Working File" }, + { + "command": "gitlens.views.openPreviousChangesWithWorking:commitDetails", + "title": "Open Previous Changes with Working File" + }, + { + "command": "gitlens.views.openPreviousChangesWithWorking:graphDetails", + "title": "Open Previous Changes with Working File" + }, { "command": "gitlens.views.openPullRequest", "title": "Open Pull Request", @@ -10072,6 +10314,14 @@ "command": "gitlens.views.selectFileForCompare", "title": "Select for Compare" }, + { + "command": "gitlens.views.selectFileForCompare:commitDetails", + "title": "Select for Compare" + }, + { + "command": "gitlens.views.selectFileForCompare:graphDetails", + "title": "Select for Compare" + }, { "command": "gitlens.views.selectForCompare", "title": "Select for Compare" @@ -10149,6 +10399,16 @@ "icon": "$(add)", "enablement": "!operationInProgress" }, + { + "command": "gitlens.views.stageFile:commitDetails", + "title": "Stage Changes", + "icon": "$(add)" + }, + { + "command": "gitlens.views.stageFile:graphDetails", + "title": "Stage Changes", + "icon": "$(add)" + }, { "command": "gitlens.views.stashes.attach", "title": "Group into GitLens View", @@ -10312,6 +10572,16 @@ "icon": "$(remove)", "enablement": "!operationInProgress" }, + { + "command": "gitlens.views.unstageFile:commitDetails", + "title": "Unstage Changes", + "icon": "$(remove)" + }, + { + "command": "gitlens.views.unstageFile:graphDetails", + "title": "Unstage Changes", + "icon": "$(remove)" + }, { "command": "gitlens.views.workspaces.addRepos", "title": "Add Repositories...", @@ -10486,6 +10756,11 @@ "category": "GitLens", "icon": "$(graph-scatter)" }, + { + "command": "gitlens.visualizeHistory.file:commitDetails", + "title": "Open Visual File History", + "icon": "$(graph-scatter)" + }, { "command": "gitlens.visualizeHistory.file:editor", "title": "Open Visual File History", @@ -10496,6 +10771,11 @@ "title": "Open Visual File History", "icon": "$(graph-scatter)" }, + { + "command": "gitlens.visualizeHistory.file:graphDetails", + "title": "Open Visual File History", + "icon": "$(graph-scatter)" + }, { "command": "gitlens.visualizeHistory.file:scm", "title": "Open Visual File History", @@ -11124,10 +11404,6 @@ "command": "gitlens.ai.switchProvider:scm", "when": "false" }, - { - "command": "gitlens.ai.undoGenerateRebase", - "when": "false" - }, { "command": "gitlens.annotations.nextChange", "when": "false" @@ -11232,6 +11508,14 @@ "command": "gitlens.copyDeepLinkToCommit", "when": "false" }, + { + "command": "gitlens.copyDeepLinkToCommit:commitDetails", + "when": "false" + }, + { + "command": "gitlens.copyDeepLinkToCommit:graphDetails", + "when": "false" + }, { "command": "gitlens.copyDeepLinkToComparison", "when": "false" @@ -11240,10 +11524,26 @@ "command": "gitlens.copyDeepLinkToFile", "when": "false" }, + { + "command": "gitlens.copyDeepLinkToFile:commitDetails", + "when": "false" + }, + { + "command": "gitlens.copyDeepLinkToFile:graphDetails", + "when": "false" + }, { "command": "gitlens.copyDeepLinkToFileAtRevision", "when": "false" }, + { + "command": "gitlens.copyDeepLinkToFileAtRevision:commitDetails", + "when": "false" + }, + { + "command": "gitlens.copyDeepLinkToFileAtRevision:graphDetails", + "when": "false" + }, { "command": "gitlens.copyDeepLinkToLines", "when": "false" @@ -11268,10 +11568,18 @@ "command": "gitlens.copyPatchToClipboard", "when": "gitlens:enabled && !gitlens:untrusted && !gitlens:hasVirtualFolders" }, + { + "command": "gitlens.copyPatchToClipboard:commitDetails", + "when": "false" + }, { "command": "gitlens.copyPatchToClipboard:graph", "when": "false" }, + { + "command": "gitlens.copyPatchToClipboard:graphDetails", + "when": "false" + }, { "command": "gitlens.copyPatchToClipboard:scm", "when": "false" @@ -11284,6 +11592,14 @@ "command": "gitlens.copyRelativePathToClipboard", "when": "gitlens:enabled" }, + { + "command": "gitlens.copyRelativePathToClipboard:commitDetails", + "when": "false" + }, + { + "command": "gitlens.copyRelativePathToClipboard:graphDetails", + "when": "false" + }, { "command": "gitlens.copyRemoteBranchesUrl", "when": "false" @@ -11304,6 +11620,14 @@ "command": "gitlens.copyRemoteFileUrlFrom", "when": "gitlens:repos:withRemotes" }, + { + "command": "gitlens.copyRemoteFileUrlFrom:commitDetails", + "when": "false" + }, + { + "command": "gitlens.copyRemoteFileUrlFrom:graphDetails", + "when": "false" + }, { "command": "gitlens.copyRemoteFileUrlToClipboard", "when": "gitlens:repos:withRemotes" @@ -11312,6 +11636,14 @@ "command": "gitlens.copyRemoteFileUrlWithoutRange", "when": "false" }, + { + "command": "gitlens.copyRemoteFileUrlWithoutRange:commitDetails", + "when": "false" + }, + { + "command": "gitlens.copyRemoteFileUrlWithoutRange:graphDetails", + "when": "false" + }, { "command": "gitlens.copyRemotePullRequestUrl", "when": "false" @@ -11404,10 +11736,26 @@ "command": "gitlens.diffWithRevision", "when": "resource in gitlens:tabs:tracked" }, + { + "command": "gitlens.diffWithRevision:commitDetails", + "when": "false" + }, + { + "command": "gitlens.diffWithRevision:graphDetails", + "when": "false" + }, { "command": "gitlens.diffWithRevisionFrom", "when": "resource in gitlens:tabs:tracked" }, + { + "command": "gitlens.diffWithRevisionFrom:commitDetails", + "when": "false" + }, + { + "command": "gitlens.diffWithRevisionFrom:graphDetails", + "when": "false" + }, { "command": "gitlens.diffWithWorking", "when": "gitlens:enabled && resourceScheme =~ /^(gitlens|git|pr)$/" @@ -11448,6 +11796,14 @@ "command": "gitlens.externalDiff", "when": "!gitlens:hasVirtualFolders && resource in gitlens:tabs:tracked" }, + { + "command": "gitlens.externalDiff:commitDetails", + "when": "false" + }, + { + "command": "gitlens.externalDiff:graphDetails", + "when": "false" + }, { "command": "gitlens.externalDiffAll", "when": "gitlens:enabled && !gitlens:hasVirtualFolders" @@ -12064,10 +12420,6 @@ "command": "gitlens.openChangedFiles", "when": "gitlens:enabled" }, - { - "command": "gitlens.openCloudPatch", - "when": "false" - }, { "command": "gitlens.openCommitOnRemote", "when": "gitlens:repos:withRemotes" @@ -12088,10 +12440,26 @@ "command": "gitlens.openFileHistory", "when": "resource in gitlens:tabs:tracked" }, + { + "command": "gitlens.openFileHistory:commitDetails", + "when": "false" + }, + { + "command": "gitlens.openFileHistory:graphDetails", + "when": "false" + }, { "command": "gitlens.openFileOnRemote", "when": "gitlens:repos:withRemotes" }, + { + "command": "gitlens.openFileOnRemote:commitDetails", + "when": "false" + }, + { + "command": "gitlens.openFileOnRemote:graphDetails", + "when": "false" + }, { "command": "gitlens.openFileOnRemoteFrom", "when": "gitlens:repos:withRemotes" @@ -12208,14 +12576,38 @@ "command": "gitlens.quickOpenFileHistory", "when": "resource in gitlens:tabs:tracked" }, + { + "command": "gitlens.quickOpenFileHistory:commitDetails", + "when": "false" + }, + { + "command": "gitlens.quickOpenFileHistory:graphDetails", + "when": "false" + }, { "command": "gitlens.regenerateMarkdownDocument", "when": "false" }, + { + "command": "gitlens.restore.file:commitDetails", + "when": "false" + }, + { + "command": "gitlens.restore.file:graphDetails", + "when": "false" + }, { "command": "gitlens.restore.file:views", "when": "false" }, + { + "command": "gitlens.restorePrevious.file:commitDetails", + "when": "false" + }, + { + "command": "gitlens.restorePrevious.file:graphDetails", + "when": "false" + }, { "command": "gitlens.restorePrevious.file:views", "when": "false" @@ -12236,6 +12628,14 @@ "command": "gitlens.shareAsCloudPatch", "when": "gitlens:enabled && gitlens:gk:organization:drafts:enabled && config.gitlens.cloudPatches.enabled" }, + { + "command": "gitlens.shareAsCloudPatch:commitDetails", + "when": "false" + }, + { + "command": "gitlens.shareAsCloudPatch:graphDetails", + "when": "false" + }, { "command": "gitlens.showBranchesView", "when": "gitlens:enabled" @@ -12288,10 +12688,6 @@ "command": "gitlens.showInCommitGraph", "when": "false" }, - { - "command": "gitlens.showInCommitGraphView", - "when": "false" - }, { "command": "gitlens.showInDetailsView", "when": "false" @@ -12326,7 +12722,7 @@ }, { "command": "gitlens.showQuickCommitDetails", - "when": "false" + "when": "resource in gitlens:tabs:blameable" }, { "command": "gitlens.showQuickCommitFileDetails", @@ -12420,10 +12816,6 @@ "command": "gitlens.showSettingsPage!tags-view", "when": "false" }, - { - "command": "gitlens.showSettingsPage!views", - "when": "false" - }, { "command": "gitlens.showSettingsPage!worktrees-view", "when": "false" @@ -12588,10 +12980,6 @@ "command": "gitlens.toggleFileChanges:editor/title", "when": "false" }, - { - "command": "gitlens.toggleFileChangesOnly", - "when": "false" - }, { "command": "gitlens.toggleFileHeatmap", "when": "resource in gitlens:tabs:blameable || config.gitlens.heatmap.toggleMode == window" @@ -12669,15 +13057,19 @@ "when": "false" }, { - "command": "gitlens.views.addPullRequestRemote", + "command": "gitlens.views.addRemote", "when": "false" }, { - "command": "gitlens.views.addRemote", + "command": "gitlens.views.applyChanges", "when": "false" }, { - "command": "gitlens.views.applyChanges", + "command": "gitlens.views.applyChanges:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.applyChanges:graphDetails", "when": "false" }, { @@ -12892,6 +13284,14 @@ "command": "gitlens.views.compareFileWithSelected", "when": "false" }, + { + "command": "gitlens.views.compareFileWithSelected:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.compareFileWithSelected:graphDetails", + "when": "false" + }, { "command": "gitlens.views.compareWithHead", "when": "false" @@ -12980,6 +13380,14 @@ "command": "gitlens.views.copy", "when": "false" }, + { + "command": "gitlens.views.copy:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.copy:graphDetails", + "when": "false" + }, { "command": "gitlens.views.copyAsMarkdown", "when": "false" @@ -12988,6 +13396,14 @@ "command": "gitlens.views.copyRemoteCommitUrl", "when": "false" }, + { + "command": "gitlens.views.copyRemoteCommitUrl:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.copyRemoteCommitUrl:graphDetails", + "when": "false" + }, { "command": "gitlens.views.copyRemoteCommitUrl.multi", "when": "false" @@ -13184,10 +13600,26 @@ "command": "gitlens.views.highlightChanges", "when": "false" }, + { + "command": "gitlens.views.highlightChanges:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.highlightChanges:graphDetails", + "when": "false" + }, { "command": "gitlens.views.highlightRevisionChanges", "when": "false" }, + { + "command": "gitlens.views.highlightRevisionChanges:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.highlightRevisionChanges:graphDetails", + "when": "false" + }, { "command": "gitlens.views.home.disablePreview", "when": "false" @@ -13297,15 +13729,19 @@ "when": "false" }, { - "command": "gitlens.views.loadMoreChildren", + "command": "gitlens.views.mergeBranchInto", "when": "false" }, { - "command": "gitlens.views.mergeBranchInto", + "command": "gitlens.views.mergeChangesWithWorking", "when": "false" }, { - "command": "gitlens.views.mergeChangesWithWorking", + "command": "gitlens.views.mergeChangesWithWorking:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.mergeChangesWithWorking:graphDetails", "when": "false" }, { @@ -13348,6 +13784,14 @@ "command": "gitlens.views.openChanges", "when": "false" }, + { + "command": "gitlens.views.openChanges:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.openChanges:graphDetails", + "when": "false" + }, { "command": "gitlens.views.openChangesWithMergeBase", "when": "false" @@ -13356,6 +13800,14 @@ "command": "gitlens.views.openChangesWithWorking", "when": "false" }, + { + "command": "gitlens.views.openChangesWithWorking:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.openChangesWithWorking:graphDetails", + "when": "false" + }, { "command": "gitlens.views.openCommitOnRemote", "when": "false" @@ -13376,10 +13828,26 @@ "command": "gitlens.views.openFile", "when": "false" }, + { + "command": "gitlens.views.openFile:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.openFile:graphDetails", + "when": "false" + }, { "command": "gitlens.views.openFileRevision", "when": "false" }, + { + "command": "gitlens.views.openFileRevision:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.openFileRevision:graphDetails", + "when": "false" + }, { "command": "gitlens.views.openInIntegratedTerminal", "when": "false" @@ -13404,6 +13872,14 @@ "command": "gitlens.views.openPreviousChangesWithWorking", "when": "false" }, + { + "command": "gitlens.views.openPreviousChangesWithWorking:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.openPreviousChangesWithWorking:graphDetails", + "when": "false" + }, { "command": "gitlens.views.openPullRequest", "when": "false" @@ -14084,6 +14560,14 @@ "command": "gitlens.views.selectFileForCompare", "when": "false" }, + { + "command": "gitlens.views.selectFileForCompare:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.selectFileForCompare:graphDetails", + "when": "false" + }, { "command": "gitlens.views.selectForCompare", "when": "false" @@ -14148,6 +14632,14 @@ "command": "gitlens.views.stageFile", "when": "false" }, + { + "command": "gitlens.views.stageFile:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.stageFile:graphDetails", + "when": "false" + }, { "command": "gitlens.views.stashes.attach", "when": "false" @@ -14268,6 +14760,14 @@ "command": "gitlens.views.unstageFile", "when": "false" }, + { + "command": "gitlens.views.unstageFile:commitDetails", + "when": "false" + }, + { + "command": "gitlens.views.unstageFile:graphDetails", + "when": "false" + }, { "command": "gitlens.views.workspaces.addRepos", "when": "false" @@ -14412,6 +14912,10 @@ "command": "gitlens.visualizeHistory.file", "when": "gitlens:enabled && resource in gitlens:tabs:tracked" }, + { + "command": "gitlens.visualizeHistory.file:commitDetails", + "when": "false" + }, { "command": "gitlens.visualizeHistory.file:editor", "when": "false" @@ -14420,6 +14924,10 @@ "command": "gitlens.visualizeHistory.file:explorer", "when": "false" }, + { + "command": "gitlens.visualizeHistory.file:graphDetails", + "when": "false" + }, { "command": "gitlens.visualizeHistory.file:scm", "when": "false" @@ -14537,6 +15045,16 @@ } ], "editor/title": [ + { + "command": "gitlens.annotations.previousChange", + "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated =~ /computed:changes\\b/ || (resource in gitlens:tabs:annotated:changes && resource not in gitlens:tabs:annotated:computing)) && config.gitlens.menus.editorGroup.blame", + "group": "navigation@-100" + }, + { + "command": "gitlens.annotations.nextChange", + "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated =~ /computed:changes\\b/ || (resource in gitlens:tabs:annotated:changes && resource not in gitlens:tabs:annotated:computing)) && config.gitlens.menus.editorGroup.blame", + "group": "navigation@-99" + }, { "command": "gitlens.composer.refresh", "when": "activeWebviewPanelId === gitlens.composer", @@ -14552,6 +15070,11 @@ "when": "activeWebviewPanelId === gitlens.timeline", "group": "navigation@-99" }, + { + "submenu": "gitlens/graph/configuration", + "when": "activeWebviewPanelId === gitlens.graph", + "group": "navigation@-98" + }, { "command": "gitlens.graph.split", "when": "activeWebviewPanelId == gitlens.graph && resourceScheme == webview-panel && config.gitlens.graph.allowMultiple", @@ -14564,12 +15087,12 @@ }, { "command": "gitlens.clearFileAnnotations", - "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated == computed || (resource in gitlens:tabs:annotated && resource not in gitlens:tabs:annotated:computing)) && config.gitlens.menus.editorGroup.blame", + "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated =~ /computed\\b/ || (resource in gitlens:tabs:annotated && resource not in gitlens:tabs:annotated:computing)) && config.gitlens.menus.editorGroup.blame", "group": "navigation@100" }, { "command": "gitlens.computingFileAnnotations", - "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated == computing || resource in gitlens:tabs:annotated:computing) && config.gitlens.menus.editorGroup.blame", + "when": "resource in gitlens:tabs:blameable && (gitlens:window:annotated =~ /computed\\b/ || resource in gitlens:tabs:annotated:computing) && config.gitlens.menus.editorGroup.blame", "group": "navigation@100" }, { @@ -14626,11 +15149,6 @@ "when": "resourceScheme =~ /^(gitlens|pr)$/ && gitlens:enabled", "group": "navigation@-98" }, - { - "submenu": "gitlens/graph/configuration", - "when": "activeWebviewPanelId === gitlens.graph", - "group": "navigation@-98" - }, { "command": "gitlens.openRevisionFile:editor/title", "when": "resourceScheme =~ /^(gitlens|pr)$/ && gitlens:enabled && isInDiffEditor", @@ -14886,16 +15404,18 @@ }, { "command": "gitlens.diffWithRevision", + "when": "viewItem =~ /gitlens:file\\b/", "group": "1_gitlens@3" }, { "command": "gitlens.diffWithRevisionFrom", + "when": "viewItem =~ /gitlens:file\\b/", "group": "1_gitlens@4" }, { "command": "gitlens.externalDiff", "when": "viewItem =~ /gitlens:file\\b(?!.*?\\b\\+conflicted\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders", - "group": "1_gitlens_@1" + "group": "1_gitlens_@5" }, { "command": "gitlens.views.highlightChanges", @@ -14911,6 +15431,76 @@ "command": "gitlens.views.openChangesWithMergeBase", "when": "viewItem =~ /gitlens:file:results\\b/", "group": "1_gitlens@2" + }, + { + "command": "gitlens.views.openChangesWithWorking:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens@1" + }, + { + "command": "gitlens.views.openChangesWithWorking:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens@1" + }, + { + "command": "gitlens.views.openPreviousChangesWithWorking:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens@2" + }, + { + "command": "gitlens.views.openPreviousChangesWithWorking:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens@2" + }, + { + "command": "gitlens.diffWithRevision:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens@3" + }, + { + "command": "gitlens.diffWithRevision:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens@3" + }, + { + "command": "gitlens.diffWithRevisionFrom:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens@4" + }, + { + "command": "gitlens.diffWithRevisionFrom:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens@4" + }, + { + "command": "gitlens.externalDiff:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)(?!.*?\\b\\+conflicted\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "1_gitlens_@5" + }, + { + "command": "gitlens.externalDiff:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)(?!.*?\\b\\+conflicted\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "1_gitlens_@5" + }, + { + "command": "gitlens.views.highlightChanges:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.commitDetails", + "group": "2_gitlens@1" + }, + { + "command": "gitlens.views.highlightChanges:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.graphDetails", + "group": "2_gitlens@1" + }, + { + "command": "gitlens.views.highlightRevisionChanges:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.commitDetails", + "group": "2_gitlens@2" + }, + { + "command": "gitlens.views.highlightRevisionChanges:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.graphDetails", + "group": "2_gitlens@2" } ], "gitlens/commit/file/commit": [ @@ -15004,15 +15594,47 @@ "gitlens/commit/file/history": [ { "command": "gitlens.openFileHistory", - "when": "view != gitlens.views.fileHistory/", + "when": "viewItem =~ /gitlens:file\\b/ && view != gitlens.views.fileHistory/", "group": "1_gitlens@1" }, { "command": "gitlens.visualizeHistory.file:views", + "when": "viewItem =~ /gitlens:file\\b/", "group": "1_gitlens@2" }, { "command": "gitlens.quickOpenFileHistory", + "when": "viewItem =~ /gitlens:file\\b/", + "group": "1_gitlens_quick@1" + }, + { + "command": "gitlens.openFileHistory:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens@1" + }, + { + "command": "gitlens.openFileHistory:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens@1" + }, + { + "command": "gitlens.visualizeHistory.file:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens@2" + }, + { + "command": "gitlens.visualizeHistory.file:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens@2" + }, + { + "command": "gitlens.quickOpenFileHistory:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens_quick@1" + }, + { + "command": "gitlens.quickOpenFileHistory:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", "group": "1_gitlens_quick@1" } ], @@ -15595,12 +16217,12 @@ }, { "command": "gitlens.copyDeepLinkToCommit", - "when": "viewItem =~ /gitlens:(commit|file\\b(?=.*?\\b\\+committed\\b))/ && !listMultiSelection", + "when": "viewItem =~ /gitlens:(commit|file\\b(?=.*?\\b\\+committed\\b))\\b/ && !listMultiSelection", "group": "1_gitlens@25" }, { "command": "gitlens.views.copyRemoteCommitUrl", - "when": "viewItem =~ /gitlens:(commit|file\\b(?=.*?\\b\\+committed\\b))/ && !listMultiSelection && gitlens:repos:withRemotes", + "when": "viewItem =~ /gitlens:(commit|file\\b(?=.*?\\b\\+committed\\b))\\b/ && !listMultiSelection && gitlens:repos:withRemotes", "group": "2_gitlens@25" }, { @@ -15683,6 +16305,76 @@ "when": "webviewItem =~ /gitlens:commit\\b/ && !listMultiSelection && gitlens:repos:withRemotes", "group": "2_gitlens@25" }, + { + "command": "gitlens.shareAsCloudPatch:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:drafts:enabled && config.gitlens.cloudPatches.enabled && webview == gitlens.views.commitDetails", + "group": "1_a_gitlens@1" + }, + { + "command": "gitlens.shareAsCloudPatch:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && !gitlens:untrusted && !gitlens:hasVirtualFolders && gitlens:gk:organization:drafts:enabled && config.gitlens.cloudPatches.enabled && webview == gitlens.views.graphDetails", + "group": "1_a_gitlens@1" + }, + { + "command": "gitlens.copyDeepLinkToCommit:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && webview == gitlens.views.commitDetails", + "group": "1_gitlens@25" + }, + { + "command": "gitlens.copyDeepLinkToCommit:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && webview == gitlens.views.graphDetails", + "group": "1_gitlens@25" + }, + { + "command": "gitlens.copyDeepLinkToFile:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "1_gitlens@26" + }, + { + "command": "gitlens.copyDeepLinkToFile:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "1_gitlens@26" + }, + { + "command": "gitlens.copyDeepLinkToFileAtRevision:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "1_gitlens@27" + }, + { + "command": "gitlens.copyDeepLinkToFileAtRevision:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "1_gitlens@27" + }, + { + "command": "gitlens.copyRemoteFileUrlWithoutRange:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "2_gitlens@1" + }, + { + "command": "gitlens.copyRemoteFileUrlWithoutRange:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "2_gitlens@1" + }, + { + "command": "gitlens.copyRemoteFileUrlFrom:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "2_gitlens@2" + }, + { + "command": "gitlens.copyRemoteFileUrlFrom:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "2_gitlens@2" + }, + { + "command": "gitlens.views.copyRemoteCommitUrl:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "2_gitlens@25" + }, + { + "command": "gitlens.views.copyRemoteCommitUrl:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)\\b/ && !listMultiSelection && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "2_gitlens@25" + }, { "command": "gitlens.graph.copyDeepLinkToTag", "when": "webviewItem =~ /gitlens:tag\\b/ && !listMultiSelection", @@ -17494,7 +18186,7 @@ }, { "submenu": "gitlens/commit/browse", - "when": "viewItem =~ /gitlens:(branch|commit|file\\b(?=.*?\\b\\+committed\\b)|stash|tag)\\b/ && !listMultiSelection && !gitlens:hasVirtualFolders", + "when": "viewItem =~ /gitlens:(branch|commit|stash|tag)\\b/ && !listMultiSelection && !gitlens:hasVirtualFolders", "group": "3_gitlens_explore@100" }, { @@ -23376,7 +24068,7 @@ }, { "submenu": "gitlens/share", - "when": "webviewItem =~ /gitlens:(branch|commit|stash|tag)\\b/", + "when": "webviewItem =~ /gitlens:(branch|commit|stash|tag|file\\b(?=.*?\\b\\+(committed|staged|unstaged)\\b))\\b/", "group": "7_gitlens_a_share@1" }, { @@ -23514,6 +24206,201 @@ "when": "webviewItem =~ /gitlens:contributor\\b(?!.*?\\b\\+current\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders", "group": "1_gitlens_actions@2" }, + { + "command": "gitlens.views.applyChanges:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "1_gitlens_actions@1" + }, + { + "command": "gitlens.views.applyChanges:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "1_gitlens_actions@1" + }, + { + "command": "gitlens.views.stageFile:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+unstaged\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens_actions@1" + }, + { + "command": "gitlens.views.stageFile:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+unstaged\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens_actions@1" + }, + { + "command": "gitlens.views.mergeChangesWithWorking:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens_actions@2" + }, + { + "command": "gitlens.views.mergeChangesWithWorking:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens_actions@2" + }, + { + "command": "gitlens.views.unstageFile:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+staged\\b)/ && webview == gitlens.views.commitDetails", + "group": "1_gitlens_actions@2" + }, + { + "command": "gitlens.views.unstageFile:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+staged\\b)/ && webview == gitlens.views.graphDetails", + "group": "1_gitlens_actions@2" + }, + { + "command": "gitlens.restore.file:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "1_gitlens_actions@3" + }, + { + "command": "gitlens.restore.file:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+stashed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "1_gitlens_actions@3" + }, + { + "command": "gitlens.views.openChanges:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "2_gitlens_quickopen@1" + }, + { + "command": "gitlens.views.openChanges:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "2_gitlens_quickopen@1" + }, + { + "submenu": "gitlens/commit/file/changes", + "when": "webviewItem =~ /gitlens:file\\b/", + "group": "2_gitlens_quickopen@2" + }, + { + "command": "gitlens.views.openFile:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "2_gitlens_quickopen_file@3" + }, + { + "command": "gitlens.views.openFile:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "2_gitlens_quickopen_file@3" + }, + { + "command": "gitlens.views.openFileRevision:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.commitDetails", + "group": "2_gitlens_quickopen_file@4" + }, + { + "command": "gitlens.views.openFileRevision:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && webview == gitlens.views.graphDetails", + "group": "2_gitlens_quickopen_file@4" + }, + { + "command": "gitlens.openFileOnRemote:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && gitlens:repos:withRemotes && webview == gitlens.views.commitDetails", + "group": "2_gitlens_quickopen_file@5" + }, + { + "command": "gitlens.openFileOnRemote:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+(committed|stashed)\\b)/ && gitlens:repos:withRemotes && webview == gitlens.views.graphDetails", + "group": "2_gitlens_quickopen_file@5" + }, + { + "submenu": "gitlens/commit/file/history", + "when": "webviewItem =~ /gitlens:file\\b/", + "group": "3_gitlens_explore@2" + }, + { + "command": "gitlens.views.compareFileWithSelected:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && !listMultiSelection && gitlens:views:canCompare:file && webview == gitlens.views.commitDetails", + "group": "4_gitlens_compare@99" + }, + { + "command": "gitlens.views.compareFileWithSelected:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && !listMultiSelection && gitlens:views:canCompare:file && webview == gitlens.views.graphDetails", + "group": "4_gitlens_compare@99" + }, + { + "command": "gitlens.views.selectFileForCompare:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?!.*?\\b\\+conflicted\\b)/ && webview == gitlens.views.commitDetails", + "group": "4_gitlens_compare@99" + }, + { + "command": "gitlens.views.selectFileForCompare:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?!.*?\\b\\+conflicted\\b)/ && webview == gitlens.views.graphDetails", + "group": "4_gitlens_compare@99" + }, + { + "command": "gitlens.views.copy:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?!.*?\\b\\+(staged|unstaged)\\b)/ && webview == gitlens.views.commitDetails", + "group": "7_gitlens_cutcopypaste@1" + }, + { + "command": "gitlens.views.copy:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?!.*?\\b\\+(staged|unstaged)\\b)/ && webview == gitlens.views.graphDetails", + "group": "7_gitlens_cutcopypaste@1" + }, + { + "command": "gitlens.copyRelativePathToClipboard:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.commitDetails", + "group": "7_gitlens_cutcopypaste@2" + }, + { + "command": "gitlens.copyRelativePathToClipboard:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b/ && webview == gitlens.views.graphDetails", + "group": "7_gitlens_cutcopypaste@2" + }, + { + "command": "gitlens.copyPatchToClipboard:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "7_gitlens_cutcopypaste@3" + }, + { + "command": "gitlens.copyPatchToClipboard:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "7_gitlens_cutcopypaste@3" + }, + { + "submenu": "gitlens/commit/copy", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/", + "group": "7_gitlens_cutcopypaste@10" + }, + { + "command": "gitlens.views.applyChanges:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "8_gitlens_actions@1" + }, + { + "command": "gitlens.views.applyChanges:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "8_gitlens_actions@1" + }, + { + "command": "gitlens.views.mergeChangesWithWorking:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.commitDetails", + "group": "8_gitlens_actions@2" + }, + { + "command": "gitlens.views.mergeChangesWithWorking:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.graphDetails", + "group": "8_gitlens_actions@2" + }, + { + "command": "gitlens.restore.file:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.commitDetails", + "group": "8_gitlens_actions@3" + }, + { + "command": "gitlens.restore.file:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && !gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && webview == gitlens.views.graphDetails", + "group": "8_gitlens_actions@3" + }, + { + "command": "gitlens.restorePrevious.file:commitDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.commitDetails", + "group": "8_gitlens_actions@4" + }, + { + "command": "gitlens.restorePrevious.file:graphDetails", + "when": "webviewItem =~ /gitlens:file\\b(?=.*?\\b\\+committed\\b)/ && webview == gitlens.views.graphDetails", + "group": "8_gitlens_actions@4" + }, { "submenu": "gitlens/graph/markers", "when": "webviewItem =~ /gitlens:graph:(columns|settings)\\b/", @@ -24156,19 +25043,19 @@ { "command": "gitlens.views.branches.copy", "key": "ctrl+c", - "when": "focusedView == gitlens.views.branches", + "when": "focusedView == gitlens.views.branches || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == branches)", "mac": "cmd+c" }, { "command": "gitlens.views.commits.copy", "key": "ctrl+c", - "when": "focusedView == gitlens.views.commits", + "when": "focusedView == gitlens.views.commits || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == commits)", "mac": "cmd+c" }, { "command": "gitlens.views.contributors.copy", "key": "ctrl+c", - "when": "focusedView == gitlens.views.contributors", + "when": "focusedView == gitlens.views.contributors || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == contributors)", "mac": "cmd+c" }, { @@ -24180,7 +25067,13 @@ { "command": "gitlens.views.fileHistory.copy", "key": "ctrl+c", - "when": "focusedView == gitlens.views.fileHistory", + "when": "focusedView == gitlens.views.fileHistory || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == fileHistory)", + "mac": "cmd+c" + }, + { + "command": "gitlens.views.launchpad.copy", + "key": "ctrl+c", + "when": "focusedView == gitlens.views.launchpad || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == launchpad)", "mac": "cmd+c" }, { @@ -24198,13 +25091,13 @@ { "command": "gitlens.views.remotes.copy", "key": "ctrl+c", - "when": "focusedView == gitlens.views.remotes", + "when": "focusedView == gitlens.views.remotes || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == remotes)", "mac": "cmd+c" }, { "command": "gitlens.views.repositories.copy", "key": "ctrl+c", - "when": "focusedView == gitlens.views.repositories", + "when": "focusedView == gitlens.views.repositories || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == repositories)", "mac": "cmd+c" }, { @@ -24260,19 +25153,19 @@ { "command": "gitlens.views.searchAndCompare.copy", "key": "ctrl+c", - "when": "focusedView == gitlens.views.searchAndCompare", + "when": "focusedView == gitlens.views.searchAndCompare || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == searchAndCompare)", "mac": "cmd+c" }, { "command": "gitlens.views.stashes.copy", "key": "ctrl+c", - "when": "focusedView == gitlens.views.stashes", + "when": "focusedView == gitlens.views.stashes || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == stashes)", "mac": "cmd+c" }, { "command": "gitlens.views.tags.copy", "key": "ctrl+c", - "when": "focusedView == gitlens.views.tags", + "when": "focusedView == gitlens.views.tags || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == tags)", "mac": "cmd+c" }, { @@ -24284,7 +25177,7 @@ { "command": "gitlens.views.worktrees.copy", "key": "ctrl+c", - "when": "focusedView == gitlens.views.worktrees", + "when": "focusedView == gitlens.views.worktrees || (focusedView == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == worktrees)", "mac": "cmd+c" } ], @@ -24990,6 +25883,7 @@ "build:extension": "webpack --mode development --config-name extension:node", "build:extension:browser": "webpack --mode development --config-name extension:webworker", "build:webviews": "node ./scripts/compile-composer-templates.mjs && webpack --mode development --config-name webviews:common --config-name webviews", + "build:webviews:quick": "node ./scripts/compile-composer-templates.mjs && webpack --mode development --config-name webviews:common --config-name webviews --env skipLint", "build:icons": "pnpm run icons:svgo && pnpm fantasticon && pnpm run icons:apply && pnpm run icons:export", "build:tests": "node ./scripts/esbuild.tests.mjs", "// Extracts the contributions from package.json into contributions.json": "//", @@ -25046,7 +25940,7 @@ "vscode:prepublish": "pnpm run bundle" }, "dependencies": { - "@gitkraken/gitkraken-components": "13.0.0-vnext.9", + "@gitkraken/gitkraken-components": "13.0.0-vnext.10", "@gitkraken/provider-apis": "0.29.7", "@gitkraken/shared-web-components": "0.1.1-rc.15", "@gk-nzaytsev/fast-string-truncated-width": "1.1.0", @@ -25055,17 +25949,17 @@ "@lit/context": "1.1.6", "@lit/react": "1.0.8", "@lit/task": "1.0.3", - "@octokit/graphql": "9.0.1", - "@octokit/request": "10.0.3", - "@octokit/request-error": "7.0.0", - "@octokit/types": "14.1.0", + "@octokit/graphql": "9.0.2", + "@octokit/request": "10.0.5", + "@octokit/request-error": "7.0.1", + "@octokit/types": "15.0.0", "@opentelemetry/api": "1.9.0", - "@opentelemetry/exporter-trace-otlp-http": "0.205.0", + "@opentelemetry/exporter-trace-otlp-http": "0.206.0", "@opentelemetry/resources": "2.1.0", "@opentelemetry/sdk-trace-base": "2.1.0", "@opentelemetry/semantic-conventions": "1.37.0", "@shoelace-style/shoelace": "2.20.1", - "@vscode/codicons": "0.0.40", + "@vscode/codicons": "0.0.41", "billboard.js": "3.17.0", "diff2html": "3.4.52", "driver.js": "1.3.6", @@ -25073,7 +25967,7 @@ "https-proxy-agent": "5.0.1", "iconv-lite": "0.6.3", "lit": "3.3.1", - "marked": "16.3.0", + "marked": "16.4.0", "node-fetch": "2.7.0", "os-browserify": "0.3.0", "path-browserify": "1.0.1", @@ -25081,29 +25975,30 @@ "react-dom": "19.0.0", "signal-utils": "0.21.1", "slug": "11.0.0", - "sortablejs": "1.15.6" + "sortablejs": "1.15.6", + "vscode-uri": "3.1.0" }, "devDependencies": { - "@custom-elements-manifest/analyzer": "0.10.5", - "@eamodio/eslint-lite-webpack-plugin": "0.3.2", + "@custom-elements-manifest/analyzer": "0.10.10", + "@eamodio/eslint-lite-webpack-plugin": "0.3.4", "@eslint/compat": "1.4.0", - "@eslint/js": "9.36.0", - "@playwright/test": "1.55.0", + "@eslint/js": "9.37.0", + "@playwright/test": "1.56.0", "@prettier/plugin-oxc": "0.0.4", "@swc/core": "1.13.5", "@twbs/fantasticon": "3.1.0", "@types/mocha": "10.0.10", - "@types/node": "20.14.15", - "@types/react": "19.0.12", - "@types/react-dom": "19.0.4", + "@types/node": "20.16.15", + "@types/react": "19.0.14", + "@types/react-dom": "19.0.6", "@types/sinon": "17.0.4", "@types/slug": "5.0.9", "@types/sortablejs": "1.15.8", - "@types/vscode": "1.92.0", - "@typescript-eslint/parser": "8.45.0", - "@vscode/test-cli": "0.0.11", + "@types/vscode": "1.95.0", + "@typescript-eslint/parser": "8.46.1", + "@vscode/test-cli": "0.0.12", "@vscode/test-electron": "2.5.2", - "@vscode/test-web": "0.0.73", + "@vscode/test-web": "0.0.74", "@vscode/vsce": "3.6.2", "cheerio": "1.0.0-rc.12", "circular-dependency-plugin": "5.2.2", @@ -25114,15 +26009,15 @@ "css-minimizer-webpack-plugin": "7.0.2", "cssnano-preset-advanced": "7.0.9", "esbuild": "0.25.10", - "esbuild-loader": "4.3.0", + "esbuild-loader": "4.4.0", "esbuild-node-externals": "1.18.0", "esbuild-sass-plugin": "3.3.1", - "eslint": "9.36.0", + "eslint": "9.37.0", "eslint-import-resolver-typescript": "4.4.4", "eslint-plugin-anti-trojan-source": "1.1.1", "eslint-plugin-import-x": "4.16.1", "eslint-plugin-lit": "2.1.1", - "eslint-plugin-wc": "3.0.1", + "eslint-plugin-wc": "3.0.2", "fork-ts-checker-webpack-plugin": "9.1.0", "glob": "11.0.3", "globals": "16.4.0", @@ -25133,28 +26028,28 @@ "license-checker-rseidelsohn": "4.4.2", "lz-string": "1.5.0", "mini-css-extract-plugin": "2.9.4", - "ovsx": "0.10.5", - "playwright": "1.55.0", + "ovsx": "0.10.6", + "playwright": "1.56.0", "prettier": "3.6.2", "regex-to-strings": "2.1.0", - "sass": "1.90.0", + "sass": "1.93.2", "sass-loader": "16.0.5", - "schema-utils": "4.3.2", - "sharp": "0.34.3", + "schema-utils": "4.3.3", + "sharp": "0.34.4", "sinon": "21.0.0", "svgo": "4.0.0", "terser-webpack-plugin": "5.3.14", "ts-loader": "9.5.4", - "typescript": "5.9.2", - "typescript-eslint": "8.45.0", - "webpack": "5.101.3", + "typescript": "5.9.3", + "typescript-eslint": "8.46.0", + "webpack": "5.102.1", "webpack-bundle-analyzer": "4.10.2", "webpack-cli": "6.0.1", "webpack-node-externals": "3.0.0", "webpack-require-from": "1.8.6" }, "resolutions": { - "@types/vscode": "1.92.0", + "@types/vscode": "1.95.0", "esbuild": "0.25.10", "https-proxy-agent": "5.0.1", "iconv-lite": "0.6.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86c22d1c365a1..6724dc4901f78 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,7 +5,7 @@ settings: excludeLinksFromLockfile: false overrides: - '@types/vscode': 1.92.0 + '@types/vscode': 1.95.0 esbuild: 0.25.10 https-proxy-agent: 5.0.1 iconv-lite: 0.6.3 @@ -16,8 +16,8 @@ importers: .: dependencies: '@gitkraken/gitkraken-components': - specifier: 13.0.0-vnext.9 - version: 13.0.0-vnext.9(@types/react@19.0.12)(react@19.0.0) + specifier: 13.0.0-vnext.10 + version: 13.0.0-vnext.10(@types/react@19.0.14)(react@19.0.0) '@gitkraken/provider-apis': specifier: 0.29.7 version: 0.29.7(encoding@0.1.13) @@ -38,28 +38,28 @@ importers: version: 1.1.6 '@lit/react': specifier: 1.0.8 - version: 1.0.8(@types/react@19.0.12) + version: 1.0.8(@types/react@19.0.14) '@lit/task': specifier: 1.0.3 version: 1.0.3 '@octokit/graphql': - specifier: 9.0.1 - version: 9.0.1 + specifier: 9.0.2 + version: 9.0.2 '@octokit/request': - specifier: 10.0.3 - version: 10.0.3 + specifier: 10.0.5 + version: 10.0.5 '@octokit/request-error': - specifier: 7.0.0 - version: 7.0.0 + specifier: 7.0.1 + version: 7.0.1 '@octokit/types': - specifier: 14.1.0 - version: 14.1.0 + specifier: 15.0.0 + version: 15.0.0 '@opentelemetry/api': specifier: 1.9.0 version: 1.9.0 '@opentelemetry/exporter-trace-otlp-http': - specifier: 0.205.0 - version: 0.205.0(@opentelemetry/api@1.9.0) + specifier: 0.206.0 + version: 0.206.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources': specifier: 2.1.0 version: 2.1.0(@opentelemetry/api@1.9.0) @@ -71,10 +71,10 @@ importers: version: 1.37.0 '@shoelace-style/shoelace': specifier: 2.20.1 - version: 2.20.1(@floating-ui/utils@0.2.10)(@types/react@19.0.12) + version: 2.20.1(@floating-ui/utils@0.2.10)(@types/react@19.0.14) '@vscode/codicons': - specifier: 0.0.40 - version: 0.0.40 + specifier: 0.0.41 + version: 0.0.41 billboard.js: specifier: 3.17.0 version: 3.17.0 @@ -97,8 +97,8 @@ importers: specifier: 3.3.1 version: 3.3.1 marked: - specifier: 16.3.0 - version: 16.3.0 + specifier: 16.4.0 + version: 16.4.0 node-fetch: specifier: 2.7.0 version: 2.7.0(encoding@0.1.13) @@ -123,22 +123,25 @@ importers: sortablejs: specifier: 1.15.6 version: 1.15.6 + vscode-uri: + specifier: 3.1.0 + version: 3.1.0 devDependencies: '@custom-elements-manifest/analyzer': - specifier: 0.10.5 - version: 0.10.5 + specifier: 0.10.10 + version: 0.10.10 '@eamodio/eslint-lite-webpack-plugin': - specifier: 0.3.2 - version: 0.3.2(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(eslint@9.36.0(jiti@2.4.0))(webpack-cli@6.0.1)(webpack@5.101.3) + specifier: 0.3.4 + version: 0.3.4(eslint@9.37.0(jiti@2.4.0))(webpack@5.102.1) '@eslint/compat': specifier: 1.4.0 - version: 1.4.0(eslint@9.36.0(jiti@2.4.0)) + version: 1.4.0(eslint@9.37.0(jiti@2.4.0)) '@eslint/js': - specifier: 9.36.0 - version: 9.36.0 + specifier: 9.37.0 + version: 9.37.0 '@playwright/test': - specifier: 1.55.0 - version: 1.55.0 + specifier: 1.56.0 + version: 1.56.0 '@prettier/plugin-oxc': specifier: 0.0.4 version: 0.0.4 @@ -152,14 +155,14 @@ importers: specifier: 10.0.10 version: 10.0.10 '@types/node': - specifier: 20.14.15 - version: 20.14.15 + specifier: 20.16.15 + version: 20.16.15 '@types/react': - specifier: 19.0.12 - version: 19.0.12 + specifier: 19.0.14 + version: 19.0.14 '@types/react-dom': - specifier: 19.0.4 - version: 19.0.4(@types/react@19.0.12) + specifier: 19.0.6 + version: 19.0.6(@types/react@19.0.14) '@types/sinon': specifier: 17.0.4 version: 17.0.4 @@ -170,20 +173,20 @@ importers: specifier: 1.15.8 version: 1.15.8 '@types/vscode': - specifier: 1.92.0 - version: 1.92.0 + specifier: 1.95.0 + version: 1.95.0 '@typescript-eslint/parser': - specifier: 8.45.0 - version: 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) + specifier: 8.46.1 + version: 8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) '@vscode/test-cli': - specifier: 0.0.11 - version: 0.0.11 + specifier: 0.0.12 + version: 0.0.12 '@vscode/test-electron': specifier: 2.5.2 version: 2.5.2 '@vscode/test-web': - specifier: 0.0.73 - version: 0.0.73 + specifier: 0.0.74 + version: 0.0.74 '@vscode/vsce': specifier: 3.6.2 version: 3.6.2 @@ -192,22 +195,22 @@ importers: version: 1.0.0-rc.12 circular-dependency-plugin: specifier: 5.2.2 - version: 5.2.2(webpack@5.101.3) + version: 5.2.2(webpack@5.102.1) clean-webpack-plugin: specifier: 4.0.0 - version: 4.0.0(webpack@5.101.3) + version: 4.0.0(webpack@5.102.1) copy-webpack-plugin: specifier: 13.0.1 - version: 13.0.1(webpack@5.101.3) + version: 13.0.1(webpack@5.102.1) csp-html-webpack-plugin: specifier: 5.1.0 - version: 5.1.0(html-webpack-plugin@5.6.4(webpack@5.101.3))(webpack@5.101.3) + version: 5.1.0(html-webpack-plugin@5.6.4(webpack@5.102.1))(webpack@5.102.1) css-loader: specifier: 7.1.2 - version: 7.1.2(webpack@5.101.3) + version: 7.1.2(webpack@5.102.1) css-minimizer-webpack-plugin: specifier: 7.0.2 - version: 7.0.2(esbuild@0.25.10)(webpack@5.101.3) + version: 7.0.2(esbuild@0.25.10)(webpack@5.102.1) cssnano-preset-advanced: specifier: 7.0.9 version: 7.0.9(postcss@8.5.6) @@ -215,8 +218,8 @@ importers: specifier: 0.25.10 version: 0.25.10 esbuild-loader: - specifier: 4.3.0 - version: 4.3.0(webpack@5.101.3) + specifier: 4.4.0 + version: 4.4.0(webpack@5.102.1) esbuild-node-externals: specifier: 1.18.0 version: 1.18.0(esbuild@0.25.10) @@ -224,26 +227,26 @@ importers: specifier: 3.3.1 version: 3.3.1(esbuild@0.25.10)(sass-embedded@1.77.8) eslint: - specifier: 9.36.0 - version: 9.36.0(jiti@2.4.0) + specifier: 9.37.0 + version: 9.37.0(jiti@2.4.0) eslint-import-resolver-typescript: specifier: 4.4.4 - version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.4.0)))(eslint-plugin-import@2.29.1)(eslint@9.36.0(jiti@2.4.0)) + version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.4.0)))(eslint-plugin-import@2.29.1)(eslint@9.37.0(jiti@2.4.0)) eslint-plugin-anti-trojan-source: specifier: 1.1.1 version: 1.1.1 eslint-plugin-import-x: specifier: 4.16.1 - version: 4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.4.0)) + version: 4.16.1(@typescript-eslint/utils@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.4.0)) eslint-plugin-lit: specifier: 2.1.1 - version: 2.1.1(eslint@9.36.0(jiti@2.4.0)) + version: 2.1.1(eslint@9.37.0(jiti@2.4.0)) eslint-plugin-wc: - specifier: 3.0.1 - version: 3.0.1(eslint@9.36.0(jiti@2.4.0)) + specifier: 3.0.2 + version: 3.0.2(eslint@9.37.0(jiti@2.4.0)) fork-ts-checker-webpack-plugin: specifier: 9.1.0 - version: 9.1.0(typescript@5.9.2)(webpack@5.101.3) + version: 9.1.0(typescript@5.9.3)(webpack@5.102.1) glob: specifier: 11.0.3 version: 11.0.3 @@ -255,13 +258,13 @@ importers: version: 3.0.2 html-loader: specifier: 5.1.0 - version: 5.1.0(webpack@5.101.3) + version: 5.1.0(webpack@5.102.1) html-webpack-plugin: specifier: 5.6.4 - version: 5.6.4(webpack@5.101.3) + version: 5.6.4(webpack@5.102.1) image-minimizer-webpack-plugin: specifier: 4.1.4 - version: 4.1.4(sharp@0.34.3)(svgo@4.0.0)(webpack@5.101.3) + version: 4.1.4(sharp@0.34.4)(svgo@4.0.0)(webpack@5.102.1) license-checker-rseidelsohn: specifier: 4.4.2 version: 4.4.2 @@ -270,13 +273,13 @@ importers: version: 1.5.0 mini-css-extract-plugin: specifier: 2.9.4 - version: 2.9.4(webpack@5.101.3) + version: 2.9.4(webpack@5.102.1) ovsx: - specifier: 0.10.5 - version: 0.10.5 + specifier: 0.10.6 + version: 0.10.6 playwright: - specifier: 1.55.0 - version: 1.55.0 + specifier: 1.56.0 + version: 1.56.0 prettier: specifier: 3.6.2 version: 3.6.2 @@ -284,17 +287,17 @@ importers: specifier: 2.1.0 version: 2.1.0 sass: - specifier: 1.90.0 - version: 1.90.0 + specifier: 1.93.2 + version: 1.93.2 sass-loader: specifier: 16.0.5 - version: 16.0.5(sass-embedded@1.77.8)(sass@1.90.0)(webpack@5.101.3) + version: 16.0.5(sass-embedded@1.77.8)(sass@1.93.2)(webpack@5.102.1) schema-utils: - specifier: 4.3.2 - version: 4.3.2 + specifier: 4.3.3 + version: 4.3.3 sharp: - specifier: 0.34.3 - version: 0.34.3 + specifier: 0.34.4 + version: 0.34.4 sinon: specifier: 21.0.0 version: 21.0.0 @@ -303,31 +306,31 @@ importers: version: 4.0.0 terser-webpack-plugin: specifier: 5.3.14 - version: 5.3.14(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack@5.101.3) + version: 5.3.14(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack@5.102.1) ts-loader: specifier: 9.5.4 - version: 9.5.4(typescript@5.9.2)(webpack@5.101.3) + version: 9.5.4(typescript@5.9.3)(webpack@5.102.1) typescript: - specifier: 5.9.2 - version: 5.9.2 + specifier: 5.9.3 + version: 5.9.3 typescript-eslint: - specifier: 8.45.0 - version: 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) + specifier: 8.46.0 + version: 8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) webpack: - specifier: 5.101.3 - version: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + specifier: 5.102.1 + version: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) webpack-bundle-analyzer: specifier: 4.10.2 version: 4.10.2 webpack-cli: specifier: 6.0.1 - version: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.101.3) + version: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.102.1) webpack-node-externals: specifier: 3.0.0 version: 3.0.0 webpack-require-from: specifier: 1.8.6 - version: 1.8.6(tapable@2.2.3) + version: 1.8.6(tapable@2.3.0) packages: @@ -367,24 +370,24 @@ packages: resolution: {integrity: sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==} engines: {node: '>=20.0.0'} - '@azure/identity@4.12.0': - resolution: {integrity: sha512-6vuh2R3Cte6SD6azNalLCjIDoryGdcvDVEV7IDRPtm5lHX5ffkDlIalaoOp5YJU08e4ipjJENel20kSMDLAcug==} + '@azure/identity@4.13.0': + resolution: {integrity: sha512-uWC0fssc+hs1TGGVkkghiaFkkS7NkTxfnCH+Hdg+yTehTpMcehpok4PgUKKdyCH+9ldu6FhiHRv84Ntqj1vVcw==} engines: {node: '>=20.0.0'} '@azure/logger@1.3.0': resolution: {integrity: sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==} engines: {node: '>=20.0.0'} - '@azure/msal-browser@4.23.0': - resolution: {integrity: sha512-uHnfRwGAEHaYVXzpCtYsruy6PQxL2v76+MJ3+n/c/3PaTiTIa5ch7VofTUNoA39nHyjJbdiqTwFZK40OOTOkjw==} + '@azure/msal-browser@4.25.0': + resolution: {integrity: sha512-kbL+Ae7/UC62wSzxirZddYeVnHvvkvAnSZkBqL55X+jaSXTAXfngnNsDM5acEWU0Q/SAv3gEQfxO1igWOn87Pg==} engines: {node: '>=0.8.0'} - '@azure/msal-common@15.12.0': - resolution: {integrity: sha512-4ucXbjVw8KJ5QBgnGJUeA07c8iznwlk5ioHIhI4ASXcXgcf2yRFhWzYOyWg/cI49LC9ekpFJeQtO3zjDTbl6TQ==} + '@azure/msal-common@15.13.0': + resolution: {integrity: sha512-8oF6nj02qX7eE/6+wFT5NluXRHc05AgdCC3fJnkjiJooq8u7BcLmxaYYSwc2AfEkWRMRi6Eyvvbeqk4U4412Ag==} engines: {node: '>=0.8.0'} - '@azure/msal-node@3.7.4': - resolution: {integrity: sha512-fjqvhrThwzzPvqhFOdkkGRJCHPQZTNijpceVy8QjcfQuH482tOVEjHyamZaioOhVtx+FK1u+eMpJA2Zz4U9LVg==} + '@azure/msal-node@3.8.0': + resolution: {integrity: sha512-23BXm82Mp5XnRhrcd4mrHa0xuUNRp96ivu3nRatrfdAqjoeWAGyD0eEAafxAOHAEWWmdlyFK4ELFcdziXyw2sA==} engines: {node: '>=16'} '@babel/code-frame@7.27.1': @@ -399,8 +402,9 @@ packages: resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} - '@bcoe/v8-coverage@0.2.3': - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} '@bufbuild/protobuf@1.10.1': resolution: {integrity: sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ==} @@ -409,12 +413,12 @@ packages: resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} engines: {node: '>=14'} - '@custom-elements-manifest/analyzer@0.10.5': - resolution: {integrity: sha512-Y9iUIhTDtcoaiH9XLwkK5POTxVJkcDuN9buCH4kQJmPmTMdm8Fhq7yk0l8Pu3TYC+RuXy6xA49+1IwvFJLF5mg==} + '@custom-elements-manifest/analyzer@0.10.10': + resolution: {integrity: sha512-R1pbKssP3Psb2OiGfheiUbXtBgTGQ0Vu5cn2CHSdZoJV66oZPSSw/TdCf8WlnQ6dfKSy5L8hNneClnmD80GEwA==} hasBin: true - '@custom-elements-manifest/find-dependencies@0.0.5': - resolution: {integrity: sha512-fKIMMZCDFSoL2ySUoz8knWgpV4jpb0lUXgLOvdZQMQFHxgxz1PqOJpUIypwvEVyKk3nEHRY4f10gNol02HjeCg==} + '@custom-elements-manifest/find-dependencies@0.0.6': + resolution: {integrity: sha512-2iVksJ156XuaeeC6jB6oMG6k9ROHS3W1delwJLL804yQMri9NnQW78JDCYMtFfW8b4locUG+3+hrtAHxk+fNGg==} '@discoveryjs/json-ext@0.5.7': resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} @@ -424,8 +428,8 @@ packages: resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==} engines: {node: '>=14.17.0'} - '@eamodio/eslint-lite-webpack-plugin@0.3.2': - resolution: {integrity: sha512-vTjob+y8He0tiRSplYngmRF6cqBKau5MKWH67HGPU7UtMS9PVs+6oIBPsdwEeWvCHrM6AIiPjWKv8T2R+sQ6Bg==} + '@eamodio/eslint-lite-webpack-plugin@0.3.4': + resolution: {integrity: sha512-rz0HMmv1HzEHY4iSepH1JeKLUGTZdKWof/V3pVDmq5UZY7r4lGSqwyVveNqGbSwX9PrSjHXHtHdjmbMmufHr5g==} engines: {node: '>= 22.12.0', pnpm: '>= 10.0.0'} peerDependencies: eslint: ^9.23.0 @@ -619,12 +623,8 @@ packages: resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.3.1': - resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.15.2': - resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} + '@eslint/config-helpers@0.4.0': + resolution: {integrity: sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/core@0.16.0': @@ -635,16 +635,16 @@ packages: resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.36.0': - resolution: {integrity: sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==} + '@eslint/js@9.37.0': + resolution: {integrity: sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.3.5': - resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} + '@eslint/plugin-kit@0.4.0': + resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@floating-ui/core@1.7.3': @@ -662,8 +662,8 @@ packages: '@github/catalyst@1.7.0': resolution: {integrity: sha512-qOAxrDdRZz9+v4y2WoAfh11rpRY/x4FRofPNmJyZFzAjubtzE3sCa/tAycWWufmQGoYiwwzL/qJBBgyg7avxPw==} - '@gitkraken/gitkraken-components@13.0.0-vnext.9': - resolution: {integrity: sha512-PvwOVrCk27aRG/J/Khx1EuipDfpULmmCi2YnKCQSFESY+uo12I2e7RIA4EPJ516/PaeQUvo6Zgps7Jjz0SOiRw==} + '@gitkraken/gitkraken-components@13.0.0-vnext.10': + resolution: {integrity: sha512-2V1ANVfW9mQZV/AQYCIt2yBIfqjet3WL05O/i2ptCbgmdqIVeDalNSQAodZWqtLqpXCIg59y7b2vtOzo6bYPBw==} peerDependencies: react: 19.0.0 @@ -698,138 +698,142 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@img/sharp-darwin-arm64@0.34.3': - resolution: {integrity: sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==} + '@img/colour@1.0.0': + resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.4': + resolution: {integrity: sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.34.3': - resolution: {integrity: sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==} + '@img/sharp-darwin-x64@0.34.4': + resolution: {integrity: sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] - '@img/sharp-libvips-darwin-arm64@1.2.0': - resolution: {integrity: sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==} + '@img/sharp-libvips-darwin-arm64@1.2.3': + resolution: {integrity: sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==} cpu: [arm64] os: [darwin] - '@img/sharp-libvips-darwin-x64@1.2.0': - resolution: {integrity: sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==} + '@img/sharp-libvips-darwin-x64@1.2.3': + resolution: {integrity: sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==} cpu: [x64] os: [darwin] - '@img/sharp-libvips-linux-arm64@1.2.0': - resolution: {integrity: sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==} + '@img/sharp-libvips-linux-arm64@1.2.3': + resolution: {integrity: sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==} cpu: [arm64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-arm@1.2.0': - resolution: {integrity: sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==} + '@img/sharp-libvips-linux-arm@1.2.3': + resolution: {integrity: sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==} cpu: [arm] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-ppc64@1.2.0': - resolution: {integrity: sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==} + '@img/sharp-libvips-linux-ppc64@1.2.3': + resolution: {integrity: sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==} cpu: [ppc64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-s390x@1.2.0': - resolution: {integrity: sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==} + '@img/sharp-libvips-linux-s390x@1.2.3': + resolution: {integrity: sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==} cpu: [s390x] os: [linux] libc: [glibc] - '@img/sharp-libvips-linux-x64@1.2.0': - resolution: {integrity: sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==} + '@img/sharp-libvips-linux-x64@1.2.3': + resolution: {integrity: sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==} cpu: [x64] os: [linux] libc: [glibc] - '@img/sharp-libvips-linuxmusl-arm64@1.2.0': - resolution: {integrity: sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==} + '@img/sharp-libvips-linuxmusl-arm64@1.2.3': + resolution: {integrity: sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==} cpu: [arm64] os: [linux] libc: [musl] - '@img/sharp-libvips-linuxmusl-x64@1.2.0': - resolution: {integrity: sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==} + '@img/sharp-libvips-linuxmusl-x64@1.2.3': + resolution: {integrity: sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==} cpu: [x64] os: [linux] libc: [musl] - '@img/sharp-linux-arm64@0.34.3': - resolution: {integrity: sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==} + '@img/sharp-linux-arm64@0.34.4': + resolution: {integrity: sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] libc: [glibc] - '@img/sharp-linux-arm@0.34.3': - resolution: {integrity: sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==} + '@img/sharp-linux-arm@0.34.4': + resolution: {integrity: sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] libc: [glibc] - '@img/sharp-linux-ppc64@0.34.3': - resolution: {integrity: sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==} + '@img/sharp-linux-ppc64@0.34.4': + resolution: {integrity: sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@img/sharp-linux-s390x@0.34.3': - resolution: {integrity: sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==} + '@img/sharp-linux-s390x@0.34.4': + resolution: {integrity: sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] libc: [glibc] - '@img/sharp-linux-x64@0.34.3': - resolution: {integrity: sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==} + '@img/sharp-linux-x64@0.34.4': + resolution: {integrity: sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] libc: [glibc] - '@img/sharp-linuxmusl-arm64@0.34.3': - resolution: {integrity: sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==} + '@img/sharp-linuxmusl-arm64@0.34.4': + resolution: {integrity: sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] libc: [musl] - '@img/sharp-linuxmusl-x64@0.34.3': - resolution: {integrity: sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==} + '@img/sharp-linuxmusl-x64@0.34.4': + resolution: {integrity: sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] libc: [musl] - '@img/sharp-wasm32@0.34.3': - resolution: {integrity: sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==} + '@img/sharp-wasm32@0.34.4': + resolution: {integrity: sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] - '@img/sharp-win32-arm64@0.34.3': - resolution: {integrity: sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==} + '@img/sharp-win32-arm64@0.34.4': + resolution: {integrity: sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [win32] - '@img/sharp-win32-ia32@0.34.3': - resolution: {integrity: sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==} + '@img/sharp-win32-ia32@0.34.4': + resolution: {integrity: sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.34.3': - resolution: {integrity: sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==} + '@img/sharp-win32-x64@0.34.4': + resolution: {integrity: sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] @@ -1028,30 +1032,30 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} deprecated: This functionality has been moved to @npmcli/fs - '@octokit/endpoint@11.0.0': - resolution: {integrity: sha512-hoYicJZaqISMAI3JfaDr1qMNi48OctWuOih1m80bkYow/ayPw6Jj52tqWJ6GEoFTk1gBqfanSoI1iY99Z5+ekQ==} + '@octokit/endpoint@11.0.1': + resolution: {integrity: sha512-7P1dRAZxuWAOPI7kXfio88trNi/MegQ0IJD3vfgC3b+LZo1Qe6gRJc2v0mz2USWWJOKrB2h5spXCzGbw+fAdqA==} engines: {node: '>= 20'} - '@octokit/graphql@9.0.1': - resolution: {integrity: sha512-j1nQNU1ZxNFx2ZtKmL4sMrs4egy5h65OMDmSbVyuCzjOcwsHq6EaYjOTGXPQxgfiN8dJ4CriYHk6zF050WEULg==} + '@octokit/graphql@9.0.2': + resolution: {integrity: sha512-iz6KzZ7u95Fzy9Nt2L8cG88lGRMr/qy1Q36ih/XVzMIlPDMYwaNLE/ENhqmIzgPrlNWiYJkwmveEetvxAgFBJw==} engines: {node: '>= 20'} - '@octokit/openapi-types@25.1.0': - resolution: {integrity: sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==} + '@octokit/openapi-types@26.0.0': + resolution: {integrity: sha512-7AtcfKtpo77j7Ts73b4OWhOZHTKo/gGY8bB3bNBQz4H+GRSWqx2yvj8TXRsbdTE0eRmYmXOEY66jM7mJ7LzfsA==} - '@octokit/request-error@7.0.0': - resolution: {integrity: sha512-KRA7VTGdVyJlh0cP5Tf94hTiYVVqmt2f3I6mnimmaVz4UG3gQV/k4mDJlJv3X67iX6rmN7gSHCF8ssqeMnmhZg==} + '@octokit/request-error@7.0.1': + resolution: {integrity: sha512-CZpFwV4+1uBrxu7Cw8E5NCXDWFNf18MSY23TdxCBgjw1tXXHvTrZVsXlW8hgFTOLw8RQR1BBrMvYRtuyaijHMA==} engines: {node: '>= 20'} - '@octokit/request@10.0.3': - resolution: {integrity: sha512-V6jhKokg35vk098iBqp2FBKunk3kMTXlmq+PtbV9Gl3TfskWlebSofU9uunVKhUN7xl+0+i5vt0TGTG8/p/7HA==} + '@octokit/request@10.0.5': + resolution: {integrity: sha512-TXnouHIYLtgDhKo+N6mXATnDBkV05VwbR0TtMWpgTHIoQdRQfCSzmy/LGqR1AbRMbijq/EckC/E3/ZNcU92NaQ==} engines: {node: '>= 20'} - '@octokit/types@14.1.0': - resolution: {integrity: sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==} + '@octokit/types@15.0.0': + resolution: {integrity: sha512-8o6yDfmoGJUIeR9OfYU0/TUJTnMPG2r68+1yEdUeG2Fdqpj8Qetg0ziKIgcBm0RW/j29H41WP37CYCEhp6GoHQ==} - '@opentelemetry/api-logs@0.205.0': - resolution: {integrity: sha512-wBlPk1nFB37Hsm+3Qy73yQSobVn28F4isnWIBvKpd5IUH/eat8bwcL02H9yzmHyyPmukeccSl2mbN5sDQZYnPg==} + '@opentelemetry/api-logs@0.206.0': + resolution: {integrity: sha512-yIVDu9jX//nV5wSMLZLdHdb1SKHIMj9k+wQVFtln5Flcgdldz9BkHtavvExQiJqBZg2OpEEJEZmzQazYztdz2A==} engines: {node: '>=8.0.0'} '@opentelemetry/api@1.9.0': @@ -1064,20 +1068,20 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/exporter-trace-otlp-http@0.205.0': - resolution: {integrity: sha512-vr2bwwPCSc9u7rbKc74jR+DXFvyMFQo9o5zs+H/fgbK672Whw/1izUKVf+xfWOdJOvuwTnfWxy+VAY+4TSo74Q==} + '@opentelemetry/exporter-trace-otlp-http@0.206.0': + resolution: {integrity: sha512-xiEhJZxE9yDb13FVW4XaF7J56boLv1NALOGEVu3F8jMC24iZmX5TSVRJCNGLWyy1Xb3N27Yu31kdSsmEBCnxyw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/otlp-exporter-base@0.205.0': - resolution: {integrity: sha512-2MN0C1IiKyo34M6NZzD6P9Nv9Dfuz3OJ3rkZwzFmF6xzjDfqqCTatc9v1EpNfaP55iDOCLHFyYNCgs61FFgtUQ==} + '@opentelemetry/otlp-exporter-base@0.206.0': + resolution: {integrity: sha512-Rv54oSNKMHYS5hv+H5EGksfBUtvPQWFTK+Dk6MjJun9tOijCsFJrhRFvAqg5d67TWSMn+ZQYRKIeXh5oLVrpAQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/otlp-transformer@0.205.0': - resolution: {integrity: sha512-KmObgqPtk9k/XTlWPJHdMbGCylRAmMJNXIRh6VYJmvlRDMfe+DonH41G7eenG8t4FXn3fxOGh14o/WiMRR6vPg==} + '@opentelemetry/otlp-transformer@0.206.0': + resolution: {integrity: sha512-Li2Cik1WnmNbU2mmTnw7DxvRiXhMcnAuTfAclP8y/zy7h5+GrLDpTZ+Z0XUs+Q3MLkb/h3ry4uFrC/z+2a6X7g==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 @@ -1088,8 +1092,8 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/sdk-logs@0.205.0': - resolution: {integrity: sha512-nyqhNQ6eEzPWQU60Nc7+A5LIq8fz3UeIzdEVBQYefB4+msJZ2vuVtRuk9KxPMw1uHoHDtYEwkr2Ct0iG29jU8w==} + '@opentelemetry/sdk-logs@0.206.0': + resolution: {integrity: sha512-SQ2yTmqe4Mw9RI3a/glVkfjWPsXh6LySvnljXubiZq4zu+UP8NMJt2j82ZsYb+KpD7Eu+/41/7qlJnjdeVjz7Q==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.4.0 <1.10.0' @@ -1300,12 +1304,12 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@playwright/browser-chromium@1.55.0': - resolution: {integrity: sha512-HxG0+6v8NGLFLYMxrGb4T4DAmKwwx6C0V3uIn/i91tOVqcNnaBBllhpxLEqXCnxjprL3HDDMXsVPjk1/vsCVAw==} + '@playwright/browser-chromium@1.56.0': + resolution: {integrity: sha512-+OABx0PwbzoWXO5qOmonvQlIZq0u89XpDkRYf+ZTOs+wsI3r/NV90rzGr8nsJZTj7o10tdPMmuGmZ3OKP9ag4Q==} engines: {node: '>=18'} - '@playwright/test@1.55.0': - resolution: {integrity: sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==} + '@playwright/test@1.56.0': + resolution: {integrity: sha512-Tzh95Twig7hUwwNe381/K3PggZBZblKUe2wv25oIpzWLr6Z0m4KgV1ZVIjnR6GM9ANEqjZD7XsZEa6JL/7YEgg==} engines: {node: '>=18'} hasBin: true @@ -1597,8 +1601,8 @@ packages: '@types/mocha@10.0.10': resolution: {integrity: sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==} - '@types/node@20.14.15': - resolution: {integrity: sha512-Fz1xDMCF/B00/tYSVMlmK7hVeLh7jE5f3B7X1/hmV0MJBwE27KlS7EvD/Yp+z1lm8mVhwV5w+n8jOZG8AfTlKw==} + '@types/node@20.16.15': + resolution: {integrity: sha512-DV58qQz9dBMqVVn+qnKwGa51QzCD4YM/tQM16qLKxdf5tqz5W4QwtrMzjSTbabN1cFTSuyxVYBy+QWHjWW8X/g==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -1606,8 +1610,8 @@ packages: '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - '@types/react-dom@19.0.4': - resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==} + '@types/react-dom@19.0.6': + resolution: {integrity: sha512-lo6MuY+rFr8kIiFnr+7TzO+Av0wUPcEcepiPV4epGP0eTQpkDfp9czudg73isV8UxKauCUNlL1N8fXhcnx4iBw==} peerDependencies: '@types/react': ^19.0.0 @@ -1616,8 +1620,8 @@ packages: peerDependencies: '@types/react': '*' - '@types/react@19.0.12': - resolution: {integrity: sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==} + '@types/react@19.0.14': + resolution: {integrity: sha512-ixLZ7zG7j1fM0DijL9hDArwhwcCb4vqmePgwtV0GfnkHRSCUEv4LvzarcTdhoqgyMznUx/EhoTUv31CKZzkQlw==} '@types/sarif@2.1.7': resolution: {integrity: sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==} @@ -1637,78 +1641,119 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@types/vscode@1.92.0': - resolution: {integrity: sha512-DcZoCj17RXlzB4XJ7IfKdPTcTGDLYvTOcTNkvtjXWF+K2TlKzHHkBEXNWQRpBIXixNEUgx39cQeTFunY0E2msw==} + '@types/vscode@1.95.0': + resolution: {integrity: sha512-0LBD8TEiNbet3NvWsmn59zLzOFu/txSlGxnv5yAFHCrhG9WvAnR3IvfHzMOs2aeWqgvNjq9pO99IUw8d3n+unw==} '@types/warning@3.0.3': resolution: {integrity: sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==} - '@types/webpack@5.28.5': - resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==} - '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} '@types/yargs@17.0.33': resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - '@typescript-eslint/eslint-plugin@8.45.0': - resolution: {integrity: sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==} + '@typescript-eslint/eslint-plugin@8.46.0': + resolution: {integrity: sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.46.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.46.0': + resolution: {integrity: sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.45.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.45.0': - resolution: {integrity: sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==} + '@typescript-eslint/parser@8.46.1': + resolution: {integrity: sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.45.0': - resolution: {integrity: sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==} + '@typescript-eslint/project-service@8.46.0': + resolution: {integrity: sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.46.1': + resolution: {integrity: sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.45.0': - resolution: {integrity: sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==} + '@typescript-eslint/scope-manager@8.46.0': + resolution: {integrity: sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/scope-manager@8.46.1': + resolution: {integrity: sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.45.0': - resolution: {integrity: sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w==} + '@typescript-eslint/tsconfig-utils@8.46.0': + resolution: {integrity: sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.45.0': - resolution: {integrity: sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==} + '@typescript-eslint/tsconfig-utils@8.46.1': + resolution: {integrity: sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.46.0': + resolution: {integrity: sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.45.0': - resolution: {integrity: sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==} + '@typescript-eslint/types@8.46.0': + resolution: {integrity: sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/types@8.46.1': + resolution: {integrity: sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.46.0': + resolution: {integrity: sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/typescript-estree@8.45.0': - resolution: {integrity: sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==} + '@typescript-eslint/typescript-estree@8.46.1': + resolution: {integrity: sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.45.0': - resolution: {integrity: sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==} + '@typescript-eslint/utils@8.46.0': + resolution: {integrity: sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.45.0': - resolution: {integrity: sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==} + '@typescript-eslint/utils@8.46.1': + resolution: {integrity: sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.46.0': + resolution: {integrity: sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/visitor-keys@8.46.1': + resolution: {integrity: sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typespec/ts-http-runtime@0.3.1': @@ -1818,11 +1863,11 @@ packages: cpu: [x64] os: [win32] - '@vscode/codicons@0.0.40': - resolution: {integrity: sha512-R8sEDXthD86JHsk3xERrMcTN6sMovbk1AXYB5/tGoEYCE8DWwya6al5VLrAmQYXC1bQhUHIfHALj8ijQUs11cQ==} + '@vscode/codicons@0.0.41': + resolution: {integrity: sha512-v6/8nx76zau3Joxjzi3eN/FVw+7jKBq4j7LTZY5FhFhq2g0OoFebZ3vRZbv/pUopGpbCnJJ4FOz+NzbjVsmoiw==} - '@vscode/test-cli@0.0.11': - resolution: {integrity: sha512-qO332yvzFqGhBMJrp6TdwbIydiHgCtxXc2Nl6M58mbH/Z+0CyLR76Jzv4YWPEthhrARprzCRJUqzFvTHFhTj7Q==} + '@vscode/test-cli@0.0.12': + resolution: {integrity: sha512-iYN0fDg29+a2Xelle/Y56Xvv7Nc8Thzq4VwpzAF/SIE6918rDicqfsQxV6w1ttr2+SOm+10laGuY9FG2ptEKsQ==} engines: {node: '>=18'} hasBin: true @@ -1830,8 +1875,8 @@ packages: resolution: {integrity: sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg==} engines: {node: '>=16'} - '@vscode/test-web@0.0.73': - resolution: {integrity: sha512-xCvUsZi33/asatnFZHOUzrlcfjwqy+I34tjG0pM4LZmDV1jAeczNAyFRZw6VJE+uSAy9N4ncZz/cemdBaU+yZg==} + '@vscode/test-web@0.0.74': + resolution: {integrity: sha512-rXIcru66y56j1RPOhFJYSNs5MAw6yZCFUktqa5tPrxsRel/Lj6vDszq8E47XsVN1NjwsLj8L3FMqwR4/B+0QmA==} engines: {node: '>=20'} hasBin: true @@ -1845,13 +1890,13 @@ packages: cpu: [x64] os: [alpine] - '@vscode/vsce-sign-darwin-arm64@2.0.6': - resolution: {integrity: sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==} + '@vscode/vsce-sign-darwin-arm64@2.0.2': + resolution: {integrity: sha512-rz8F4pMcxPj8fjKAJIfkUT8ycG9CjIp888VY/6pq6cuI2qEzQ0+b5p3xb74CJnBbSC0p2eRVoe+WgNCAxCLtzQ==} cpu: [arm64] os: [darwin] - '@vscode/vsce-sign-darwin-x64@2.0.6': - resolution: {integrity: sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==} + '@vscode/vsce-sign-darwin-x64@2.0.2': + resolution: {integrity: sha512-MCjPrQ5MY/QVoZ6n0D92jcRb7eYvxAujG/AH2yM6lI0BspvJQxp0o9s5oiAM9r32r9tkLpiy5s2icsbwefAQIw==} cpu: [x64] os: [darwin] @@ -1880,8 +1925,8 @@ packages: cpu: [x64] os: [win32] - '@vscode/vsce-sign@2.0.7': - resolution: {integrity: sha512-cz0GFW8qCxpypOy3y509u26K1FIPMlDIHBwGmDyvEbgoma2v3y5YIHHuijr8zCYBp9kzCCOJd28s/0PG7cA7ew==} + '@vscode/vsce-sign@2.0.8': + resolution: {integrity: sha512-H7p8E11cZMj6mt8xIi3QXZ7dSU/2MH3Y7c+5JfUhHAV4xfaPNc8ozwLVK282c6ah596KoIJIdPUlNHV7Qs/5JA==} '@vscode/vsce@3.6.2': resolution: {integrity: sha512-gvBfarWF+Ii20ESqjA3dpnPJpQJ8fFJYtcWtjwbRADommCzGg1emtmb34E+DKKhECYvaVyAl+TF9lWS/3GSPvg==} @@ -1967,6 +2012,60 @@ packages: engines: {node: '>=10.0.0'} deprecated: this version is no longer supported, please update to at least 0.8.* + '@xn-sakina/rml-darwin-arm64@2.6.0': + resolution: {integrity: sha512-RuFHj6ro6Q24gPqNQGvH4uxpsvbgqBBy+ZUK+jbMuMaw4wyti7F6klQWuikBJAxhWpmRbhAB/jrq0PC82qlh5A==} + engines: {node: '>=14'} + cpu: [arm64] + os: [darwin] + + '@xn-sakina/rml-darwin-x64@2.6.0': + resolution: {integrity: sha512-85bsP7viqtgw5nVYBdl8I4c2+q4sYFcBMTeFnTf4RqhUUwBLerP7D+XXnWwv3waO+aZ0Fe0ij9Fji3oTiREOCg==} + engines: {node: '>=14'} + cpu: [x64] + os: [darwin] + + '@xn-sakina/rml-linux-arm-gnueabihf@2.6.0': + resolution: {integrity: sha512-ySI529TPraG1Mf/YiKhLLNGJ1js0Y3BnZRAihUpF4IlyFKmeL3slXEdvK2tVndyX2O21EYWv/DcSAmFMNOolfA==} + engines: {node: '>=14'} + cpu: [arm] + os: [linux] + + '@xn-sakina/rml-linux-arm64-gnu@2.6.0': + resolution: {integrity: sha512-Ytzkmty4vVWAqe+mbu/ql5dqwUH49eVgPT38uJK78LTZRsdogxlQbuAoLKlb/N8CIXAE7BRoywz3lSEGToXylw==} + engines: {node: '>=14'} + cpu: [arm64] + os: [linux] + + '@xn-sakina/rml-linux-arm64-musl@2.6.0': + resolution: {integrity: sha512-DIBSDWlTmWk+r6Xp7mL9Cw8DdWNyJGg7YhOV1sSSRykdGs2TNtS3z0nbHRuUBMqrbtDk0IwqFSepLx12Bix/zw==} + engines: {node: '>=14'} + cpu: [arm64] + os: [linux] + + '@xn-sakina/rml-linux-x64-gnu@2.6.0': + resolution: {integrity: sha512-8Pks6hMicFGWYQmylKul7Gmn64pG4HkRL7skVWEPAF0LZHeI5yvV/EnQUnXXbxPp4Viy2H4420jl6BVS7Uetng==} + engines: {node: '>=14'} + cpu: [x64] + os: [linux] + + '@xn-sakina/rml-linux-x64-musl@2.6.0': + resolution: {integrity: sha512-xHX/rNKcATVrJt2no0FdO6kqnV4P5cP/3MgHA0KwhD/YJmWa66JIfWtzrPv9n/s0beGSorLkh8PLt5lVLFGvlQ==} + engines: {node: '>=14'} + cpu: [x64] + os: [linux] + + '@xn-sakina/rml-win32-arm64-msvc@2.6.0': + resolution: {integrity: sha512-aIOu5frDsxRp5naN6YjBtbCHS4K2WHIx2EClGclv3wGFrOn1oSROxpVOV/MODUuWITj/26pWbZ/tnbvva6ZV8A==} + engines: {node: '>=14'} + cpu: [arm64] + os: [win32] + + '@xn-sakina/rml-win32-x64-msvc@2.6.0': + resolution: {integrity: sha512-XXbzy2gLEs6PpHdM2IUC5QujOIjz6LpSQpJ+ow43gVc7BhagIF5YlMyTFZCbJehjK9yNgPCzdrzsukCjsH5kIA==} + engines: {node: '>=14'} + cpu: [x64] + os: [win32] + '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -2044,8 +2143,8 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - ansi-escapes@7.1.0: - resolution: {integrity: sha512-YdhtCd19sKRKfAAUsrcC1wzm4JuzJoiX4pOJqIoW2qmKj5WzG/dL8uUJ0361zaXtHqK7gEhOwtAtz7t3Yq3X5g==} + ansi-escapes@7.1.1: + resolution: {integrity: sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==} engines: {node: '>=18'} ansi-regex@5.0.1: @@ -2171,8 +2270,8 @@ packages: azure-devops-node-api@12.5.0: resolution: {integrity: sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==} - b4a@1.7.1: - resolution: {integrity: sha512-ZovbrBV0g6JxK5cGUF1Suby1vLfKjv4RWi8IxoaO/Mon8BDD9I21RxjHFtgQ+kskJqLAVyQZly3uMBui+vhc8Q==} + b4a@1.7.3: + resolution: {integrity: sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==} peerDependencies: react-native-b4a: '*' peerDependenciesMeta: @@ -2182,11 +2281,16 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - bare-events@2.7.0: - resolution: {integrity: sha512-b3N5eTW1g7vXkw+0CXh/HazGTcO5KYuu/RCNaJbDMPI6LHDi+7qe8EmxKUVe1sUbY2KZOVZFyj62x0OEz9qyAA==} + bare-events@2.8.0: + resolution: {integrity: sha512-AOhh6Bg5QmFIXdViHbMc2tLDsBIRxdkIaIddPslJF9Z5De3APBScuqGP2uThXnIpqFrgoxMNC6km7uXNIMLHXA==} + peerDependencies: + bare-abort-controller: '*' + peerDependenciesMeta: + bare-abort-controller: + optional: true - bare-fs@4.4.4: - resolution: {integrity: sha512-Q8yxM1eLhJfuM7KXVP3zjhBvtMJCYRByoTT+wHXjpdMELv0xICFJX+1w4c7csa+WZEOsq4ItJ4RGwvzid6m/dw==} + bare-fs@4.4.10: + resolution: {integrity: sha512-arqVF+xX/rJHwrONZaSPhlzleT2gXwVs9rsAe1p1mIVwWZI2A76/raio+KwwxfWMO8oV9Wo90EaUkS2QwVmy4w==} engines: {bare: '>=1.16.0'} peerDependencies: bare-buffer: '*' @@ -2218,8 +2322,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.8.6: - resolution: {integrity: sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==} + baseline-browser-mapping@2.8.16: + resolution: {integrity: sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==} hasBin: true basic-auth@2.0.1: @@ -2268,8 +2372,8 @@ packages: browserify-zlib@0.1.4: resolution: {integrity: sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==} - browserslist@4.26.2: - resolution: {integrity: sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==} + browserslist@4.26.3: + resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -2296,10 +2400,15 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} - c8@9.1.0: - resolution: {integrity: sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==} - engines: {node: '>=14.14.0'} + c8@10.1.3: + resolution: {integrity: sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==} + engines: {node: '>=18'} hasBin: true + peerDependencies: + monocart-coverage-reports: ^2 + peerDependenciesMeta: + monocart-coverage-reports: + optional: true cacache@16.1.3: resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} @@ -2335,8 +2444,8 @@ packages: caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - caniuse-lite@1.0.30001743: - resolution: {integrity: sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==} + caniuse-lite@1.0.30001749: + resolution: {integrity: sha512-0rw2fJOmLfnzCRbkm8EyHL8SvI2Apu5UbnQuTsJ0ClgrH8hcwFooJ1s5R0EP8o8aVrFu8++ae29Kt9/gZAZp/Q==} case@1.6.3: resolution: {integrity: sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==} @@ -2441,17 +2550,10 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - color-support@1.1.3: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true - color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - colord@2.9.3: resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} @@ -2880,8 +2982,8 @@ packages: engines: {node: '>=0.10'} hasBin: true - detect-libc@2.1.0: - resolution: {integrity: sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} diff2html@3.4.52: @@ -2961,8 +3063,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.222: - resolution: {integrity: sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==} + electron-to-chromium@1.5.234: + resolution: {integrity: sha512-RXfEp2x+VRYn8jbKfQlRImzoJU01kyDvVPBmG39eU2iuRVhuS6vQNocB8J0/8GrIMLnPzgz4eW6WiRnJkTuNWg==} emoji-regex@10.5.0: resolution: {integrity: sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==} @@ -3006,8 +3108,8 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - envinfo@7.14.0: - resolution: {integrity: sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==} + envinfo@7.17.0: + resolution: {integrity: sha512-GpfViocsFM7viwClFgxK26OtjMlKN67GCR5v6ASFkotxtpBWd9d+vNy+AH7F2E1TUkMDZ8P/dDPZX71/NG8xnQ==} engines: {node: '>=4'} hasBin: true @@ -3033,9 +3135,6 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@0.9.3: - resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} - es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -3055,8 +3154,8 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - esbuild-loader@4.3.0: - resolution: {integrity: sha512-D7HeJNdkDKKMarPQO/3dlJT6RwN2YJO7ENU6RPlpOz5YxSHnUNi2yvW41Bckvi1EVwctIaLzlb0ni5ag2GINYA==} + esbuild-loader@4.4.0: + resolution: {integrity: sha512-4J+hXTpTtEdzUNLoY8ReqDNJx2NoldfiljRCiKbeYUuZmVaiJeDqFgyAzz8uOopaekwRoCcqBFyEroGQLFVZ1g==} peerDependencies: webpack: ^4.40.0 || ^5.0.0 @@ -3170,8 +3269,8 @@ packages: peerDependencies: eslint: '>= 8' - eslint-plugin-wc@3.0.1: - resolution: {integrity: sha512-0p1wkSlA2Ue3FA4qW+5LZ+15sy0p1nUyVl1eyBMLq4rtN1LtE9IdI49BXNWMz8N8bM/y7Ulx8SWGAni5f8XO5g==} + eslint-plugin-wc@3.0.2: + resolution: {integrity: sha512-siwTrxPTw6GU2JmP3faInw8nhi0ZCnKsiSRM3j7EAkZmBTGYdDAToeseLYsvPrc5Urp/vPz+g7Ewh7XcICLxww==} peerDependencies: eslint: '>=8.40.0' @@ -3191,8 +3290,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.36.0: - resolution: {integrity: sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==} + eslint@9.37.0: + resolution: {integrity: sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -3230,8 +3329,8 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - events-universal@1.0.0: - resolution: {integrity: sha512-1KVXP1Oq8SiC0HsRraCryA4XGrZ2uJgIt/h4X+mB/8pzMKE7L8yBDN2lBlqJZeUwLAt7kf80m/5GX3HvoCrSGA==} + events-universal@1.0.1: + resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} @@ -3407,6 +3506,10 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} deprecated: This package is no longer supported. + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -3427,8 +3530,8 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.10.1: - resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + get-tsconfig@4.12.0: + resolution: {integrity: sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw==} github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} @@ -3716,8 +3819,8 @@ packages: resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} engines: {node: '>=12'} - index-to-position@1.1.0: - resolution: {integrity: sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==} + index-to-position@1.2.0: + resolution: {integrity: sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==} engines: {node: '>=18'} infer-owner@1.0.4: @@ -3762,9 +3865,6 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-arrayish@0.3.4: - resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} - is-async-function@2.1.1: resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} engines: {node: '>= 0.4'} @@ -3824,8 +3924,8 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-function@1.1.0: - resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} engines: {node: '>= 0.4'} is-glob@4.0.3: @@ -3880,6 +3980,10 @@ packages: resolution: {integrity: sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==} engines: {node: '>=6'} + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + is-plain-obj@1.1.0: resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} engines: {node: '>=0.10.0'} @@ -4140,8 +4244,8 @@ packages: lit@3.3.1: resolution: {integrity: sha512-Ksr/8L3PTapbdXJCk+EJVB78jDodUMaP54gD24W186zGRARvwrsPfS60wae/SSCTCNZVPd1chXqio1qHQmu4NA==} - loader-runner@4.3.0: - resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + loader-runner@4.3.1: + resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} engines: {node: '>=6.11.5'} loader-utils@2.0.4: @@ -4219,8 +4323,8 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.2.1: - resolution: {integrity: sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==} + lru-cache@11.2.2: + resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} engines: {node: 20 || >=22} lru-cache@6.0.0: @@ -4255,8 +4359,8 @@ packages: resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true - marked@16.3.0: - resolution: {integrity: sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==} + marked@16.4.0: + resolution: {integrity: sha512-CTPAcRBq57cn3R8n3hwc2REddc28hjR7RzDXQ+lXLmMJYqn20BaI2cGw6QjgZGIgVfp2Wdfw4aMzgNteQ6qJgQ==} engines: {node: '>= 20'} hasBin: true @@ -4407,8 +4511,8 @@ packages: mnemonist@0.39.8: resolution: {integrity: sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ==} - mocha@11.7.2: - resolution: {integrity: sha512-lkqVJPmqqG/w5jmmFtiRvtA2jkDyNVUcefFJKb2uyX4dekk8Okgqop3cgbFiaIvj8uCRJVTP5x9dfxGyXm2jvQ==} + mocha@11.7.4: + resolution: {integrity: sha512-1jYAaY8x0kAZ0XszLWu14pzsf4KV740Gld4HXkhNTXwcHx4AUEDkPzgEHg9CM5dVcW+zv036tjpsEbLraPJj4w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true @@ -4440,8 +4544,8 @@ packages: napi-build-utils@2.0.0: resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} - napi-postinstall@0.3.3: - resolution: {integrity: sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==} + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} hasBin: true @@ -4462,8 +4566,8 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - node-abi@3.77.0: - resolution: {integrity: sha512-DSmt0OEcLoK4i3NuscSbGjOf3bqiDEutejqENSplMSFA/gmB8mkED9G4pKWnPl7MDU4rSHebKPHeitpDfyH0cQ==} + node-abi@3.78.0: + resolution: {integrity: sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ==} engines: {node: '>=10'} node-abort-controller@3.1.1: @@ -4489,8 +4593,8 @@ packages: engines: {node: ^12.13 || ^14.13 || >=16} hasBin: true - node-releases@2.0.21: - resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==} + node-releases@2.0.23: + resolution: {integrity: sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==} node-sarif-builder@3.2.0: resolution: {integrity: sha512-kVIOdynrF2CRodHZeP/97Rh1syTUHBNiw17hUCIVhlhEsWlfJm19MuO56s4MdKbr22xWx6mzMnNAgXzVlIYM9Q==} @@ -4611,8 +4715,8 @@ packages: os-browserify@0.3.0: resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} - ovsx@0.10.5: - resolution: {integrity: sha512-jfulG5k9vjWcolg2kubC51t1eHKA8ANPcKCQKaWPfOsJZ9VlIppP0Anf8pJ1LJHZFHoRmeMXITG9a5NXHwY9tA==} + ovsx@0.10.6: + resolution: {integrity: sha512-MZ7pgQ+IS5kumAfZGnhEjmdOUwW0UlmlekMwuA5DeUJeft7jFu9fTIEhH71ypjdUSpdqchodoKgb5y/ilh7b5g==} engines: {node: '>= 20'} hasBin: true @@ -4782,13 +4886,13 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} - playwright-core@1.55.0: - resolution: {integrity: sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==} + playwright-core@1.56.0: + resolution: {integrity: sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==} engines: {node: '>=18'} hasBin: true - playwright@1.55.0: - resolution: {integrity: sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==} + playwright@1.56.0: + resolution: {integrity: sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==} engines: {node: '>=18'} hasBin: true @@ -5280,6 +5384,10 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + rs-module-lexer@2.6.0: + resolution: {integrity: sha512-aT0lO0icZ3Hq0IWvo+ORgVc6BJDoKfaDBdRIDQkL2PtBnFQJ0DuvExiiWI4GxjEjH8Yyro++NPArHFaD8bvS9w==} + engines: {node: '>=14'} + run-applescript@7.1.0: resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} engines: {node: '>=18'} @@ -5457,8 +5565,8 @@ packages: webpack: optional: true - sass@1.90.0: - resolution: {integrity: sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==} + sass@1.93.2: + resolution: {integrity: sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==} engines: {node: '>=14.0.0'} hasBin: true @@ -5472,8 +5580,8 @@ packages: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} - schema-utils@4.3.2: - resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==} + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} engines: {node: '>= 10.13.0'} secretlint@10.2.2: @@ -5489,8 +5597,8 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true @@ -5525,8 +5633,8 @@ packages: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} - sharp@0.34.3: - resolution: {integrity: sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==} + sharp@0.34.4: + resolution: {integrity: sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@2.0.0: @@ -5578,9 +5686,6 @@ packages: resolution: {integrity: sha512-1sbhsxqI+I2tqlmjbz99GXNmZtr6tKIyEgGGnJw/MKGblalqk/XoOYYFJlBzTKZCxx8kLaD3FD5s9BEEjx5Pyg==} engines: {node: '>=10'} - simple-swizzle@0.2.4: - resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} - sinon@21.0.0: resolution: {integrity: sha512-TOgRcwFPbfGtpqvZw+hyqJDvqfapr1qUlOizROIk4bBLjlsjlB00Pg6wMFXNtJRpu+eCZuVOaLatG7M8105kAw==} @@ -5769,6 +5874,10 @@ packages: peerDependencies: postcss: ^8.4.32 + supports-color@10.2.2: + resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} + engines: {node: '>=18'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -5777,10 +5886,6 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} - supports-color@9.4.0: - resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==} - engines: {node: '>=12'} - supports-hyperlinks@3.2.0: resolution: {integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==} engines: {node: '>=14.18'} @@ -5814,8 +5919,8 @@ packages: resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} engines: {node: '>=10.0.0'} - tapable@2.2.3: - resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==} + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} tar-fs@2.1.4: @@ -5860,9 +5965,9 @@ packages: engines: {node: '>=10'} hasBin: true - test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} + test-exclude@7.0.1: + resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + engines: {node: '>=18'} text-decoder@1.2.3: resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} @@ -6001,8 +6106,8 @@ packages: typed-rest-client@1.8.11: resolution: {integrity: sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==} - typescript-eslint@8.45.0: - resolution: {integrity: sha512-qzDmZw/Z5beNLUrXfd0HIW6MzIaAV5WNDxmMs9/3ojGOpYavofgNAAD/nC6tGV2PczIi0iw8vot2eAe/sBn7zg==} + typescript-eslint@8.46.0: + resolution: {integrity: sha512-6+ZrB6y2bT2DX3K+Qd9vn7OFOJR+xSLDj+Aw/N3zBwUt27uTw2sw2TE2+UcY1RiyBZkaGbTkVg9SSdPNUG6aUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -6018,8 +6123,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - typescript@5.9.2: - resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true @@ -6052,8 +6157,8 @@ packages: underscore@1.13.7: resolution: {integrity: sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==} - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} unfetch@4.2.0: resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} @@ -6176,8 +6281,8 @@ packages: resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} engines: {node: '>=10.13.0'} - webpack@5.101.3: - resolution: {integrity: sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==} + webpack@5.102.1: + resolution: {integrity: sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -6369,7 +6474,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@azure/identity@4.12.0': + '@azure/identity@4.13.0': dependencies: '@azure/abort-controller': 2.1.2 '@azure/core-auth': 1.10.1 @@ -6378,8 +6483,8 @@ snapshots: '@azure/core-tracing': 1.3.1 '@azure/core-util': 1.13.1 '@azure/logger': 1.3.0 - '@azure/msal-browser': 4.23.0 - '@azure/msal-node': 3.7.4 + '@azure/msal-browser': 4.25.0 + '@azure/msal-node': 3.8.0 open: 10.2.0 tslib: 2.8.1 transitivePeerDependencies: @@ -6392,15 +6497,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@azure/msal-browser@4.23.0': + '@azure/msal-browser@4.25.0': dependencies: - '@azure/msal-common': 15.12.0 + '@azure/msal-common': 15.13.0 - '@azure/msal-common@15.12.0': {} + '@azure/msal-common@15.13.0': {} - '@azure/msal-node@3.7.4': + '@azure/msal-node@3.8.0': dependencies: - '@azure/msal-common': 15.12.0 + '@azure/msal-common': 15.13.0 jsonwebtoken: 9.0.2 uuid: 8.3.2 @@ -6414,15 +6519,15 @@ snapshots: '@babel/runtime@7.28.4': {} - '@bcoe/v8-coverage@0.2.3': {} + '@bcoe/v8-coverage@1.0.2': {} '@bufbuild/protobuf@1.10.1': {} '@ctrl/tinycolor@4.2.0': {} - '@custom-elements-manifest/analyzer@0.10.5': + '@custom-elements-manifest/analyzer@0.10.10': dependencies: - '@custom-elements-manifest/find-dependencies': 0.0.5 + '@custom-elements-manifest/find-dependencies': 0.0.6 '@github/catalyst': 1.7.0 '@web/config-loader': 0.1.3 chokidar: 3.5.2 @@ -6433,26 +6538,19 @@ snapshots: globby: 11.0.4 typescript: 5.4.5 - '@custom-elements-manifest/find-dependencies@0.0.5': + '@custom-elements-manifest/find-dependencies@0.0.6': dependencies: - es-module-lexer: 0.9.3 + rs-module-lexer: 2.6.0 '@discoveryjs/json-ext@0.5.7': {} '@discoveryjs/json-ext@0.6.3': {} - '@eamodio/eslint-lite-webpack-plugin@0.3.2(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(eslint@9.36.0(jiti@2.4.0))(webpack-cli@6.0.1)(webpack@5.101.3)': + '@eamodio/eslint-lite-webpack-plugin@0.3.4(eslint@9.37.0(jiti@2.4.0))(webpack@5.102.1)': dependencies: - '@types/eslint': 9.6.1 - '@types/webpack': 5.28.5(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) - eslint: 9.36.0(jiti@2.4.0) + eslint: 9.37.0(jiti@2.4.0) minimatch: 10.0.3 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - - webpack-cli + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) '@emnapi/core@1.5.0': dependencies: @@ -6548,18 +6646,18 @@ snapshots: '@esbuild/win32-x64@0.25.10': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.4.0))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.37.0(jiti@2.4.0))': dependencies: - eslint: 9.36.0(jiti@2.4.0) + eslint: 9.37.0(jiti@2.4.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} - '@eslint/compat@1.4.0(eslint@9.36.0(jiti@2.4.0))': + '@eslint/compat@1.4.0(eslint@9.37.0(jiti@2.4.0))': dependencies: '@eslint/core': 0.16.0 optionalDependencies: - eslint: 9.36.0(jiti@2.4.0) + eslint: 9.37.0(jiti@2.4.0) '@eslint/config-array@0.21.0': dependencies: @@ -6569,11 +6667,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.3.1': {} - - '@eslint/core@0.15.2': + '@eslint/config-helpers@0.4.0': dependencies: - '@types/json-schema': 7.0.15 + '@eslint/core': 0.16.0 '@eslint/core@0.16.0': dependencies: @@ -6593,13 +6689,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.36.0': {} + '@eslint/js@9.37.0': {} '@eslint/object-schema@2.1.6': {} - '@eslint/plugin-kit@0.3.5': + '@eslint/plugin-kit@0.4.0': dependencies: - '@eslint/core': 0.15.2 + '@eslint/core': 0.16.0 levn: 0.4.1 '@floating-ui/core@1.7.3': @@ -6617,13 +6713,13 @@ snapshots: '@github/catalyst@1.7.0': {} - '@gitkraken/gitkraken-components@13.0.0-vnext.9(@types/react@19.0.12)(react@19.0.0)': + '@gitkraken/gitkraken-components@13.0.0-vnext.10(@types/react@19.0.14)(react@19.0.0)': dependencies: '@axosoft/react-virtualized': 9.22.3-gitkraken.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0) classnames: 2.5.1 re-resizable: 6.11.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react: 19.0.0 - react-bootstrap: 2.10.7(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react-bootstrap: 2.10.7(@types/react@19.0.14)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react-dom: 19.0.0(react@19.0.0) react-dragula: 1.1.17 react-onclickoutside: 6.13.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -6660,90 +6756,92 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@img/sharp-darwin-arm64@0.34.3': + '@img/colour@1.0.0': {} + + '@img/sharp-darwin-arm64@0.34.4': optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.2.0 + '@img/sharp-libvips-darwin-arm64': 1.2.3 optional: true - '@img/sharp-darwin-x64@0.34.3': + '@img/sharp-darwin-x64@0.34.4': optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.2.0 + '@img/sharp-libvips-darwin-x64': 1.2.3 optional: true - '@img/sharp-libvips-darwin-arm64@1.2.0': + '@img/sharp-libvips-darwin-arm64@1.2.3': optional: true - '@img/sharp-libvips-darwin-x64@1.2.0': + '@img/sharp-libvips-darwin-x64@1.2.3': optional: true - '@img/sharp-libvips-linux-arm64@1.2.0': + '@img/sharp-libvips-linux-arm64@1.2.3': optional: true - '@img/sharp-libvips-linux-arm@1.2.0': + '@img/sharp-libvips-linux-arm@1.2.3': optional: true - '@img/sharp-libvips-linux-ppc64@1.2.0': + '@img/sharp-libvips-linux-ppc64@1.2.3': optional: true - '@img/sharp-libvips-linux-s390x@1.2.0': + '@img/sharp-libvips-linux-s390x@1.2.3': optional: true - '@img/sharp-libvips-linux-x64@1.2.0': + '@img/sharp-libvips-linux-x64@1.2.3': optional: true - '@img/sharp-libvips-linuxmusl-arm64@1.2.0': + '@img/sharp-libvips-linuxmusl-arm64@1.2.3': optional: true - '@img/sharp-libvips-linuxmusl-x64@1.2.0': + '@img/sharp-libvips-linuxmusl-x64@1.2.3': optional: true - '@img/sharp-linux-arm64@0.34.3': + '@img/sharp-linux-arm64@0.34.4': optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.2.0 + '@img/sharp-libvips-linux-arm64': 1.2.3 optional: true - '@img/sharp-linux-arm@0.34.3': + '@img/sharp-linux-arm@0.34.4': optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.2.0 + '@img/sharp-libvips-linux-arm': 1.2.3 optional: true - '@img/sharp-linux-ppc64@0.34.3': + '@img/sharp-linux-ppc64@0.34.4': optionalDependencies: - '@img/sharp-libvips-linux-ppc64': 1.2.0 + '@img/sharp-libvips-linux-ppc64': 1.2.3 optional: true - '@img/sharp-linux-s390x@0.34.3': + '@img/sharp-linux-s390x@0.34.4': optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.2.0 + '@img/sharp-libvips-linux-s390x': 1.2.3 optional: true - '@img/sharp-linux-x64@0.34.3': + '@img/sharp-linux-x64@0.34.4': optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.2.0 + '@img/sharp-libvips-linux-x64': 1.2.3 optional: true - '@img/sharp-linuxmusl-arm64@0.34.3': + '@img/sharp-linuxmusl-arm64@0.34.4': optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.2.0 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.3 optional: true - '@img/sharp-linuxmusl-x64@0.34.3': + '@img/sharp-linuxmusl-x64@0.34.4': optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.2.0 + '@img/sharp-libvips-linuxmusl-x64': 1.2.3 optional: true - '@img/sharp-wasm32@0.34.3': + '@img/sharp-wasm32@0.34.4': dependencies: '@emnapi/runtime': 1.5.0 optional: true - '@img/sharp-win32-arm64@0.34.3': + '@img/sharp-win32-arm64@0.34.4': optional: true - '@img/sharp-win32-ia32@0.34.3': + '@img/sharp-win32-ia32@0.34.4': optional: true - '@img/sharp-win32-x64@0.34.3': + '@img/sharp-win32-x64@0.34.4': optional: true '@isaacs/balanced-match@4.0.1': {} @@ -6772,7 +6870,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.15 + '@types/node': 20.16.15 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -6832,9 +6930,9 @@ snapshots: dependencies: '@lit/reactive-element': 2.1.1 - '@lit/react@1.0.8(@types/react@19.0.12)': + '@lit/react@1.0.8(@types/react@19.0.14)': dependencies: - '@types/react': 19.0.12 + '@types/react': 19.0.14 '@lit/reactive-element@2.1.1': dependencies: @@ -6927,47 +7025,47 @@ snapshots: '@npmcli/fs@2.1.2': dependencies: '@gar/promisify': 1.1.3 - semver: 7.7.2 + semver: 7.7.3 '@npmcli/fs@3.1.1': dependencies: - semver: 7.7.2 + semver: 7.7.3 '@npmcli/move-file@2.0.1': dependencies: mkdirp: 1.0.4 rimraf: 3.0.2 - '@octokit/endpoint@11.0.0': + '@octokit/endpoint@11.0.1': dependencies: - '@octokit/types': 14.1.0 + '@octokit/types': 15.0.0 universal-user-agent: 7.0.3 - '@octokit/graphql@9.0.1': + '@octokit/graphql@9.0.2': dependencies: - '@octokit/request': 10.0.3 - '@octokit/types': 14.1.0 + '@octokit/request': 10.0.5 + '@octokit/types': 15.0.0 universal-user-agent: 7.0.3 - '@octokit/openapi-types@25.1.0': {} + '@octokit/openapi-types@26.0.0': {} - '@octokit/request-error@7.0.0': + '@octokit/request-error@7.0.1': dependencies: - '@octokit/types': 14.1.0 + '@octokit/types': 15.0.0 - '@octokit/request@10.0.3': + '@octokit/request@10.0.5': dependencies: - '@octokit/endpoint': 11.0.0 - '@octokit/request-error': 7.0.0 - '@octokit/types': 14.1.0 + '@octokit/endpoint': 11.0.1 + '@octokit/request-error': 7.0.1 + '@octokit/types': 15.0.0 fast-content-type-parse: 3.0.0 universal-user-agent: 7.0.3 - '@octokit/types@14.1.0': + '@octokit/types@15.0.0': dependencies: - '@octokit/openapi-types': 25.1.0 + '@octokit/openapi-types': 26.0.0 - '@opentelemetry/api-logs@0.205.0': + '@opentelemetry/api-logs@0.206.0': dependencies: '@opentelemetry/api': 1.9.0 @@ -6978,28 +7076,28 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.37.0 - '@opentelemetry/exporter-trace-otlp-http@0.205.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-trace-otlp-http@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.205.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.205.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base@0.205.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/otlp-exporter-base@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.205.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer@0.205.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/otlp-transformer@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.205.0 + '@opentelemetry/api-logs': 0.206.0 '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.205.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.206.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 2.1.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.1.0(@opentelemetry/api@1.9.0) protobufjs: 7.5.4 @@ -7010,10 +7108,10 @@ snapshots: '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.37.0 - '@opentelemetry/sdk-logs@0.205.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-logs@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.205.0 + '@opentelemetry/api-logs': 0.206.0 '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) @@ -7145,13 +7243,13 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@playwright/browser-chromium@1.55.0': + '@playwright/browser-chromium@1.56.0': dependencies: - playwright-core: 1.55.0 + playwright-core: 1.56.0 - '@playwright/test@1.55.0': + '@playwright/test@1.56.0': dependencies: - playwright: 1.55.0 + playwright: 1.56.0 '@polka/url@1.0.0-next.29': {} @@ -7291,11 +7389,11 @@ snapshots: '@shoelace-style/localize@3.2.1': {} - '@shoelace-style/shoelace@2.20.1(@floating-ui/utils@0.2.10)(@types/react@19.0.12)': + '@shoelace-style/shoelace@2.20.1(@floating-ui/utils@0.2.10)(@types/react@19.0.14)': dependencies: '@ctrl/tinycolor': 4.2.0 '@floating-ui/dom': 1.7.4 - '@lit/react': 1.0.8(@types/react@19.0.12) + '@lit/react': 1.0.8(@types/react@19.0.14) '@shoelace-style/animations': 1.2.0 '@shoelace-style/localize': 3.2.1 composed-offset-position: 0.0.6(@floating-ui/utils@0.2.10) @@ -7454,7 +7552,7 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 6.0.0 - '@types/node': 20.14.15 + '@types/node': 20.16.15 '@types/html-minifier-terser@6.1.0': {} @@ -7481,23 +7579,23 @@ snapshots: '@types/mocha@10.0.10': {} - '@types/node@20.14.15': + '@types/node@20.16.15': dependencies: - undici-types: 5.26.5 + undici-types: 6.19.8 '@types/normalize-package-data@2.4.4': {} '@types/prop-types@15.7.15': {} - '@types/react-dom@19.0.4(@types/react@19.0.12)': + '@types/react-dom@19.0.6(@types/react@19.0.14)': dependencies: - '@types/react': 19.0.12 + '@types/react': 19.0.14 - '@types/react-transition-group@4.4.12(@types/react@19.0.12)': + '@types/react-transition-group@4.4.12(@types/react@19.0.14)': dependencies: - '@types/react': 19.0.12 + '@types/react': 19.0.14 - '@types/react@19.0.12': + '@types/react@19.0.14': dependencies: csstype: 3.1.3 @@ -7515,118 +7613,172 @@ snapshots: '@types/trusted-types@2.0.7': {} - '@types/vscode@1.92.0': {} + '@types/vscode@1.95.0': {} '@types/warning@3.0.3': {} - '@types/webpack@5.28.5(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1)': - dependencies: - '@types/node': 20.14.15 - tapable: 2.2.3 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - - webpack-cli - '@types/yargs-parser@21.0.3': {} '@types/yargs@17.0.33': dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) - '@typescript-eslint/scope-manager': 8.45.0 - '@typescript-eslint/type-utils': 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.45.0 - eslint: 9.36.0(jiti@2.4.0) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.46.0 + '@typescript-eslint/type-utils': 8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.0 + eslint: 9.37.0(jiti@2.4.0) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2)': + '@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.45.0 - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.45.0 + '@typescript-eslint/scope-manager': 8.46.0 + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.0 debug: 4.4.3(supports-color@8.1.1) - eslint: 9.36.0(jiti@2.4.0) - typescript: 5.9.2 + eslint: 9.37.0(jiti@2.4.0) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.45.0(typescript@5.9.2)': + '@typescript-eslint/parser@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.2) - '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/scope-manager': 8.46.1 + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.1 debug: 4.4.3(supports-color@8.1.1) - typescript: 5.9.2 + eslint: 9.37.0(jiti@2.4.0) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.45.0': + '@typescript-eslint/project-service@8.46.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/visitor-keys': 8.45.0 + '@typescript-eslint/tsconfig-utils': 8.46.0(typescript@5.9.3) + '@typescript-eslint/types': 8.46.0 + debug: 4.4.3(supports-color@8.1.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color - '@typescript-eslint/tsconfig-utils@8.45.0(typescript@5.9.2)': + '@typescript-eslint/project-service@8.46.1(typescript@5.9.3)': dependencies: - typescript: 5.9.2 + '@typescript-eslint/tsconfig-utils': 8.46.1(typescript@5.9.3) + '@typescript-eslint/types': 8.46.1 + debug: 4.4.3(supports-color@8.1.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.46.0': + dependencies: + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/visitor-keys': 8.46.0 + + '@typescript-eslint/scope-manager@8.46.1': + dependencies: + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/visitor-keys': 8.46.1 + + '@typescript-eslint/tsconfig-utils@8.46.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 - '@typescript-eslint/type-utils@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2)': + '@typescript-eslint/tsconfig-utils@8.46.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) debug: 4.4.3(supports-color@8.1.1) - eslint: 9.36.0(jiti@2.4.0) - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + eslint: 9.37.0(jiti@2.4.0) + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.45.0': {} + '@typescript-eslint/types@8.46.0': {} + + '@typescript-eslint/types@8.46.1': {} - '@typescript-eslint/typescript-estree@8.45.0(typescript@5.9.2)': + '@typescript-eslint/typescript-estree@8.46.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.45.0(typescript@5.9.2) - '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.2) - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/visitor-keys': 8.45.0 + '@typescript-eslint/project-service': 8.46.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.46.0(typescript@5.9.3) + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/visitor-keys': 8.46.0 debug: 4.4.3(supports-color@8.1.1) fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.7.2 - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + semver: 7.7.3 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@8.46.1(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.46.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.46.1(typescript@5.9.3) + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/visitor-keys': 8.46.1 + debug: 4.4.3(supports-color@8.1.1) + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.3 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.4.0)) + '@typescript-eslint/scope-manager': 8.46.0 + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + eslint: 9.37.0(jiti@2.4.0) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2)': + '@typescript-eslint/utils@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.4.0)) - '@typescript-eslint/scope-manager': 8.45.0 - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.2) - eslint: 9.36.0(jiti@2.4.0) - typescript: 5.9.2 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.4.0)) + '@typescript-eslint/scope-manager': 8.46.1 + '@typescript-eslint/types': 8.46.1 + '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) + eslint: 9.37.0(jiti@2.4.0) + typescript: 5.9.3 transitivePeerDependencies: - supports-color + optional: true + + '@typescript-eslint/visitor-keys@8.46.0': + dependencies: + '@typescript-eslint/types': 8.46.0 + eslint-visitor-keys: 4.2.1 - '@typescript-eslint/visitor-keys@8.45.0': + '@typescript-eslint/visitor-keys@8.46.1': dependencies: - '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/types': 8.46.1 eslint-visitor-keys: 4.2.1 '@typespec/ts-http-runtime@0.3.1': @@ -7696,19 +7848,21 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vscode/codicons@0.0.40': {} + '@vscode/codicons@0.0.41': {} - '@vscode/test-cli@0.0.11': + '@vscode/test-cli@0.0.12': dependencies: '@types/mocha': 10.0.10 - c8: 9.1.0 + c8: 10.1.3 chokidar: 3.6.0 enhanced-resolve: 5.18.3 glob: 10.4.5 minimatch: 9.0.5 - mocha: 11.7.2 - supports-color: 9.4.0 + mocha: 11.7.4 + supports-color: 10.2.2 yargs: 17.7.2 + transitivePeerDependencies: + - monocart-coverage-reports '@vscode/test-electron@2.5.2': dependencies: @@ -7716,15 +7870,15 @@ snapshots: https-proxy-agent: 5.0.1 jszip: 3.10.1 ora: 8.2.0 - semver: 7.7.2 + semver: 7.7.3 transitivePeerDependencies: - supports-color - '@vscode/test-web@0.0.73': + '@vscode/test-web@0.0.74': dependencies: '@koa/cors': 5.0.0 '@koa/router': 14.0.0 - '@playwright/browser-chromium': 1.55.0 + '@playwright/browser-chromium': 1.56.0 gunzip-maybe: 1.4.2 http-proxy-agent: 7.0.2 https-proxy-agent: 5.0.1 @@ -7733,11 +7887,12 @@ snapshots: koa-mount: 4.2.0 koa-static: 5.0.0 minimist: 1.2.8 - playwright: 1.55.0 + playwright: 1.56.0 tar-fs: 3.1.1 tinyglobby: 0.2.14 vscode-uri: 3.1.0 transitivePeerDependencies: + - bare-abort-controller - bare-buffer - react-native-b4a - supports-color @@ -7748,10 +7903,10 @@ snapshots: '@vscode/vsce-sign-alpine-x64@2.0.6': optional: true - '@vscode/vsce-sign-darwin-arm64@2.0.6': + '@vscode/vsce-sign-darwin-arm64@2.0.2': optional: true - '@vscode/vsce-sign-darwin-x64@2.0.6': + '@vscode/vsce-sign-darwin-x64@2.0.2': optional: true '@vscode/vsce-sign-linux-arm64@2.0.6': @@ -7769,12 +7924,12 @@ snapshots: '@vscode/vsce-sign-win32-x64@2.0.6': optional: true - '@vscode/vsce-sign@2.0.7': + '@vscode/vsce-sign@2.0.8': optionalDependencies: '@vscode/vsce-sign-alpine-arm64': 2.0.6 '@vscode/vsce-sign-alpine-x64': 2.0.6 - '@vscode/vsce-sign-darwin-arm64': 2.0.6 - '@vscode/vsce-sign-darwin-x64': 2.0.6 + '@vscode/vsce-sign-darwin-arm64': 2.0.2 + '@vscode/vsce-sign-darwin-x64': 2.0.2 '@vscode/vsce-sign-linux-arm': 2.0.6 '@vscode/vsce-sign-linux-arm64': 2.0.6 '@vscode/vsce-sign-linux-x64': 2.0.6 @@ -7783,12 +7938,12 @@ snapshots: '@vscode/vsce@3.6.2': dependencies: - '@azure/identity': 4.12.0 + '@azure/identity': 4.13.0 '@secretlint/node': 10.2.2 '@secretlint/secretlint-formatter-sarif': 10.2.2 '@secretlint/secretlint-rule-no-dotenv': 10.2.2 '@secretlint/secretlint-rule-preset-recommend': 10.2.2 - '@vscode/vsce-sign': 2.0.7 + '@vscode/vsce-sign': 2.0.8 azure-devops-node-api: 12.5.0 chalk: 4.1.2 cheerio: 1.0.0-rc.12 @@ -7805,7 +7960,7 @@ snapshots: parse-semver: 1.1.1 read: 1.0.7 secretlint: 10.2.2 - semver: 7.7.2 + semver: 7.7.3 tmp: 0.2.5 typed-rest-client: 1.8.11 url-join: 4.0.1 @@ -7819,7 +7974,7 @@ snapshots: '@web/config-loader@0.1.3': dependencies: - semver: 7.7.2 + semver: 7.7.3 '@webassemblyjs/ast@1.14.1': dependencies: @@ -7897,23 +8052,50 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.101.3)': + '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)': dependencies: - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.101.3) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.102.1) - '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.101.3)': + '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)': dependencies: - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.101.3) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.102.1) - '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.101.3)': + '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)': dependencies: - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.101.3) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.102.1) '@xmldom/xmldom@0.7.13': {} + '@xn-sakina/rml-darwin-arm64@2.6.0': + optional: true + + '@xn-sakina/rml-darwin-x64@2.6.0': + optional: true + + '@xn-sakina/rml-linux-arm-gnueabihf@2.6.0': + optional: true + + '@xn-sakina/rml-linux-arm64-gnu@2.6.0': + optional: true + + '@xn-sakina/rml-linux-arm64-musl@2.6.0': + optional: true + + '@xn-sakina/rml-linux-x64-gnu@2.6.0': + optional: true + + '@xn-sakina/rml-linux-x64-musl@2.6.0': + optional: true + + '@xn-sakina/rml-win32-arm64-msvc@2.6.0': + optional: true + + '@xn-sakina/rml-win32-x64-msvc@2.6.0': + optional: true + '@xtuc/ieee754@1.2.0': {} '@xtuc/long@4.2.2': {} @@ -7985,7 +8167,7 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - ansi-escapes@7.1.0: + ansi-escapes@7.1.1: dependencies: environment: 1.1.0 @@ -8107,8 +8289,8 @@ snapshots: autoprefixer@10.4.21(postcss@8.5.6): dependencies: - browserslist: 4.26.2 - caniuse-lite: 1.0.30001743 + browserslist: 4.26.3 + caniuse-lite: 1.0.30001749 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -8125,20 +8307,21 @@ snapshots: tunnel: 0.0.6 typed-rest-client: 1.8.11 - b4a@1.7.1: {} + b4a@1.7.3: {} balanced-match@1.0.2: {} - bare-events@2.7.0: {} + bare-events@2.8.0: {} - bare-fs@4.4.4: + bare-fs@4.4.10: dependencies: - bare-events: 2.7.0 + bare-events: 2.8.0 bare-path: 3.0.0 - bare-stream: 2.7.0(bare-events@2.7.0) + bare-stream: 2.7.0(bare-events@2.8.0) bare-url: 2.2.2 fast-fifo: 1.3.2 transitivePeerDependencies: + - bare-abort-controller - react-native-b4a optional: true @@ -8150,12 +8333,13 @@ snapshots: bare-os: 3.6.2 optional: true - bare-stream@2.7.0(bare-events@2.7.0): + bare-stream@2.7.0(bare-events@2.8.0): dependencies: streamx: 2.23.0 optionalDependencies: - bare-events: 2.7.0 + bare-events: 2.8.0 transitivePeerDependencies: + - bare-abort-controller - react-native-b4a optional: true @@ -8167,7 +8351,7 @@ snapshots: base64-js@1.5.1: optional: true - baseline-browser-mapping@2.8.6: {} + baseline-browser-mapping@2.8.16: {} basic-auth@2.0.1: dependencies: @@ -8233,13 +8417,13 @@ snapshots: dependencies: pako: 0.2.9 - browserslist@4.26.2: + browserslist@4.26.3: dependencies: - baseline-browser-mapping: 2.8.6 - caniuse-lite: 1.0.30001743 - electron-to-chromium: 1.5.222 - node-releases: 2.0.21 - update-browserslist-db: 1.1.3(browserslist@4.26.2) + baseline-browser-mapping: 2.8.16 + caniuse-lite: 1.0.30001749 + electron-to-chromium: 1.5.234 + node-releases: 2.0.23 + update-browserslist-db: 1.1.3(browserslist@4.26.3) buffer-builder@0.2.0: {} @@ -8263,16 +8447,16 @@ snapshots: dependencies: run-applescript: 7.1.0 - c8@9.1.0: + c8@10.1.3: dependencies: - '@bcoe/v8-coverage': 0.2.3 + '@bcoe/v8-coverage': 1.0.2 '@istanbuljs/schema': 0.1.3 find-up: 5.0.0 foreground-child: 3.3.1 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-reports: 3.2.0 - test-exclude: 6.0.0 + test-exclude: 7.0.1 v8-to-istanbul: 9.3.0 yargs: 17.7.2 yargs-parser: 21.1.1 @@ -8336,12 +8520,12 @@ snapshots: caniuse-api@3.0.0: dependencies: - browserslist: 4.26.2 - caniuse-lite: 1.0.30001743 + browserslist: 4.26.3 + caniuse-lite: 1.0.30001749 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 - caniuse-lite@1.0.30001743: {} + caniuse-lite@1.0.30001749: {} case@1.6.3: {} @@ -8410,9 +8594,9 @@ snapshots: ci-info@3.9.0: {} - circular-dependency-plugin@5.2.2(webpack@5.101.3): + circular-dependency-plugin@5.2.2(webpack@5.102.1): dependencies: - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) classnames@2.5.1: {} @@ -8422,10 +8606,10 @@ snapshots: clean-stack@2.2.0: {} - clean-webpack-plugin@4.0.0(webpack@5.101.3): + clean-webpack-plugin@4.0.0(webpack@5.102.1): dependencies: del: 4.1.1 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) cli-cursor@5.0.0: dependencies: @@ -8455,18 +8639,8 @@ snapshots: color-name@1.1.4: {} - color-string@1.9.1: - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.4 - color-support@1.1.3: {} - color@4.2.3: - dependencies: - color-convert: 2.0.1 - color-string: 1.9.1 - colord@2.9.3: {} colorette@2.0.20: {} @@ -8528,25 +8702,25 @@ snapshots: depd: 2.0.0 keygrip: 1.1.0 - copy-webpack-plugin@13.0.1(webpack@5.101.3): + copy-webpack-plugin@13.0.1(webpack@5.102.1): dependencies: glob-parent: 6.0.2 normalize-path: 3.0.0 - schema-utils: 4.3.2 + schema-utils: 4.3.3 serialize-javascript: 6.0.2 tinyglobby: 0.2.15 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) core-util-is@1.0.3: {} - cosmiconfig@8.3.6(typescript@5.9.2): + cosmiconfig@8.3.6(typescript@5.9.3): dependencies: import-fresh: 3.3.1 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 cross-spawn@7.0.6: dependencies: @@ -8558,18 +8732,18 @@ snapshots: dependencies: custom-event: 1.0.0 - csp-html-webpack-plugin@5.1.0(html-webpack-plugin@5.6.4(webpack@5.101.3))(webpack@5.101.3): + csp-html-webpack-plugin@5.1.0(html-webpack-plugin@5.6.4(webpack@5.102.1))(webpack@5.102.1): dependencies: cheerio: 1.0.0-rc.12 - html-webpack-plugin: 5.6.4(webpack@5.101.3) + html-webpack-plugin: 5.6.4(webpack@5.102.1) lodash: 4.17.21 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) css-declaration-sorter@7.3.0(postcss@8.5.6): dependencies: postcss: 8.5.6 - css-loader@7.1.2(webpack@5.101.3): + css-loader@7.1.2(webpack@5.102.1): dependencies: icss-utils: 5.1.0(postcss@8.5.6) postcss: 8.5.6 @@ -8578,19 +8752,19 @@ snapshots: postcss-modules-scope: 3.2.1(postcss@8.5.6) postcss-modules-values: 4.0.0(postcss@8.5.6) postcss-value-parser: 4.2.0 - semver: 7.7.2 + semver: 7.7.3 optionalDependencies: - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) - css-minimizer-webpack-plugin@7.0.2(esbuild@0.25.10)(webpack@5.101.3): + css-minimizer-webpack-plugin@7.0.2(esbuild@0.25.10)(webpack@5.102.1): dependencies: '@jridgewell/trace-mapping': 0.3.31 cssnano: 7.1.1(postcss@8.5.6) jest-worker: 29.7.0 postcss: 8.5.6 - schema-utils: 4.3.2 + schema-utils: 4.3.3 serialize-javascript: 6.0.2 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) optionalDependencies: esbuild: 0.25.10 @@ -8627,7 +8801,7 @@ snapshots: cssnano-preset-advanced@7.0.9(postcss@8.5.6): dependencies: autoprefixer: 10.4.21(postcss@8.5.6) - browserslist: 4.26.2 + browserslist: 4.26.3 cssnano-preset-default: 7.0.9(postcss@8.5.6) postcss: 8.5.6 postcss-discard-unused: 7.0.4(postcss@8.5.6) @@ -8637,7 +8811,7 @@ snapshots: cssnano-preset-default@7.0.9(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 css-declaration-sorter: 7.3.0(postcss@8.5.6) cssnano-utils: 5.0.1(postcss@8.5.6) postcss: 8.5.6 @@ -8881,7 +9055,7 @@ snapshots: detect-libc@1.0.3: optional: true - detect-libc@2.1.0: {} + detect-libc@2.1.2: {} diff2html@3.4.52: dependencies: @@ -8983,7 +9157,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.222: {} + electron-to-chromium@1.5.234: {} emoji-regex@10.5.0: {} @@ -9007,7 +9181,7 @@ snapshots: enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 - tapable: 2.2.3 + tapable: 2.3.0 entities@2.2.0: {} @@ -9017,7 +9191,7 @@ snapshots: env-paths@2.2.1: {} - envinfo@7.14.0: {} + envinfo@7.17.0: {} environment@1.1.0: {} @@ -9089,8 +9263,6 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@0.9.3: {} - es-module-lexer@1.7.0: {} es-object-atoms@1.1.1: @@ -9116,12 +9288,12 @@ snapshots: is-symbol: 1.1.1 optional: true - esbuild-loader@4.3.0(webpack@5.101.3): + esbuild-loader@4.4.0(webpack@5.102.1): dependencies: esbuild: 0.25.10 - get-tsconfig: 4.10.1 + get-tsconfig: 4.12.0 loader-utils: 2.0.4 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) webpack-sources: 1.4.3 esbuild-node-externals@1.18.0(esbuild@0.25.10): @@ -9134,7 +9306,7 @@ snapshots: esbuild: 0.25.10 resolve: 1.22.10 safe-identifier: 0.4.2 - sass: 1.90.0 + sass: 1.93.2 sass-embedded: 1.77.8 esbuild@0.25.10: @@ -9176,7 +9348,7 @@ snapshots: eslint-import-context@0.1.9(unrs-resolver@1.11.1): dependencies: - get-tsconfig: 4.10.1 + get-tsconfig: 4.12.0 stable-hash-x: 0.2.0 optionalDependencies: unrs-resolver: 1.11.1 @@ -9190,30 +9362,30 @@ snapshots: - supports-color optional: true - eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.4.0)))(eslint-plugin-import@2.29.1)(eslint@9.36.0(jiti@2.4.0)): + eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.4.0)))(eslint-plugin-import@2.29.1)(eslint@9.37.0(jiti@2.4.0)): dependencies: debug: 4.4.3(supports-color@8.1.1) - eslint: 9.36.0(jiti@2.4.0) + eslint: 9.37.0(jiti@2.4.0) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) - get-tsconfig: 4.10.1 + get-tsconfig: 4.12.0 is-bun-module: 2.0.0 stable-hash-x: 0.2.0 tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.4.0)) - eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.4.0)) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.4.0)) + eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.4.0)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.4.0)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.4.0)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) - eslint: 9.36.0(jiti@2.4.0) + '@typescript-eslint/parser': 8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) + eslint: 9.37.0(jiti@2.4.0) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.4.0)))(eslint-plugin-import@2.29.1)(eslint@9.36.0(jiti@2.4.0)) + eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.4.0)))(eslint-plugin-import@2.29.1)(eslint@9.37.0(jiti@2.4.0)) transitivePeerDependencies: - supports-color optional: true @@ -9222,25 +9394,25 @@ snapshots: dependencies: anti-trojan-source: 1.4.1 - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.4.0)): + eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.4.0)): dependencies: - '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/types': 8.46.1 comment-parser: 1.4.1 debug: 4.4.3(supports-color@8.1.1) - eslint: 9.36.0(jiti@2.4.0) + eslint: 9.37.0(jiti@2.4.0) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) is-glob: 4.0.3 minimatch: 10.0.3 - semver: 7.7.2 + semver: 7.7.3 stable-hash-x: 0.2.0 unrs-resolver: 1.11.1 optionalDependencies: - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) + '@typescript-eslint/utils': 8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.4.0)): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.4.0)): dependencies: array-includes: 3.1.9 array.prototype.findlastindex: 1.2.6 @@ -9248,9 +9420,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.36.0(jiti@2.4.0) + eslint: 9.37.0(jiti@2.4.0) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.4.0)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.4.0)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -9261,22 +9433,22 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) + '@typescript-eslint/parser': 8.46.1(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color optional: true - eslint-plugin-lit@2.1.1(eslint@9.36.0(jiti@2.4.0)): + eslint-plugin-lit@2.1.1(eslint@9.37.0(jiti@2.4.0)): dependencies: - eslint: 9.36.0(jiti@2.4.0) + eslint: 9.37.0(jiti@2.4.0) parse5: 6.0.1 parse5-htmlparser2-tree-adapter: 6.0.1 - eslint-plugin-wc@3.0.1(eslint@9.36.0(jiti@2.4.0)): + eslint-plugin-wc@3.0.2(eslint@9.37.0(jiti@2.4.0)): dependencies: - eslint: 9.36.0(jiti@2.4.0) + eslint: 9.37.0(jiti@2.4.0) is-valid-element-name: 1.0.0 js-levenshtein-esm: 2.0.0 @@ -9294,16 +9466,16 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.36.0(jiti@2.4.0): + eslint@9.37.0(jiti@2.4.0): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.4.0)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.4.0)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 - '@eslint/config-helpers': 0.3.1 - '@eslint/core': 0.15.2 + '@eslint/config-helpers': 0.4.0 + '@eslint/core': 0.16.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.36.0 - '@eslint/plugin-kit': 0.3.5 + '@eslint/js': 9.37.0 + '@eslint/plugin-kit': 0.4.0 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -9358,9 +9530,11 @@ snapshots: esutils@2.0.3: {} - events-universal@1.0.0: + events-universal@1.0.1: dependencies: - bare-events: 2.7.0 + bare-events: 2.8.0 + transitivePeerDependencies: + - bare-abort-controller events@3.3.0: {} @@ -9454,22 +9628,22 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.2)(webpack@5.101.3): + fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.102.1): dependencies: '@babel/code-frame': 7.27.1 chalk: 4.1.2 chokidar: 4.0.3 - cosmiconfig: 8.3.6(typescript@5.9.2) + cosmiconfig: 8.3.6(typescript@5.9.3) deepmerge: 4.3.1 fs-extra: 10.1.0 memfs: 3.5.3 minimatch: 3.1.2 node-abort-controller: 3.1.1 schema-utils: 3.3.0 - semver: 7.7.2 - tapable: 2.2.3 - typescript: 5.9.2 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + semver: 7.7.3 + tapable: 2.3.0 + typescript: 5.9.3 + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) form-data@4.0.4: dependencies: @@ -9538,6 +9712,9 @@ snapshots: strip-ansi: 6.0.1 wide-align: 1.1.5 + generator-function@2.0.1: + optional: true + get-caller-file@2.0.5: {} get-east-asian-width@1.4.0: {} @@ -9567,7 +9744,7 @@ snapshots: get-intrinsic: 1.3.0 optional: true - get-tsconfig@4.10.1: + get-tsconfig@4.12.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -9745,11 +9922,11 @@ snapshots: html-escaper@2.0.2: {} - html-loader@5.1.0(webpack@5.101.3): + html-loader@5.1.0(webpack@5.102.1): dependencies: html-minifier-terser: 7.2.0 parse5: 7.3.0 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) html-minifier-terser@6.1.0: dependencies: @@ -9771,15 +9948,15 @@ snapshots: relateurl: 0.2.7 terser: 5.44.0 - html-webpack-plugin@5.6.4(webpack@5.101.3): + html-webpack-plugin@5.6.4(webpack@5.102.1): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 lodash: 4.17.21 pretty-error: 4.0.0 - tapable: 2.2.3 + tapable: 2.3.0 optionalDependencies: - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) htmlparser2@6.1.0: dependencies: @@ -9866,13 +10043,13 @@ snapshots: ignore@7.0.5: {} - image-minimizer-webpack-plugin@4.1.4(sharp@0.34.3)(svgo@4.0.0)(webpack@5.101.3): + image-minimizer-webpack-plugin@4.1.4(sharp@0.34.4)(svgo@4.0.0)(webpack@5.102.1): dependencies: - schema-utils: 4.3.2 + schema-utils: 4.3.3 serialize-javascript: 6.0.2 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) optionalDependencies: - sharp: 0.34.3 + sharp: 0.34.4 svgo: 4.0.0 immediate@3.0.6: {} @@ -9897,7 +10074,7 @@ snapshots: indent-string@5.0.0: {} - index-to-position@1.1.0: {} + index-to-position@1.2.0: {} infer-owner@1.0.4: {} @@ -9939,8 +10116,6 @@ snapshots: is-arrayish@0.2.1: {} - is-arrayish@0.3.4: {} - is-async-function@2.1.1: dependencies: async-function: 1.0.0 @@ -9967,7 +10142,7 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 is-callable@1.2.7: optional: true @@ -10006,9 +10181,10 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-generator-function@1.1.0: + is-generator-function@1.1.2: dependencies: call-bound: 1.0.4 + generator-function: 2.0.1 get-proto: 1.0.1 has-tostringtag: 1.0.2 safe-regex-test: 1.1.0 @@ -10056,6 +10232,8 @@ snapshots: dependencies: path-is-inside: 1.0.2 + is-path-inside@3.0.3: {} + is-plain-obj@1.1.0: {} is-plain-obj@2.1.0: {} @@ -10176,7 +10354,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.15 + '@types/node': 20.16.15 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -10184,13 +10362,13 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.14.15 + '@types/node': 20.16.15 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.14.15 + '@types/node': 20.16.15 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -10251,7 +10429,7 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.7.2 + semver: 7.7.3 jszip@3.10.1: dependencies: @@ -10353,7 +10531,7 @@ snapshots: mkdirp: 1.0.4 nopt: 7.2.1 read-installed-packages: 2.0.1 - semver: 7.7.2 + semver: 7.7.3 spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 spdx-satisfies: 5.0.1 @@ -10389,7 +10567,7 @@ snapshots: lit-element: 4.2.1 lit-html: 3.3.1 - loader-runner@4.3.0: {} + loader-runner@4.3.1: {} loader-utils@2.0.4: dependencies: @@ -10455,7 +10633,7 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.2.1: {} + lru-cache@11.2.2: {} lru-cache@6.0.0: dependencies: @@ -10467,7 +10645,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 make-fetch-happen@10.2.1: dependencies: @@ -10504,7 +10682,7 @@ snapshots: punycode.js: 2.3.1 uc.micro: 2.1.0 - marked@16.3.0: {} + marked@16.4.0: {} math-intrinsics@1.1.0: {} @@ -10565,11 +10743,11 @@ snapshots: mimic-response@3.1.0: optional: true - mini-css-extract-plugin@2.9.4(webpack@5.101.3): + mini-css-extract-plugin@2.9.4(webpack@5.102.1): dependencies: - schema-utils: 4.3.2 - tapable: 2.2.3 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + schema-utils: 4.3.3 + tapable: 2.3.0 + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) minimatch@10.0.3: dependencies: @@ -10643,7 +10821,7 @@ snapshots: dependencies: obliterator: 2.0.5 - mocha@11.7.2: + mocha@11.7.4: dependencies: browser-stdout: 1.3.1 chokidar: 4.0.3 @@ -10653,6 +10831,7 @@ snapshots: find-up: 5.0.0 glob: 10.4.5 he: 1.2.0 + is-path-inside: 3.0.3 js-yaml: 4.1.0 log-symbols: 4.1.0 minimatch: 9.0.5 @@ -10691,7 +10870,7 @@ snapshots: napi-build-utils@2.0.0: optional: true - napi-postinstall@0.3.3: {} + napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} @@ -10706,9 +10885,9 @@ snapshots: lower-case: 2.0.2 tslib: 2.8.1 - node-abi@3.77.0: + node-abi@3.78.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 optional: true node-abort-controller@3.1.1: {} @@ -10735,14 +10914,14 @@ snapshots: nopt: 6.0.0 npmlog: 6.0.2 rimraf: 3.0.2 - semver: 7.7.2 + semver: 7.7.3 tar: 6.2.1 which: 2.0.2 transitivePeerDependencies: - bluebird - supports-color - node-releases@2.0.21: {} + node-releases@2.0.23: {} node-sarif-builder@3.2.0: dependencies: @@ -10765,20 +10944,20 @@ snapshots: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.16.1 - semver: 7.7.2 + semver: 7.7.3 validate-npm-package-license: 3.0.4 normalize-package-data@5.0.0: dependencies: hosted-git-info: 6.1.3 is-core-module: 2.16.1 - semver: 7.7.2 + semver: 7.7.3 validate-npm-package-license: 3.0.4 normalize-package-data@6.0.2: dependencies: hosted-git-info: 7.0.2 - semver: 7.7.2 + semver: 7.7.3 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} @@ -10889,14 +11068,14 @@ snapshots: os-browserify@0.3.0: {} - ovsx@0.10.5: + ovsx@0.10.6: dependencies: '@vscode/vsce': 3.6.2 commander: 6.2.1 follow-redirects: 1.15.11 is-ci: 2.0.0 leven: 3.1.0 - semver: 7.7.2 + semver: 7.7.3 tmp: 0.2.5 yauzl-promise: 4.0.0 transitivePeerDependencies: @@ -10985,7 +11164,7 @@ snapshots: parse-json@8.3.0: dependencies: '@babel/code-frame': 7.27.1 - index-to-position: 1.1.0 + index-to-position: 1.2.0 type-fest: 4.41.0 parse-semver@1.1.1: @@ -11033,7 +11212,7 @@ snapshots: path-scurry@2.0.0: dependencies: - lru-cache: 11.2.1 + lru-cache: 11.2.2 minipass: 7.1.2 path-to-regexp@8.3.0: {} @@ -11070,11 +11249,11 @@ snapshots: dependencies: find-up: 4.1.0 - playwright-core@1.55.0: {} + playwright-core@1.56.0: {} - playwright@1.55.0: + playwright@1.56.0: dependencies: - playwright-core: 1.55.0 + playwright-core: 1.56.0 optionalDependencies: fsevents: 2.3.2 @@ -11093,7 +11272,7 @@ snapshots: postcss-colormin@7.0.4(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 caniuse-api: 3.0.0 colord: 2.9.3 postcss: 8.5.6 @@ -11101,7 +11280,7 @@ snapshots: postcss-convert-values@7.0.7(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -11141,7 +11320,7 @@ snapshots: postcss-merge-rules@7.0.6(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 caniuse-api: 3.0.0 cssnano-utils: 5.0.1(postcss@8.5.6) postcss: 8.5.6 @@ -11161,7 +11340,7 @@ snapshots: postcss-minify-params@7.0.4(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 cssnano-utils: 5.0.1(postcss@8.5.6) postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -11224,7 +11403,7 @@ snapshots: postcss-normalize-unicode@7.0.4(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -11251,7 +11430,7 @@ snapshots: postcss-reduce-initial@7.0.4(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 caniuse-api: 3.0.0 postcss: 8.5.6 @@ -11290,13 +11469,13 @@ snapshots: prebuild-install@7.1.3: dependencies: - detect-libc: 2.1.0 + detect-libc: 2.1.2 expand-template: 2.0.3 github-from-package: 0.0.0 minimist: 1.2.8 mkdirp-classic: 0.5.3 napi-build-utils: 2.0.0 - node-abi: 3.77.0 + node-abi: 3.78.0 pump: 3.0.3 rc: 1.2.8 simple-get: 4.0.1 @@ -11346,7 +11525,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 20.14.15 + '@types/node': 20.16.15 long: 5.3.2 pump@2.0.1: @@ -11405,13 +11584,13 @@ snapshots: react: 19.0.0 react-dom: 19.0.0(react@19.0.0) - react-bootstrap@2.10.7(@types/react@19.0.12)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + react-bootstrap@2.10.7(@types/react@19.0.14)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: '@babel/runtime': 7.28.4 '@restart/hooks': 0.4.16(react@19.0.0) '@restart/ui': 1.9.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@types/prop-types': 15.7.15 - '@types/react-transition-group': 4.4.12(@types/react@19.0.12) + '@types/react-transition-group': 4.4.12(@types/react@19.0.14) classnames: 2.5.1 dom-helpers: 5.2.1 invariant: 2.2.4 @@ -11423,7 +11602,7 @@ snapshots: uncontrollable: 7.2.1(react@19.0.0) warning: 4.0.3 optionalDependencies: - '@types/react': 19.0.12 + '@types/react': 19.0.14 react-dom@19.0.0(react@19.0.0): dependencies: @@ -11460,7 +11639,7 @@ snapshots: '@npmcli/fs': 3.1.1 debug: 4.4.3(supports-color@8.1.1) read-package-json: 6.0.4 - semver: 7.7.2 + semver: 7.7.3 slide: 1.1.6 optionalDependencies: graceful-fs: 4.2.11 @@ -11612,6 +11791,18 @@ snapshots: dependencies: glob: 7.2.3 + rs-module-lexer@2.6.0: + optionalDependencies: + '@xn-sakina/rml-darwin-arm64': 2.6.0 + '@xn-sakina/rml-darwin-x64': 2.6.0 + '@xn-sakina/rml-linux-arm-gnueabihf': 2.6.0 + '@xn-sakina/rml-linux-arm64-gnu': 2.6.0 + '@xn-sakina/rml-linux-arm64-musl': 2.6.0 + '@xn-sakina/rml-linux-x64-gnu': 2.6.0 + '@xn-sakina/rml-linux-x64-musl': 2.6.0 + '@xn-sakina/rml-win32-arm64-msvc': 2.6.0 + '@xn-sakina/rml-win32-x64-msvc': 2.6.0 + run-applescript@7.1.0: {} run-parallel@1.2.0: @@ -11732,15 +11923,15 @@ snapshots: sass-embedded-win32-ia32: 1.77.8 sass-embedded-win32-x64: 1.77.8 - sass-loader@16.0.5(sass-embedded@1.77.8)(sass@1.90.0)(webpack@5.101.3): + sass-loader@16.0.5(sass-embedded@1.77.8)(sass@1.93.2)(webpack@5.102.1): dependencies: neo-async: 2.6.2 optionalDependencies: - sass: 1.90.0 + sass: 1.93.2 sass-embedded: 1.77.8 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) - sass@1.90.0: + sass@1.93.2: dependencies: chokidar: 4.0.3 immutable: 5.1.3 @@ -11758,7 +11949,7 @@ snapshots: ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) - schema-utils@4.3.2: + schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 ajv: 8.17.1 @@ -11782,7 +11973,7 @@ snapshots: semver@6.3.1: optional: true - semver@7.7.2: {} + semver@7.7.3: {} serialize-javascript@6.0.2: dependencies: @@ -11825,34 +12016,34 @@ snapshots: dependencies: kind-of: 6.0.3 - sharp@0.34.3: + sharp@0.34.4: dependencies: - color: 4.2.3 - detect-libc: 2.1.0 - semver: 7.7.2 + '@img/colour': 1.0.0 + detect-libc: 2.1.2 + semver: 7.7.3 optionalDependencies: - '@img/sharp-darwin-arm64': 0.34.3 - '@img/sharp-darwin-x64': 0.34.3 - '@img/sharp-libvips-darwin-arm64': 1.2.0 - '@img/sharp-libvips-darwin-x64': 1.2.0 - '@img/sharp-libvips-linux-arm': 1.2.0 - '@img/sharp-libvips-linux-arm64': 1.2.0 - '@img/sharp-libvips-linux-ppc64': 1.2.0 - '@img/sharp-libvips-linux-s390x': 1.2.0 - '@img/sharp-libvips-linux-x64': 1.2.0 - '@img/sharp-libvips-linuxmusl-arm64': 1.2.0 - '@img/sharp-libvips-linuxmusl-x64': 1.2.0 - '@img/sharp-linux-arm': 0.34.3 - '@img/sharp-linux-arm64': 0.34.3 - '@img/sharp-linux-ppc64': 0.34.3 - '@img/sharp-linux-s390x': 0.34.3 - '@img/sharp-linux-x64': 0.34.3 - '@img/sharp-linuxmusl-arm64': 0.34.3 - '@img/sharp-linuxmusl-x64': 0.34.3 - '@img/sharp-wasm32': 0.34.3 - '@img/sharp-win32-arm64': 0.34.3 - '@img/sharp-win32-ia32': 0.34.3 - '@img/sharp-win32-x64': 0.34.3 + '@img/sharp-darwin-arm64': 0.34.4 + '@img/sharp-darwin-x64': 0.34.4 + '@img/sharp-libvips-darwin-arm64': 1.2.3 + '@img/sharp-libvips-darwin-x64': 1.2.3 + '@img/sharp-libvips-linux-arm': 1.2.3 + '@img/sharp-libvips-linux-arm64': 1.2.3 + '@img/sharp-libvips-linux-ppc64': 1.2.3 + '@img/sharp-libvips-linux-s390x': 1.2.3 + '@img/sharp-libvips-linux-x64': 1.2.3 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.3 + '@img/sharp-libvips-linuxmusl-x64': 1.2.3 + '@img/sharp-linux-arm': 0.34.4 + '@img/sharp-linux-arm64': 0.34.4 + '@img/sharp-linux-ppc64': 0.34.4 + '@img/sharp-linux-s390x': 0.34.4 + '@img/sharp-linux-x64': 0.34.4 + '@img/sharp-linuxmusl-arm64': 0.34.4 + '@img/sharp-linuxmusl-x64': 0.34.4 + '@img/sharp-wasm32': 0.34.4 + '@img/sharp-win32-arm64': 0.34.4 + '@img/sharp-win32-ia32': 0.34.4 + '@img/sharp-win32-x64': 0.34.4 shebang-command@2.0.0: dependencies: @@ -11910,10 +12101,6 @@ snapshots: simple-invariant@2.0.1: {} - simple-swizzle@0.2.4: - dependencies: - is-arrayish: 0.3.4 - sinon@21.0.0: dependencies: '@sinonjs/commons': 3.0.1 @@ -12030,10 +12217,11 @@ snapshots: streamx@2.23.0: dependencies: - events-universal: 1.0.0 + events-universal: 1.0.1 fast-fifo: 1.3.2 text-decoder: 1.2.3 transitivePeerDependencies: + - bare-abort-controller - react-native-b4a string-width@4.2.3: @@ -12112,10 +12300,12 @@ snapshots: stylehacks@7.0.6(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 postcss: 8.5.6 postcss-selector-parser: 7.1.0 + supports-color@10.2.2: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -12124,8 +12314,6 @@ snapshots: dependencies: has-flag: 4.0.0 - supports-color@9.4.0: {} - supports-hyperlinks@3.2.0: dependencies: has-flag: 4.0.0 @@ -12171,7 +12359,7 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - tapable@2.2.3: {} + tapable@2.3.0: {} tar-fs@2.1.4: dependencies: @@ -12186,9 +12374,10 @@ snapshots: pump: 3.0.3 tar-stream: 3.1.7 optionalDependencies: - bare-fs: 4.4.4 + bare-fs: 4.4.10 bare-path: 3.0.0 transitivePeerDependencies: + - bare-abort-controller - bare-buffer - react-native-b4a @@ -12203,10 +12392,11 @@ snapshots: tar-stream@3.1.7: dependencies: - b4a: 1.7.1 + b4a: 1.7.3 fast-fifo: 1.3.2 streamx: 2.23.0 transitivePeerDependencies: + - bare-abort-controller - react-native-b4a tar@6.2.1: @@ -12220,17 +12410,17 @@ snapshots: terminal-link@4.0.0: dependencies: - ansi-escapes: 7.1.0 + ansi-escapes: 7.1.1 supports-hyperlinks: 3.2.0 - terser-webpack-plugin@5.3.14(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack@5.101.3): + terser-webpack-plugin@5.3.14(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack@5.102.1): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 - schema-utils: 4.3.2 + schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.44.0 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) optionalDependencies: '@swc/core': 1.13.5(@swc/helpers@0.5.17) esbuild: 0.25.10 @@ -12242,15 +12432,15 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 - test-exclude@6.0.0: + test-exclude@7.0.1: dependencies: '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 + glob: 10.4.5 + minimatch: 9.0.5 text-decoder@1.2.3: dependencies: - b4a: 1.7.1 + b4a: 1.7.3 transitivePeerDependencies: - react-native-b4a @@ -12293,19 +12483,19 @@ snapshots: trim-newlines@4.1.1: {} - ts-api-utils@2.1.0(typescript@5.9.2): + ts-api-utils@2.1.0(typescript@5.9.3): dependencies: - typescript: 5.9.2 + typescript: 5.9.3 - ts-loader@9.5.4(typescript@5.9.2)(webpack@5.101.3): + ts-loader@9.5.4(typescript@5.9.3)(webpack@5.102.1): dependencies: chalk: 4.1.2 enhanced-resolve: 5.18.3 micromatch: 4.0.8 - semver: 7.7.2 + semver: 7.7.3 source-map: 0.7.6 - typescript: 5.9.2 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + typescript: 5.9.3 + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) tsconfig-paths@3.15.0: dependencies: @@ -12406,14 +12596,14 @@ snapshots: tunnel: 0.0.6 underscore: 1.13.7 - typescript-eslint@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2): + typescript-eslint@8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.4.0))(typescript@5.9.2) - eslint: 9.36.0(jiti@2.4.0) - typescript: 5.9.2 + '@typescript-eslint/eslint-plugin': 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3))(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.4.0))(typescript@5.9.3) + eslint: 9.37.0(jiti@2.4.0) + typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -12421,7 +12611,7 @@ snapshots: typescript@5.4.5: {} - typescript@5.9.2: {} + typescript@5.9.3: {} typical@4.0.0: {} @@ -12441,7 +12631,7 @@ snapshots: uncontrollable@7.2.1(react@19.0.0): dependencies: '@babel/runtime': 7.28.4 - '@types/react': 19.0.12 + '@types/react': 19.0.14 invariant: 2.2.4 react: 19.0.0 react-lifecycles-compat: 3.0.4 @@ -12452,7 +12642,7 @@ snapshots: underscore@1.13.7: {} - undici-types@5.26.5: {} + undici-types@6.19.8: {} unfetch@4.2.0: {} @@ -12474,7 +12664,7 @@ snapshots: unrs-resolver@1.11.1: dependencies: - napi-postinstall: 0.3.3 + napi-postinstall: 0.3.4 optionalDependencies: '@unrs/resolver-binding-android-arm-eabi': 1.11.1 '@unrs/resolver-binding-android-arm64': 1.11.1 @@ -12496,9 +12686,9 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - update-browserslist-db@1.1.3(browserslist@4.26.2): + update-browserslist-db@1.1.3(browserslist@4.26.3): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 escalade: 3.2.0 picocolors: 1.1.1 @@ -12562,21 +12752,21 @@ snapshots: - bufferutil - utf-8-validate - webpack-cli@6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.101.3): + webpack-cli@6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.102.1): dependencies: '@discoveryjs/json-ext': 0.6.3 - '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.101.3) - '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.101.3) - '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.101.3) + '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1) + '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1) + '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1) colorette: 2.0.20 commander: 12.1.0 cross-spawn: 7.0.6 - envinfo: 7.14.0 + envinfo: 7.17.0 fastest-levenshtein: 1.0.16 import-local: 3.2.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) + webpack: 5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1) webpack-merge: 6.0.1 optionalDependencies: webpack-bundle-analyzer: 4.10.2 @@ -12589,9 +12779,9 @@ snapshots: webpack-node-externals@3.0.0: {} - webpack-require-from@1.8.6(tapable@2.2.3): + webpack-require-from@1.8.6(tapable@2.3.0): dependencies: - tapable: 2.2.3 + tapable: 2.3.0 webpack-sources@1.4.3: dependencies: @@ -12600,7 +12790,7 @@ snapshots: webpack-sources@3.3.3: {} - webpack@5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1): + webpack@5.102.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack-cli@6.0.1): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -12610,7 +12800,7 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.26.2 + browserslist: 4.26.3 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.3 es-module-lexer: 1.7.0 @@ -12619,16 +12809,16 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 + loader-runner: 4.3.1 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 4.3.2 - tapable: 2.2.3 - terser-webpack-plugin: 5.3.14(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack@5.101.3) + schema-utils: 4.3.3 + tapable: 2.3.0 + terser-webpack-plugin: 5.3.14(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.10)(webpack@5.102.1) watchpack: 2.4.4 webpack-sources: 3.3.3 optionalDependencies: - webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.101.3) + webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack@5.102.1) transitivePeerDependencies: - '@swc/core' - esbuild @@ -12656,7 +12846,7 @@ snapshots: is-async-function: 2.1.1 is-date-object: 1.1.0 is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.0 + is-generator-function: 1.1.2 is-regex: 1.2.1 is-weakref: 1.1.1 isarray: 2.0.5 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index fe4ab98c4af42..19108aab17898 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,7 +1,6 @@ minimumReleaseAge: 10080 minimumReleaseAgeExclude: + - '@eamodio/eslint-lite-webpack-plugin' - '@gitkraken/*' - '@typescript-eslint/*' - - '@vscode/vsce' - - 'billboard.js' - 'typescript-eslint' diff --git a/scripts/generateCommandTypes.mts b/scripts/generateCommandTypes.mts index cb6320dfd0a9d..84c04e1bd1dc5 100644 --- a/scripts/generateCommandTypes.mts +++ b/scripts/generateCommandTypes.mts @@ -16,41 +16,81 @@ function generateCommandTypesFromContributions(): void { readFileSync(path.join(__dirname, 'contributions.json'), 'utf8'), ); - const commands: string[] = []; - const kbCommands: string[] = []; - const paletteCommands: string[] = []; + const commands = new Set(); + const paletteCommands = new Set(); + const kbCommands = new Set(); + const internalCommands = new Set(); + let internal: boolean; for (const [id, command] of Object.entries(contributions.commands)) { + internal = true; + if (command.menus) { + internal = false; + commands.add(id); + + for (const menus of Object.values(command.menus)) { + for (const menu of menus) { + if (menu.alt) { + commands.add(menu.alt); + } + } + } + } + if (command.commandPalette) { - paletteCommands.push(id); - } else { - commands.push(id); + internal = false; + paletteCommands.add(id); + } + + if (command.keybindings) { + internal = false; + kbCommands.add(id); + } + + if (internal) { + internalCommands.add(id); } } for (const kb of contributions.keybindings) { - kbCommands.push(kb.command); + kbCommands.add(kb.command); + } + + // Remove from internal any commands that are in other lists + for (const id of [...commands, ...paletteCommands, ...kbCommands]) { + internalCommands.delete(id); } const contents = `// This file is generated by (vscode-gitlens)/${relativeFilename} // Do not edit this file directly -export type ContributedCommands = ContributedKeybindingCommands | ContributedPaletteCommands | ${commands +export type ContributedCommands = ContributedKeybindingCommands | ContributedPaletteCommands | ContributedOrphansOrInternalCommands | ${[ + ...commands, + ] .sort() .map(c => `'${c}'`) .join(' | ')}; -export type ContributedPaletteCommands = ${paletteCommands +export type ContributedPaletteCommands = ${[...paletteCommands] .sort() .map(c => `'${c}'`) .join(' | ')}; -export type ContributedKeybindingCommands = ${kbCommands +export type ContributedKeybindingCommands = ${[...kbCommands] .filter(c => c.startsWith('gitlens.')) .sort() .map(c => `'${c}'`) .join(' | ')}; +/** + * Commands that are not contributed anywhere, not the command palette, menus (or alts), nor keybindings. + * Either their contribution point is missing or are simply internal and should be removed at some point + */ +export type ContributedOrphansOrInternalCommands = ${[...internalCommands] + .sort() + .map(c => `'${c}'`) + .join(' | ')}; + `; const file = path.join(__dirname, 'src', 'constants.commands.generated.ts'); diff --git a/src/annotations/fileAnnotationController.ts b/src/annotations/fileAnnotationController.ts index 0340250cfa071..688cc20183971 100644 --- a/src/annotations/fileAnnotationController.ts +++ b/src/annotations/fileAnnotationController.ts @@ -334,10 +334,12 @@ export class FileAnnotationController implements Disposable { } private readonly _annotatedUris = new UriSet(); + private readonly _annotatedChangesUris = new UriSet(); private readonly _computingUris = new UriSet(); async onProviderEditorStatusChanged( editor: TextEditor | undefined, + annotationType: FileAnnotationType | undefined, status: AnnotationStatus | undefined, ): Promise { if (editor == null) return; @@ -346,10 +348,11 @@ export class FileAnnotationController implements Disposable { let windowStatus; if (this.isInWindowToggle()) { - windowStatus = status; + windowStatus = status ? (annotationType ? (`${status}:${annotationType}` as const) : status) : undefined; changed = Boolean(this._annotatedUris.size || this._computingUris.size); this._annotatedUris.clear(); + this._annotatedChangesUris.clear(); this._computingUris.clear(); } else { windowStatus = undefined; @@ -373,11 +376,19 @@ export class FileAnnotationController implements Disposable { if (provider == null) { if (this._annotatedUris.has(uri)) { this._annotatedUris.delete(uri); + this._annotatedChangesUris.delete(uri); + changed = true; + } + } else { + if (!this._annotatedUris.has(uri)) { + this._annotatedUris.add(uri); + changed = true; + } + + if (provider.annotationType === 'changes' && !this._annotatedChangesUris.has(uri)) { + this._annotatedChangesUris.add(uri); changed = true; } - } else if (!this._annotatedUris.has(uri)) { - this._annotatedUris.add(uri); - changed = true; } if (this._computingUris.has(uri)) { @@ -389,6 +400,7 @@ export class FileAnnotationController implements Disposable { default: if (this._annotatedUris.has(uri)) { this._annotatedUris.delete(uri); + this._annotatedChangesUris.delete(uri); changed = true; } @@ -406,6 +418,7 @@ export class FileAnnotationController implements Disposable { setContext('gitlens:window:annotated', windowStatus), setContext('gitlens:tabs:annotated:computing', [...this._computingUris]), setContext('gitlens:tabs:annotated', [...this._annotatedUris]), + setContext('gitlens:tabs:annotated:changes', [...this._annotatedChangesUris]), ]); } @@ -463,12 +476,12 @@ export class FileAnnotationController implements Disposable { const provider = await window.withProgress( { location: ProgressLocation.Window }, async (progress: Progress<{ message: string }>) => { - void this.onProviderEditorStatusChanged(editor, 'computing'); + void this.onProviderEditorStatusChanged(editor, type, 'computing'); const computingAnnotations = this.showAnnotationsCore(currentProvider, editor, type, context, progress); void (await computingAnnotations); - void this.onProviderEditorStatusChanged(editor, 'computed'); + void this.onProviderEditorStatusChanged(editor, type, 'computed'); return computingAnnotations; }, @@ -574,7 +587,7 @@ export class FileAnnotationController implements Disposable { if (!this._annotationProviders.size || key === getEditorCorrelationKey(this._editor)) { if (this._editor != null) { - void this.onProviderEditorStatusChanged(this._editor, undefined); + void this.onProviderEditorStatusChanged(this._editor, undefined, undefined); } await this.detachKeyboardHook(); @@ -636,7 +649,7 @@ export class FileAnnotationController implements Disposable { ); provider = new GutterBlameAnnotationProvider( this.container, - e => this.onProviderEditorStatusChanged(e.editor, e.status), + e => this.onProviderEditorStatusChanged(e.editor, type, e.status), editor, trackedDocument, ); @@ -648,7 +661,7 @@ export class FileAnnotationController implements Disposable { ); provider = new GutterChangesAnnotationProvider( this.container, - e => this.onProviderEditorStatusChanged(e.editor, e.status), + e => this.onProviderEditorStatusChanged(e.editor, type, e.status), editor, trackedDocument, ); @@ -660,7 +673,7 @@ export class FileAnnotationController implements Disposable { ); provider = new GutterHeatmapBlameAnnotationProvider( this.container, - e => this.onProviderEditorStatusChanged(e.editor, e.status), + e => this.onProviderEditorStatusChanged(e.editor, type, e.status), editor, trackedDocument, ); diff --git a/src/autolinks/autolinksProvider.ts b/src/autolinks/autolinksProvider.ts index 547a03bb5c84d..1222ed2cb56ab 100644 --- a/src/autolinks/autolinksProvider.ts +++ b/src/autolinks/autolinksProvider.ts @@ -120,7 +120,7 @@ export class AutolinksProvider implements Disposable { } } - if (promises.length === 0) return; + if (!promises.length) return; await Promise.allSettled(promises); } @@ -144,7 +144,7 @@ export class AutolinksProvider implements Disposable { } private async getRefSets(remote?: GitRemote, forBranch?: boolean) { - return this._refsetCache.get(remote?.remoteKey, async () => { + return this._refsetCache.get(`${remote?.remoteKey}${forBranch ? ':branch' : ''}`, async () => { const refsets: RefSet[] = []; await this.collectIntegrationAutolinks(forBranch ? undefined : remote, refsets); @@ -158,29 +158,21 @@ export class AutolinksProvider implements Disposable { /** @returns A sorted list of autolinks. the first match is the most relevant */ async getBranchAutolinks(branchName: string, remote?: GitRemote): Promise> { const refsets = await this.getRefSets(remote, true); - if (refsets.length === 0) return emptyAutolinkMap; + if (!refsets.length) return emptyAutolinkMap; return getBranchAutolinks(branchName, refsets); } - @debug({ - args: { - 0: '', - 1: false, - }, - }) + @debug({ args: { 0: '', 1: false } }) async getAutolinks(message: string, remote?: GitRemote): Promise> { const refsets = await this.getRefSets(remote); - if (refsets.length === 0) return emptyAutolinkMap; + if (!refsets.length) return emptyAutolinkMap; return getAutolinks(message, refsets); } getAutolinkEnrichableId(autolink: Autolink): { id: string; key: string } { - return { - id: autolink.id, - key: `${autolink.prefix}${autolink.id}`, - }; + return { id: autolink.id, key: `${autolink.prefix}${autolink.id}` }; } async getEnrichedAutolinks( @@ -205,7 +197,7 @@ export class AutolinksProvider implements Disposable { if (typeof messageOrAutolinks === 'string') { messageOrAutolinks = await this.getAutolinks(messageOrAutolinks, remote); } - if (messageOrAutolinks.size === 0) return undefined; + if (!messageOrAutolinks.size) return undefined; let integration = await remote?.getIntegration(); if (integration != null) { @@ -339,7 +331,7 @@ export class AutolinksProvider implements Disposable { } } - if (tokenMapping.size !== 0) { + if (tokenMapping.size) { // eslint-disable-next-line no-control-regex text = text.replace(/(\x00\d+\x00)/g, (_, t: string) => tokenMapping.get(t) ?? t); } @@ -388,10 +380,9 @@ export class AutolinksProvider implements Disposable { if (issueResult?.value != null) { if (issueResult.paused) { if (footnotes != null && !prs?.has(num)) { - let name = ref.description?.replace(numRegex, num); - if (name == null) { - name = `Custom Autolink ${ref.prefix}${num}`; - } + const name = + ref.description?.replace(numRegex, num) ?? + `Custom Autolink ${ref.prefix}${num}`; footnoteIndex = footnotes.size + 1; footnotes.set( footnoteIndex, @@ -426,10 +417,9 @@ export class AutolinksProvider implements Disposable { )}`; } } else if (footnotes != null && !prs?.has(num)) { - let name = ref.description?.replace(numRegex, num); - if (name == null) { - name = `Custom Autolink ${ref.prefix}${num}`; - } + const name = + ref.description?.replace(numRegex, num) ?? + `Custom Autolink ${ref.prefix}${num}`; footnoteIndex = footnotes.size + 1; footnotes.set( footnoteIndex, @@ -460,10 +450,9 @@ export class AutolinksProvider implements Disposable { if (issueResult?.value != null) { if (issueResult.paused) { if (footnotes != null && !prs?.has(num)) { - let name = ref.description?.replace(numRegex, num); - if (name == null) { - name = `Custom Autolink ${ref.prefix}${num}`; - } + const name = + ref.description?.replace(numRegex, num) ?? + `Custom Autolink ${ref.prefix}${num}`; footnoteIndex = footnotes.size + 1; footnotes.set( footnoteIndex, @@ -498,10 +487,9 @@ export class AutolinksProvider implements Disposable { )}`; } } else if (footnotes != null && !prs?.has(num)) { - let name = ref.description?.replace(numRegex, num); - if (name == null) { - name = `Custom Autolink ${ref.prefix}${num}`; - } + const name = + ref.description?.replace(numRegex, num) ?? + `Custom Autolink ${ref.prefix}${num}`; footnoteIndex = footnotes.size + 1; footnotes.set( footnoteIndex, diff --git a/src/commands/createPullRequestOnRemote.ts b/src/commands/createPullRequestOnRemote.ts index ab89e9327c30f..bbd42f734cec1 100644 --- a/src/commands/createPullRequestOnRemote.ts +++ b/src/commands/createPullRequestOnRemote.ts @@ -5,7 +5,8 @@ import type { GitRemote } from '../git/models/remote'; import type { CreatePullRequestRemoteResource } from '../git/models/remoteResource'; import { RemoteResourceType } from '../git/models/remoteResource'; import type { RemoteProvider } from '../git/remotes/remoteProvider'; -import { getRemoteNameFromBranchName } from '../git/utils/branch.utils'; +import { getBranchMergeTargetName } from '../git/utils/-webview/branch.utils'; +import { getBranchNameWithoutRemote, getRemoteNameFromBranchName } from '../git/utils/branch.utils'; import { getRepositoryOrShowPicker } from '../quickpicks/repositoryPicker'; import { command, executeCommand } from '../system/-webview/command'; import { GlCommandBase } from './commandBase'; @@ -67,6 +68,17 @@ export class CreatePullRequestOnRemoteCommand extends GlCommandBase { sort: true, })) as GitRemote[]; + if (args.base == null) { + const branch = await repo.git.branches.getBranch(args.compare); + if (branch != null) { + const mergeTargetResult = await getBranchMergeTargetName(this.container, branch); + if (!mergeTargetResult.paused && mergeTargetResult.value != null) { + // Strip the remote name from the branch name + args.base = getBranchNameWithoutRemote(mergeTargetResult.value); + } + } + } + const resource: CreatePullRequestRemoteResource = { type: RemoteResourceType.CreatePullRequest, repoPath: repo.path, diff --git a/src/commands/generateRebase.ts b/src/commands/generateRebase.ts index 8bb21fb1a3cbe..36fd998a08732 100644 --- a/src/commands/generateRebase.ts +++ b/src/commands/generateRebase.ts @@ -243,13 +243,13 @@ export class UndoGenerateRebaseCommand extends GlCommandBase { if (result !== confirm) return; // Check if there are working tree changes and stash them - const status = await svc.status.getStatus(); - if (status?.files && status.files.length > 0) { + const hasChanges = await svc.status.hasWorkingChanges(); + if (hasChanges) { await svc.stash?.saveStash(undefined, undefined, { includeUntracked: true }); } // Reset hard to the previous HEAD - await svc.reset(args.previousHeadRef.ref, { hard: true }); + await svc.ops?.reset(args.previousHeadRef.ref, { hard: true }); // Apply the generated stash try { @@ -351,7 +351,7 @@ export async function generateRebase( } // reset the current branch to the new shas - await svc.reset(shas[shas.length - 1], { hard: true }); + await svc.ops?.reset(shas[shas.length - 1], { hard: true }); // Capture the new HEAD after reset generatedHeadRef = createReference(shas[shas.length - 1], svc.path, { refType: 'revision' }); diff --git a/src/commands/ghpr/openOrCreateWorktree.ts b/src/commands/ghpr/openOrCreateWorktree.ts index 60b7f97c70c7d..6ab1ee29c660f 100644 --- a/src/commands/ghpr/openOrCreateWorktree.ts +++ b/src/commands/ghpr/openOrCreateWorktree.ts @@ -93,7 +93,7 @@ export class OpenOrCreateWorktreeCommand extends GlCommandBase { if (remote != null) { remoteName = remote.name; // Ensure we have the latest from the remote - await repo.git.fetch({ remote: remote.name }); + await repo.git.ops?.fetch({ remote: remote.name }); } else { remoteName = remoteOwner; addRemote = { name: remoteOwner, url: remoteUrl }; diff --git a/src/commands/git/cherry-pick.ts b/src/commands/git/cherry-pick.ts index 2a52bbeedde1a..9580d7c358026 100644 --- a/src/commands/git/cherry-pick.ts +++ b/src/commands/git/cherry-pick.ts @@ -90,7 +90,7 @@ export class CherryPickGitCommand extends QuickCommand { private async execute(state: CherryPickStepState>) { try { - await state.repo.git.commits.cherryPick?.( + await state.repo.git.ops?.cherryPick?.( state.references.map(c => c.ref), { edit: state.flags.includes('--edit'), @@ -102,10 +102,10 @@ export class CherryPickGitCommand extends QuickCommand { if (ex instanceof CherryPickError && ex.reason === CherryPickErrorReason.EmptyCommit) { let pausedOperation: GitPausedOperationStatus | undefined; try { - pausedOperation = await state.repo.git.status.getPausedOperationStatus?.(); + pausedOperation = await state.repo.git.pausedOps?.getPausedOperationStatus?.(); pausedOperation ??= await state.repo .waitForRepoChange(500) - .then(() => state.repo.git.status.getPausedOperationStatus?.()); + .then(() => state.repo.git.pausedOps?.getPausedOperationStatus?.()); } catch {} const pausedAt = pausedOperation diff --git a/src/commands/git/reset.ts b/src/commands/git/reset.ts index c38c98db240a6..55f26f549e836 100644 --- a/src/commands/git/reset.ts +++ b/src/commands/git/reset.ts @@ -73,7 +73,7 @@ export class ResetGitCommand extends QuickCommand { private async execute(state: ResetStepState) { try { - await state.repo.git.reset( + await state.repo.git.ops?.reset( state.reference.ref, state.flags.includes('--hard') ? { hard: true } diff --git a/src/commands/git/worktree.ts b/src/commands/git/worktree.ts index 4ba507e65f611..f016b70ab8167 100644 --- a/src/commands/git/worktree.ts +++ b/src/commands/git/worktree.ts @@ -887,12 +887,12 @@ export class WorktreeGitCommand extends QuickCommand { try { if (force) { - let status; + let hasChanges; try { - status = await worktree?.getStatus(); + hasChanges = await worktree?.hasWorkingChanges(); } catch {} - if ((status?.hasChanges ?? false) && !skipHasChangesPrompt) { + if ((hasChanges ?? false) && !skipHasChangesPrompt) { const confirm: MessageItem = { title: 'Force Delete' }; const cancel: MessageItem = { title: 'Cancel', isCloseAffordance: true }; const result = await window.showWarningMessage( @@ -1201,9 +1201,7 @@ export class WorktreeGitCommand extends QuickCommand { try { if (state.changes.type !== 'index') { // stage any untracked files to include them in the diff - const status = await sourceSvc.status.getStatus(); - - untrackedPaths = status?.untrackedChanges.map(f => f.path); + untrackedPaths = (await sourceSvc.status?.getUntrackedFiles())?.map(f => f.path); if (untrackedPaths?.length) { try { await sourceSvc.staging?.stageFiles(untrackedPaths); diff --git a/src/commands/patches.ts b/src/commands/patches.ts index 62ea6e626d221..d9c262e37efce 100644 --- a/src/commands/patches.ts +++ b/src/commands/patches.ts @@ -171,9 +171,7 @@ abstract class CreatePatchCommandBase extends GlCommandBase { try { if (args?.to === uncommitted) { // stage any untracked files to include them in the diff - const status = await repo.git.status?.getStatus(); - - untrackedPaths = status?.untrackedChanges.map(f => f.path); + untrackedPaths = (await repo.git.status?.getUntrackedFiles())?.map(f => f.path); if (untrackedPaths?.length) { try { await repo.git.staging?.stageFiles(untrackedPaths); diff --git a/src/commands/quickCommand.steps.ts b/src/commands/quickCommand.steps.ts index b392e457f7062..1a277b2681c8e 100644 --- a/src/commands/quickCommand.steps.ts +++ b/src/commands/quickCommand.steps.ts @@ -262,10 +262,10 @@ export async function getWorktrees( if ((excludeOpened && w.opened) || filter?.(w) === false) return undefined; let missing = false; - let status; + let hasChanges; if (includeStatus) { try { - status = await w.getStatus(); + hasChanges = await w.hasWorkingChanges(); } catch (ex) { Logger.error(ex, `Worktree status failed: ${w.uri.toString(true)}`); missing = true; @@ -277,12 +277,7 @@ export async function getWorktrees( picked != null && (typeof picked === 'string' ? w.uri.toString() === picked : picked.includes(w.uri.toString())), missing, - { - buttons: buttons, - includeStatus: includeStatus, - path: true, - status: status, - }, + { buttons: buttons, hasChanges: hasChanges, includeStatus: includeStatus, path: true }, ); }), ), diff --git a/src/commands/showQuickCommit.ts b/src/commands/showQuickCommit.ts index 136af74f87d2c..44a30b158e205 100644 --- a/src/commands/showQuickCommit.ts +++ b/src/commands/showQuickCommit.ts @@ -47,8 +47,7 @@ export class ShowQuickCommitCommand extends ActiveEditorCachedCommand { } if (context.type === 'viewItem') { - args = { ...args }; - args.sha = context.node.uri.sha; + args = { ...args, sha: context.node.uri.sha }; if (isCommandContextViewNodeHasCommit(context)) { args.commit = context.node.commit; @@ -59,6 +58,8 @@ export class ShowQuickCommitCommand extends ActiveEditorCachedCommand { } async execute(editor?: TextEditor, uri?: Uri, args?: ShowQuickCommitCommandArgs): Promise { + args = { ...args }; + let gitUri; let repoPath; if (args?.commit == null) { @@ -73,19 +74,14 @@ export class ShowQuickCommitCommand extends ActiveEditorCachedCommand { repoPath = gitUri.repoPath!; } } else { - if (args.sha == null) { - args.sha = args.commit.sha; - } + args.sha ??= args.commit.sha; gitUri = args.commit.getGitUri(); repoPath = args.commit.repoPath; - if (uri == null) { - uri = args.commit.file?.uri; - } + uri ??= args.commit.file?.uri; } - args = { ...args }; if (args.sha == null) { if (editor == null) return; diff --git a/src/config.ts b/src/config.ts index a92174624cc1c..c23a12e47abe2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -438,6 +438,7 @@ export interface GraphConfig { }; readonly scrollRowPadding: number; readonly searchItemLimit: number; + readonly initialRowSelection: 'head' | 'wip'; readonly showDetailsView: 'open' | 'selection' | false; readonly showGhostRefsOnRowHover: boolean; readonly showRemoteNames: boolean; diff --git a/src/constants.commands.generated.ts b/src/constants.commands.generated.ts index 2a6f47b1eab86..3523419777cff 100644 --- a/src/constants.commands.generated.ts +++ b/src/constants.commands.generated.ts @@ -4,6 +4,8 @@ export type ContributedCommands = | ContributedKeybindingCommands | ContributedPaletteCommands + | ContributedOrphansOrInternalCommands + | 'gitlens.addAuthors' | 'gitlens.ai.explainBranch:graph' | 'gitlens.ai.explainBranch:views' | 'gitlens.ai.explainCommit:graph' @@ -24,43 +26,84 @@ export type ContributedCommands = | 'gitlens.ai.rebaseOntoCommit:graph' | 'gitlens.ai.rebaseOntoCommit:views' | 'gitlens.ai.switchProvider:scm' - | 'gitlens.ai.undoGenerateRebase' | 'gitlens.annotations.nextChange' | 'gitlens.annotations.previousChange' | 'gitlens.changeUpstream:graph' | 'gitlens.changeUpstream:views' + | 'gitlens.clearFileAnnotations' + | 'gitlens.closeUnchangedFiles' | 'gitlens.composeCommits:graph' | 'gitlens.composeCommits:scm' | 'gitlens.composeCommits:views' | 'gitlens.composer.refresh' | 'gitlens.computingFileAnnotations' + | 'gitlens.connectRemoteProvider' | 'gitlens.copyDeepLinkToBranch' | 'gitlens.copyDeepLinkToCommit' + | 'gitlens.copyDeepLinkToCommit:commitDetails' + | 'gitlens.copyDeepLinkToCommit:graphDetails' | 'gitlens.copyDeepLinkToComparison' | 'gitlens.copyDeepLinkToFile' + | 'gitlens.copyDeepLinkToFile:commitDetails' + | 'gitlens.copyDeepLinkToFile:graphDetails' | 'gitlens.copyDeepLinkToFileAtRevision' + | 'gitlens.copyDeepLinkToFileAtRevision:commitDetails' + | 'gitlens.copyDeepLinkToFileAtRevision:graphDetails' | 'gitlens.copyDeepLinkToLines' + | 'gitlens.copyDeepLinkToRepo' | 'gitlens.copyDeepLinkToTag' | 'gitlens.copyDeepLinkToWorkspace' + | 'gitlens.copyMessageToClipboard' + | 'gitlens.copyPatchToClipboard:commitDetails' | 'gitlens.copyPatchToClipboard:graph' + | 'gitlens.copyPatchToClipboard:graphDetails' | 'gitlens.copyPatchToClipboard:scm' | 'gitlens.copyPatchToClipboard:views' + | 'gitlens.copyRelativePathToClipboard' + | 'gitlens.copyRelativePathToClipboard:commitDetails' + | 'gitlens.copyRelativePathToClipboard:graphDetails' | 'gitlens.copyRemoteBranchUrl' | 'gitlens.copyRemoteBranchesUrl' + | 'gitlens.copyRemoteCommitUrl' | 'gitlens.copyRemoteComparisonUrl' + | 'gitlens.copyRemoteFileUrlFrom' + | 'gitlens.copyRemoteFileUrlFrom:commitDetails' + | 'gitlens.copyRemoteFileUrlFrom:graphDetails' + | 'gitlens.copyRemoteFileUrlToClipboard' | 'gitlens.copyRemoteFileUrlWithoutRange' + | 'gitlens.copyRemoteFileUrlWithoutRange:commitDetails' + | 'gitlens.copyRemoteFileUrlWithoutRange:graphDetails' | 'gitlens.copyRemotePullRequestUrl' | 'gitlens.copyRemoteRepositoryUrl' + | 'gitlens.copyShaToClipboard' | 'gitlens.copyWorkingChangesToWorktree:views' + | 'gitlens.createCloudPatch' + | 'gitlens.createPatch' + | 'gitlens.diffDirectory' + | 'gitlens.diffDirectoryWithHead' + | 'gitlens.diffFolderWithRevision' + | 'gitlens.diffFolderWithRevisionFrom' + | 'gitlens.diffLineWithPrevious' + | 'gitlens.diffLineWithWorking' | 'gitlens.diffWithNext:editor/title' - | 'gitlens.diffWithNext:key' | 'gitlens.diffWithPrevious:editor' | 'gitlens.diffWithPrevious:editor/title' | 'gitlens.diffWithPrevious:explorer' - | 'gitlens.diffWithPrevious:key' + | 'gitlens.diffWithRevision' + | 'gitlens.diffWithRevision:commitDetails' + | 'gitlens.diffWithRevision:graphDetails' + | 'gitlens.diffWithRevisionFrom' + | 'gitlens.diffWithRevisionFrom:commitDetails' + | 'gitlens.diffWithRevisionFrom:graphDetails' | 'gitlens.diffWithWorking:editor' | 'gitlens.diffWithWorking:editor/title' - | 'gitlens.diffWithWorking:key' + | 'gitlens.disconnectRemoteProvider' + | 'gitlens.externalDiff' + | 'gitlens.externalDiff:commitDetails' + | 'gitlens.externalDiff:graphDetails' + | 'gitlens.externalDiffAll' + | 'gitlens.fetchRepositories' + | 'gitlens.getStarted' | 'gitlens.ghpr.views.openOrCreateWorktree' | 'gitlens.graph.addAuthor' | 'gitlens.graph.associateIssueWithBranch' @@ -137,7 +180,6 @@ export type ContributedCommands = | 'gitlens.graph.publishBranch' | 'gitlens.graph.pull' | 'gitlens.graph.push' - | 'gitlens.graph.pushWithForce' | 'gitlens.graph.rebaseOntoBranch' | 'gitlens.graph.rebaseOntoCommit' | 'gitlens.graph.rebaseOntoUpstream' @@ -162,31 +204,66 @@ export type ContributedCommands = | 'gitlens.graph.scrollMarkerTagOn' | 'gitlens.graph.shareAsCloudPatch' | 'gitlens.graph.showInDetailsView' + | 'gitlens.graph.split' | 'gitlens.graph.switchToAnotherBranch' | 'gitlens.graph.switchToBranch' | 'gitlens.graph.switchToCommit' + | 'gitlens.graph.switchToEditorLayout' + | 'gitlens.graph.switchToPanelLayout' | 'gitlens.graph.switchToTag' | 'gitlens.graph.undoCommit' | 'gitlens.inviteToLiveShare' - | 'gitlens.openCloudPatch' + | 'gitlens.openBranchesOnRemote' + | 'gitlens.openChangedFiles' + | 'gitlens.openCommitOnRemote' | 'gitlens.openComparisonOnRemote' + | 'gitlens.openFileHistory' + | 'gitlens.openFileHistory:commitDetails' + | 'gitlens.openFileHistory:graphDetails' + | 'gitlens.openFileOnRemote' + | 'gitlens.openFileOnRemote:commitDetails' + | 'gitlens.openFileOnRemote:graphDetails' + | 'gitlens.openFileOnRemoteFrom' | 'gitlens.openFolderHistory' + | 'gitlens.openOnlyChangedFiles' + | 'gitlens.openPatch' | 'gitlens.openPullRequestOnRemote' + | 'gitlens.openRepoOnRemote' | 'gitlens.openRevisionFile:editor/title' | 'gitlens.openWorkingFile:editor/context' | 'gitlens.openWorkingFile:editor/title' - | 'gitlens.plus.cloudIntegrations.connect' + | 'gitlens.plus.login' + | 'gitlens.pullRepositories' + | 'gitlens.pushRepositories' + | 'gitlens.quickOpenFileHistory' + | 'gitlens.quickOpenFileHistory:commitDetails' + | 'gitlens.quickOpenFileHistory:graphDetails' | 'gitlens.regenerateMarkdownDocument' + | 'gitlens.restore.file:commitDetails' + | 'gitlens.restore.file:graphDetails' | 'gitlens.restore.file:views' + | 'gitlens.restorePrevious.file:commitDetails' + | 'gitlens.restorePrevious.file:graphDetails' | 'gitlens.restorePrevious.file:views' + | 'gitlens.revealCommitInView' | 'gitlens.setUpstream:graph' | 'gitlens.setUpstream:views' + | 'gitlens.shareAsCloudPatch' + | 'gitlens.shareAsCloudPatch:commitDetails' + | 'gitlens.shareAsCloudPatch:graphDetails' + | 'gitlens.showCommitSearch' + | 'gitlens.showCommitsInView' + | 'gitlens.showGraph' | 'gitlens.showInCommitGraph' - | 'gitlens.showInCommitGraphView' | 'gitlens.showInDetailsView' - | 'gitlens.showQuickCommitDetails' + | 'gitlens.showLineCommitInView' + | 'gitlens.showLineHistoryView' + | 'gitlens.showQuickCommitFileDetails' | 'gitlens.showQuickRevisionDetails:editor' | 'gitlens.showQuickRevisionDetails:editor/title' + | 'gitlens.showRepositoriesView' + | 'gitlens.showSettingsPage' + | 'gitlens.showSettingsPage!autolinks' | 'gitlens.showSettingsPage!branches-view' | 'gitlens.showSettingsPage!commit-graph' | 'gitlens.showSettingsPage!commits-view' @@ -199,7 +276,6 @@ export type ContributedCommands = | 'gitlens.showSettingsPage!search-compare-view' | 'gitlens.showSettingsPage!stashes-view' | 'gitlens.showSettingsPage!tags-view' - | 'gitlens.showSettingsPage!views' | 'gitlens.showSettingsPage!worktrees-view' | 'gitlens.star.branch.multi:views' | 'gitlens.star.branch:graph' @@ -215,16 +291,19 @@ export type ContributedCommands = | 'gitlens.stashRename:views' | 'gitlens.stashSave.files:scm' | 'gitlens.stashSave.files:views' + | 'gitlens.stashSave.staged:scm' + | 'gitlens.stashSave.unstaged:scm' | 'gitlens.stashSave:graph' + | 'gitlens.stashSave:scm' | 'gitlens.stashSave:views' | 'gitlens.stashesApply:views' | 'gitlens.timeline.refresh' + | 'gitlens.timeline.split' + | 'gitlens.toggleFileBlame' | 'gitlens.toggleFileBlame:editor' | 'gitlens.toggleFileBlame:editor/title' - | 'gitlens.toggleFileBlame:key' | 'gitlens.toggleFileChanges:editor' | 'gitlens.toggleFileChanges:editor/title' - | 'gitlens.toggleFileChangesOnly' | 'gitlens.toggleFileHeatmap:editor' | 'gitlens.toggleFileHeatmap:editor/title' | 'gitlens.toggleFileHeatmapInDiffLeft' @@ -238,12 +317,12 @@ export type ContributedCommands = | 'gitlens.views.addAuthor' | 'gitlens.views.addAuthor.multi' | 'gitlens.views.addAuthors' - | 'gitlens.views.addPullRequestRemote' | 'gitlens.views.addRemote' | 'gitlens.views.applyChanges' + | 'gitlens.views.applyChanges:commitDetails' + | 'gitlens.views.applyChanges:graphDetails' | 'gitlens.views.associateIssueWithBranch' | 'gitlens.views.branches.attach' - | 'gitlens.views.branches.copy' | 'gitlens.views.branches.refresh' | 'gitlens.views.branches.setFilesLayoutToAuto' | 'gitlens.views.branches.setFilesLayoutToList' @@ -273,7 +352,6 @@ export type ContributedCommands = | 'gitlens.views.collapseNode' | 'gitlens.views.commitDetails.refresh' | 'gitlens.views.commits.attach' - | 'gitlens.views.commits.copy' | 'gitlens.views.commits.refresh' | 'gitlens.views.commits.setCommitsFilterAuthors' | 'gitlens.views.commits.setCommitsFilterOff' @@ -294,6 +372,8 @@ export type ContributedCommands = | 'gitlens.views.compareAncestryWithWorking' | 'gitlens.views.compareBranchWithHead' | 'gitlens.views.compareFileWithSelected' + | 'gitlens.views.compareFileWithSelected:commitDetails' + | 'gitlens.views.compareFileWithSelected:graphDetails' | 'gitlens.views.compareWithHead' | 'gitlens.views.compareWithMergeBase' | 'gitlens.views.compareWithSelected' @@ -301,7 +381,6 @@ export type ContributedCommands = | 'gitlens.views.compareWithWorking' | 'gitlens.views.continuePausedOperation' | 'gitlens.views.contributors.attach' - | 'gitlens.views.contributors.copy' | 'gitlens.views.contributors.refresh' | 'gitlens.views.contributors.setFilesLayoutToAuto' | 'gitlens.views.contributors.setFilesLayoutToList' @@ -316,9 +395,13 @@ export type ContributedCommands = | 'gitlens.views.contributors.setShowStatisticsOn' | 'gitlens.views.contributors.viewOptionsTitle' | 'gitlens.views.copy' + | 'gitlens.views.copy:commitDetails' + | 'gitlens.views.copy:graphDetails' | 'gitlens.views.copyAsMarkdown' | 'gitlens.views.copyRemoteCommitUrl' | 'gitlens.views.copyRemoteCommitUrl.multi' + | 'gitlens.views.copyRemoteCommitUrl:commitDetails' + | 'gitlens.views.copyRemoteCommitUrl:graphDetails' | 'gitlens.views.copyUrl' | 'gitlens.views.copyUrl.multi' | 'gitlens.views.createBranch' @@ -334,7 +417,6 @@ export type ContributedCommands = | 'gitlens.views.dismissNode' | 'gitlens.views.draft.open' | 'gitlens.views.draft.openOnWeb' - | 'gitlens.views.drafts.copy' | 'gitlens.views.drafts.create' | 'gitlens.views.drafts.delete' | 'gitlens.views.drafts.info' @@ -346,7 +428,6 @@ export type ContributedCommands = | 'gitlens.views.fetch' | 'gitlens.views.fileHistory.attach' | 'gitlens.views.fileHistory.changeBase' - | 'gitlens.views.fileHistory.copy' | 'gitlens.views.fileHistory.refresh' | 'gitlens.views.fileHistory.setCursorFollowingOff' | 'gitlens.views.fileHistory.setCursorFollowingOn' @@ -367,7 +448,11 @@ export type ContributedCommands = | 'gitlens.views.graph.refresh' | 'gitlens.views.graphDetails.refresh' | 'gitlens.views.highlightChanges' + | 'gitlens.views.highlightChanges:commitDetails' + | 'gitlens.views.highlightChanges:graphDetails' | 'gitlens.views.highlightRevisionChanges' + | 'gitlens.views.highlightRevisionChanges:commitDetails' + | 'gitlens.views.highlightRevisionChanges:graphDetails' | 'gitlens.views.home.disablePreview' | 'gitlens.views.home.discussions' | 'gitlens.views.home.enablePreview' @@ -378,7 +463,6 @@ export type ContributedCommands = | 'gitlens.views.home.refresh' | 'gitlens.views.home.whatsNew' | 'gitlens.views.launchpad.attach' - | 'gitlens.views.launchpad.copy' | 'gitlens.views.launchpad.info' | 'gitlens.views.launchpad.refresh' | 'gitlens.views.launchpad.setFilesLayoutToAuto' @@ -388,16 +472,16 @@ export type ContributedCommands = | 'gitlens.views.launchpad.setShowAvatarsOn' | 'gitlens.views.launchpad.viewOptionsTitle' | 'gitlens.views.lineHistory.changeBase' - | 'gitlens.views.lineHistory.copy' | 'gitlens.views.lineHistory.refresh' | 'gitlens.views.lineHistory.setEditorFollowingOff' | 'gitlens.views.lineHistory.setEditorFollowingOn' | 'gitlens.views.lineHistory.setShowAvatarsOff' | 'gitlens.views.lineHistory.setShowAvatarsOn' | 'gitlens.views.loadAllChildren' - | 'gitlens.views.loadMoreChildren' | 'gitlens.views.mergeBranchInto' | 'gitlens.views.mergeChangesWithWorking' + | 'gitlens.views.mergeChangesWithWorking:commitDetails' + | 'gitlens.views.mergeChangesWithWorking:graphDetails' | 'gitlens.views.openBranchOnRemote' | 'gitlens.views.openBranchOnRemote.multi' | 'gitlens.views.openChangedFileDiffs' @@ -408,20 +492,30 @@ export type ContributedCommands = | 'gitlens.views.openChangedFileRevisions' | 'gitlens.views.openChangedFiles' | 'gitlens.views.openChanges' + | 'gitlens.views.openChanges:commitDetails' + | 'gitlens.views.openChanges:graphDetails' | 'gitlens.views.openChangesWithMergeBase' | 'gitlens.views.openChangesWithWorking' + | 'gitlens.views.openChangesWithWorking:commitDetails' + | 'gitlens.views.openChangesWithWorking:graphDetails' | 'gitlens.views.openCommitOnRemote' | 'gitlens.views.openCommitOnRemote.multi' | 'gitlens.views.openDirectoryDiff' | 'gitlens.views.openDirectoryDiffWithWorking' | 'gitlens.views.openFile' + | 'gitlens.views.openFile:commitDetails' + | 'gitlens.views.openFile:graphDetails' | 'gitlens.views.openFileRevision' + | 'gitlens.views.openFileRevision:commitDetails' + | 'gitlens.views.openFileRevision:graphDetails' | 'gitlens.views.openInIntegratedTerminal' | 'gitlens.views.openInTerminal' | 'gitlens.views.openInWorktree' | 'gitlens.views.openOnlyChangedFiles' | 'gitlens.views.openPausedOperationInRebaseEditor' | 'gitlens.views.openPreviousChangesWithWorking' + | 'gitlens.views.openPreviousChangesWithWorking:commitDetails' + | 'gitlens.views.openPreviousChangesWithWorking:graphDetails' | 'gitlens.views.openPullRequest' | 'gitlens.views.openPullRequestChanges' | 'gitlens.views.openPullRequestComparison' @@ -437,7 +531,6 @@ export type ContributedCommands = | 'gitlens.views.publishRepository' | 'gitlens.views.pull' | 'gitlens.views.pullRequest.close' - | 'gitlens.views.pullRequest.copy' | 'gitlens.views.pullRequest.refresh' | 'gitlens.views.pullRequest.setFilesLayoutToAuto' | 'gitlens.views.pullRequest.setFilesLayoutToList' @@ -452,7 +545,6 @@ export type ContributedCommands = | 'gitlens.views.rebaseOntoUpstream' | 'gitlens.views.refreshNode' | 'gitlens.views.remotes.attach' - | 'gitlens.views.remotes.copy' | 'gitlens.views.remotes.refresh' | 'gitlens.views.remotes.setFilesLayoutToAuto' | 'gitlens.views.remotes.setFilesLayoutToList' @@ -467,7 +559,6 @@ export type ContributedCommands = | 'gitlens.views.removeRemote' | 'gitlens.views.renameBranch' | 'gitlens.views.repositories.attach' - | 'gitlens.views.repositories.copy' | 'gitlens.views.repositories.refresh' | 'gitlens.views.repositories.setAutoRefreshToOff' | 'gitlens.views.repositories.setAutoRefreshToOn' @@ -580,7 +671,6 @@ export type ContributedCommands = | 'gitlens.views.scm.grouped.worktrees.visibility.show' | 'gitlens.views.searchAndCompare.attach' | 'gitlens.views.searchAndCompare.clear' - | 'gitlens.views.searchAndCompare.copy' | 'gitlens.views.searchAndCompare.refresh' | 'gitlens.views.searchAndCompare.searchCommits' | 'gitlens.views.searchAndCompare.selectForCompare' @@ -592,6 +682,8 @@ export type ContributedCommands = | 'gitlens.views.searchAndCompare.swapComparison' | 'gitlens.views.searchAndCompare.viewOptionsTitle' | 'gitlens.views.selectFileForCompare' + | 'gitlens.views.selectFileForCompare:commitDetails' + | 'gitlens.views.selectFileForCompare:graphDetails' | 'gitlens.views.selectForCompare' | 'gitlens.views.setAsDefault' | 'gitlens.views.setBranchComparisonToBranch' @@ -608,8 +700,9 @@ export type ContributedCommands = | 'gitlens.views.skipPausedOperation' | 'gitlens.views.stageDirectory' | 'gitlens.views.stageFile' + | 'gitlens.views.stageFile:commitDetails' + | 'gitlens.views.stageFile:graphDetails' | 'gitlens.views.stashes.attach' - | 'gitlens.views.stashes.copy' | 'gitlens.views.stashes.refresh' | 'gitlens.views.stashes.setFilesLayoutToAuto' | 'gitlens.views.stashes.setFilesLayoutToList' @@ -620,7 +713,6 @@ export type ContributedCommands = | 'gitlens.views.switchToCommit' | 'gitlens.views.switchToTag' | 'gitlens.views.tags.attach' - | 'gitlens.views.tags.copy' | 'gitlens.views.tags.refresh' | 'gitlens.views.tags.setFilesLayoutToAuto' | 'gitlens.views.tags.setFilesLayoutToList' @@ -638,11 +730,13 @@ export type ContributedCommands = | 'gitlens.views.unsetAsDefault' | 'gitlens.views.unstageDirectory' | 'gitlens.views.unstageFile' + | 'gitlens.views.unstageFile:commitDetails' + | 'gitlens.views.unstageFile:graphDetails' | 'gitlens.views.workspaces.addRepos' | 'gitlens.views.workspaces.addReposFromLinked' | 'gitlens.views.workspaces.changeAutoAddSetting' | 'gitlens.views.workspaces.convert' - | 'gitlens.views.workspaces.copy' + | 'gitlens.views.workspaces.create' | 'gitlens.views.workspaces.createLocal' | 'gitlens.views.workspaces.delete' | 'gitlens.views.workspaces.info' @@ -656,7 +750,6 @@ export type ContributedCommands = | 'gitlens.views.workspaces.repo.openInNewWindow' | 'gitlens.views.workspaces.repo.remove' | 'gitlens.views.worktrees.attach' - | 'gitlens.views.worktrees.copy' | 'gitlens.views.worktrees.refresh' | 'gitlens.views.worktrees.setFilesLayoutToAuto' | 'gitlens.views.worktrees.setFilesLayoutToList' @@ -672,8 +765,10 @@ export type ContributedCommands = | 'gitlens.views.worktrees.setShowStashesOff' | 'gitlens.views.worktrees.setShowStashesOn' | 'gitlens.views.worktrees.viewOptionsTitle' + | 'gitlens.visualizeHistory.file:commitDetails' | 'gitlens.visualizeHistory.file:editor' | 'gitlens.visualizeHistory.file:explorer' + | 'gitlens.visualizeHistory.file:graphDetails' | 'gitlens.visualizeHistory.file:scm' | 'gitlens.visualizeHistory.file:views' | 'gitlens.visualizeHistory.folder:explorer' @@ -839,6 +934,7 @@ export type ContributedPaletteCommands = | 'gitlens.showLineHistoryView' | 'gitlens.showPatchDetailsPage' | 'gitlens.showQuickBranchHistory' + | 'gitlens.showQuickCommitDetails' | 'gitlens.showQuickCommitFileDetails' | 'gitlens.showQuickFileHistory' | 'gitlens.showQuickRepoHistory' @@ -877,6 +973,11 @@ export type ContributedPaletteCommands = | 'gitlens.visualizeHistory.file'; export type ContributedKeybindingCommands = + | 'gitlens.diffLineWithPrevious' + | 'gitlens.diffWithNext:key' + | 'gitlens.diffWithPrevious:key' + | 'gitlens.diffWithWorking:key' + | 'gitlens.gitCommands' | 'gitlens.key.alt+,' | 'gitlens.key.alt+.' | 'gitlens.key.alt+enter' @@ -887,4 +988,43 @@ export type ContributedKeybindingCommands = | 'gitlens.key.ctrl+right' | 'gitlens.key.escape' | 'gitlens.key.left' - | 'gitlens.key.right'; + | 'gitlens.key.right' + | 'gitlens.showQuickCommitFileDetails' + | 'gitlens.showQuickFileHistory' + | 'gitlens.showQuickRepoHistory' + | 'gitlens.showQuickRepoStatus' + | 'gitlens.toggleCodeLens' + | 'gitlens.toggleFileBlame:key' + | 'gitlens.views.branches.copy' + | 'gitlens.views.commits.copy' + | 'gitlens.views.contributors.copy' + | 'gitlens.views.drafts.copy' + | 'gitlens.views.fileHistory.copy' + | 'gitlens.views.launchpad.copy' + | 'gitlens.views.lineHistory.copy' + | 'gitlens.views.pullRequest.copy' + | 'gitlens.views.remotes.copy' + | 'gitlens.views.repositories.copy' + | 'gitlens.views.scm.grouped.branches' + | 'gitlens.views.scm.grouped.commits' + | 'gitlens.views.scm.grouped.contributors' + | 'gitlens.views.scm.grouped.fileHistory' + | 'gitlens.views.scm.grouped.launchpad' + | 'gitlens.views.scm.grouped.remotes' + | 'gitlens.views.scm.grouped.searchAndCompare' + | 'gitlens.views.scm.grouped.stashes' + | 'gitlens.views.scm.grouped.tags' + | 'gitlens.views.scm.grouped.worktrees' + | 'gitlens.views.searchAndCompare.copy' + | 'gitlens.views.stashes.copy' + | 'gitlens.views.tags.copy' + | 'gitlens.views.workspaces.copy' + | 'gitlens.views.worktrees.copy'; + +/** + * Commands that are not contributed anywhere, not the command palette, menus (or alts), nor keybindings. + * Either their contribution point is missing or are simply internal and should be removed at some point + */ +export type ContributedOrphansOrInternalCommands = + | 'gitlens.graph.pushWithForce' + | 'gitlens.plus.cloudIntegrations.connect'; diff --git a/src/constants.commands.ts b/src/constants.commands.ts index b92c2f414180b..70e9ca263662b 100644 --- a/src/constants.commands.ts +++ b/src/constants.commands.ts @@ -94,6 +94,8 @@ type InternalSearchAndCompareViewCommands = 'gitlens.views.searchAndCompare.comp type InternalTimelineWebviewViewCommands = 'gitlens.views.timeline.openInTab'; +type InternalViewCommands = 'gitlens.views.loadMoreChildren'; + type InternalWalkthroughCommands = | 'gitlens.walkthrough.connectIntegrations' | 'gitlens.walkthrough.enableAiSetting' @@ -128,6 +130,7 @@ type InternalGlCommands = | 'gitlens.ai.feedback.helpful' | 'gitlens.ai.feedback.unhelpful' | 'gitlens.ai.mcp.authCLI' + | 'gitlens.ai.undoGenerateRebase' | 'gitlens.changeBranchMergeTarget' | 'gitlens.diffWith' | 'gitlens.diffWithPrevious:codelens' @@ -135,12 +138,15 @@ type InternalGlCommands = | 'gitlens.diffWithPrevious:views' | 'gitlens.diffWithWorking:command' | 'gitlens.diffWithWorking:views' + | 'gitlens.openCloudPatch' | 'gitlens.openOnRemote' | 'gitlens.openWalkthrough' | 'gitlens.openWorkingFile:command' | 'gitlens.refreshHover' | 'gitlens.regenerateMarkdownDocument' | 'gitlens.showComposerPage' + | 'gitlens.showInCommitGraphView' + | 'gitlens.showQuickCommitDetails' | 'gitlens.storage.store' | 'gitlens.toggleFileBlame:codelens' | 'gitlens.toggleFileBlame:mode' @@ -161,6 +167,7 @@ type InternalGlCommands = | InternalScmGroupedViewCommands | InternalSearchAndCompareViewCommands | InternalTimelineWebviewViewCommands + | InternalViewCommands | InternalWalkthroughCommands; export type GlCommands = ContributedCommands | InternalGlCommands; // | GlCommandsDeprecated; @@ -238,9 +245,32 @@ export type TreeViewCommandSuffixesByViewType = Extract TreeViewCommandsByViewType >; -export type WebviewCommands = - | FilterCommands<`gitlens.${WebviewTypes}`, GlCommands> - | FilterCommands<'gitlens.', GlCommands, `:${WebviewTypes}`>; -export type WebviewViewCommands = - | FilterCommands<`gitlens.views.${WebviewViewTypes}`, GlCommands> - | FilterCommands<'gitlens.views.', GlCommands, `:${WebviewViewTypes}`>; +export type WebviewCommands = + | FilterCommands<`gitlens.${T}`, GlCommands> + | FilterCommands<'gitlens.', GlCommands, `:${T}`>; +export type WebviewViewCommands = + | FilterCommands<`gitlens.views.${T}`, GlCommands> + | FilterCommands<'gitlens.views.', GlCommands, `:${T}`> + | FilterCommands<'gitlens.', GlCommands, `:${T}`>; + +/** + * Extracts all possible prefixes (before the colon) from a union of commands. + * Example: 'gitlens.foo:graph' | 'gitlens.bar:timeline' -> 'gitlens.foo' | 'gitlens.bar' + */ +type ExtractCommandPrefix< + T extends GlCommands, + U extends WebviewTypes | WebviewViewTypes, +> = T extends `${infer Prefix}:${U}` ? `${Prefix}:` : never; + +type WebviewCommandPrefixes = ExtractCommandPrefix, T>; +export type WebviewCommandsOrCommandsWithSuffix = + | WebviewCommands + | WebviewCommandPrefixes; + +type WebviewViewCommandPrefixes = ExtractCommandPrefix< + WebviewViewCommands, + T +>; +export type WebviewViewCommandsOrCommandsWithSuffix = + | WebviewViewCommands + | WebviewViewCommandPrefixes; diff --git a/src/constants.context.ts b/src/constants.context.ts index 62d2b717a0754..fc5291618df9e 100644 --- a/src/constants.context.ts +++ b/src/constants.context.ts @@ -1,4 +1,5 @@ import type { Uri } from 'vscode'; +import type { FileAnnotationType } from './config'; import type { AnnotationStatus, Keys } from './constants'; import type { SubscriptionState } from './constants.subscription'; import type { CustomEditorTypes, GroupableTreeViewTypes, WebviewTypes, WebviewViewTypes } from './constants.views'; @@ -8,6 +9,12 @@ import type { OrgAIProviders } from './plus/gk/models/organization'; import type { PromoKeys } from './plus/gk/models/promo'; import type { SubscriptionPlanIds } from './plus/gk/models/subscription'; +interface CompareSelectedFileInfo { + ref: string; + repoPath: string | undefined; + uri: Uri; +} + export type ContextKeys = { 'gitlens:debugging': boolean; 'gitlens:disabled': boolean; @@ -42,12 +49,13 @@ export type ContextKeys = { 'gitlens:tabs:ai:unhelpful': Uri[]; 'gitlens:tabs:ai:changelog': Uri[]; 'gitlens:tabs:annotated': Uri[]; + 'gitlens:tabs:annotated:changes': Uri[]; 'gitlens:tabs:annotated:computing': Uri[]; 'gitlens:tabs:blameable': Uri[]; 'gitlens:tabs:tracked': Uri[]; 'gitlens:untrusted': boolean; 'gitlens:views:canCompare': boolean; - 'gitlens:views:canCompare:file': boolean; + 'gitlens:views:canCompare:file': CompareSelectedFileInfo; 'gitlens:views:commits:filtered': boolean; 'gitlens:views:commits:hideMergeCommits': boolean; 'gitlens:views:contributors:hideMergeCommits': boolean; @@ -63,7 +71,7 @@ export type ContextKeys = { 'gitlens:views:scm:grouped:view': GroupableTreeViewTypes; 'gitlens:views:scm:grouped:welcome': boolean; 'gitlens:vsls': boolean | 'host' | 'guest'; - 'gitlens:window:annotated': AnnotationStatus; + 'gitlens:window:annotated': AnnotationStatus | `${AnnotationStatus}:${FileAnnotationType}`; 'gitlens:walkthroughSupported': boolean; } & Record<`gitlens:action:${string}`, number> & Record<`gitlens:feature:unsupported:${Features}`, boolean> & diff --git a/src/constants.telemetry.ts b/src/constants.telemetry.ts index 1622d10ea6e0a..b772a6db8d739 100644 --- a/src/constants.telemetry.ts +++ b/src/constants.telemetry.ts @@ -258,6 +258,9 @@ export interface TelemetryEvents extends WebviewShowAbortedEvents, WebviewShownE /** Sent when a PR review was started in the inspect overview */ openReviewMode: OpenReviewModeEvent; + 'op/gate/deadlock': OperationGateDeadlockEvent; + 'op/git/aborted': OperationGitAbortedEvent; + /** Sent when fetching the product config fails */ 'productConfig/failed': ProductConfigFailedEvent; @@ -944,6 +947,19 @@ interface OpenReviewModeEvent { source: Sources; } +interface OperationGateDeadlockEvent { + key: string; + prop: string; + timeout: number; +} + +interface OperationGitAbortedEvent { + operation: string; + duration: number; + timeout: number; + reason: 'timeout' | 'cancellation' | 'unknown'; +} + interface ProductConfigFailedEvent { reason: 'fetch' | 'validation'; json: string | undefined; diff --git a/src/constants.views.ts b/src/constants.views.ts index 806942df0f542..9a32dd2be6851 100644 --- a/src/constants.views.ts +++ b/src/constants.views.ts @@ -43,6 +43,22 @@ export type WebviewIds = `gitlens.${WebviewTypes}`; export type WebviewViewTypes = 'commitDetails' | 'graph' | 'graphDetails' | 'home' | 'patchDetails' | 'timeline'; export type WebviewViewIds = `gitlens.views.${T}`; +export type WebviewTypeFromId = T extends `gitlens.${infer U}` + ? U extends WebviewTypes + ? U + : never + : never; +export type WebviewViewTypeFromId = T extends `gitlens.views.${infer U}` + ? U extends WebviewViewTypes + ? U + : never + : never; +export type WebviewOrWebviewViewTypeFromId = T extends WebviewIds + ? WebviewTypeFromId + : T extends WebviewViewIds + ? WebviewViewTypeFromId + : never; + export type ViewTypes = TreeViewTypes | WebviewViewTypes; export type ViewIds = TreeViewIds | WebviewViewIds; diff --git a/src/container.ts b/src/container.ts index 9df704e5d432d..95462b620b72b 100644 --- a/src/container.ts +++ b/src/container.ts @@ -7,6 +7,7 @@ import { getSupportedGitProviders, getSupportedRepositoryLocationProvider, getSupportedWorkspacesStorageProvider, + setTelemetryService, } from '@env/providers'; import { FileAnnotationController } from './annotations/fileAnnotationController'; import { LineAnnotationController } from './annotations/lineAnnotationController'; @@ -190,6 +191,7 @@ export class Container { this._context = context; this._prerelease = prerelease; this._version = version; + this._previousVersion = previousVersion; this.ensureModeApplied(); this._disposables = [ @@ -199,6 +201,7 @@ export class Container { (this._usage = new UsageTracker(this, storage)), configuration.onDidChangeAny(this.onAnyConfigurationChanged, this), ]; + setTelemetryService(this._telemetry); this._urls = new UrlsProvider(this.env); this._disposables.push((this._connection = new ServerConnection(this, this._urls))); @@ -747,6 +750,11 @@ export class Container { return this._version; } + private readonly _previousVersion: string | undefined; + get previousVersion(): string | undefined { + return this._previousVersion; + } + private readonly _views: Views; get views(): Views { return this._views; diff --git a/src/env/browser/json.ts b/src/env/browser/json.ts index 0e68de716527b..817e1505e59ae 100644 --- a/src/env/browser/json.ts +++ b/src/env/browser/json.ts @@ -1,5 +1,11 @@ +import { URI } from 'vscode-uri'; +import type { IpcDate, IpcPromise } from '../../webviews/ipc'; +import { getIpcTaggedType, isIpcPromise } from '../../webviews/ipc'; +import { IpcPromiseSettled } from '../../webviews/protocol'; + export function loggingJsonReplacer(key: string, value: unknown): unknown { if (key === '' || value == null || typeof value !== 'object') return value; + if (key.charCodeAt(0) === 95) return undefined; // '_' = 95 if (value instanceof Error) return String(value); @@ -7,11 +13,95 @@ export function loggingJsonReplacer(key: string, value: unknown): unknown { } export function serializeJsonReplacer(this: any, key: string, value: unknown): unknown { - if (value instanceof Date) return value.getTime(); - if (value instanceof Map || value instanceof Set) return [...value.entries()]; - if (value instanceof Function || value instanceof Error) return undefined; - if (value instanceof RegExp) return value.toString(); + if (typeof value === 'object' && value != null) { + // Dates and Uris are automatically converted by JSON.stringify, so we check the original below + // if (value instanceof Date) return value.getTime(); + // if (value instanceof RegExp) return value.toString(); + if (value instanceof Map || value instanceof Set) return [...value.entries()]; + if (value instanceof Function || value instanceof Error) return undefined; + } + + const original = this[key]; + if (original !== value && typeof original === 'object' && original != null) { + if (original instanceof Date) return original.getTime(); + } + return value; +} + +export function serializeIpcJsonReplacer( + this: any, + key: string, + value: unknown, + nextIpcId: () => string, + pendingPromises: IpcPromise[], +): unknown { + // Filter out __promise property from IpcPromise objects to avoid circular references + if (key === '__promise') return undefined; + + if (typeof value === 'object' && value != null) { + if ('__ipc' in value) { + if (isIpcPromise(value)) { + value.value.id = nextIpcId(); + pendingPromises.push(value); + } + return value; + } + + // Dates and Uris are automatically converted by JSON.stringify, so we check the original below + // if (value instanceof Date) { + // return { __ipc: 'date', value: value.getTime() } satisfies IpcDate; + // } + // if (value instanceof Uri) { + // return { __ipc: 'uri', value: value.toJSON() } satisfies IpcUri; + // } + if (value instanceof Promise) { + const ipcPromise: IpcPromise = { + __ipc: 'promise', + __promise: value, + value: { + id: nextIpcId(), + method: IpcPromiseSettled.method, + }, + }; + pendingPromises.push(ipcPromise); + return ipcPromise; + } + + if (value instanceof RegExp) return value.toString(); + if (value instanceof Map || value instanceof Set) return [...value.entries()]; + if (value instanceof Error || value instanceof Function) return undefined; + // if (isContainer(value)) return undefined; + } + + if (!key) return value; const original = this[key]; - return original instanceof Date ? original.getTime() : value; + if (original !== value && typeof original === 'object' && original != null) { + if (original instanceof Date) { + return { __ipc: 'date', value: original.getTime() } satisfies IpcDate; + } + // if (original instanceof Uri) { + // return { __ipc: 'uri', value: original.toJSON() } satisfies IpcUri; + // } + } + return value; +} + +export function deserializeIpcJsonReviver( + this: any, + _key: string, + value: unknown, + promiseFactory: (value: IpcPromise['value']) => Promise, +): unknown { + const tagged = getIpcTaggedType(value); + if (tagged == null) return value; + + switch (tagged.__ipc) { + case 'date': + return new Date(tagged.value); + case 'promise': + return promiseFactory(tagged.value); + case 'uri': + return URI.revive(tagged.value); + } } diff --git a/src/env/browser/platform.ts b/src/env/browser/platform.ts index 0e5d8294f9596..ee5eecf0e520a 100644 --- a/src/env/browser/platform.ts +++ b/src/env/browser/platform.ts @@ -1,6 +1,7 @@ import type { Platform } from '../node/platform'; export const isWeb = true; +export const isOffline = false; const _platform = (navigator as any)?.userAgentData?.platform; const _userAgent = navigator.userAgent; diff --git a/src/env/browser/providers.ts b/src/env/browser/providers.ts index b52ceb5739fb3..6997d79598d76 100644 --- a/src/env/browser/providers.ts +++ b/src/env/browser/providers.ts @@ -8,6 +8,7 @@ import type { RepositoryLocationProvider } from '../../git/location/repositorylo import { GitHubGitProvider } from '../../plus/integrations/providers/github/githubGitProvider'; import type { SharedGkStorageLocationProvider } from '../../plus/repos/sharedGkStorageLocationProvider'; import type { GkWorkspacesSharedStorageProvider } from '../../plus/workspaces/workspacesSharedStorageProvider'; +import type { TelemetryService } from '../../telemetry/telemetry'; import type { GitResult } from '../node/git/git'; export function git( @@ -47,3 +48,12 @@ export function getGkCliIntegrationProvider(_container: Container): undefined { export function getMcpProviders(_container: Container): Promise { return Promise.resolve(undefined); } + +let _telemetryService: TelemetryService | undefined; +export function getTelementryService(): TelemetryService | undefined { + return _telemetryService; +} + +export function setTelemetryService(service: TelemetryService): void { + _telemetryService = service; +} diff --git a/src/env/node/git/git.ts b/src/env/node/git/git.ts index 493a74da6a5e8..83b827154695e 100644 --- a/src/env/node/git/git.ts +++ b/src/env/node/git/git.ts @@ -34,6 +34,7 @@ import { } from '../../../git/errors'; import type { GitDir } from '../../../git/gitProvider'; import type { GitDiffFilter } from '../../../git/models/diff'; +import { rootSha } from '../../../git/models/revision'; import { parseGitRemoteUrl } from '../../../git/parsers/remoteParser'; import { isUncommitted, isUncommittedStaged, shortenRevision } from '../../../git/utils/revision.utils'; import { getCancellationTokenId } from '../../../system/-webview/cancellation'; @@ -69,9 +70,6 @@ export const maxGitCliLength = 30000; const textDecoder = new TextDecoder('utf8'); -// This is a root sha of all git repo's if using sha1 -const rootSha = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'; - export const GitErrors = { alreadyCheckedOut: /already checked out/i, alreadyExists: /already exists/i, @@ -247,7 +245,7 @@ export class Git implements Disposable { /** Map of running git commands -- avoids running duplicate overlapping commands */ private readonly pendingCommands = new Map>>(); - constructor(container: Container) { + constructor(private readonly container: Container) { this._disposable = container.events.on('git:cache:reset', e => { // Ignore provider resets (e.g. it needs to be git specific) if (e.data.types?.every(t => t === 'providers')) return; @@ -349,6 +347,26 @@ export class Git implements Disposable { exitCode: result.exitCode ?? 0, }; } catch (ex) { + if (ex instanceof CancelledRunError) { + const duration = getDurationMilliseconds(start); + const timeout = runOpts.timeout ?? 0; + const reason = + timeout > 0 && duration >= timeout - 100 + ? 'timeout' + : cancellation?.isCancellationRequested + ? 'cancellation' + : 'unknown'; + Logger.warn( + `${getLoggableScopeBlockOverride('GIT')} ${gitCommand} ${GlyphChars.Dot} ABORTED after ${duration}ms (${reason})`, + ); + this.container.telemetry.sendEvent('op/git/aborted', { + operation: gitCommand, + reason: reason, + duration: duration, + timeout: timeout, + }); + } + if (errorHandling === GitErrorHandling.Ignore) { if (ex instanceof RunError) { return { @@ -515,7 +533,11 @@ export class Git implements Disposable { } } } finally { - // I have NO idea why this HAS to be in a finally block, but it does + // This await MUST be in this inner finally block to ensure the child process close event completes + // before we call removeAllListeners() in the outer finally. When consumers break early from the + // async generator (e.g., reading only the first chunk), the git process receives SIGPIPE and triggers + // the close handler asynchronously. Without awaiting here, removeAllListeners() would execute before + // the close handler finishes, causing a race condition and potential resource leaks. await promise; } } catch (ex) { diff --git a/src/env/node/git/localGitProvider.ts b/src/env/node/git/localGitProvider.ts index cdb2ae59bbad0..4871ed8359e6c 100644 --- a/src/env/node/git/localGitProvider.ts +++ b/src/env/node/git/localGitProvider.ts @@ -12,14 +12,7 @@ import type { Container } from '../../../container'; import type { Features } from '../../../features'; import { GitCache } from '../../../git/cache'; import { GitErrorHandling } from '../../../git/commandOptions'; -import { - BlameIgnoreRevsFileBadRevisionError, - BlameIgnoreRevsFileError, - FetchError, - PullError, - PushError, - PushErrorReason, -} from '../../../git/errors'; +import { BlameIgnoreRevsFileBadRevisionError, BlameIgnoreRevsFileError } from '../../../git/errors'; import type { GitProvider, GitProviderDescriptor, @@ -37,7 +30,6 @@ import type { GitBlame, GitBlameAuthor, GitBlameLine } from '../../../git/models import type { GitCommit } from '../../../git/models/commit'; import type { GitLineDiff, ParsedGitDiffHunks } from '../../../git/models/diff'; import type { GitLog } from '../../../git/models/log'; -import type { GitBranchReference, GitReference } from '../../../git/models/reference'; import type { GitRemote } from '../../../git/models/remote'; import { RemoteResourceType } from '../../../git/models/remoteResource'; import type { RepositoryChangeEvent } from '../../../git/models/repository'; @@ -45,8 +37,6 @@ import { Repository, RepositoryChange, RepositoryChangeComparisonMode } from '.. import { deletedOrMissing } from '../../../git/models/revision'; import { parseGitBlame } from '../../../git/parsers/blameParser'; import { parseGitFileDiff } from '../../../git/parsers/diffParser'; -import { getBranchNameAndRemote, getBranchTrackingWithoutRemote } from '../../../git/utils/branch.utils'; -import { isBranchReference } from '../../../git/utils/reference.utils'; import { getVisibilityCacheKey } from '../../../git/utils/remote.utils'; import { isUncommitted, isUncommittedStaged, shortenRevision } from '../../../git/utils/revision.utils'; import { @@ -74,7 +64,7 @@ import { equalsIgnoreCase, getDurationMilliseconds } from '../../../system/strin import { compare, fromString } from '../../../system/version'; import type { CachedBlame, CachedDiff, TrackedGitDocument } from '../../../trackers/trackedDocument'; import { GitDocumentState } from '../../../trackers/trackedDocument'; -import type { Git, PushForceOptions } from './git'; +import type { Git } from './git'; import type { GitLocation } from './locator'; import { findGitPath, InvalidGitConfigError, UnableToFindGitError } from './locator'; import { fsExists } from './shell'; @@ -84,7 +74,9 @@ import { ConfigGitSubProvider } from './sub-providers/config'; import { ContributorsGitSubProvider } from './sub-providers/contributors'; import { DiffGitSubProvider, findPathStatusChanged } from './sub-providers/diff'; import { GraphGitSubProvider } from './sub-providers/graph'; +import { OperationsGitSubProvider } from './sub-providers/operations'; import { PatchGitSubProvider } from './sub-providers/patch'; +import { PausedOperationsGitSubProvider } from './sub-providers/pausedOperations'; import { RefsGitSubProvider } from './sub-providers/refs'; import { RemotesGitSubProvider } from './sub-providers/remotes'; import { RevisionGitSubProvider } from './sub-providers/revision'; @@ -170,49 +162,59 @@ export class LocalGitProvider implements GitProvider, Disposable { } private onRepositoryChanged(repo: Repository, e: RepositoryChangeEvent) { - if (e.changed(RepositoryChange.Config, RepositoryChangeComparisonMode.Any)) { - this._cache.repoInfo?.delete(repo.path); - } + if (e.changed(RepositoryChange.Unknown, RepositoryChangeComparisonMode.Any)) { + this._cache.clearCaches(repo.path); + } else { + if (e.changed(RepositoryChange.Config, RepositoryChangeComparisonMode.Any)) { + this._cache.repoInfo?.delete(repo.path); + } - if (e.changed(RepositoryChange.Heads, RepositoryChange.Remotes, RepositoryChangeComparisonMode.Any)) { - this._cache.branch?.delete(repo.path); - this._cache.branches?.delete(repo.path); - this._cache.contributors?.delete(repo.path); - this._cache.worktrees?.delete(repo.path); - } + if (e.changed(RepositoryChange.Heads, RepositoryChange.Remotes, RepositoryChangeComparisonMode.Any)) { + this._cache.branch?.delete(repo.path); + this._cache.branches?.delete(repo.path); + this._cache.contributors?.delete(repo.path); + this._cache.worktrees?.delete(repo.path); + } - if (e.changed(RepositoryChange.Remotes, RepositoryChange.RemoteProviders, RepositoryChangeComparisonMode.Any)) { - this._cache.remotes?.delete(repo.path); - this._cache.bestRemotes?.delete(repo.path); - } + if ( + e.changed( + RepositoryChange.Remotes, + RepositoryChange.RemoteProviders, + RepositoryChangeComparisonMode.Any, + ) + ) { + this._cache.remotes?.delete(repo.path); + this._cache.bestRemotes?.delete(repo.path); + } - if (e.changed(RepositoryChange.Index, RepositoryChange.Unknown, RepositoryChangeComparisonMode.Any)) { - this._cache.trackedPaths.clear(); - } + if (e.changed(RepositoryChange.Index, RepositoryChangeComparisonMode.Any)) { + this._cache.trackedPaths.clear(); + } - if ( - e.changed( - RepositoryChange.CherryPick, - RepositoryChange.Merge, - RepositoryChange.Rebase, - RepositoryChange.Revert, - RepositoryChangeComparisonMode.Any, - ) - ) { - this._cache.branch?.delete(repo.path); - this._cache.pausedOperationStatus?.delete(repo.path); - } + if ( + e.changed( + RepositoryChange.CherryPick, + RepositoryChange.Merge, + RepositoryChange.Rebase, + RepositoryChange.Revert, + RepositoryChangeComparisonMode.Any, + ) + ) { + this._cache.branch?.delete(repo.path); + this._cache.pausedOperationStatus?.delete(repo.path); + } - if (e.changed(RepositoryChange.Stash, RepositoryChangeComparisonMode.Any)) { - this._cache.stashes?.delete(repo.path); - } + if (e.changed(RepositoryChange.Stash, RepositoryChangeComparisonMode.Any)) { + this._cache.stashes?.delete(repo.path); + } - if (e.changed(RepositoryChange.Tags, RepositoryChangeComparisonMode.Any)) { - this._cache.tags?.delete(repo.path); - } + if (e.changed(RepositoryChange.Tags, RepositoryChangeComparisonMode.Any)) { + this._cache.tags?.delete(repo.path); + } - if (e.changed(RepositoryChange.Worktrees, RepositoryChangeComparisonMode.Any)) { - this._cache.worktrees?.delete(repo.path); + if (e.changed(RepositoryChange.Worktrees, RepositoryChangeComparisonMode.Any)) { + this._cache.worktrees?.delete(repo.path); + } } this._onWillChangeRepository.fire(e); @@ -419,13 +421,7 @@ export class LocalGitProvider implements GitProvider, Disposable { } @debug({ exit: true }) - openRepository( - folder: WorkspaceFolder | undefined, - uri: Uri, - root: boolean, - suspended?: boolean, - closed?: boolean, - ): Repository[] { + openRepository(folder: WorkspaceFolder | undefined, uri: Uri, root: boolean, closed?: boolean): Repository[] { if (!closed) { void this.getOrOpenScmRepository(uri); } @@ -441,7 +437,6 @@ export class LocalGitProvider implements GitProvider, Disposable { folder ?? workspace.getWorkspaceFolder(uri), uri, root, - suspended ?? !window.state.focused, closed, ), ]; @@ -460,7 +455,6 @@ export class LocalGitProvider implements GitProvider, Disposable { folder ?? workspace.getWorkspaceFolder(canonicalUri), canonicalUri, root, - suspended ?? !window.state.focused, true, ), ); @@ -630,7 +624,7 @@ export class LocalGitProvider implements GitProvider, Disposable { } Logger.log(scope, `found ${root ? 'root ' : ''}repository in '${uri.fsPath}'`); - repositories.push(...this.openRepository(folder, uri, root, undefined, silent)); + repositories.push(...this.openRepository(folder, uri, root, silent)); } const uri = await this.findRepositoryUri(rootUri, true); @@ -975,31 +969,6 @@ export class LocalGitProvider implements GitProvider, Disposable { } } - @log() - async checkout( - repoPath: string, - ref: string, - options?: { createBranch?: string } | { path?: string }, - ): Promise { - const scope = getLogScope(); - - try { - await this.git.checkout(repoPath, ref, options); - this.container.events.fire('git:cache:reset', { repoPath: repoPath, types: ['branches', 'status'] }); - } catch (ex) { - const msg: string = ex?.toString() ?? ''; - if (/overwritten by checkout/i.test(msg)) { - void showGenericErrorMessage( - `Unable to checkout '${ref}'. Please commit or stash your changes before switching branches`, - ); - return; - } - - Logger.error(ex, scope); - void showGenericErrorMessage(`Unable to checkout '${ref}'`); - } - } - @log() async clone(url: string, parentPath: string): Promise { const scope = getLogScope(); @@ -1036,158 +1005,6 @@ export class LocalGitProvider implements GitProvider, Disposable { return [...paths.values()]; } - @gate() - @log() - async fetch( - repoPath: string, - options?: { all?: boolean; branch?: GitBranchReference; prune?: boolean; pull?: boolean; remote?: string }, - ): Promise { - const scope = getLogScope(); - - const { branch, ...opts } = options ?? {}; - try { - if (isBranchReference(branch)) { - const [branchName, remoteName] = getBranchNameAndRemote(branch); - if (remoteName == null) return undefined; - - await this.git.fetch(repoPath, { - branch: branchName, - remote: remoteName, - upstream: getBranchTrackingWithoutRemote(branch)!, - pull: options?.pull, - }); - } else { - await this.git.fetch(repoPath, opts); - } - - this.container.events.fire('git:cache:reset', { repoPath: repoPath }); - } catch (ex) { - Logger.error(ex, scope); - if (!FetchError.is(ex)) throw ex; - - void window.showErrorMessage(ex.message); - } - } - - @gate() - @log() - async push( - repoPath: string, - options?: { reference?: GitReference; force?: boolean; publish?: { remote: string } }, - ): Promise { - const scope = getLogScope(); - - let branchName: string; - let remoteName: string | undefined; - let upstreamName: string | undefined; - let setUpstream: - | { - branch: string; - remote: string; - remoteBranch: string; - } - | undefined; - - if (isBranchReference(options?.reference)) { - if (options.publish != null) { - branchName = options.reference.name; - remoteName = options.publish.remote; - } else { - [branchName, remoteName] = getBranchNameAndRemote(options.reference); - } - upstreamName = getBranchTrackingWithoutRemote(options.reference); - } else { - const branch = await this.branches.getBranch(repoPath); - if (branch == null) return; - - branchName = - options?.reference != null - ? `${options.reference.ref}:${ - options?.publish != null ? 'refs/heads/' : '' - }${branch.getNameWithoutRemote()}` - : branch.name; - remoteName = branch.getRemoteName() ?? options?.publish?.remote; - upstreamName = options?.reference == null && options?.publish != null ? branch.name : undefined; - - // Git can't setup upstream tracking when publishing a new branch to a specific commit, so we'll need to do it after the push - if (options?.publish?.remote != null && options?.reference != null) { - setUpstream = { - branch: branch.getNameWithoutRemote(), - remote: remoteName!, - remoteBranch: branch.getNameWithoutRemote(), - }; - } - } - - if (options?.publish == null && remoteName == null && upstreamName == null) { - debugger; - throw new PushError(PushErrorReason.Other); - } - - let forceOpts: PushForceOptions | undefined; - if (options?.force) { - const withLease = configuration.getCore('git.useForcePushWithLease') ?? true; - if (withLease) { - forceOpts = { - withLease: withLease, - ifIncludes: configuration.getCore('git.useForcePushIfIncludes') ?? true, - }; - } else { - forceOpts = { - withLease: withLease, - }; - } - } - - try { - await this.git.push(repoPath, { - branch: branchName, - remote: remoteName, - upstream: upstreamName, - force: forceOpts, - publish: options?.publish != null, - }); - - // Since Git can't setup upstream tracking when publishing a new branch to a specific commit, do it now - if (setUpstream != null) { - await this.git.exec( - { cwd: repoPath }, - 'branch', - '--set-upstream-to', - `${setUpstream.remote}/${setUpstream.remoteBranch}`, - setUpstream.branch, - ); - } - - this.container.events.fire('git:cache:reset', { repoPath: repoPath }); - } catch (ex) { - Logger.error(ex, scope); - if (!PushError.is(ex)) throw ex; - - void window.showErrorMessage(ex.message); - } - } - - @gate() - @log() - async pull(repoPath: string, options?: { rebase?: boolean; tags?: boolean }): Promise { - const scope = getLogScope(); - - try { - await this.git.pull(repoPath, { - rebase: options?.rebase, - tags: options?.tags, - }); - - this.container.events.fire('git:cache:reset', { repoPath: repoPath }); - } catch (ex) { - Logger.error(ex, scope); - if (!PullError.is(ex)) throw ex; - - void window.showErrorMessage(ex.message); - } - } - private readonly toCanonicalMap = new Map(); private readonly fromCanonicalMap = new Map(); protected readonly unsafePaths = new Set(); @@ -2063,11 +1880,6 @@ export class LocalGitProvider implements GitProvider, Disposable { } } - @log() - async reset(repoPath: string, ref: string, options?: { hard?: boolean } | { soft?: boolean }): Promise { - await this.git.reset(repoPath, [], { ...options, ref: ref }); - } - @log({ args: { 2: false } }) async runGitCommandViaTerminal( repoPath: string, @@ -2116,11 +1928,31 @@ export class LocalGitProvider implements GitProvider, Disposable { return (this._graph ??= new GraphGitSubProvider(this.container, this.git, this._cache, this)); } + private _operations: OperationsGitSubProvider | undefined; + get ops(): OperationsGitSubProvider { + return (this._operations ??= new OperationsGitSubProvider( + this.container, + this.git, + this._cache, + this as unknown as LocalGitProviderInternal, + )); + } + private _patch: PatchGitSubProvider | undefined; get patch(): PatchGitSubProvider | undefined { return (this._patch ??= new PatchGitSubProvider(this.container, this.git, this)); } + private _pausedOperations: PausedOperationsGitSubProvider | undefined; + get pausedOps(): PausedOperationsGitSubProvider { + return (this._pausedOperations ??= new PausedOperationsGitSubProvider( + this.container, + this.git, + this._cache, + this as unknown as LocalGitProviderInternal, + )); + } + private _refs: RefsGitSubProvider | undefined; get refs(): RefsGitSubProvider { return (this._refs ??= new RefsGitSubProvider(this.container, this.git, this._cache, this)); diff --git a/src/env/node/git/sub-providers/branches.ts b/src/env/node/git/sub-providers/branches.ts index 8a74fa0c0086e..3e46c3785050b 100644 --- a/src/env/node/git/sub-providers/branches.ts +++ b/src/env/node/git/sub-providers/branches.ts @@ -88,7 +88,7 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider { const [pausedOpStatusResult, committerDateResult, defaultWorktreePathResult] = await Promise.allSettled([ isDetachedHead(ref.name) - ? this.provider.status?.getPausedOperationStatus(repoPath, cancellation) + ? this.provider.pausedOps.getPausedOperationStatus(repoPath, cancellation) : undefined, this.git .exec( diff --git a/src/env/node/git/sub-providers/commits.ts b/src/env/node/git/sub-providers/commits.ts index e1fac471ce675..e248bb578ada2 100644 --- a/src/env/node/git/sub-providers/commits.ts +++ b/src/env/node/git/sub-providers/commits.ts @@ -6,7 +6,6 @@ import { CancellationError, isCancellationError } from '../../../../errors'; import type { GitCache } from '../../../../git/cache'; import type { GitCommandOptions } from '../../../../git/commandOptions'; import { GitErrorHandling } from '../../../../git/commandOptions'; -import { CherryPickError, CherryPickErrorReason } from '../../../../git/errors'; import type { GitCommitsSubProvider, GitLogForPathOptions, @@ -37,7 +36,6 @@ import type { } from '../../../../git/parsers/logParser'; import { getCommitsLogParser, - getShaAndDatesLogParser, getShaAndFilesAndStatsLogParser, getShaLogParser, } from '../../../../git/parsers/logParser'; @@ -49,15 +47,16 @@ import { isRevisionRange, isSha, isUncommitted, isUncommittedStaged } from '../. import { isUserMatch } from '../../../../git/utils/user.utils'; import { configuration } from '../../../../system/-webview/configuration'; import { splitPath } from '../../../../system/-webview/path'; -import { log } from '../../../../system/decorators/log'; +import { debug, log } from '../../../../system/decorators/log'; import { filterMap, first, join, last, some } from '../../../../system/iterable'; import { Logger } from '../../../../system/logger'; import { getLogScope } from '../../../../system/logger.scope'; import { isFolderGlob, stripFolderGlob } from '../../../../system/path'; +import { maybeStopWatch } from '../../../../system/stopwatch'; import type { CachedLog, TrackedGitDocument } from '../../../../trackers/trackedDocument'; import { GitDocumentState } from '../../../../trackers/trackedDocument'; import type { Git, GitResult } from '../git'; -import { gitConfigsLog, gitConfigsLogWithFiles, GitErrors } from '../git'; +import { gitConfigsLog, gitConfigsLogWithFiles } from '../git'; import type { LocalGitProviderInternal } from '../localGitProvider'; import { convertStashesToStdin } from './stash'; @@ -76,63 +75,6 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider { return configuration.get('advanced.caching.enabled'); } - @log() - async cherryPick( - repoPath: string, - revs: string[], - options?: { edit?: boolean; noCommit?: boolean }, - ): Promise { - const args = ['cherry-pick']; - if (options?.edit) { - args.push('-e'); - } - if (options?.noCommit) { - args.push('-n'); - } - - if (revs.length > 1) { - const parser = getShaAndDatesLogParser(); - // Ensure the revs are in reverse committer date order - const result = await this.git.exec( - { cwd: repoPath, stdin: join(revs, '\n') }, - 'log', - '--no-walk', - '--stdin', - ...parser.arguments, - '--', - ); - const commits = [...parser.parse(result.stdout)].sort( - (c1, c2) => - Number(c1.committerDate) - Number(c2.committerDate) || - Number(c1.authorDate) - Number(c2.authorDate), - ); - revs = commits.map(c => c.sha); - } - - args.push(...revs); - - try { - await this.git.exec({ cwd: repoPath, errors: GitErrorHandling.Throw }, ...args); - } catch (ex) { - const msg: string = ex?.toString() ?? ''; - - let reason: CherryPickErrorReason = CherryPickErrorReason.Other; - if ( - GitErrors.changesWouldBeOverwritten.test(msg) || - GitErrors.changesWouldBeOverwritten.test(ex.stderr ?? '') - ) { - reason = CherryPickErrorReason.AbortedWouldOverwrite; - } else if (GitErrors.conflict.test(msg) || GitErrors.conflict.test(ex.stdout ?? '')) { - reason = CherryPickErrorReason.Conflicts; - } else if (GitErrors.emptyPreviousCherryPick.test(msg)) { - reason = CherryPickErrorReason.EmptyCommit; - } - - debugger; - throw new CherryPickError(reason, ex, revs); - } - } - @log() async getCommit(repoPath: string, rev: string, cancellation?: CancellationToken): Promise { if (isUncommitted(rev, true)) { @@ -380,6 +322,7 @@ export class CommitsGitSubProvider implements GitCommitsSubProvider { return this.getLogCore(repoPath, rev, options, cancellation); } + @debug({ args: { 2: false, 3: false, 4: false }, exit: true }) private async getLogCore( repoPath: string, rev?: string | undefined, @@ -1326,6 +1269,9 @@ async function parseCommits( if (resultOrStream instanceof Promise) { const result = await resultOrStream; + const scope = getLogScope(); + using sw = maybeStopWatch(scope, { log: false, logLevel: 'debug' }); + if (stashes?.size) { const allowFilteredFiles = searchFilters?.files ?? false; const stashesOnly = searchFilters?.type === 'stash'; @@ -1367,6 +1313,8 @@ async function parseCommits( } } + sw?.stop({ suffix: ` created ${count} commits` }); + return { commits: commits, count: count, countStashChildCommits: countStashChildCommits }; } diff --git a/src/env/node/git/sub-providers/graph.ts b/src/env/node/git/sub-providers/graph.ts index 0cd258f46d7e8..7e2c12752ebaa 100644 --- a/src/env/node/git/sub-providers/graph.ts +++ b/src/env/node/git/sub-providers/graph.ts @@ -40,7 +40,7 @@ import { } from '../../../../git/utils/branch.utils'; import { getChangedFilesCount } from '../../../../git/utils/commit.utils'; import { createReference } from '../../../../git/utils/reference.utils'; -import { isUncommittedStaged } from '../../../../git/utils/revision.utils'; +import { isUncommitted } from '../../../../git/utils/revision.utils'; import { getTagId } from '../../../../git/utils/tag.utils'; import { isUserMatch } from '../../../../git/utils/user.utils'; import { getWorktreeId } from '../../../../git/utils/worktree.utils'; @@ -94,14 +94,16 @@ export class GraphGitSubProvider implements GitGraphSubProvider { const [shaResult, stashResult, branchesResult, remotesResult, currentUserResult, worktreesResult] = await Promise.allSettled([ - this.git.exec( - { cwd: repoPath, configs: gitConfigsLog }, - 'log', - ...shaParser.arguments, - '-n1', - rev && !isUncommittedStaged(rev) ? rev : 'HEAD', - '--', - ), + !isUncommitted(rev, true) + ? this.git.exec( + { cwd: repoPath, configs: gitConfigsLog }, + 'log', + ...shaParser.arguments, + '-n1', + rev ?? 'HEAD', + '--', + ) + : undefined, this.provider.stash?.getStash(repoPath, undefined, cancellation), this.provider.branches.getBranches(repoPath, undefined, cancellation), this.provider.remotes.getRemotes(repoPath, undefined, cancellation), @@ -131,7 +133,8 @@ export class GraphGitSubProvider implements GitGraphSubProvider { const remotes = getSettledValue(remotesResult); const remoteMap = remotes != null ? new Map(remotes.map(r => [r.name, r])) : new Map(); - const selectSha = first(shaParser.parse(getSettledValue(shaResult)?.stdout)); + const shas = getSettledValue(shaResult)?.stdout; + const selectSha = shas != null ? first(shaParser.parse(shas)) : undefined; const downstreamMap = new Map(); @@ -589,7 +592,7 @@ export class GraphGitSubProvider implements GitGraphSubProvider { worktrees: worktrees, worktreesByBranch: worktreesByBranch, rows: rows, - id: sha, + id: sha ?? rev, rowsStats: rowStats, rowsStatsDeferred: rowsStatsDeferred, paging: { diff --git a/src/env/node/git/sub-providers/operations.ts b/src/env/node/git/sub-providers/operations.ts new file mode 100644 index 0000000000000..259b423620c37 --- /dev/null +++ b/src/env/node/git/sub-providers/operations.ts @@ -0,0 +1,275 @@ +import { window } from 'vscode'; +import type { Container } from '../../../../container'; +import type { GitCache } from '../../../../git/cache'; +import { GitErrorHandling } from '../../../../git/commandOptions'; +import { + CherryPickError, + CherryPickErrorReason, + FetchError, + PullError, + PushError, + PushErrorReason, +} from '../../../../git/errors'; +import type { GitOperationsSubProvider } from '../../../../git/gitProvider'; +import type { GitBranchReference, GitReference } from '../../../../git/models/reference'; +import { getShaAndDatesLogParser } from '../../../../git/parsers/logParser'; +import { getBranchNameAndRemote, getBranchTrackingWithoutRemote } from '../../../../git/utils/branch.utils'; +import { isBranchReference } from '../../../../git/utils/reference.utils'; +import { showGenericErrorMessage } from '../../../../messages'; +import { configuration } from '../../../../system/-webview/configuration'; +import { log } from '../../../../system/decorators/log'; +import { sequentialize } from '../../../../system/decorators/sequentialize'; +import { join } from '../../../../system/iterable'; +import { Logger } from '../../../../system/logger'; +import { getLogScope } from '../../../../system/logger.scope'; +import type { Git, PushForceOptions } from '../git'; +import { GitErrors } from '../git'; +import type { LocalGitProviderInternal } from '../localGitProvider'; + +export class OperationsGitSubProvider implements GitOperationsSubProvider { + constructor( + private readonly container: Container, + private readonly git: Git, + private readonly cache: GitCache, + private readonly provider: LocalGitProviderInternal, + ) {} + + @log() + async checkout( + repoPath: string, + ref: string, + options?: { createBranch?: string } | { path?: string }, + ): Promise { + const scope = getLogScope(); + + try { + await this.git.checkout(repoPath, ref, options); + this.container.events.fire('git:cache:reset', { repoPath: repoPath, types: ['branches', 'status'] }); + } catch (ex) { + const msg: string = ex?.toString() ?? ''; + if (/overwritten by checkout/i.test(msg)) { + void showGenericErrorMessage( + `Unable to checkout '${ref}'. Please commit or stash your changes before switching branches`, + ); + return; + } + + Logger.error(ex, scope); + void showGenericErrorMessage(`Unable to checkout '${ref}'`); + } + } + + @log() + async cherryPick( + repoPath: string, + revs: string[], + options?: { edit?: boolean; noCommit?: boolean }, + ): Promise { + const args = ['cherry-pick']; + if (options?.edit) { + args.push('-e'); + } + if (options?.noCommit) { + args.push('-n'); + } + + if (revs.length > 1) { + const parser = getShaAndDatesLogParser(); + // Ensure the revs are in reverse committer date order + const result = await this.git.exec( + { cwd: repoPath, stdin: join(revs, '\n') }, + 'log', + '--no-walk', + '--stdin', + ...parser.arguments, + '--', + ); + const commits = [...parser.parse(result.stdout)].sort( + (c1, c2) => + Number(c1.committerDate) - Number(c2.committerDate) || + Number(c1.authorDate) - Number(c2.authorDate), + ); + revs = commits.map(c => c.sha); + } + + args.push(...revs); + + try { + await this.git.exec({ cwd: repoPath, errors: GitErrorHandling.Throw }, ...args); + } catch (ex) { + const msg: string = ex?.toString() ?? ''; + + let reason: CherryPickErrorReason = CherryPickErrorReason.Other; + if ( + GitErrors.changesWouldBeOverwritten.test(msg) || + GitErrors.changesWouldBeOverwritten.test(ex.stderr ?? '') + ) { + reason = CherryPickErrorReason.AbortedWouldOverwrite; + } else if (GitErrors.conflict.test(msg) || GitErrors.conflict.test(ex.stdout ?? '')) { + reason = CherryPickErrorReason.Conflicts; + } else if (GitErrors.emptyPreviousCherryPick.test(msg)) { + reason = CherryPickErrorReason.EmptyCommit; + } + + debugger; + throw new CherryPickError(reason, ex, revs); + } + } + + @sequentialize({ getQueueKey: rp => rp }) + @log() + async fetch( + repoPath: string, + options?: { all?: boolean; branch?: GitBranchReference; prune?: boolean; pull?: boolean; remote?: string }, + ): Promise { + const scope = getLogScope(); + + const { branch, ...opts } = options ?? {}; + try { + if (isBranchReference(branch)) { + const [branchName, remoteName] = getBranchNameAndRemote(branch); + if (remoteName == null) return undefined; + + await this.git.fetch(repoPath, { + branch: branchName, + remote: remoteName, + upstream: getBranchTrackingWithoutRemote(branch)!, + pull: options?.pull, + }); + } else { + await this.git.fetch(repoPath, opts); + } + + this.container.events.fire('git:cache:reset', { repoPath: repoPath }); + } catch (ex) { + Logger.error(ex, scope); + if (!FetchError.is(ex)) throw ex; + + void window.showErrorMessage(ex.message); + } + } + + @sequentialize({ getQueueKey: rp => rp }) + @log() + async pull(repoPath: string, options?: { rebase?: boolean; tags?: boolean }): Promise { + const scope = getLogScope(); + + try { + await this.git.pull(repoPath, { + rebase: options?.rebase, + tags: options?.tags, + }); + + this.container.events.fire('git:cache:reset', { repoPath: repoPath }); + } catch (ex) { + Logger.error(ex, scope); + if (!PullError.is(ex)) throw ex; + + void window.showErrorMessage(ex.message); + } + } + + @sequentialize({ getQueueKey: rp => rp }) + @log() + async push( + repoPath: string, + options?: { reference?: GitReference; force?: boolean; publish?: { remote: string } }, + ): Promise { + const scope = getLogScope(); + + let branchName: string; + let remoteName: string | undefined; + let upstreamName: string | undefined; + let setUpstream: + | { + branch: string; + remote: string; + remoteBranch: string; + } + | undefined; + + if (isBranchReference(options?.reference)) { + if (options.publish != null) { + branchName = options.reference.name; + remoteName = options.publish.remote; + } else { + [branchName, remoteName] = getBranchNameAndRemote(options.reference); + } + upstreamName = getBranchTrackingWithoutRemote(options.reference); + } else { + const branch = await this.provider.branches.getBranch(repoPath); + if (branch == null) return; + + branchName = + options?.reference != null + ? `${options.reference.ref}:${ + options?.publish != null ? 'refs/heads/' : '' + }${branch.getNameWithoutRemote()}` + : branch.name; + remoteName = branch.getRemoteName() ?? options?.publish?.remote; + upstreamName = options?.reference == null && options?.publish != null ? branch.name : undefined; + + // Git can't setup upstream tracking when publishing a new branch to a specific commit, so we'll need to do it after the push + if (options?.publish?.remote != null && options?.reference != null) { + setUpstream = { + branch: branch.getNameWithoutRemote(), + remote: remoteName!, + remoteBranch: branch.getNameWithoutRemote(), + }; + } + } + + if (options?.publish == null && remoteName == null && upstreamName == null) { + debugger; + throw new PushError(PushErrorReason.Other); + } + + let forceOpts: PushForceOptions | undefined; + if (options?.force) { + const withLease = configuration.getCore('git.useForcePushWithLease') ?? true; + if (withLease) { + forceOpts = { + withLease: withLease, + ifIncludes: configuration.getCore('git.useForcePushIfIncludes') ?? true, + }; + } else { + forceOpts = { + withLease: withLease, + }; + } + } + + try { + await this.git.push(repoPath, { + branch: branchName, + remote: remoteName, + upstream: upstreamName, + force: forceOpts, + publish: options?.publish != null, + }); + + // Since Git can't setup upstream tracking when publishing a new branch to a specific commit, do it now + if (setUpstream != null) { + await this.git.exec( + { cwd: repoPath }, + 'branch', + '--set-upstream-to', + `${setUpstream.remote}/${setUpstream.remoteBranch}`, + setUpstream.branch, + ); + } + + this.container.events.fire('git:cache:reset', { repoPath: repoPath }); + } catch (ex) { + Logger.error(ex, scope); + if (!PushError.is(ex)) throw ex; + + void window.showErrorMessage(ex.message); + } + } + + @log() + async reset(repoPath: string, ref: string, options?: { hard?: boolean } | { soft?: boolean }): Promise { + await this.git.reset(repoPath, [], { ...options, ref: ref }); + } +} diff --git a/src/env/node/git/sub-providers/patch.ts b/src/env/node/git/sub-providers/patch.ts index c5460f4d9f4b3..f8e062d2a6fe2 100644 --- a/src/env/node/git/sub-providers/patch.ts +++ b/src/env/node/git/sub-providers/patch.ts @@ -40,8 +40,8 @@ export class PatchGitSubProvider implements GitPatchSubProvider { if (options?.stash) { // Stash any changes first - const status = await this.provider.status?.getStatus(repoPath); - if (status?.files?.length) { + const hasChanges = await this.provider.status?.hasWorkingChanges(repoPath); + if (hasChanges) { if (options.stash === 'prompt') { const confirm = { title: 'Stash Changes' }; const cancel = { title: 'Cancel', isCloseAffordance: true }; @@ -122,14 +122,14 @@ export class PatchGitSubProvider implements GitPatchSubProvider { if (options?.branchName != null && currentBranch?.name !== options.branchName) { const checkoutRef = shouldCreate ? (currentBranch?.ref ?? 'HEAD') : options.branchName; - await this.provider.checkout(targetPath, checkoutRef, { + await this.provider.ops.checkout(targetPath, checkoutRef, { createBranch: shouldCreate ? options.branchName : undefined, }); } // Apply the patch using a cherry pick without committing try { - await this.provider.commits.cherryPick(targetPath, [rev], { noCommit: true }); + await this.provider.ops.cherryPick(targetPath, [rev], { noCommit: true }); } catch (ex) { Logger.error(ex, scope); if (ex instanceof CherryPickError) { @@ -177,7 +177,7 @@ export class PatchGitSubProvider implements GitPatchSubProvider { @log({ args: { 2: p => p.length } }) async createUnreachableCommitsFromPatches( repoPath: string, - base: string, + base: string | undefined, patches: { message: string; patch: string }[], ): Promise { // Create a temporary index file @@ -198,7 +198,7 @@ export class PatchGitSubProvider implements GitPatchSubProvider { private async createUnreachableCommitForPatchCore( env: Record, repoPath: string, - base: string, + base: string | undefined, message: string, patch: string, ): Promise { @@ -222,7 +222,14 @@ export class PatchGitSubProvider implements GitPatchSubProvider { const tree = result.stdout.trim(); // Create new commit from the tree - result = await this.git.exec({ cwd: repoPath, env: env }, 'commit-tree', tree, '-p', base, '-m', message); + result = await this.git.exec( + { cwd: repoPath, env: env }, + 'commit-tree', + tree, + ...(base ? ['-p', base] : []), + '-m', + message, + ); const sha = result.stdout.trim(); return sha; @@ -234,6 +241,16 @@ export class PatchGitSubProvider implements GitPatchSubProvider { } } + async createEmptyInitialCommit(repoPath: string): Promise { + const emptyTree = await this.git.exec({ cwd: repoPath }, 'hash-object', '-t', 'tree', '/dev/null'); + const result = await this.git.exec({ cwd: repoPath }, 'commit-tree', emptyTree.stdout.trim(), '-m', 'temp'); + // create ref/heaads/main and point to it + await this.git.exec({ cwd: repoPath }, 'update-ref', 'refs/heads/main', result.stdout.trim()); + // point HEAD to the branch + await this.git.exec({ cwd: repoPath }, 'symbolic-ref', 'HEAD', 'refs/heads/main'); + return result.stdout.trim(); + } + @log({ args: { 1: false } }) async validatePatch(repoPath: string | undefined, contents: string): Promise { try { diff --git a/src/env/node/git/sub-providers/pausedOperations.ts b/src/env/node/git/sub-providers/pausedOperations.ts new file mode 100644 index 0000000000000..909026b85433a --- /dev/null +++ b/src/env/node/git/sub-providers/pausedOperations.ts @@ -0,0 +1,516 @@ +import { readdir } from 'fs'; +import type { CancellationToken } from 'vscode'; +import type { Container } from '../../../../container'; +import { CancellationError } from '../../../../errors'; +import type { GitCache } from '../../../../git/cache'; +import { GitErrorHandling } from '../../../../git/commandOptions'; +import { + PausedOperationAbortError, + PausedOperationAbortErrorReason, + PausedOperationContinueError, + PausedOperationContinueErrorReason, +} from '../../../../git/errors'; +import type { GitPausedOperationsSubProvider } from '../../../../git/gitProvider'; +import type { + GitCherryPickStatus, + GitMergeStatus, + GitPausedOperationStatus, + GitRebaseStatus, + GitRevertStatus, +} from '../../../../git/models/pausedOperationStatus'; +import type { GitBranchReference, GitTagReference } from '../../../../git/models/reference'; +import { createReference } from '../../../../git/utils/reference.utils'; +import { gate } from '../../../../system/decorators/gate'; +import { log } from '../../../../system/decorators/log'; +import { Logger } from '../../../../system/logger'; +import { getLogScope, setLogScopeExit } from '../../../../system/logger.scope'; +import { getSettledValue } from '../../../../system/promise'; +import type { Git } from '../git'; +import { GitErrors } from '../git'; +import type { LocalGitProviderInternal } from '../localGitProvider'; + +type Operation = 'cherry-pick' | 'merge' | 'rebase-apply' | 'rebase-merge' | 'revert'; + +const orderedOperations: Operation[] = ['rebase-apply', 'rebase-merge', 'merge', 'cherry-pick', 'revert']; + +export class PausedOperationsGitSubProvider implements GitPausedOperationsSubProvider { + constructor( + private readonly container: Container, + private readonly git: Git, + private readonly cache: GitCache, + private readonly provider: LocalGitProviderInternal, + ) {} + + @log() + async getPausedOperationStatus( + repoPath: string, + cancellation?: CancellationToken, + ): Promise { + const scope = getLogScope(); + + const status = this.cache.pausedOperationStatus?.getOrCreate(repoPath, async _cancellable => { + const gitDir = await this.provider.config.getGitDir(repoPath); + + const operations = await new Promise>((resolve, _) => { + readdir(gitDir.uri.fsPath, { withFileTypes: true }, (err, entries) => { + const operations = new Set(); + if (err != null) { + resolve(operations); + return; + } + + if (entries.length === 0) { + resolve(operations); + return; + } + + let entry; + for (entry of entries) { + if (entry.isFile()) { + switch (entry.name) { + case 'CHERRY_PICK_HEAD': + operations.add('cherry-pick'); + break; + case 'MERGE_HEAD': + operations.add('merge'); + break; + case 'REVERT_HEAD': + operations.add('revert'); + break; + } + } else if (entry.isDirectory()) { + switch (entry.name) { + case 'rebase-apply': + operations.add('rebase-apply'); + break; + case 'rebase-merge': + operations.add('rebase-merge'); + break; + } + } + } + + resolve(operations); + }); + }); + + if (!operations.size) return undefined; + if (cancellation?.isCancellationRequested) throw new CancellationError(); + + const sortedOperations = [...operations].sort( + (a, b) => orderedOperations.indexOf(a) - orderedOperations.indexOf(b), + ); + Logger.log(`Detected paused operations: ${sortedOperations.join(', ')}`); + + const operation = sortedOperations[0]; + switch (operation) { + case 'cherry-pick': { + const result = await this.git.exec( + { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, + 'rev-parse', + '--quiet', + '--verify', + 'CHERRY_PICK_HEAD', + ); + if (result.cancelled || cancellation?.isCancellationRequested) { + throw new CancellationError(); + } + + const cherryPickHead = result.stdout.trim(); + if (!cherryPickHead) { + setLogScopeExit(scope, 'No CHERRY_PICK_HEAD found'); + return undefined; + } + + const current = (await this.provider.branches.getCurrentBranchReference(repoPath, cancellation))!; + + return { + type: 'cherry-pick', + repoPath: repoPath, + // TODO: Validate that these are correct + HEAD: createReference(cherryPickHead, repoPath, { refType: 'revision' }), + current: current, + incoming: createReference(cherryPickHead, repoPath, { refType: 'revision' }), + } satisfies GitCherryPickStatus; + } + case 'merge': { + const result = await this.git.exec( + { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, + 'rev-parse', + '--quiet', + '--verify', + 'MERGE_HEAD', + ); + if (result.cancelled || cancellation?.isCancellationRequested) { + throw new CancellationError(); + } + + const mergeHead = result.stdout.trim(); + if (!mergeHead) { + setLogScopeExit(scope, 'No MERGE_HEAD found'); + return undefined; + } + + const [branchResult, mergeBaseResult, possibleSourceBranchesResult] = await Promise.allSettled([ + this.provider.branches.getCurrentBranchReference(repoPath, cancellation), + this.provider.refs.getMergeBase(repoPath, 'MERGE_HEAD', 'HEAD', undefined, cancellation), + this.provider.branches.getBranchesWithCommits( + repoPath, + ['MERGE_HEAD'], + undefined, + { all: true, mode: 'pointsAt' }, + cancellation, + ), + ]); + + if (cancellation?.isCancellationRequested) throw new CancellationError(); + + const current = getSettledValue(branchResult)!; + const mergeBase = getSettledValue(mergeBaseResult); + const possibleSourceBranches = getSettledValue(possibleSourceBranchesResult); + + return { + type: 'merge', + repoPath: repoPath, + mergeBase: mergeBase, + HEAD: createReference(mergeHead, repoPath, { refType: 'revision' }), + current: current, + incoming: + possibleSourceBranches?.length === 1 + ? createReference(possibleSourceBranches[0], repoPath, { + refType: 'branch', + name: possibleSourceBranches[0], + remote: false, + }) + : createReference(mergeHead, repoPath, { refType: 'revision' }), + } satisfies GitMergeStatus; + } + case 'revert': { + const result = await this.git.exec( + { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, + 'rev-parse', + '--quiet', + '--verify', + 'REVERT_HEAD', + ); + if (result.cancelled || cancellation?.isCancellationRequested) { + throw new CancellationError(); + } + + const revertHead = result.stdout.trim(); + if (!revertHead) { + setLogScopeExit(scope, 'No REVERT_HEAD found'); + return undefined; + } + + const current = (await this.provider.branches.getCurrentBranchReference(repoPath, cancellation))!; + + return { + type: 'revert', + repoPath: repoPath, + HEAD: createReference(revertHead, repoPath, { refType: 'revision' }), + current: current, + incoming: createReference(revertHead, repoPath, { refType: 'revision' }), + } satisfies GitRevertStatus; + } + case 'rebase-apply': + case 'rebase-merge': { + let branch = await this.git.readDotGitFile(gitDir, [operation, 'head-name']); + if (!branch) { + setLogScopeExit(scope, `No '${operation}/head-name' found`); + return undefined; + } + + const [ + rebaseHeadResult, + origHeadResult, + ontoResult, + stepsNumberResult, + stepsTotalResult, + stepsMessageResult, + ] = await Promise.allSettled([ + this.git.exec( + { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, + 'rev-parse', + '--quiet', + '--verify', + 'REBASE_HEAD', + ), + this.git.readDotGitFile(gitDir, [operation, 'orig-head']), + this.git.readDotGitFile(gitDir, [operation, 'onto']), + this.git.readDotGitFile(gitDir, [operation, 'msgnum'], { numeric: true }), + this.git.readDotGitFile(gitDir, [operation, 'end'], { numeric: true }), + this.git + .readDotGitFile(gitDir, [operation, 'message'], { throw: true }) + .catch(() => this.git.readDotGitFile(gitDir, [operation, 'message-squashed'])), + ]); + + if (cancellation?.isCancellationRequested) throw new CancellationError(); + + const origHead = getSettledValue(origHeadResult); + const onto = getSettledValue(ontoResult); + if (origHead == null || onto == null) { + setLogScopeExit(scope, `Neither '${operation}/orig-head' nor '${operation}/onto' found`); + return undefined; + } + + const rebaseHead = getSettledValue(rebaseHeadResult)?.stdout.trim(); + + if (branch.startsWith('refs/heads/')) { + branch = branch.substring(11).trim(); + } + + const [mergeBaseResult, branchTipsResult, tagTipsResult] = await Promise.allSettled([ + rebaseHead != null + ? this.provider.refs.getMergeBase(repoPath, rebaseHead, 'HEAD', undefined, cancellation) + : this.provider.refs.getMergeBase(repoPath, onto, origHead, undefined, cancellation), + this.provider.branches.getBranchesWithCommits( + repoPath, + [onto], + undefined, + { + all: true, + mode: 'pointsAt', + }, + cancellation, + ), + this.provider.tags.getTagsWithCommit(repoPath, onto, { mode: 'pointsAt' }, cancellation), + ]); + + if (cancellation?.isCancellationRequested) throw new CancellationError(); + + const mergeBase = getSettledValue(mergeBaseResult); + const branchTips = getSettledValue(branchTipsResult); + const tagTips = getSettledValue(tagTipsResult); + + let ontoRef: GitBranchReference | GitTagReference | undefined; + if (branchTips != null) { + for (const ref of branchTips) { + if (ref.startsWith('(no branch, rebasing')) continue; + + ontoRef = createReference(ref, repoPath, { + refType: 'branch', + name: ref, + remote: false, + }); + break; + } + } + if (ontoRef == null && tagTips != null) { + for (const ref of tagTips) { + if (ref.startsWith('(no branch, rebasing')) continue; + + ontoRef = createReference(ref, repoPath, { + refType: 'tag', + name: ref, + }); + break; + } + } + + return { + type: 'rebase', + repoPath: repoPath, + mergeBase: mergeBase, + HEAD: createReference(rebaseHead ?? origHead, repoPath, { refType: 'revision' }), + onto: createReference(onto, repoPath, { refType: 'revision' }), + current: ontoRef, + incoming: createReference(branch, repoPath, { + refType: 'branch', + name: branch, + remote: false, + }), + steps: { + current: { + number: getSettledValue(stepsNumberResult) ?? 0, + commit: + rebaseHead != null + ? createReference(rebaseHead, repoPath, { + refType: 'revision', + message: getSettledValue(stepsMessageResult), + }) + : undefined, + }, + total: getSettledValue(stepsTotalResult) ?? 0, + }, + } satisfies GitRebaseStatus; + } + } + }); + + return status; + } + + @gate((rp, o) => `${rp ?? ''}:${o?.quit ?? false}`) + @log() + async abortPausedOperation(repoPath: string, options?: { quit?: boolean }): Promise { + const status = await this.getPausedOperationStatus(repoPath); + if (status == null) return; + + try { + switch (status.type) { + case 'cherry-pick': + await this.git.exec( + { cwd: repoPath, errors: GitErrorHandling.Throw }, + 'cherry-pick', + options?.quit ? '--quit' : '--abort', + ); + break; + + case 'merge': + await this.git.exec( + { cwd: repoPath, errors: GitErrorHandling.Throw }, + 'merge', + options?.quit ? '--quit' : '--abort', + ); + break; + + case 'rebase': + await this.git.exec( + { cwd: repoPath, errors: GitErrorHandling.Throw }, + 'rebase', + options?.quit ? '--quit' : '--abort', + ); + break; + + case 'revert': + await this.git.exec( + { cwd: repoPath, errors: GitErrorHandling.Throw }, + 'revert', + options?.quit ? '--quit' : '--abort', + ); + break; + } + } catch (ex) { + debugger; + Logger.error(ex); + const msg: string = ex?.toString() ?? ''; + if (GitErrors.noPausedOperation.test(msg)) { + throw new PausedOperationAbortError( + PausedOperationAbortErrorReason.NothingToAbort, + status.type, + `Cannot abort as there is no ${status.type} operation in progress`, + ex, + ); + } + + throw new PausedOperationAbortError(undefined, status.type, `Cannot abort ${status.type}; ${msg}`, ex); + } + } + + @gate((rp, o) => `${rp ?? ''}:${o?.skip ?? false}`) + @log() + async continuePausedOperation(repoPath: string, options?: { skip?: boolean }): Promise { + const status = await this.getPausedOperationStatus(repoPath); + if (status == null) return; + + try { + switch (status.type) { + case 'cherry-pick': + await this.git.exec( + { cwd: repoPath, errors: GitErrorHandling.Throw }, + 'cherry-pick', + options?.skip ? '--skip' : '--continue', + ); + break; + + case 'merge': + if (options?.skip) throw new Error('Skipping a merge is not supported'); + await this.git.exec({ cwd: repoPath, errors: GitErrorHandling.Throw }, 'merge', '--continue'); + break; + + case 'rebase': + await this.git.exec( + { cwd: repoPath, errors: GitErrorHandling.Throw }, + 'rebase', + options?.skip ? '--skip' : '--continue', + ); + break; + + case 'revert': + await this.git.exec( + { cwd: repoPath, errors: GitErrorHandling.Throw }, + 'revert', + options?.skip ? '--skip' : '--abort', + ); + break; + } + } catch (ex) { + debugger; + Logger.error(ex); + + const msg: string = ex?.toString() ?? ''; + if (GitErrors.emptyPreviousCherryPick.test(msg)) { + throw new PausedOperationContinueError( + PausedOperationContinueErrorReason.EmptyCommit, + status, + `Cannot continue ${status.type} as the previous cherry-pick is empty`, + ex, + ); + } + + if (GitErrors.noPausedOperation.test(msg)) { + throw new PausedOperationContinueError( + PausedOperationContinueErrorReason.NothingToContinue, + status, + `Cannot ${options?.skip ? 'skip' : 'continue'} as there is no ${status.type} operation in progress`, + ex, + ); + } + + if (GitErrors.uncommittedChanges.test(msg)) { + throw new PausedOperationContinueError( + PausedOperationContinueErrorReason.UncommittedChanges, + status, + `Cannot ${options?.skip ? 'skip' : `continue ${status.type}`} as there are uncommitted changes`, + ex, + ); + } + + if (GitErrors.unmergedFiles.test(msg)) { + throw new PausedOperationContinueError( + PausedOperationContinueErrorReason.UnmergedFiles, + status, + `Cannot ${options?.skip ? 'skip' : `continue ${status.type}`} as there are unmerged files`, + ex, + ); + } + + if (GitErrors.unresolvedConflicts.test(msg)) { + throw new PausedOperationContinueError( + PausedOperationContinueErrorReason.UnresolvedConflicts, + status, + `Cannot ${options?.skip ? 'skip' : `continue ${status.type}`} as there are unresolved conflicts`, + ex, + ); + } + + if (GitErrors.unstagedChanges.test(msg)) { + throw new PausedOperationContinueError( + PausedOperationContinueErrorReason.UnstagedChanges, + status, + `Cannot ${options?.skip ? 'skip' : `continue ${status.type}`} as there are unstaged changes`, + ex, + ); + } + + if (GitErrors.changesWouldBeOverwritten.test(msg)) { + throw new PausedOperationContinueError( + PausedOperationContinueErrorReason.WouldOverwrite, + status, + `Cannot ${ + options?.skip ? 'skip' : `continue ${status.type}` + } as local changes would be overwritten`, + ex, + ); + } + + throw new PausedOperationContinueError( + undefined, + status, + `Cannot ${options?.skip ? 'skip' : `continue ${status.type}`}; ${msg}`, + ex, + ); + } + } +} diff --git a/src/env/node/git/sub-providers/remotes.ts b/src/env/node/git/sub-providers/remotes.ts index ec2f2634f755f..615efeccd66b3 100644 --- a/src/env/node/git/sub-providers/remotes.ts +++ b/src/env/node/git/sub-providers/remotes.ts @@ -4,10 +4,9 @@ import type { GitCache } from '../../../../git/cache'; import type { GitRemotesSubProvider } from '../../../../git/gitProvider'; import type { GitRemote } from '../../../../git/models/remote'; import { parseGitRemotes } from '../../../../git/parsers/remoteParser'; -import { getRemoteProviderMatcher, loadRemoteProviders } from '../../../../git/remotes/remoteProviders'; +import { getRemoteProviderMatcher, loadRemoteProvidersFromConfig } from '../../../../git/remotes/remoteProviders'; import { RemotesGitProviderBase } from '../../../../git/sub-providers/remotes'; import { sortRemotes } from '../../../../git/utils/-webview/sorting'; -import { configuration } from '../../../../system/-webview/configuration'; import { gate } from '../../../../system/decorators/gate'; import { log } from '../../../../system/decorators/log'; import { Logger } from '../../../../system/logger'; @@ -36,8 +35,8 @@ export class RemotesGitSubProvider extends RemotesGitProviderBase implements Git const scope = getLogScope(); const remotesPromise = this.cache.remotes?.getOrCreate(repoPath, async cancellable => { - const providers = loadRemoteProviders( - configuration.get('remotes', this.container.git.getRepository(repoPath)?.folder?.uri ?? null), + const providers = loadRemoteProvidersFromConfig( + this.container.git.getRepository(repoPath)?.folder?.uri ?? null, await this.container.integrations.getConfigured(), ); diff --git a/src/env/node/git/sub-providers/revision.ts b/src/env/node/git/sub-providers/revision.ts index 4d57f530a8fa0..83661f23850f3 100644 --- a/src/env/node/git/sub-providers/revision.ts +++ b/src/env/node/git/sub-providers/revision.ts @@ -6,8 +6,9 @@ import type { GitRevisionSubProvider, ResolvedRevision } from '../../../../git/g import type { GitFileStatus } from '../../../../git/models/fileStatus'; import { deletedOrMissing } from '../../../../git/models/revision'; import type { GitTreeEntry } from '../../../../git/models/tree'; +import { parseGitLsFilesStaged } from '../../../../git/parsers/indexParser'; import { getShaAndFileSummaryLogParser } from '../../../../git/parsers/logParser'; -import { parseGitLsFilesStaged, parseGitTree } from '../../../../git/parsers/treeParser'; +import { parseGitTree } from '../../../../git/parsers/treeParser'; import { isRevisionWithSuffix, isSha, @@ -79,6 +80,7 @@ export class RevisionGitSubProvider implements GitRevisionSubProvider { let result = await this.git.exec( { cwd: root, errors: GitErrorHandling.Ignore }, 'ls-files', + '-z', '--stage', '--', relativePath, diff --git a/src/env/node/git/sub-providers/staging.ts b/src/env/node/git/sub-providers/staging.ts index b247ab6ed3693..a5e4b7b95550e 100644 --- a/src/env/node/git/sub-providers/staging.ts +++ b/src/env/node/git/sub-providers/staging.ts @@ -4,12 +4,14 @@ import type { Uri } from 'vscode'; import type { Container } from '../../../../container'; import type { DisposableTemporaryGitIndex, GitStagingSubProvider } from '../../../../git/gitProvider'; import { splitPath } from '../../../../system/-webview/path'; +import { chunk, countStringLength } from '../../../../system/array'; import { log } from '../../../../system/decorators/log'; import { Logger } from '../../../../system/logger'; import { joinPaths } from '../../../../system/path'; import { mixinAsyncDisposable } from '../../../../system/unifiedDisposable'; import { scope } from '../../../../webviews/commitDetails/protocol'; import type { Git } from '../git'; +import { maxGitCliLength } from '../git'; export class StagingGitSubProvider implements GitStagingSubProvider { constructor( @@ -18,7 +20,7 @@ export class StagingGitSubProvider implements GitStagingSubProvider { ) {} @log() - async createTemporaryIndex(repoPath: string, base: string): Promise { + async createTemporaryIndex(repoPath: string, base: string | undefined): Promise { // Create a temporary index file const tempDir = await fs.mkdtemp(joinPaths(tmpdir(), 'gl-')); const tempIndex = joinPaths(tempDir, 'index'); @@ -37,24 +39,27 @@ export class StagingGitSubProvider implements GitStagingSubProvider { const env = { GIT_INDEX_FILE: tempIndex }; // Create the temp index file from a base ref/sha + if (base) { + // Get the tree of the base + const newIndexResult = await this.git.exec( + { cwd: repoPath, env: env }, + 'ls-tree', + '-z', + '-r', + '--full-name', + base, + ); - // Get the tree of the base - const newIndexResult = await this.git.exec( - { cwd: repoPath, env: env }, - 'ls-tree', - '-z', - '-r', - '--full-name', - base, - ); - - // Write the tree to our temp index - await this.git.exec( - { cwd: repoPath, env: env, stdin: newIndexResult.stdout }, - 'update-index', - '-z', - '--index-info', - ); + if (newIndexResult.stdout.trim()) { + // Write the tree to our temp index + await this.git.exec( + { cwd: repoPath, env: env, stdin: newIndexResult.stdout }, + 'update-index', + '-z', + '--index-info', + ); + } + } return mixinAsyncDisposable({ path: tempIndex, env: { GIT_INDEX_FILE: tempIndex } }, dispose); } catch (ex) { @@ -78,14 +83,22 @@ export class StagingGitSubProvider implements GitStagingSubProvider { } @log() - async stageFiles(repoPath: string, pathOrUri: string[] | Uri[]): Promise { - await this.git.exec( - { cwd: repoPath }, - 'add', - '-A', - '--', - ...pathOrUri.map(p => (typeof p === 'string' ? p : splitPath(p, repoPath)[0])), - ); + async stageFiles( + repoPath: string, + pathOrUri: string[] | Uri[], + options?: { intentToAdd?: boolean }, + ): Promise { + const pathspecs = pathOrUri.map(p => (typeof p === 'string' ? p : splitPath(p, repoPath)[0])); + + // Calculate a safe batch size based on average path length + const avgPathLength = countStringLength(pathspecs) / pathspecs.length; + const batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength)); + + // Process files in batches (will be a single batch if under the limit) + const batches = chunk(pathspecs, batchSize); + for (const batch of batches) { + await this.git.exec({ cwd: repoPath }, 'add', options?.intentToAdd ? '-N' : '-A', '--', ...batch); + } } @log() @@ -106,10 +119,17 @@ export class StagingGitSubProvider implements GitStagingSubProvider { @log() async unstageFiles(repoPath: string, pathOrUri: string[] | Uri[]): Promise { - await this.git.reset( - repoPath, - pathOrUri.map(p => (typeof p === 'string' ? p : splitPath(p, repoPath)[0])), - ); + const pathspecs = pathOrUri.map(p => (typeof p === 'string' ? p : splitPath(p, repoPath)[0])); + + // Calculate a safe batch size based on average path length + const avgPathLength = countStringLength(pathspecs) / pathspecs.length; + const batchSize = Math.max(1, Math.floor(maxGitCliLength / avgPathLength)); + + // Process files in batches (will be a single batch if under the limit) + const batches = chunk(pathspecs, batchSize); + for (const batch of batches) { + await this.git.reset(repoPath, batch); + } } @log() diff --git a/src/env/node/git/sub-providers/status.ts b/src/env/node/git/sub-providers/status.ts index 33aa12e524d3b..074455a30c620 100644 --- a/src/env/node/git/sub-providers/status.ts +++ b/src/env/node/git/sub-providers/status.ts @@ -1,28 +1,16 @@ -import { readdir } from 'fs'; import type { CancellationToken, Uri } from 'vscode'; import type { Container } from '../../../../container'; -import { CancellationError } from '../../../../errors'; +import { isCancellationError } from '../../../../errors'; import type { GitCache } from '../../../../git/cache'; import { GitErrorHandling } from '../../../../git/commandOptions'; -import { - PausedOperationAbortError, - PausedOperationAbortErrorReason, - PausedOperationContinueError, - PausedOperationContinueErrorReason, -} from '../../../../git/errors'; -import type { GitStatusSubProvider } from '../../../../git/gitProvider'; -import type { - GitCherryPickStatus, - GitMergeStatus, - GitPausedOperationStatus, - GitRebaseStatus, - GitRevertStatus, -} from '../../../../git/models/pausedOperationStatus'; -import type { GitBranchReference, GitTagReference } from '../../../../git/models/reference'; +import type { GitStatusSubProvider, GitWorkingChangesState } from '../../../../git/gitProvider'; +import type { GitConflictFile } from '../../../../git/models'; +import type { GitFile } from '../../../../git/models/file'; +import { GitFileWorkingTreeStatus } from '../../../../git/models/fileStatus'; import { GitStatus } from '../../../../git/models/status'; import type { GitStatusFile } from '../../../../git/models/statusFile'; +import { parseGitConflictFiles } from '../../../../git/parsers/indexParser'; import { parseGitStatus } from '../../../../git/parsers/statusParser'; -import { createReference } from '../../../../git/utils/reference.utils'; import { configuration } from '../../../../system/-webview/configuration'; import { splitPath } from '../../../../system/-webview/path'; import { gate } from '../../../../system/decorators/gate'; @@ -30,15 +18,10 @@ import { log } from '../../../../system/decorators/log'; import { Logger } from '../../../../system/logger'; import { getLogScope, setLogScopeExit } from '../../../../system/logger.scope'; import { stripFolderGlob } from '../../../../system/path'; -import { getSettledValue } from '../../../../system/promise'; +import { iterateByDelimiter } from '../../../../system/string'; import type { Git } from '../git'; -import { GitErrors } from '../git'; import type { LocalGitProvider } from '../localGitProvider'; -type Operation = 'cherry-pick' | 'merge' | 'rebase-apply' | 'rebase-merge' | 'revert'; - -const orderedOperations: Operation[] = ['rebase-apply', 'rebase-merge', 'merge', 'cherry-pick', 'revert']; - export class StatusGitSubProvider implements GitStatusSubProvider { constructor( private readonly container: Container, @@ -47,480 +30,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider { private readonly provider: LocalGitProvider, ) {} - @log() - async getPausedOperationStatus( - repoPath: string, - cancellation?: CancellationToken, - ): Promise { - const scope = getLogScope(); - - const status = this.cache.pausedOperationStatus?.getOrCreate(repoPath, async _cancellable => { - const gitDir = await this.provider.config.getGitDir(repoPath); - - const operations = await new Promise>((resolve, _) => { - readdir(gitDir.uri.fsPath, { withFileTypes: true }, (err, entries) => { - const operations = new Set(); - if (err != null) { - resolve(operations); - return; - } - - if (entries.length === 0) { - resolve(operations); - return; - } - - let entry; - for (entry of entries) { - if (entry.isFile()) { - switch (entry.name) { - case 'CHERRY_PICK_HEAD': - operations.add('cherry-pick'); - break; - case 'MERGE_HEAD': - operations.add('merge'); - break; - case 'REVERT_HEAD': - operations.add('revert'); - break; - } - } else if (entry.isDirectory()) { - switch (entry.name) { - case 'rebase-apply': - operations.add('rebase-apply'); - break; - case 'rebase-merge': - operations.add('rebase-merge'); - break; - } - } - } - - resolve(operations); - }); - }); - - if (!operations.size) return undefined; - if (cancellation?.isCancellationRequested) throw new CancellationError(); - - const sortedOperations = [...operations].sort( - (a, b) => orderedOperations.indexOf(a) - orderedOperations.indexOf(b), - ); - Logger.log(`Detected paused operations: ${sortedOperations.join(', ')}`); - - const operation = sortedOperations[0]; - switch (operation) { - case 'cherry-pick': { - const result = await this.git.exec( - { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, - 'rev-parse', - '--quiet', - '--verify', - 'CHERRY_PICK_HEAD', - ); - if (result.cancelled || cancellation?.isCancellationRequested) { - throw new CancellationError(); - } - - const cherryPickHead = result.stdout.trim(); - if (!cherryPickHead) { - setLogScopeExit(scope, 'No CHERRY_PICK_HEAD found'); - return undefined; - } - - const current = (await this.provider.branches.getCurrentBranchReference(repoPath, cancellation))!; - - return { - type: 'cherry-pick', - repoPath: repoPath, - // TODO: Validate that these are correct - HEAD: createReference(cherryPickHead, repoPath, { refType: 'revision' }), - current: current, - incoming: createReference(cherryPickHead, repoPath, { refType: 'revision' }), - } satisfies GitCherryPickStatus; - } - case 'merge': { - const result = await this.git.exec( - { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, - 'rev-parse', - '--quiet', - '--verify', - 'MERGE_HEAD', - ); - if (result.cancelled || cancellation?.isCancellationRequested) { - throw new CancellationError(); - } - - const mergeHead = result.stdout.trim(); - if (!mergeHead) { - setLogScopeExit(scope, 'No MERGE_HEAD found'); - return undefined; - } - - const [branchResult, mergeBaseResult, possibleSourceBranchesResult] = await Promise.allSettled([ - this.provider.branches.getCurrentBranchReference(repoPath, cancellation), - this.provider.refs.getMergeBase(repoPath, 'MERGE_HEAD', 'HEAD', undefined, cancellation), - this.provider.branches.getBranchesWithCommits( - repoPath, - ['MERGE_HEAD'], - undefined, - { all: true, mode: 'pointsAt' }, - cancellation, - ), - ]); - - if (cancellation?.isCancellationRequested) throw new CancellationError(); - - const current = getSettledValue(branchResult)!; - const mergeBase = getSettledValue(mergeBaseResult); - const possibleSourceBranches = getSettledValue(possibleSourceBranchesResult); - - return { - type: 'merge', - repoPath: repoPath, - mergeBase: mergeBase, - HEAD: createReference(mergeHead, repoPath, { refType: 'revision' }), - current: current, - incoming: - possibleSourceBranches?.length === 1 - ? createReference(possibleSourceBranches[0], repoPath, { - refType: 'branch', - name: possibleSourceBranches[0], - remote: false, - }) - : createReference(mergeHead, repoPath, { refType: 'revision' }), - } satisfies GitMergeStatus; - } - case 'revert': { - const result = await this.git.exec( - { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, - 'rev-parse', - '--quiet', - '--verify', - 'REVERT_HEAD', - ); - if (result.cancelled || cancellation?.isCancellationRequested) { - throw new CancellationError(); - } - - const revertHead = result.stdout.trim(); - if (!revertHead) { - setLogScopeExit(scope, 'No REVERT_HEAD found'); - return undefined; - } - - const current = (await this.provider.branches.getCurrentBranchReference(repoPath, cancellation))!; - - return { - type: 'revert', - repoPath: repoPath, - HEAD: createReference(revertHead, repoPath, { refType: 'revision' }), - current: current, - incoming: createReference(revertHead, repoPath, { refType: 'revision' }), - } satisfies GitRevertStatus; - } - case 'rebase-apply': - case 'rebase-merge': { - let branch = await this.git.readDotGitFile(gitDir, [operation, 'head-name']); - if (!branch) { - setLogScopeExit(scope, `No '${operation}/head-name' found`); - return undefined; - } - - const [ - rebaseHeadResult, - origHeadResult, - ontoResult, - stepsNumberResult, - stepsTotalResult, - stepsMessageResult, - ] = await Promise.allSettled([ - this.git.exec( - { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, - 'rev-parse', - '--quiet', - '--verify', - 'REBASE_HEAD', - ), - this.git.readDotGitFile(gitDir, [operation, 'orig-head']), - this.git.readDotGitFile(gitDir, [operation, 'onto']), - this.git.readDotGitFile(gitDir, [operation, 'msgnum'], { numeric: true }), - this.git.readDotGitFile(gitDir, [operation, 'end'], { numeric: true }), - this.git - .readDotGitFile(gitDir, [operation, 'message'], { throw: true }) - .catch(() => this.git.readDotGitFile(gitDir, [operation, 'message-squashed'])), - ]); - - if (cancellation?.isCancellationRequested) throw new CancellationError(); - - const origHead = getSettledValue(origHeadResult); - const onto = getSettledValue(ontoResult); - if (origHead == null || onto == null) { - setLogScopeExit(scope, `Neither '${operation}/orig-head' nor '${operation}/onto' found`); - return undefined; - } - - const rebaseHead = getSettledValue(rebaseHeadResult)?.stdout.trim(); - - if (branch.startsWith('refs/heads/')) { - branch = branch.substring(11).trim(); - } - - const [mergeBaseResult, branchTipsResult, tagTipsResult] = await Promise.allSettled([ - rebaseHead != null - ? this.provider.refs.getMergeBase(repoPath, rebaseHead, 'HEAD', undefined, cancellation) - : this.provider.refs.getMergeBase(repoPath, onto, origHead, undefined, cancellation), - this.provider.branches.getBranchesWithCommits( - repoPath, - [onto], - undefined, - { - all: true, - mode: 'pointsAt', - }, - cancellation, - ), - this.provider.tags.getTagsWithCommit(repoPath, onto, { mode: 'pointsAt' }, cancellation), - ]); - - if (cancellation?.isCancellationRequested) throw new CancellationError(); - - const mergeBase = getSettledValue(mergeBaseResult); - const branchTips = getSettledValue(branchTipsResult); - const tagTips = getSettledValue(tagTipsResult); - - let ontoRef: GitBranchReference | GitTagReference | undefined; - if (branchTips != null) { - for (const ref of branchTips) { - if (ref.startsWith('(no branch, rebasing')) continue; - - ontoRef = createReference(ref, repoPath, { - refType: 'branch', - name: ref, - remote: false, - }); - break; - } - } - if (ontoRef == null && tagTips != null) { - for (const ref of tagTips) { - if (ref.startsWith('(no branch, rebasing')) continue; - - ontoRef = createReference(ref, repoPath, { - refType: 'tag', - name: ref, - }); - break; - } - } - - return { - type: 'rebase', - repoPath: repoPath, - mergeBase: mergeBase, - HEAD: createReference(rebaseHead ?? origHead, repoPath, { refType: 'revision' }), - onto: createReference(onto, repoPath, { refType: 'revision' }), - current: ontoRef, - incoming: createReference(branch, repoPath, { - refType: 'branch', - name: branch, - remote: false, - }), - steps: { - current: { - number: getSettledValue(stepsNumberResult) ?? 0, - commit: - rebaseHead != null - ? createReference(rebaseHead, repoPath, { - refType: 'revision', - message: getSettledValue(stepsMessageResult), - }) - : undefined, - }, - total: getSettledValue(stepsTotalResult) ?? 0, - }, - } satisfies GitRebaseStatus; - } - } - }); - - return status; - } - - @gate(rp => rp ?? '') - @log() - async abortPausedOperation(repoPath: string, options?: { quit?: boolean }): Promise { - const status = await this.getPausedOperationStatus(repoPath); - if (status == null) return; - - try { - switch (status.type) { - case 'cherry-pick': - await this.git.exec( - { cwd: repoPath, errors: GitErrorHandling.Throw }, - 'cherry-pick', - options?.quit ? '--quit' : '--abort', - ); - break; - - case 'merge': - await this.git.exec( - { cwd: repoPath, errors: GitErrorHandling.Throw }, - 'merge', - options?.quit ? '--quit' : '--abort', - ); - break; - - case 'rebase': - await this.git.exec( - { cwd: repoPath, errors: GitErrorHandling.Throw }, - 'rebase', - options?.quit ? '--quit' : '--abort', - ); - break; - - case 'revert': - await this.git.exec( - { cwd: repoPath, errors: GitErrorHandling.Throw }, - 'revert', - options?.quit ? '--quit' : '--abort', - ); - break; - } - } catch (ex) { - debugger; - Logger.error(ex); - const msg: string = ex?.toString() ?? ''; - if (GitErrors.noPausedOperation.test(msg)) { - throw new PausedOperationAbortError( - PausedOperationAbortErrorReason.NothingToAbort, - status.type, - `Cannot abort as there is no ${status.type} operation in progress`, - ex, - ); - } - - throw new PausedOperationAbortError(undefined, status.type, `Cannot abort ${status.type}; ${msg}`, ex); - } - } - - @gate(rp => rp ?? '') - @log() - async continuePausedOperation(repoPath: string, options?: { skip?: boolean }): Promise { - const status = await this.getPausedOperationStatus(repoPath); - if (status == null) return; - - try { - switch (status.type) { - case 'cherry-pick': - await this.git.exec( - { cwd: repoPath, errors: GitErrorHandling.Throw }, - 'cherry-pick', - options?.skip ? '--skip' : '--continue', - ); - break; - - case 'merge': - if (options?.skip) throw new Error('Skipping a merge is not supported'); - await this.git.exec({ cwd: repoPath, errors: GitErrorHandling.Throw }, 'merge', '--continue'); - break; - - case 'rebase': - await this.git.exec( - { cwd: repoPath, errors: GitErrorHandling.Throw }, - 'rebase', - options?.skip ? '--skip' : '--continue', - ); - break; - - case 'revert': - await this.git.exec( - { cwd: repoPath, errors: GitErrorHandling.Throw }, - 'revert', - options?.skip ? '--skip' : '--abort', - ); - break; - } - } catch (ex) { - debugger; - Logger.error(ex); - - const msg: string = ex?.toString() ?? ''; - if (GitErrors.emptyPreviousCherryPick.test(msg)) { - throw new PausedOperationContinueError( - PausedOperationContinueErrorReason.EmptyCommit, - status, - `Cannot continue ${status.type} as the previous cherry-pick is empty`, - ex, - ); - } - - if (GitErrors.noPausedOperation.test(msg)) { - throw new PausedOperationContinueError( - PausedOperationContinueErrorReason.NothingToContinue, - status, - `Cannot ${options?.skip ? 'skip' : 'continue'} as there is no ${status.type} operation in progress`, - ex, - ); - } - - if (GitErrors.uncommittedChanges.test(msg)) { - throw new PausedOperationContinueError( - PausedOperationContinueErrorReason.UncommittedChanges, - status, - `Cannot ${options?.skip ? 'skip' : `continue ${status.type}`} as there are uncommitted changes`, - ex, - ); - } - - if (GitErrors.unmergedFiles.test(msg)) { - throw new PausedOperationContinueError( - PausedOperationContinueErrorReason.UnmergedFiles, - status, - `Cannot ${options?.skip ? 'skip' : `continue ${status.type}`} as there are unmerged files`, - ex, - ); - } - - if (GitErrors.unresolvedConflicts.test(msg)) { - throw new PausedOperationContinueError( - PausedOperationContinueErrorReason.UnresolvedConflicts, - status, - `Cannot ${options?.skip ? 'skip' : `continue ${status.type}`} as there are unresolved conflicts`, - ex, - ); - } - - if (GitErrors.unstagedChanges.test(msg)) { - throw new PausedOperationContinueError( - PausedOperationContinueErrorReason.UnstagedChanges, - status, - `Cannot ${options?.skip ? 'skip' : `continue ${status.type}`} as there are unstaged changes`, - ex, - ); - } - - if (GitErrors.changesWouldBeOverwritten.test(msg)) { - throw new PausedOperationContinueError( - PausedOperationContinueErrorReason.WouldOverwrite, - status, - `Cannot ${ - options?.skip ? 'skip' : `continue ${status.type}` - } as local changes would be overwritten`, - ex, - ); - } - - throw new PausedOperationContinueError( - undefined, - status, - `Cannot ${options?.skip ? 'skip' : `continue ${status.type}`}; ${msg}`, - ex, - ); - } - } - - @gate() + @gate(rp => rp ?? '') @log() async getStatus(repoPath: string | undefined, cancellation?: CancellationToken): Promise { if (repoPath == null) return undefined; @@ -536,7 +46,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider { const status = parseGitStatus(this.container, result.stdout, repoPath, porcelainVersion); if (status?.detached) { - const pausedOpStatus = await this.getPausedOperationStatus(repoPath, cancellation); + const pausedOpStatus = await this.provider.pausedOps.getPausedOperationStatus?.(repoPath, cancellation); if (pausedOpStatus?.type === 'rebase') { return new GitStatus( this.container, @@ -573,7 +83,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider { return this.getStatusForPathCore(repoPath, pathOrUri, { ...options, exact: false }, cancellation); } - @gate() + @gate(rp => rp ?? '') private async getStatusForPathCore( repoPath: string, pathOrUri: string | Uri, @@ -606,4 +116,224 @@ export class StatusGitSubProvider implements GitStatusSubProvider { const files = status?.files.filter(f => f.path.startsWith(relativePath)); return files; } + + @gate( + (rp, o) => `${rp ?? ''}:${o?.staged ?? true}:${o?.unstaged ?? true}:${o?.untracked ?? true}`, + ) + @log() + async hasWorkingChanges( + repoPath: string, + options?: { staged?: boolean; unstaged?: boolean; untracked?: boolean }, + cancellation?: CancellationToken, + ): Promise { + const scope = getLogScope(); + + try { + const staged = options?.staged ?? true; + const unstaged = options?.unstaged ?? true; + if (staged || unstaged) { + const result = await this.git.exec( + { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, + 'diff', + '--quiet', + staged && unstaged ? 'HEAD' : staged ? '--staged' : undefined, + ); + if (result.exitCode === 1) { + if (staged && unstaged) { + setLogScopeExit(scope, ' \u2022 has staged and unstaged changes'); + } else if (staged) { + setLogScopeExit(scope, ' \u2022 has staged changes'); + } else { + setLogScopeExit(scope, ' \u2022 has unstaged changes'); + } + return true; + } + } + + // Check for untracked files + const untracked = options?.untracked ?? true; + if (untracked) { + const hasUntracked = await this.hasUntrackedFiles(repoPath, cancellation); + if (hasUntracked) { + setLogScopeExit(scope, ' \u2022 has untracked files'); + return true; + } + } + + setLogScopeExit(scope, ' \u2022 no working changes'); + return false; + } catch (ex) { + // Re-throw cancellation errors + if (isCancellationError(ex)) throw ex; + + // Log other errors and return false for graceful degradation + Logger.error(ex, scope); + setLogScopeExit(scope, ' \u2022 error checking for changes'); + return false; + } + } + + @gate(rp => rp ?? '') + @log() + async getWorkingChangesState(repoPath: string, cancellation?: CancellationToken): Promise { + const scope = getLogScope(); + + try { + const [stagedResult, unstagedResult, untrackedResult] = await Promise.allSettled([ + // Check for staged changes + this.git.exec( + { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, + 'diff', + '--quiet', + '--staged', + ), + // Check for unstaged changes + this.git.exec( + { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, + 'diff', + '--quiet', + ), + // Check for untracked files + this.hasUntrackedFiles(repoPath, cancellation), + ]); + + const result = { + staged: Boolean(stagedResult.status === 'fulfilled' && stagedResult.value.exitCode === 1), + unstaged: Boolean(unstagedResult.status === 'fulfilled' && unstagedResult.value.exitCode === 1), + untracked: untrackedResult.status === 'fulfilled' && untrackedResult.value === true, + }; + + setLogScopeExit( + scope, + result.staged || result.unstaged || result.untracked + ? ` \u2022 has ${result.staged ? 'staged' : ''}${result.unstaged ? (result.staged ? ', unstaged' : 'unstaged ') : ''}${ + result.untracked ? (result.staged || result.unstaged ? ', untracked' : 'untracked') : '' + } changes` + : ' \u2022 no working changes', + ); + + return result; + } catch (ex) { + if (isCancellationError(ex)) throw ex; + Logger.error(ex, scope); + setLogScopeExit(scope, ' \u2022 error checking for changes'); + // Return all false on error for graceful degradation + return { staged: false, unstaged: false, untracked: false }; + } + } + + async hasConflictingFiles(repoPath: string, cancellation?: CancellationToken): Promise { + try { + const stream = this.git.stream({ cwd: repoPath, cancellation: cancellation }, 'ls-files', '--unmerged'); + + // Early exit on first chunk - breaking causes SIGPIPE, killing git process + for await (const _chunk of stream) { + return true; + } + + return false; + } catch (ex) { + // Re-throw cancellation errors + if (isCancellationError(ex)) throw ex; + + return false; + } + } + + @gate(rp => rp ?? '') + @log() + async getConflictingFiles(repoPath: string, cancellation?: CancellationToken): Promise { + const scope = getLogScope(); + + try { + const result = await this.git.exec( + { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, + 'ls-files', + '-z', + '--unmerged', + ); + + if (!result.stdout) { + setLogScopeExit(scope, ' \u2022 no conflicting files'); + return []; + } + + const files = parseGitConflictFiles(result.stdout, repoPath); + setLogScopeExit(scope, ` \u2022 ${files.length} conflicting file(s)`); + return files; + } catch (ex) { + // Re-throw cancellation errors + if (isCancellationError(ex)) throw ex; + + // Log other errors and return empty array for graceful degradation + Logger.error(ex, scope); + setLogScopeExit(scope, ' \u2022 error getting conflicting files'); + return []; + } + } + + private async hasUntrackedFiles(repoPath: string, cancellation?: CancellationToken): Promise { + try { + const stream = this.git.stream( + { cwd: repoPath, cancellation: cancellation }, + 'ls-files', + // '-z', // Unneeded since we are only looking for presence + '--others', + '--exclude-standard', + ); + + // Early exit on first chunk - breaking causes SIGPIPE, killing git process + for await (const _chunk of stream) { + return true; + } + + return false; + } catch (ex) { + // Re-throw cancellation errors + if (isCancellationError(ex)) throw ex; + + // Treat other errors as "no untracked files" for graceful degradation + return false; + } + } + + @gate(rp => rp ?? '') + @log() + async getUntrackedFiles(repoPath: string, cancellation?: CancellationToken): Promise { + const scope = getLogScope(); + + try { + const result = await this.git.exec( + { cwd: repoPath, cancellation: cancellation, errors: GitErrorHandling.Ignore }, + 'ls-files', + '-z', + '--others', + '--exclude-standard', + ); + + if (!result.stdout) { + setLogScopeExit(scope, ' \u2022 no untracked files'); + return []; + } + + const files: GitFile[] = []; + + for (const line of iterateByDelimiter(result.stdout, '\0')) { + if (!line.length) continue; + + files.push({ path: line, repoPath: repoPath, status: GitFileWorkingTreeStatus.Untracked }); + } + + setLogScopeExit(scope, ` \u2022 ${files.length} untracked file(s)`); + return files; + } catch (ex) { + // Re-throw cancellation errors + if (isCancellationError(ex)) throw ex; + + // Log other errors and return empty array for graceful degradation + Logger.error(ex, scope); + setLogScopeExit(scope, ' \u2022 error getting untracked files'); + return []; + } + } } diff --git a/src/env/node/git/vslsGitProvider.ts b/src/env/node/git/vslsGitProvider.ts index f4cf2a68d8b07..6d3773309283b 100644 --- a/src/env/node/git/vslsGitProvider.ts +++ b/src/env/node/git/vslsGitProvider.ts @@ -68,7 +68,7 @@ export class VslsGitProvider extends LocalGitProvider { if (repositories == null || repositories.length === 0) return []; return repositories.flatMap(r => - this.openRepository(undefined, Uri.parse(r.folderUri, true), r.root, undefined, r.closed), + this.openRepository(undefined, Uri.parse(r.folderUri, true), r.root, r.closed), ); } catch (ex) { Logger.error(ex, scope); diff --git a/src/env/node/gk/cli/commands.ts b/src/env/node/gk/cli/commands.ts index 36b7a429d4757..6690a2dbdb1e8 100644 --- a/src/env/node/gk/cli/commands.ts +++ b/src/env/node/gk/cli/commands.ts @@ -8,9 +8,10 @@ import { executeCommand } from '../../../../system/-webview/command'; import { createCommandDecorator } from '../../../../system/decorators/command'; import type { CliCommandRequest, CliCommandResponse, CliIpcServer } from './integration'; +type CliCommand = 'cherry-pick' | 'compare' | 'graph' | 'merge' | 'rebase'; type CliCommandHandler = (request: CliCommandRequest, repo?: Repository | undefined) => Promise; -const { command, getCommands } = createCommandDecorator(); +const { command, getCommands } = createCommandDecorator(); export class CliCommandHandlers implements Disposable { constructor( diff --git a/src/env/node/gk/cli/integration.ts b/src/env/node/gk/cli/integration.ts index e67af6ceb770f..1b71a867b8d1c 100644 --- a/src/env/node/gk/cli/integration.ts +++ b/src/env/node/gk/cli/integration.ts @@ -17,7 +17,7 @@ import { debug, log } from '../../../../system/decorators/log'; import { Logger } from '../../../../system/logger'; import { getLogScope, setLogScopeExit } from '../../../../system/logger.scope'; import { compare } from '../../../../system/version'; -import { getPlatform, isWeb } from '../../platform'; +import { getPlatform, isOffline, isWeb } from '../../platform'; import { CliCommandHandlers } from './commands'; import type { IpcServer } from './ipcServer'; import { createIpcServer } from './ipcServer'; @@ -32,6 +32,7 @@ const enum CLIInstallErrorReason { ProxyFetch, GlobalStorageDirectory, CoreInstall, + Offline, } const enum McpSetupErrorReason { @@ -44,6 +45,7 @@ const enum McpSetupErrorReason { UnsupportedHost, UnsupportedClient, UnexpectedOutput, + Offline, } export interface CliCommandRequest { @@ -118,6 +120,11 @@ export class GkCliIntegrationProvider implements Disposable { return; } + // Reset the attempts count if GitLens extension version has changed + if (reachedMaxAttempts(cliInstall) && this.container.version !== this.container.previousVersion) { + void this.container.storage.store('gk:cli:install', undefined); + } + if (!mcpExtensionRegistrationAllowed() || reachedMaxAttempts(cliInstall)) { return; } @@ -164,6 +171,7 @@ export class GkCliIntegrationProvider implements Disposable { switch (ex.reason) { case McpSetupErrorReason.WebUnsupported: case McpSetupErrorReason.VSCodeVersionUnsupported: + case McpSetupErrorReason.Offline: void window.showWarningMessage(ex.message); break; case McpSetupErrorReason.InstallationFailed: @@ -383,6 +391,12 @@ export class GkCliIntegrationProvider implements Disposable { message = 'Unable to locally install the GitKraken MCP server. Please try again.'; telemetryReason = 'local installation failed'; break; + case CLIInstallErrorReason.Offline: + reason = McpSetupErrorReason.Offline; + message = + 'Unable to setup the GitKraken MCP server when offline. Please try again when you are online.'; + telemetryReason = 'offline'; + break; default: reason = McpSetupErrorReason.CLIUnknownError; message = 'Unable to setup the GitKraken MCP: Unknown error.'; @@ -446,6 +460,21 @@ export class GkCliIntegrationProvider implements Disposable { } try { + if (isWeb) { + void this.container.storage + .store('gk:cli:install', { + status: 'unsupported', + attempts: cliInstallAttempts, + }) + .catch(); + + throw new CLIInstallError(CLIInstallErrorReason.UnsupportedPlatform, undefined, 'web'); + } + + if (isOffline) { + throw new CLIInstallError(CLIInstallErrorReason.Offline); + } + cliInstallAttempts += 1; if (this.container.telemetry.enabled) { this.container.telemetry.sendEvent('cli/install/started', { @@ -461,17 +490,6 @@ export class GkCliIntegrationProvider implements Disposable { }) .catch(); - if (isWeb) { - void this.container.storage - .store('gk:cli:install', { - status: 'unsupported', - attempts: cliInstallAttempts, - }) - .catch(); - - throw new CLIInstallError(CLIInstallErrorReason.UnsupportedPlatform, undefined, 'web'); - } - // Map platform names for the API and get architecture let platformName: string; let architecture: string; @@ -797,6 +815,9 @@ class CLIInstallError extends Error { case CLIInstallErrorReason.GlobalStorageDirectory: message = 'Failed to create global storage directory'; break; + case CLIInstallErrorReason.Offline: + message = 'Offline'; + break; default: message = 'An unknown error occurred'; break; diff --git a/src/env/node/gk/mcp/integration.ts b/src/env/node/gk/mcp/integration.ts index 6f1dd15de9fe0..94f48e479229f 100644 --- a/src/env/node/gk/mcp/integration.ts +++ b/src/env/node/gk/mcp/integration.ts @@ -95,18 +95,24 @@ export class GkMcpProvider implements McpServerDefinitionProvider, Disposable { return undefined; } - let output = await runCLICommand(['mcp', 'config', appName, '--source=gitlens', `--scheme=${env.uriScheme}`], { - cwd: cliPath, - }); - output = output.replace(CLIProxyMCPConfigOutputs.checkingForUpdates, '').trim(); - try { + let output = await runCLICommand( + ['mcp', 'config', appName, '--source=gitlens', `--scheme=${env.uriScheme}`], + { + cwd: cliPath, + }, + ); + output = output.replace(CLIProxyMCPConfigOutputs.checkingForUpdates, '').trim(); + const config: McpConfiguration = JSON.parse(output); + if (!config.type || !config.command || !Array.isArray(config.args)) { + throw new Error(`Invalid MCP configuration: missing required properties (${output})`); + } this.onRegistrationCompleted(cliInstall.version); return { - name: config.name, + name: config.name ?? 'GitKraken', type: config.type, command: config.command, args: config.args, @@ -114,7 +120,7 @@ export class GkMcpProvider implements McpServerDefinitionProvider, Disposable { }; } catch (ex) { Logger.error(`Error getting MCP configuration: ${ex}`); - this.onRegistrationFailed('Error getting MCP configuration', undefined, cliInstall.version); + this.onRegistrationFailed('Error getting MCP configuration', String(ex), cliInstall.version); } return undefined; diff --git a/src/env/node/json.ts b/src/env/node/json.ts index 5b50b7ac0b9ee..216e94005bdb2 100644 --- a/src/env/node/json.ts +++ b/src/env/node/json.ts @@ -7,26 +7,33 @@ import { isRepository } from '../../git/models/repository'; import { isTag } from '../../git/models/tag'; import { isWorktree } from '../../git/models/worktree'; import { isViewNode } from '../../views/nodes/utils/-webview/node.utils'; +import type { IpcDate, IpcPromise, IpcUri } from '../../webviews/ipc'; +import { getIpcTaggedType, isIpcPromise } from '../../webviews/ipc'; +import { IpcPromiseSettled } from '../../webviews/protocol'; export function loggingJsonReplacer(key: string, value: unknown): unknown { if (key === '' || value == null || typeof value !== 'object') return value; - if (key.startsWith('_')) return undefined; + if (key.charCodeAt(0) === 95) return undefined; // '_' = 95 - if (value instanceof Error) return String(value); if (value instanceof Uri) { if ('sha' in value && typeof value.sha === 'string' && value.sha) { return `${value.sha}:${value.toString()}`; } return value.toString(); } + if (value instanceof Error) return String(value); + + // Checks for toString first to avoid function calls if possible if ( - isRepository(value) || - isBranch(value) || - isCommit(value) || - isRemote(value) || - isTag(value) || - isWorktree(value) || - isViewNode(value) + 'toString' in value && + typeof value.toString === 'function' && + (isRepository(value) || + isBranch(value) || + isCommit(value) || + isRemote(value) || + isTag(value) || + isWorktree(value) || + isViewNode(value)) ) { return value.toString(); } @@ -36,13 +43,97 @@ export function loggingJsonReplacer(key: string, value: unknown): unknown { } export function serializeJsonReplacer(this: any, key: string, value: unknown): unknown { - if (value instanceof Date) return value.getTime(); - if (value instanceof Map || value instanceof Set) return [...value.entries()]; - if (value instanceof Function || value instanceof Error) return undefined; - if (value instanceof RegExp) return value.toString(); - if (value instanceof Uri) return value.toString(); - if (isContainer(value)) return undefined; + if (typeof value === 'object' && value != null) { + // Dates and Uris are automatically converted by JSON.stringify, so we check the original below + // if (value instanceof Date) return value.getTime(); + // if (value instanceof Uri) return value.toString(); + if (value instanceof RegExp) return value.toString(); + if (value instanceof Map || value instanceof Set) return [...value.entries()]; + if (value instanceof Error || value instanceof Function) return undefined; + if (isContainer(value)) return undefined; + } const original = this[key]; - return original instanceof Date ? original.getTime() : original instanceof Uri ? original.toString() : value; + if (original !== value && typeof original === 'object' && original != null) { + if (original instanceof Date) return original.getTime(); + if (original instanceof Uri) return original.toString(); + } + return value; +} + +export function serializeIpcJsonReplacer( + this: any, + key: string, + value: unknown, + nextIpcId: () => string, + pendingPromises: IpcPromise[], +): unknown { + // Filter out __promise property from IpcPromise objects to avoid circular references + if (key === '__promise') return undefined; + + if (typeof value === 'object' && value != null) { + if ('__ipc' in value) { + if (isIpcPromise(value)) { + value.value.id = nextIpcId(); + pendingPromises.push(value); + } + return value; + } + + // Dates and Uris are automatically converted by JSON.stringify, so we check the original below + // if (value instanceof Date) { + // return { __ipc: 'date', value: value.getTime() } satisfies IpcDate; + // } + // if (value instanceof Uri) { + // return { __ipc: 'uri', value: value.toJSON() } satisfies IpcUri; + // } + if (value instanceof Promise) { + const ipcPromise: IpcPromise = { + __ipc: 'promise', + __promise: value, + value: { + id: nextIpcId(), + method: IpcPromiseSettled.method, + }, + }; + pendingPromises.push(ipcPromise); + return ipcPromise; + } + + if (value instanceof RegExp) return value.toString(); + if (value instanceof Map || value instanceof Set) return [...value.entries()]; + if (value instanceof Error || value instanceof Function) return undefined; + if (isContainer(value)) return undefined; + } + + if (!key) return value; + + const original = this[key]; + if (original !== value && typeof original === 'object' && original != null) { + if (original instanceof Date) { + return { __ipc: 'date', value: original.getTime() } satisfies IpcDate; + } + if (original instanceof Uri) { + return { __ipc: 'uri', value: original.toJSON() } satisfies IpcUri; + } + } + return value; +} + +export function deserializeIpcJsonReviver( + _key: string, + value: unknown, + promiseFactory: (value: IpcPromise['value']) => Promise, +): unknown { + const tagged = getIpcTaggedType(value); + if (tagged == null) return value; + + switch (tagged.__ipc) { + case 'date': + return new Date(tagged.value); + case 'promise': + return promiseFactory(tagged.value); + case 'uri': + return Uri.from(tagged.value); + } } diff --git a/src/env/node/platform.ts b/src/env/node/platform.ts index a052589c3fb08..c6cde90778bb6 100644 --- a/src/env/node/platform.ts +++ b/src/env/node/platform.ts @@ -1,9 +1,10 @@ -import { tmpdir } from 'os'; +import { networkInterfaces, tmpdir } from 'os'; import { join } from 'path'; import { platform } from 'process'; import { env, UIKind } from 'vscode'; export const isWeb = env.uiKind === UIKind.Web; +export const isOffline = Object.values(networkInterfaces()).every(iface => iface?.every(addr => addr.internal)); export const isLinux = platform === 'linux'; export const isMac = platform === 'darwin'; diff --git a/src/env/node/providers.ts b/src/env/node/providers.ts index 3308dc47d7b9a..2660a779c0802 100644 --- a/src/env/node/providers.ts +++ b/src/env/node/providers.ts @@ -8,6 +8,7 @@ import type { SharedGkStorageLocationProvider } from '../../plus/repos/sharedGkS import type { GkWorkspacesSharedStorageProvider } from '../../plus/workspaces/workspacesSharedStorageProvider'; import { configuration } from '../../system/-webview/configuration'; // import { GitHubGitProvider } from '../../plus/github/githubGitProvider'; +import type { TelemetryService } from '../../telemetry/telemetry'; import type { GitResult } from './git/git'; import { Git } from './git/git'; import { LocalGitProvider } from './git/localGitProvider'; @@ -84,3 +85,12 @@ export async function getMcpProviders( return [new mcpModule.GkMcpProvider(container)]; } + +let _telemetryService: TelemetryService | undefined; +export function getTelementryService(): TelemetryService | undefined { + return _telemetryService; +} + +export function setTelemetryService(service: TelemetryService): void { + _telemetryService = service; +} diff --git a/src/eventBus.ts b/src/eventBus.ts index fb47ef3069094..d2abe7663bb83 100644 --- a/src/eventBus.ts +++ b/src/eventBus.ts @@ -83,6 +83,11 @@ const _cacheableEventNames = new Set([ 'file:selected', ]); const _cachedEventArgs = new Map(); +// Cache events by source to avoid stale data from different contexts (e.g., graph vs commitDetails) +const _cachedEventArgsBySource = new Map< + string, + Map +>(); export class EventBus implements Disposable { private readonly _emitter = new EventEmitter(); @@ -94,12 +99,17 @@ export class EventBus implements Disposable { fire(name: T, data: EventsMapping[T], options?: EventBusOptions): void { if (canCacheEventArgs(name)) { _cachedEventArgs.set(name, data as CacheableEventsMapping[typeof name]); + // Also cache by source to avoid stale data from different contexts + if (options?.source != null) { + let sourceCache = _cachedEventArgsBySource.get(options.source); + if (sourceCache == null) { + sourceCache = new Map(); + _cachedEventArgsBySource.set(options.source, sourceCache); + } + sourceCache.set(name, data as CacheableEventsMapping[typeof name]); + } } - this._emitter.fire({ - name: name, - data: data, - source: options?.source, - }); + this._emitter.fire({ name: name, data: data, source: options?.source }); } fireAsync(name: T, data: EventsMapping[T], options?: EventBusOptions): void { @@ -110,6 +120,13 @@ export class EventBus implements Disposable { return _cachedEventArgs.get(name) as CacheableEventsMapping[T] | undefined; } + getCachedEventArgsBySource( + name: T, + source: EventBusSource, + ): CacheableEventsMapping[T] | undefined { + return _cachedEventArgsBySource.get(source)?.get(name) as CacheableEventsMapping[T] | undefined; + } + on(name: T, handler: (e: EventBusEvent) => void, thisArgs?: unknown): Disposable { return this._emitter.event( // eslint-disable-next-line prefer-arrow-callback diff --git a/src/extension.ts b/src/extension.ts index 06d3f1f03597c..862657333c9ce 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -395,6 +395,7 @@ async function showWhatsNew( function showMcp(version: string, previousVersion: string | undefined): void { if ( + isWeb || previousVersion == null || version === previousVersion || compare(version, previousVersion) !== 1 || diff --git a/src/git/actions/commit.ts b/src/git/actions/commit.ts index d4cf35fe1c2de..9236e0cf2933d 100644 --- a/src/git/actions/commit.ts +++ b/src/git/actions/commit.ts @@ -691,7 +691,7 @@ export async function restoreFile( } } - await Container.instance.git.getRepositoryService(revision.repoPath).checkout(rev, { path: path }); + await Container.instance.git.getRepositoryService(revision.repoPath).ops?.checkout(rev, { path: path }); } export function revealCommit(commit: GitRevisionReference, options?: RevealOptions): Promise { @@ -801,8 +801,9 @@ export async function undoCommit(container: Container, commit: GitRevisionRefere return; } - const status = await svc.status.getStatus(); - if (status?.files.length) { + // Check for uncommitted changes before prompting + const hasChanges = await svc.status.hasWorkingChanges(); + if (hasChanges) { const confirm = { title: 'Undo Commit' }; const cancel = { title: 'Cancel', isCloseAffordance: true }; const result = await window.showWarningMessage( diff --git a/src/git/actions/pausedOperation.ts b/src/git/actions/pausedOperation.ts index 41b539939a20c..2f1ae724c4be9 100644 --- a/src/git/actions/pausedOperation.ts +++ b/src/git/actions/pausedOperation.ts @@ -7,7 +7,7 @@ import { getReferenceLabel } from '../utils/reference.utils'; export async function abortPausedOperation(svc: GitRepositoryService, options?: { quit?: boolean }): Promise { try { - return await svc.status.abortPausedOperation?.(options); + return await svc.pausedOps?.abortPausedOperation?.(options); } catch (ex) { void window.showErrorMessage(ex.message); } @@ -23,23 +23,16 @@ export async function skipPausedOperation(svc: GitRepositoryService): Promise { try { - return await svc.status.continuePausedOperation?.(skip ? { skip: true } : undefined); + return await svc.pausedOps?.continuePausedOperation?.(skip ? { skip: true } : undefined); } catch (ex) { if ( ex instanceof PausedOperationContinueError && ex.reason === PausedOperationContinueErrorReason.EmptyCommit ) { - let operation: GitPausedOperationStatus | undefined; - try { - const repo = svc.getRepository(); - if (repo != null) { - operation = await repo.git.status.getPausedOperationStatus?.(); - operation ??= await repo - .waitForRepoChange(500) - .then(() => repo.git.status.getPausedOperationStatus?.()); - } - } catch {} - operation ??= ex.operation; + // Use the operation status from the error - it's already accurate + // The previous code tried to wait for a repo change, but that would fire on the + // change event from the failed continue (not the skip), resulting in stale data + const operation: GitPausedOperationStatus = ex.operation; const pausedAt = getReferenceLabel(operation.incoming, { icon: false, label: true, quoted: true }); diff --git a/src/git/errors.ts b/src/git/errors.ts index 8de1659b39d06..65b0f25df0d23 100644 --- a/src/git/errors.ts +++ b/src/git/errors.ts @@ -372,41 +372,52 @@ export class CherryPickError extends Error { return ex instanceof CherryPickError && (reason == null || ex.reason === reason); } + private static buildErrorMessage(reason?: CherryPickErrorReason, revs?: string[]): string { + const baseMessage = `Unable to cherry-pick${ + revs?.length ? (revs.length === 1 ? ` commit '${revs[0]}'` : ` ${pluralize('commit', revs.length)}`) : '' + }`; + + switch (reason) { + case CherryPickErrorReason.AbortedWouldOverwrite: + return `${baseMessage} as some local changes would be overwritten.`; + case CherryPickErrorReason.Conflicts: + return `${baseMessage} due to conflicts.`; + default: + return baseMessage; + } + } + readonly original?: Error; readonly reason: CherryPickErrorReason | undefined; + private _revs?: string[]; + get revs(): string[] | undefined { + return this._revs; + } constructor(reason?: CherryPickErrorReason, original?: Error, revs?: string[]); constructor(message?: string, original?: Error); constructor(messageOrReason: string | CherryPickErrorReason | undefined, original?: Error, revs?: string[]) { let message; - const baseMessage = `Unable to cherry-pick${ - revs?.length ? (revs.length === 1 ? ` commit '${revs[0]}'` : ` ${pluralize('commit', revs.length)}`) : '' - }`; let reason: CherryPickErrorReason | undefined; - if (messageOrReason == null) { - message = baseMessage; - } else if (typeof messageOrReason === 'string') { - message = messageOrReason; - reason = undefined; - } else { + if (messageOrReason == null || typeof messageOrReason !== 'string') { reason = messageOrReason; - switch (reason) { - case CherryPickErrorReason.AbortedWouldOverwrite: - message = `${baseMessage} as some local changes would be overwritten.`; - break; - case CherryPickErrorReason.Conflicts: - message = `${baseMessage} due to conflicts.`; - break; - default: - message = baseMessage; - } + message = CherryPickError.buildErrorMessage(reason, revs); + } else { + message = messageOrReason; } super(message); this.original = original; this.reason = reason; + this._revs = revs; Error.captureStackTrace?.(this, CherryPickError); } + + update(changes: { revs?: string[] }): this { + this._revs = changes.revs === null ? undefined : (changes.revs ?? this._revs); + this.message = CherryPickError.buildErrorMessage(this.reason, this._revs); + return this; + } } export class WorkspaceUntrustedError extends Error { @@ -515,6 +526,27 @@ export class BranchError extends Error { return ex instanceof BranchError && (reason == null || ex.reason === reason); } + private static buildErrorMessage(reason?: BranchErrorReason, branch?: string, action?: string): string { + let baseMessage: string; + if (action != null) { + baseMessage = `Unable to ${action} branch ${branch ? `'${branch}'` : ''}`; + } else { + baseMessage = `Unable to perform action ${branch ? `with branch '${branch}'` : 'on branch'}`; + } + switch (reason) { + case BranchErrorReason.BranchAlreadyExists: + return `${baseMessage} because it already exists`; + case BranchErrorReason.BranchNotFullyMerged: + return `${baseMessage} because it is not fully merged`; + case BranchErrorReason.NoRemoteReference: + return `${baseMessage} because the remote reference does not exist`; + case BranchErrorReason.InvalidBranchName: + return `${baseMessage} because the branch name is invalid`; + default: + return baseMessage; + } + } + readonly original?: Error; readonly reason: BranchErrorReason | undefined; private _branch?: string; @@ -536,8 +568,8 @@ export class BranchError extends Error { ) { let message; let reason: BranchErrorReason | undefined; - if (typeof messageOrReason !== 'string') { - reason = messageOrReason as BranchErrorReason; + if (messageOrReason == null || typeof messageOrReason !== 'string') { + reason = messageOrReason; message = BranchError.buildErrorMessage(reason, branch, action); } else { message = messageOrReason; @@ -551,27 +583,6 @@ export class BranchError extends Error { Error.captureStackTrace?.(this, BranchError); } - private static buildErrorMessage(reason?: BranchErrorReason, branch?: string, action?: string): string { - let baseMessage: string; - if (action != null) { - baseMessage = `Unable to ${action} branch ${branch ? `'${branch}'` : ''}`; - } else { - baseMessage = `Unable to perform action ${branch ? `with branch '${branch}'` : 'on branch'}`; - } - switch (reason) { - case BranchErrorReason.BranchAlreadyExists: - return `${baseMessage} because it already exists`; - case BranchErrorReason.BranchNotFullyMerged: - return `${baseMessage} because it is not fully merged`; - case BranchErrorReason.NoRemoteReference: - return `${baseMessage} because the remote reference does not exist`; - case BranchErrorReason.InvalidBranchName: - return `${baseMessage} because the branch name is invalid`; - default: - return baseMessage; - } - } - update(changes: { branch?: string; action?: string }): this { this._branch = changes.branch === null ? undefined : (changes.branch ?? this._branch); this._action = changes.action === null ? undefined : (changes.action ?? this._action); @@ -594,6 +605,30 @@ export class TagError extends Error { return ex instanceof TagError && (reason == null || ex.reason === reason); } + private static buildErrorMessage(reason?: TagErrorReason, tag?: string, action?: string): string { + let baseMessage: string; + if (action != null) { + baseMessage = `Unable to ${action} tag ${tag ? `'${tag}'` : ''}`; + } else { + baseMessage = `Unable to perform action${tag ? ` with tag '${tag}'` : 'on tag'}`; + } + + switch (reason) { + case TagErrorReason.TagAlreadyExists: + return `${baseMessage} because it already exists`; + case TagErrorReason.TagNotFound: + return `${baseMessage} because it does not exist`; + case TagErrorReason.InvalidTagName: + return `${baseMessage} because the tag name is invalid`; + case TagErrorReason.PermissionDenied: + return `${baseMessage} because you don't have permission to push to this remote repository.`; + case TagErrorReason.RemoteRejected: + return `${baseMessage} because the remote repository rejected the push.`; + default: + return baseMessage; + } + } + readonly original?: Error; readonly reason: TagErrorReason | undefined; private _tag?: string; @@ -610,8 +645,8 @@ export class TagError extends Error { constructor(messageOrReason: string | TagErrorReason | undefined, original?: Error, tag?: string, action?: string) { let message; let reason: TagErrorReason | undefined; - if (typeof messageOrReason !== 'string') { - reason = messageOrReason as TagErrorReason; + if (messageOrReason == null || typeof messageOrReason !== 'string') { + reason = messageOrReason; message = TagError.buildErrorMessage(reason, tag, action); } else { message = messageOrReason; @@ -625,30 +660,6 @@ export class TagError extends Error { Error.captureStackTrace?.(this, TagError); } - private static buildErrorMessage(reason?: TagErrorReason, tag?: string, action?: string): string { - let baseMessage: string; - if (action != null) { - baseMessage = `Unable to ${action} tag ${tag ? `'${tag}'` : ''}`; - } else { - baseMessage = `Unable to perform action${tag ? ` with tag '${tag}'` : 'on tag'}`; - } - - switch (reason) { - case TagErrorReason.TagAlreadyExists: - return `${baseMessage} because it already exists`; - case TagErrorReason.TagNotFound: - return `${baseMessage} because it does not exist`; - case TagErrorReason.InvalidTagName: - return `${baseMessage} because the tag name is invalid`; - case TagErrorReason.PermissionDenied: - return `${baseMessage} because you don't have permission to push to this remote repository.`; - case TagErrorReason.RemoteRejected: - return `${baseMessage} because the remote repository rejected the push.`; - default: - return baseMessage; - } - } - update(changes: { tag?: string; action?: string }): this { this._tag = changes.tag === null ? undefined : (changes.tag ?? this._tag); this._action = changes.action === null ? undefined : (changes.action ?? this._action); diff --git a/src/git/gitProvider.ts b/src/git/gitProvider.ts index 462e3af94b83a..c92dddfc449ee 100644 --- a/src/git/gitProvider.ts +++ b/src/git/gitProvider.ts @@ -8,6 +8,7 @@ import type { Features } from '../features'; import type { GitHostIntegration } from '../plus/integrations/models/gitHostIntegration'; import type { UnifiedAsyncDisposable } from '../system/unifiedDisposable'; import type { GitUri } from './gitUri'; +import type { GitConflictFile } from './models'; import type { GitBlame, GitBlameLine } from './models/blame'; import type { GitBranch } from './models/branch'; import type { GitCommit, GitCommitStats, GitStashCommit } from './models/commit'; @@ -153,39 +154,7 @@ export interface BranchContributionsOverview extends GitCommitStats { } export interface GitRepositoryProvider { - checkout?( - repoPath: string, - ref: string, - options?: { createBranch?: string | undefined } | { path?: string | undefined }, - ): Promise; excludeIgnoredUris(repoPath: string, uris: Uri[]): Promise; - fetch?( - repoPath: string, - options?: { - all?: boolean | undefined; - branch?: GitBranchReference | undefined; - prune?: boolean | undefined; - pull?: boolean | undefined; - remote?: string | undefined; - }, - ): Promise; - pull?( - repoPath: string, - options?: { - branch?: GitBranchReference | undefined; - rebase?: boolean | undefined; - tags?: boolean | undefined; - }, - ): Promise; - push?( - repoPath: string, - options?: { - reference?: GitReference | undefined; - force?: boolean | undefined; - publish?: { remote: string }; - }, - ): Promise; - reset?(repoPath: string, ref: string, options?: { hard?: boolean } | { soft?: boolean }): Promise; getLastFetchedTimestamp(repoPath: string): Promise; runGitCommandViaTerminal?( @@ -201,7 +170,9 @@ export interface GitRepositoryProvider { contributors: GitContributorsSubProvider; diff: GitDiffSubProvider; graph: GitGraphSubProvider; + ops?: GitOperationsSubProvider; patch?: GitPatchSubProvider; + pausedOps?: GitPausedOperationsSubProvider; refs: GitRefsSubProvider; remotes: GitRemotesSubProvider; revision: GitRevisionSubProvider; @@ -336,7 +307,6 @@ export interface IncomingActivityOptions extends GitLogOptionsBase { } export interface GitCommitsSubProvider { - cherryPick?(repoPath: string, revs: string[], options?: { edit?: boolean; noCommit?: boolean }): Promise; getCommit(repoPath: string, rev: string, cancellation?: CancellationToken): Promise; getCommitCount(repoPath: string, rev: string, cancellation?: CancellationToken): Promise; getCommitFiles(repoPath: string, rev: string, cancellation?: CancellationToken): Promise; @@ -394,6 +364,51 @@ export interface GitCommitsSubProvider { ): Promise; } +export interface GitOperationsSubProvider { + checkout( + repoPath: string, + ref: string, + options?: { createBranch?: string | undefined } | { path?: string | undefined }, + ): Promise; + cherryPick(repoPath: string, revs: string[], options?: { edit?: boolean; noCommit?: boolean }): Promise; + fetch( + repoPath: string, + options?: { + all?: boolean | undefined; + branch?: GitBranchReference | undefined; + prune?: boolean | undefined; + pull?: boolean | undefined; + remote?: string | undefined; + }, + ): Promise; + pull( + repoPath: string, + options?: { + branch?: GitBranchReference | undefined; + rebase?: boolean | undefined; + tags?: boolean | undefined; + }, + ): Promise; + push( + repoPath: string, + options?: { + reference?: GitReference | undefined; + force?: boolean | undefined; + publish?: { remote: string }; + }, + ): Promise; + reset(repoPath: string, ref: string, options?: { hard?: boolean } | { soft?: boolean }): Promise; +} + +export interface GitPausedOperationsSubProvider { + getPausedOperationStatus( + repoPath: string, + cancellation?: CancellationToken, + ): Promise; + abortPausedOperation(repoPath: string, options?: { quit?: boolean }): Promise; + continuePausedOperation(repoPath: string, options?: { skip?: boolean }): Promise; +} + export interface GitConfigSubProvider { getConfig?(repoPath: string, key: GitConfigKeys): Promise; setConfig?(repoPath: string, key: GitConfigKeys, value: string | undefined): Promise; @@ -534,9 +549,10 @@ export interface GitPatchSubProvider { ): Promise; createUnreachableCommitsFromPatches( repoPath: string, - base: string, + base: string | undefined, patches: { message: string; patch: string }[], ): Promise; + createEmptyInitialCommit(repoPath: string): Promise; validatePatch(repoPath: string | undefined, contents: string): Promise; } @@ -651,9 +667,9 @@ export interface DisposableTemporaryGitIndex extends UnifiedAsyncDisposable { } export interface GitStagingSubProvider { - createTemporaryIndex(repoPath: string, base: string): Promise; + createTemporaryIndex(repoPath: string, base: string | undefined): Promise; stageFile(repoPath: string, pathOrUri: string | Uri): Promise; - stageFiles(repoPath: string, pathOrUri: string[] | Uri[]): Promise; + stageFiles(repoPath: string, pathOrUri: string[] | Uri[], options?: { intentToAdd?: boolean }): Promise; stageDirectory(repoPath: string, directoryOrUri: string | Uri): Promise; unstageFile(repoPath: string, pathOrUri: string | Uri): Promise; unstageFiles(repoPath: string, pathOrUri: string[] | Uri[]): Promise; @@ -679,6 +695,12 @@ export interface GitStashSubProvider { saveSnapshot(repoPath: string, message?: string): Promise; } +export interface GitWorkingChangesState { + staged: boolean; + unstaged: boolean; + untracked: boolean; +} + export interface GitStatusSubProvider { /** * Get the status of the repository @@ -719,12 +741,53 @@ export interface GitStatusSubProvider { cancellation?: CancellationToken, ): Promise; - getPausedOperationStatus?( + /** + * Quickly check if the repository has any working changes + * @param repoPath Repository path + * @param options Options to control which types of changes to check for + * @param cancellation Cancellation token + * @returns A promise that resolves to true if any of the requested change types exist + */ + hasWorkingChanges( repoPath: string, + options?: { + /** Check for staged changes (default: true) */ + staged?: boolean; + /** Check for unstaged changes (default: true) */ + unstaged?: boolean; + /** Check for untracked files (default: true) */ + untracked?: boolean; + }, cancellation?: CancellationToken, - ): Promise; - abortPausedOperation?(repoPath: string, options?: { quit?: boolean }): Promise; - continuePausedOperation?(repoPath: string, options?: { skip?: boolean }): Promise; + ): Promise; + /** + * Get detailed information about all types of working changes in a single optimized call + * @param repoPath The repository path + * @param cancellation Cancellation token + * @returns A promise that resolves to an object with boolean flags for each change type + */ + getWorkingChangesState(repoPath: string, cancellation?: CancellationToken): Promise; + /** + * Quickly check if the repository has any conflicting files + * @param repoPath Repository path + * @param cancellation Cancellation token + * @returns A promise that resolves to true if there are any unmerged files + */ + hasConflictingFiles(repoPath: string, cancellation?: CancellationToken): Promise; + /** + * Get all conflicting files in the repository with detailed stage information + * @param repoPath Repository path + * @param cancellation Cancellation token + * @returns A promise that resolves to an array of conflicting files with stage information + */ + getConflictingFiles(repoPath: string, cancellation?: CancellationToken): Promise; + /** + * Get all untracked files in the repository + * @param repoPath Repository path + * @param cancellation Cancellation token + * @returns A promise that resolves to an array of untracked file paths (relative to repo root) + */ + getUntrackedFiles(repoPath: string, cancellation?: CancellationToken): Promise; } export interface GitTagsSubProvider { @@ -780,7 +843,9 @@ export type GitSubProvider = | GitContributorsSubProvider | GitDiffSubProvider | GitGraphSubProvider + | GitOperationsSubProvider | GitPatchSubProvider + | GitPausedOperationsSubProvider | GitRefsSubProvider | GitRemotesSubProvider | GitRevisionSubProvider @@ -830,13 +895,7 @@ export interface GitProvider extends GitRepositoryProvider, Disposable { options?: { cancellation?: CancellationToken; depth?: number; silent?: boolean }, ): Promise; updateContext?(): void; - openRepository( - folder: WorkspaceFolder | undefined, - uri: Uri, - root: boolean, - suspended?: boolean, - closed?: boolean, - ): Repository[]; + openRepository(folder: WorkspaceFolder | undefined, uri: Uri, root: boolean, closed?: boolean): Repository[]; openRepositoryInitWatcher?(): RepositoryInitWatcher; supports(feature: Features): Promise; diff --git a/src/git/gitProviderService.ts b/src/git/gitProviderService.ts index a6ee0c872a2f3..2d374bac7f09d 100644 --- a/src/git/gitProviderService.ts +++ b/src/git/gitProviderService.ts @@ -1612,7 +1612,7 @@ export class GitProviderService implements Disposable { } Logger.log(scope, `Repository found in '${repoUri.toString(true)}'`); - const repositories = provider.openRepository(root?.folder, repoUri, false, undefined, closed); + const repositories = provider.openRepository(root?.folder, repoUri, false, closed); const added: Repository[] = []; diff --git a/src/git/gitRepositoryService.ts b/src/git/gitRepositoryService.ts index 715f44a3f0f3d..cf1b0cc9b6763 100644 --- a/src/git/gitRepositoryService.ts +++ b/src/git/gitRepositoryService.ts @@ -1,8 +1,6 @@ import type { Uri } from 'vscode'; import { GlyphChars } from '../constants'; -import { ProviderNotSupportedError } from '../errors'; import type { Features } from '../features'; -import { gate } from '../system/decorators/gate'; import { debug, log } from '../system/decorators/log'; import { groupByFilterMap } from '../system/iterable'; import { getSettledValue } from '../system/promise'; @@ -13,7 +11,9 @@ import type { GitContributorsSubProvider, GitDiffSubProvider, GitGraphSubProvider, + GitOperationsSubProvider, GitPatchSubProvider, + GitPausedOperationsSubProvider, GitProvider, GitProviderDescriptor, GitRefsSubProvider, @@ -34,7 +34,6 @@ import { createSubProviderProxyForRepo } from './gitProvider'; import type { GitProviderService } from './gitProviderService'; import type { GitBranch } from './models/branch'; import type { GitFile } from './models/file'; -import type { GitBranchReference, GitReference } from './models/reference'; import { deletedOrMissing } from './models/revision'; import type { GitTag } from './models/tag'; import { getRemoteThemeIconString } from './utils/remote.utils'; @@ -74,32 +73,11 @@ export class GitRepositoryService implements IGitRepositoryService { this.getRepository = svc.getRepository.bind(svc, path); } - @log() - checkout(ref: string, options?: { createBranch?: string } | { path?: string }): Promise { - if (this._provider.checkout == null) throw new ProviderNotSupportedError(this._provider.descriptor.name); - - return this._provider.checkout(this.path, ref, options); - } - @log({ args: { 0: uris => uris.length } }) excludeIgnoredUris(uris: Uri[]): Promise { return this._provider.excludeIgnoredUris(this.path, uris); } - @gate() - @log() - fetch(options?: { - all?: boolean; - branch?: GitBranchReference; - prune?: boolean; - pull?: boolean; - remote?: string; - }): Promise { - if (this._provider.fetch == null) throw new ProviderNotSupportedError(this._provider.descriptor.name); - - return this._provider.fetch(this.path, options); - } - getAbsoluteUri: IGitRepositoryService['getAbsoluteUri']; @log() @@ -235,29 +213,6 @@ export class GitRepositoryService implements IGitRepositoryService { return this._provider.getWorkingUri(this.path, uri); } - @gate() - @log() - pull(options?: { rebase?: boolean; tags?: boolean }): Promise { - if (this._provider.pull == null) throw new ProviderNotSupportedError(this._provider.descriptor.name); - - return this._provider.pull(this.path, options); - } - - @gate() - @log() - push(options?: { reference?: GitReference; force?: boolean; publish?: { remote: string } }): Promise { - if (this._provider.push == null) throw new ProviderNotSupportedError(this._provider.descriptor.name); - - return this._provider.push(this.path, options); - } - - @log() - async reset(ref: string, options?: { hard?: boolean } | { soft?: boolean }): Promise { - if (this._provider.reset == null) throw new ProviderNotSupportedError(this._provider.descriptor.name); - - return this._provider.reset(this.path, ref, options); - } - @log({ args: false }) async runGitCommandViaTerminal(command: string, args: string[], options?: { execute?: boolean }): Promise { return this._provider.runGitCommandViaTerminal?.(this.path, command, args, options); @@ -289,9 +244,15 @@ export class GitRepositoryService implements IGitRepositoryService { get graph(): GitSubProviderForRepo { return this.getSubProviderProxy('graph'); } + get ops(): GitSubProviderForRepo | undefined { + return this.getSubProviderProxy('ops'); + } get patch(): GitSubProviderForRepo | undefined { return this.getSubProviderProxy('patch'); } + get pausedOps(): GitSubProviderForRepo | undefined { + return this.getSubProviderProxy('pausedOps'); + } get refs(): GitSubProviderForRepo { return this.getSubProviderProxy('refs'); } diff --git a/src/git/gitUri.ts b/src/git/gitUri.ts index ff1eb30022017..5ba97bfb56081 100644 --- a/src/git/gitUri.ts +++ b/src/git/gitUri.ts @@ -9,6 +9,7 @@ import { isVirtualUri } from '../system/-webview/vscode/uris'; import { debug } from '../system/decorators/log'; import { memoize } from '../system/decorators/memoize'; import { basename, normalizePath } from '../system/path'; +import type { UriComponents } from '../system/uri'; import { areUrisEqual } from '../system/uri'; import type { RevisionUriData } from './gitProvider'; import { decodeGitLensRevisionUriAuthority, decodeRemoteHubAuthority } from './gitUri.authority'; @@ -24,20 +25,12 @@ export interface GitCommitish { sha?: string; } -interface UriComponents { - scheme?: string; - authority?: string; - path?: string; - query?: string; - fragment?: string; -} - interface UriEx { new (): Uri; new (scheme: string, authority: string, path: string, query: string, fragment: string): Uri; // Use this ctor, because vscode doesn't validate it // eslint-disable-next-line @typescript-eslint/unified-signatures - new (components: UriComponents): Uri; + new (components: Partial): Uri; } export class GitUri extends (Uri as any as UriEx) { diff --git a/src/git/models/commit.ts b/src/git/models/commit.ts index 3603991134d16..264901769fb4c 100644 --- a/src/git/models/commit.ts +++ b/src/git/models/commit.ts @@ -316,8 +316,21 @@ export class GitCommit implements GitRevisionReference { } if (options?.include?.stats) { + this._recomputeStats = true; + this.computeFileStats(); + const stats = await repo?.git.diff.getChangedFilesCount(this.sha); - this._stats = stats; + if (stats != null) { + if (this._stats != null) { + this._stats = { + ...this._stats, + additions: stats.additions, + deletions: stats.deletions, + }; + } else { + this._stats = stats; + } + } this._recomputeStats = false; } else { this._recomputeStats = true; @@ -357,11 +370,7 @@ export class GitCommit implements GitRevisionReference { if (!this._recomputeStats || this.fileset == null) return; this._recomputeStats = false; - const changedFiles = { - added: 0, - deleted: 0, - changed: 0, - }; + const changedFiles = { added: 0, deleted: 0, changed: 0 }; let additions = 0; let deletions = 0; diff --git a/src/git/models/index.ts b/src/git/models/index.ts new file mode 100644 index 0000000000000..2cee564cd622b --- /dev/null +++ b/src/git/models/index.ts @@ -0,0 +1,27 @@ +import type { GitFile } from './file'; +import type { GitFileConflictStatus } from './fileStatus'; + +export type GitIndexVersion = 'normal' | 'base' | 'current' | 'incoming'; +export interface GitIndexFile { + mode: string; + oid: string; + path: string; + version: GitIndexVersion | undefined; +} + +export interface GitConflictRevision { + readonly mode: string; + readonly oid: string; + readonly version: GitIndexVersion | undefined; +} + +export interface GitConflictFile extends GitFile { + readonly path: string; + readonly repoPath: string; + readonly status: GitFileConflictStatus; + readonly conflictStatus: GitFileConflictStatus; + + readonly base?: GitConflictRevision; + readonly current?: GitConflictRevision; + readonly incoming?: GitConflictRevision; +} diff --git a/src/git/models/repository.ts b/src/git/models/repository.ts index 4b7afca264f40..d41bbd7b21adb 100644 --- a/src/git/models/repository.ts +++ b/src/git/models/repository.ts @@ -21,7 +21,7 @@ import type { Deferrable } from '../../system/function/debounce'; import { debounce } from '../../system/function/debounce'; import { filter, groupByMap, join, map, min, some } from '../../system/iterable'; import { getLoggableName, Logger } from '../../system/logger'; -import { getLogScope, startLogScope } from '../../system/logger.scope'; +import { getLogScope, setLogScopeExit, startLogScope } from '../../system/logger.scope'; import { updateRecordValue } from '../../system/object'; import { basename, normalizePath } from '../../system/path'; import type { GitDir, GitProviderDescriptor } from '../gitProvider'; @@ -191,7 +191,6 @@ export class Repository implements Disposable { public readonly folder: WorkspaceFolder | undefined, public readonly uri: Uri, public readonly root: boolean, - suspended: boolean, closed: boolean = false, ) { if (folder != null) { @@ -227,7 +226,7 @@ export class Repository implements Disposable { this.id = asRepoComparisonKey(uri); - this._suspended = suspended; + this._suspended = !window.state.focused; this._closed = closed; this._disposable = Disposable.from( @@ -275,7 +274,14 @@ export class Repository implements Disposable { using scope = startLogScope(`${getLoggableName(this)}.closed`, false); Logger.debug(scope, `setting closed=${value}`); void this.getGitDir().then(gd => this.setupRepoWatchers(gd)); - this.fireChange(this._closed ? RepositoryChange.Closed : RepositoryChange.Opened); + + if (this._closed) { + // When closing, fire the event immediately even if suspended + // This ensures views can clean up nodes for closed repositories before VS Code tries to render them + this.fireChange(RepositoryChange.Closed, true); + } else { + this.fireChange(RepositoryChange.Opened); + } } } @@ -507,7 +513,7 @@ export class Repository implements Disposable { remote?: string; }) { try { - await this.git.fetch(options); + await this.git.ops?.fetch(options); this.fireChange(RepositoryChange.Unknown); } catch (ex) { @@ -587,10 +593,10 @@ export class Repository implements Disposable { try { const withTags = configuration.getCore('git.pullTags', this.uri); if (configuration.getCore('git.fetchOnPull', this.uri)) { - await this.git.fetch(); + await this.git.ops?.fetch(); } - await this.git.pull({ ...options, tags: withTags }); + await this.git.ops?.pull({ ...options, tags: withTags }); this.fireChange(RepositoryChange.Unknown); } catch (ex) { @@ -654,7 +660,7 @@ export class Repository implements Disposable { private async pushCore(options?: { force?: boolean; reference?: GitReference; publish?: { remote: string } }) { try { - await this.git.push({ + await this.git.ops?.push({ reference: options?.reference, force: options?.force, publish: options?.publish, @@ -679,18 +685,26 @@ export class Repository implements Disposable { ); } + @debug({ singleLine: true }) resume(): void { - if (!this._suspended) return; + const scope = getLogScope(); + + if (!this._suspended) { + setLogScopeExit(scope, ' \u2022 ignored; not suspended'); + return; + } this._suspended = false; // If we've come back into focus and we are dirty, fire the change events if (this._pendingRepoChange != null) { - this._fireChangeDebounced!(); + Logger.debug(scope, `Firing pending repo ${this._pendingRepoChange.toString(true)}`); + this._fireChangeDebounced?.(); } if (this._pendingFileSystemChange != null) { + Logger.debug(scope, `Firing pending file system changes`); this._fireFileSystemChangeDebounced?.(); } } @@ -705,6 +719,7 @@ export class Repository implements Disposable { return starred != null && starred[this.id] === true; } + @log({ args: { 0: b => b?.name } }) star(branch?: GitBranch): Promise { return this.updateStarred(true, branch); } @@ -727,7 +742,7 @@ export class Repository implements Disposable { private async switchCore(ref: string, options?: { createBranch?: string }) { try { - await this.git.checkout(ref, options); + await this.git.ops?.checkout(ref, options); this.fireChange(RepositoryChange.Unknown); } catch (ex) { @@ -743,6 +758,7 @@ export class Repository implements Disposable { return rev != null ? this.git.getBestRevisionUri(path, rev) : undefined; } + @log({ args: { 0: b => b?.name } }) unstar(branch?: GitBranch): Promise { return this.updateStarred(false, branch); } @@ -771,46 +787,45 @@ export class Repository implements Disposable { return this._etagFileSystem; } + @debug({ singleLine: true }) suspend(): void { this._suspended = true; } waitForRepoChange(timeoutMs: number): Promise { - return new Promise(resolve => { - let timeoutId: NodeJS.Timeout | undefined; - let listener: Disposable | undefined; - - const cleanup = () => { - if (timeoutId != null) { - clearTimeout(timeoutId); - timeoutId = undefined; - } - listener?.dispose(); - listener = undefined; - }; + let timeoutId: NodeJS.Timeout | undefined; + let listener: Disposable | undefined; - const timeoutPromise = new Promise(r => { + const cleanup = () => { + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = undefined; + } + listener?.dispose(); + listener = undefined; + }; + + return Promise.race([ + new Promise(r => { timeoutId = setTimeout(() => { cleanup(); r(false); }, timeoutMs); - }); - - const changePromise = new Promise(r => { + }), + new Promise(r => { listener = this.onDidChange(() => { cleanup(); r(true); }); - }); - - void Promise.race([timeoutPromise, changePromise]).then(result => resolve(result)); - }); + }), + ]); } private _fsWatcherDisposable: Disposable | undefined; private _fsWatchers = new Map(); private _fsChangeDelay: number = defaultFileSystemChangeDelay; + @debug({ singleLine: true }) watchFileSystem(delay: number = defaultFileSystemChangeDelay): Disposable { const id = uuid(); this._fsWatchers.set(id, delay); @@ -857,21 +872,40 @@ export class Repository implements Disposable { this._fireFileSystemChangeDebounced = undefined; } + private fireChange(...changes: RepositoryChange[]): void; + private fireChange(change: RepositoryChange, force: boolean): void; @debug() - private fireChange(...changes: RepositoryChange[]) { + private fireChange(...args: RepositoryChange[] | [RepositoryChange, boolean]): void { const scope = getLogScope(); + // Extract force flag if present (last argument is boolean) + const lastArg = args[args.length - 1]; + const force = typeof lastArg === 'boolean' ? lastArg : false; + const changes = (force ? args.slice(0, -1) : args) as RepositoryChange[]; + this._updatedAt = Date.now(); - this._fireChangeDebounced ??= debounce(this.fireChangeCore.bind(this), defaultRepositoryChangeDelay); + if (force) { + // Cancel any pending debounced fire and clear the queue + this._fireChangeDebounced?.cancel(); + this._fireChangeDebounced = undefined; + + // Set the pending change and fire immediately, bypassing suspension + this._pendingRepoChange = new RepositoryChangeEvent(this, changes); + + this.providerService.onRepositoryChanged(this, this._pendingRepoChange); + this.fireChangeCore(); + + return; + } + this._fireChangeDebounced ??= debounce(this.fireChangeCore.bind(this), defaultRepositoryChangeDelay); this._pendingRepoChange = this._pendingRepoChange?.with(changes) ?? new RepositoryChangeEvent(this, changes); this.providerService.onRepositoryChanged(this, this._pendingRepoChange); if (this._suspended) { - Logger.debug(scope, `queueing suspended ${this._pendingRepoChange.toString(true)}`); - + Logger.debug(scope, `SUSPENDED: queueing repo ${this._pendingRepoChange.toString(true)}`); return; } @@ -879,13 +913,17 @@ export class Repository implements Disposable { } private fireChangeCore() { + using scope = startLogScope(`${getLoggableName(this)}.fireChangeCore`, false); + const e = this._pendingRepoChange; - if (e == null) return; + if (e == null) { + Logger.debug(scope, 'No pending repo changes'); + return; + } this._pendingRepoChange = undefined; - using scope = startLogScope(`${getLoggableName(this)}.fireChangeCore`, false); - Logger.debug(scope, `firing ${e.toString(true)}`); + Logger.debug(scope, `firing repo ${e.toString(true)}`); try { this._onDidChange.fire(e); } finally { @@ -908,7 +946,7 @@ export class Repository implements Disposable { if (this._suspended) { Logger.debug( scope, - `queueing suspended fs changes=${join( + `SUSPENDED: queueing fs changes=${join( map(e.uris, u => u.fsPath), ', ', )}`, @@ -920,19 +958,26 @@ export class Repository implements Disposable { } private async fireFileSystemChangeCore() { + using scope = startLogScope(`${getLoggableName(this)}.fireFileSystemChangeCore`, false); + let e = this._pendingFileSystemChange; - if (e == null) return; + if (e == null) { + Logger.debug(scope, 'No pending fs changes'); + return; + } this._pendingFileSystemChange = undefined; const uris = await this.git.excludeIgnoredUris([...e.uris]); - if (!uris.length) return; + if (!uris.length) { + Logger.debug(scope, 'No non-ignored fs changes'); + return; + } if (uris.length !== e.uris.size) { e = { ...e, uris: new UriSet(uris) }; } - using scope = startLogScope(`${getLoggableName(this)}.fireFileSystemChangeCore`, false); Logger.debug( scope, `firing fs changes=${join( diff --git a/src/git/models/revision.ts b/src/git/models/revision.ts index b08eeeea5bce9..1cabf515f05b4 100644 --- a/src/git/models/revision.ts +++ b/src/git/models/revision.ts @@ -1,6 +1,8 @@ export const deletedOrMissing = '0000000000000000000000000000000000000000-'; export const uncommitted = '0000000000000000000000000000000000000000'; export const uncommittedStaged = '0000000000000000000000000000000000000000:'; +// This is a root sha of all git repo's if using sha1 +export const rootSha = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'; export type GitRevisionRange = | `${GitRevisionRangeNotation}${string}` diff --git a/src/git/models/status.ts b/src/git/models/status.ts index c37656467c6c7..96a837fc48dc4 100644 --- a/src/git/models/status.ts +++ b/src/git/models/status.ts @@ -1,8 +1,7 @@ import type { Container } from '../../container'; import { memoize } from '../../system/decorators/memoize'; -import { pluralize } from '../../system/string'; import { formatDetachedHeadName, getRemoteNameFromBranchName, isDetachedHead } from '../utils/branch.utils'; -import { getUpstreamStatus } from '../utils/status.utils'; +import { getFormattedDiffStatus, getUpstreamStatus } from '../utils/status.utils'; import type { GitBranchStatus, GitTrackingUpstream } from './branch'; import type { GitDiffFileStats } from './diff'; import { GitFileConflictStatus, GitFileIndexStatus, GitFileWorkingTreeStatus } from './fileStatus'; @@ -175,11 +174,7 @@ export class GitStatus { @memoize() getDiffStatus(): GitDiffFileStats { - const diff = { - added: 0, - deleted: 0, - changed: 0, - }; + const diff = { added: 0, deleted: 0, changed: 0 }; if (this.files.length === 0) return diff; @@ -201,54 +196,15 @@ export class GitStatus { return diff; } - getFormattedDiffStatus({ - compact, - empty, - expand, - prefix = '', - separator = ' ', - suffix = '', - }: { + getFormattedDiffStatus(options?: { compact?: boolean; empty?: string; expand?: boolean; prefix?: string; separator?: string; suffix?: string; - } = {}): string { - const { added, changed, deleted } = this.getDiffStatus(); - if (added === 0 && changed === 0 && deleted === 0) return empty ?? ''; - - if (expand) { - let status = ''; - if (added) { - status += `${pluralize('file', added)} added`; - } - if (changed) { - status += `${status.length === 0 ? '' : separator}${pluralize('file', changed)} changed`; - } - if (deleted) { - status += `${status.length === 0 ? '' : separator}${pluralize('file', deleted)} deleted`; - } - return `${prefix}${status}${suffix}`; - } - - let status = ''; - if (compact) { - if (added !== 0) { - status += `+${added}`; - } - if (changed !== 0) { - status += `${status.length === 0 ? '' : separator}~${changed}`; - } - if (deleted !== 0) { - status += `${status.length === 0 ? '' : separator}-${deleted}`; - } - } else { - status += `+${added}${separator}~${changed}${separator}-${deleted}`; - } - - return `${prefix}${status}${suffix}`; + }): string { + return getFormattedDiffStatus(this.getDiffStatus(), options); } @memoize() diff --git a/src/git/models/tree.ts b/src/git/models/tree.ts index ec2f2ad4a3f51..5fab6814809ff 100644 --- a/src/git/models/tree.ts +++ b/src/git/models/tree.ts @@ -5,10 +5,3 @@ export interface GitTreeEntry { size: number; type: 'blob' | 'tree'; } - -export interface GitLsFilesEntry { - mode: string; - oid: string; - path: string; - stage: number; -} diff --git a/src/git/models/worktree.ts b/src/git/models/worktree.ts index 4f3783c265456..d8fe07be3dba5 100644 --- a/src/git/models/worktree.ts +++ b/src/git/models/worktree.ts @@ -53,8 +53,9 @@ export class GitWorktree { : this.formatDateFromNow(); } + private _hasWorkingChanges: boolean | undefined; get hasChanges(): boolean | undefined { - return this._status?.hasChanges; + return this._hasWorkingChanges; } get opened(): boolean { @@ -86,7 +87,6 @@ export class GitWorktree { return this.date != null ? fromNow(this.date) : ''; } - private _status: GitStatus | undefined; private _statusPromise: Promise | undefined; async getStatus(options?: { force?: boolean }): Promise { if (this.type === 'bare') return Promise.resolve(undefined); @@ -96,7 +96,9 @@ export class GitWorktree { this._statusPromise = new Promise(async (resolve, reject) => { try { const status = await this.container.git.getRepositoryService(this.uri.fsPath).status.getStatus(); - this._status = status; + if (status != null) { + this._hasWorkingChanges = status.hasChanges; + } resolve(status); } catch (ex) { // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors @@ -106,6 +108,27 @@ export class GitWorktree { } return this._statusPromise; } + + private _hasWorkingChangesPromise: Promise | undefined; + async hasWorkingChanges(options?: { + force?: boolean; + staged?: boolean; + unstaged?: boolean; + untracked?: boolean; + }): Promise { + if (this.type === 'bare') return Promise.resolve(undefined); + + if (this._hasWorkingChangesPromise == null || options?.force) { + this._hasWorkingChangesPromise = this.container.git + .getRepositoryService(this.uri.fsPath) + .status?.hasWorkingChanges({ + staged: options?.staged, + unstaged: options?.unstaged, + untracked: options?.untracked, + }); + } + return this._hasWorkingChangesPromise; + } } export function isWorktree(worktree: any): worktree is GitWorktree { diff --git a/src/git/parsers/indexParser.ts b/src/git/parsers/indexParser.ts new file mode 100644 index 0000000000000..16e66c0f5912a --- /dev/null +++ b/src/git/parsers/indexParser.ts @@ -0,0 +1,186 @@ +import { maybeStopWatch } from '../../system/stopwatch'; +import { iterateByDelimiter } from '../../system/string'; +import type { GitConflictFile, GitConflictRevision, GitIndexFile, GitIndexVersion } from '../models'; +import { GitFileConflictStatus } from '../models/fileStatus'; + +export function parseGitLsFilesStaged(data: string | undefined, singleEntry: boolean): GitIndexFile[] { + using sw = maybeStopWatch(`Git.parseLsFiles`, { log: false, logLevel: 'debug' }); + + const files: GitIndexFile[] = []; + if (!data) { + sw?.stop({ suffix: ` no data` }); + return files; + } + + // Format: \t\0 + // Using -z flag ensures filenames are NUL-delimited and not quoted + + let metadata: string; + let mode: string; + let oid: string; + let stage: number; + let path: string; + + let startIndex = 0; + let endIndex = 0; + let tabIndex = 0; + + // Avoid generator if we are only parsing a single entry + for (const line of singleEntry ? data.split('\0') : iterateByDelimiter(data, '\0')) { + if (!line) continue; + + // Split on tab to separate metadata from path + tabIndex = line.indexOf('\t'); + if (tabIndex === -1) continue; + + metadata = line.substring(0, tabIndex); + path = line.substring(tabIndex + 1); + + // Parse mode + startIndex = 0; + endIndex = metadata.indexOf(' ', startIndex); + if (endIndex === -1) continue; + + mode = metadata.substring(startIndex, endIndex); + + // Parse oid + startIndex = endIndex + 1; + endIndex = metadata.indexOf(' ', startIndex); + if (endIndex === -1) continue; + + oid = metadata.substring(startIndex, endIndex); + + // Parse stage + startIndex = endIndex + 1; + + stage = parseInt(metadata.substring(startIndex), 10); + + files.push({ mode: mode, oid: oid, path: path, version: convertStageToVersion(isNaN(stage) ? 0 : stage) }); + } + + sw?.stop({ suffix: ` parsed ${files.length} files` }); + + return files; +} + +export function parseGitConflictFiles(data: string | undefined, repoPath: string): GitConflictFile[] { + using sw = maybeStopWatch(`Git.parseConflictFiles`, { log: false, logLevel: 'debug' }); + + if (!data) { + sw?.stop({ suffix: ` no data` }); + return []; + } + + // Format: \t\0 + // Using -z flag ensures filenames are NUL-delimited and not quoted + + const files = new Map>(); + + let metadata: string; + let mode: string; + let oid: string; + let stage: number; + let path: string; + let revision: GitConflictRevision; + + let startIndex = 0; + let endIndex = 0; + let tabIndex = 0; + + for (const line of iterateByDelimiter(data, '\0')) { + if (!line) continue; + + tabIndex = line.indexOf('\t'); + if (tabIndex === -1) continue; + + metadata = line.substring(0, tabIndex); + path = line.substring(tabIndex + 1); + + // Parse mode + startIndex = 0; + endIndex = metadata.indexOf(' ', startIndex); + if (endIndex === -1) continue; + + mode = metadata.substring(startIndex, endIndex); + + // Parse oid + startIndex = endIndex + 1; + endIndex = metadata.indexOf(' ', startIndex); + if (endIndex === -1) continue; + + oid = metadata.substring(startIndex, endIndex); + + // Parse stage + startIndex = endIndex + 1; + + stage = parseInt(metadata.substring(startIndex), 10); + + revision = { mode: mode, oid: oid, version: convertStageToVersion(stage) }; + + // Get or create file entry + let file = files.get(path); + if (!file) { + file = { + path: path, + repoPath: repoPath, + get status(): GitFileConflictStatus { + const pattern = + (this.base != null ? 4 : 0) | (this.current != null ? 2 : 0) | (this.incoming != null ? 1 : 0); + + switch (pattern) { + case 0b001: + return GitFileConflictStatus.AddedByThem; // UA + case 0b010: + return GitFileConflictStatus.AddedByUs; // AU + case 0b011: + return GitFileConflictStatus.AddedByBoth; // AA + case 0b101: + return GitFileConflictStatus.DeletedByUs; // DU + case 0b110: + return GitFileConflictStatus.DeletedByThem; // UD + case 0b111: + return GitFileConflictStatus.ModifiedByBoth; // UU + default: + return GitFileConflictStatus.DeletedByBoth; // DD (0b000, 0b100) + } + }, + get conflictStatus(): GitFileConflictStatus { + return this.status; + }, + }; + files.set(path, file); + } + + // Assign revision appropriate version (stage) + switch (stage) { + case 1: + file.base = revision; + break; + case 2: + file.current = revision; + break; + case 3: + file.incoming = revision; + break; + } + } + + sw?.stop({ suffix: ` parsed ${files.size} conflict files` }); + + return [...files.values()]; +} + +function convertStageToVersion(stage: number): GitIndexVersion | undefined { + switch (stage) { + case 0: + return 'normal'; + case 1: + return 'base'; + case 2: + return 'current'; + case 3: + return 'incoming'; + default: + return undefined; + } +} diff --git a/src/git/parsers/treeParser.ts b/src/git/parsers/treeParser.ts index 47eda824e19a3..58a7561a11305 100644 --- a/src/git/parsers/treeParser.ts +++ b/src/git/parsers/treeParser.ts @@ -1,6 +1,6 @@ import { maybeStopWatch } from '../../system/stopwatch'; import { iterateByDelimiter } from '../../system/string'; -import type { GitLsFilesEntry, GitTreeEntry } from '../models/tree'; +import type { GitTreeEntry } from '../models/tree'; export function parseGitTree(data: string | undefined, ref: string, singleEntry: boolean): GitTreeEntry[] { using sw = maybeStopWatch(`Git.parseTree`, { log: false, logLevel: 'debug' }); @@ -59,57 +59,3 @@ export function parseGitTree(data: string | undefined, ref: string, singleEntry: return trees; } - -export function parseGitLsFilesStaged(data: string | undefined, singleEntry: boolean): GitLsFilesEntry[] { - using sw = maybeStopWatch(`Git.parseLsFiles`, { log: false, logLevel: 'debug' }); - - const files: GitLsFilesEntry[] = []; - if (!data) { - sw?.stop({ suffix: ` no data` }); - return files; - } - - // Format: \t - - let metadata: string; - let mode: string; - let oid: string; - let stage: number; - let path: string; - - let startIndex = 0; - let endIndex = 0; - - // Avoid generator if we are only parsing a single entry - for (let line of singleEntry ? data.split('\n') : iterateByDelimiter(data, '\n')) { - line = line.trim(); - if (!line) continue; - - [metadata, path] = line.split(/\t/); - - // Parse mode - startIndex = 0; - endIndex = metadata.indexOf(' ', startIndex); - if (endIndex === -1) continue; - - mode = metadata.substring(startIndex, endIndex); - - // Parse oid - startIndex = endIndex + 1; - endIndex = metadata.indexOf(' ', startIndex); - if (endIndex === -1) continue; - - oid = metadata.substring(startIndex, endIndex); - - // Parse stage - startIndex = endIndex + 1; - - stage = parseInt(metadata.substring(startIndex), 10); - - files.push({ mode: mode, oid: oid, path: path, stage: isNaN(stage) ? 0 : stage }); - } - - sw?.stop({ suffix: ` parsed ${files.length} files` }); - - return files; -} diff --git a/src/git/remotes/remoteProviders.ts b/src/git/remotes/remoteProviders.ts index 3e850608156ca..055b7c5fcc9d4 100644 --- a/src/git/remotes/remoteProviders.ts +++ b/src/git/remotes/remoteProviders.ts @@ -1,3 +1,4 @@ +import type { ConfigurationScope } from 'vscode'; import type { RemotesConfig } from '../../config'; import type { CloudGitSelfManagedHostIntegrationIds } from '../../constants.integrations'; import { GitSelfManagedHostIntegrationId } from '../../constants.integrations'; @@ -102,9 +103,17 @@ function cleanProtocol(scheme: string | undefined): string | undefined { return match?.[1] ?? undefined; } -export function loadRemoteProviders( +export function loadRemoteProvidersFromConfig( + scope: ConfigurationScope | null, + configuredIntegrations: ConfiguredIntegrationDescriptor[] | undefined, +): RemoteProviders { + const configuredRemotes = configuration.get('remotes', scope); + return loadRemoteProviders(configuredRemotes, configuredIntegrations); +} + +function loadRemoteProviders( cfg: RemotesConfig[] | null | undefined, - configuredIntegrations?: ConfiguredIntegrationDescriptor[], + configuredIntegrations: ConfiguredIntegrationDescriptor[] | undefined, ): RemoteProviders { const providers: RemoteProviders = []; @@ -194,13 +203,7 @@ export async function getRemoteProviderMatcher( container: Container, providers?: RemoteProviders, ): Promise<(url: string, domain: string, path: string, sheme: string | undefined) => RemoteProvider | undefined> { - if (providers == null) { - providers = loadRemoteProviders( - configuration.get('remotes', null), - await container.integrations.getConfigured(), - ); - } - + providers ??= loadRemoteProvidersFromConfig(null, await container.integrations.getConfigured()); return (url: string, domain: string, path: string, scheme) => createBestRemoteProvider(container, providers, url, domain, path, scheme); } diff --git a/src/git/utils/-webview/worktree.quickpick.ts b/src/git/utils/-webview/worktree.quickpick.ts index 8f6b80564e728..50956d77947b6 100644 --- a/src/git/utils/-webview/worktree.quickpick.ts +++ b/src/git/utils/-webview/worktree.quickpick.ts @@ -4,7 +4,6 @@ import { GlyphChars } from '../../../constants'; import { Container } from '../../../container'; import type { QuickPickItemOfT } from '../../../quickpicks/items/common'; import { pad } from '../../../system/string'; -import type { GitStatus } from '../../models/status'; import type { GitWorktree } from '../../models/worktree'; import { shortenRevision } from '../revision.utils'; import { getBranchIconPath } from './icons'; @@ -22,11 +21,11 @@ export function createWorktreeQuickPickItem( alwaysShow?: boolean; buttons?: QuickInputButton[]; checked?: boolean; + hasChanges?: boolean | undefined; includeStatus?: boolean; message?: boolean; path?: boolean; type?: boolean; - status?: GitStatus; }, ): WorktreeQuickPickItem { let description = ''; @@ -38,31 +37,27 @@ export function createWorktreeQuickPickItem( if (options?.includeStatus) { let status = ''; let blank = 0; - if (options?.status != null) { - if (options.status.upstream?.missing) { - status += GlyphChars.Warning; - blank += 3; + if (worktree.branch?.upstream?.missing) { + status += GlyphChars.Warning; + blank += 3; + } else { + if (worktree.branch?.upstream?.state.behind) { + status += GlyphChars.ArrowDown; } else { - if (options.status.upstream?.state.behind) { - status += GlyphChars.ArrowDown; - } else { - blank += 2; - } + blank += 2; + } - if (options.status.upstream?.state.ahead) { - status += GlyphChars.ArrowUp; - } else { - blank += 2; - } + if (worktree.branch?.upstream?.state.ahead) { + status += GlyphChars.ArrowUp; + } else { + blank += 2; + } - if (options.status.hasChanges) { - status += '\u00B1'; - } else { - blank += 2; - } + if (options?.hasChanges) { + status += '\u00B1'; + } else { + blank += 2; } - } else { - blank += 6; } if (blank > 0) { @@ -112,8 +107,8 @@ export function createWorktreeQuickPickItem( buttons: options?.buttons, picked: picked, item: worktree, + hasChanges: options?.hasChanges, opened: worktree.opened, - hasChanges: options?.status?.hasChanges, iconPath: iconPath, }; diff --git a/src/git/utils/fetch.utils.ts b/src/git/utils/fetch.utils.ts index 999410f8290c5..1960564d8b5d3 100644 --- a/src/git/utils/fetch.utils.ts +++ b/src/git/utils/fetch.utils.ts @@ -2,9 +2,47 @@ const millisecondsPerMinute = 60 * 1000; const millisecondsPerHour = 60 * 60 * 1000; export const millisecondsPerDay = 24 * 60 * 60 * 1000; +/** + * Calculates the update interval for fetch status based on how long ago the last fetch occurred. + * Uses stepped intervals to prevent thrashing from frequent recalculations. + * + * @param lastFetched - Timestamp (in milliseconds) of the last fetch + * @returns Update interval in milliseconds + * + * Interval schedule: + * - < 15 minutes ago: refresh every 5 minutes + * - < 30 minutes ago: refresh every 10 minutes + * - < 1 hour ago: refresh every 20 minutes + * - < 3 hours ago: refresh every 1 hour + * - < 6 hours ago: refresh every 2 hours + * - < 12 hours ago: refresh every 4 hours + * - < 2 days ago: refresh every 8 hours + * - ≥ 2 days ago: refresh every 1 day + */ export function getLastFetchedUpdateInterval(lastFetched: number): number { const timeDiff = Date.now() - lastFetched; - return timeDiff < millisecondsPerDay - ? (timeDiff < millisecondsPerHour ? millisecondsPerMinute : millisecondsPerHour) / 2 - : 0; + + // Stepped intervals to prevent thrashing + if (timeDiff < 15 * millisecondsPerMinute) { + return 5 * millisecondsPerMinute; + } + if (timeDiff < 30 * millisecondsPerMinute) { + return 10 * millisecondsPerMinute; + } + if (timeDiff < millisecondsPerHour) { + return 20 * millisecondsPerMinute; + } + if (timeDiff < 3 * millisecondsPerHour) { + return millisecondsPerHour; + } + if (timeDiff < 6 * millisecondsPerHour) { + return 2 * millisecondsPerHour; + } + if (timeDiff < 12 * millisecondsPerHour) { + return 4 * millisecondsPerHour; + } + if (timeDiff < 2 * millisecondsPerDay) { + return 8 * millisecondsPerHour; + } + return millisecondsPerDay; } diff --git a/src/git/utils/status.utils.ts b/src/git/utils/status.utils.ts index 6a81384a2196c..a27fe4be82f0c 100644 --- a/src/git/utils/status.utils.ts +++ b/src/git/utils/status.utils.ts @@ -1,6 +1,57 @@ import { GlyphChars } from '../../constants'; import { pluralize } from '../../system/string'; import type { GitTrackingUpstream } from '../models/branch'; +import type { GitDiffFileStats } from '../models/diff'; + +export function getFormattedDiffStatus( + stats: GitDiffFileStats, + options?: { + compact?: boolean; + empty?: string; + expand?: boolean; + prefix?: string; + separator?: string; + suffix?: string; + }, +): string { + const { added, changed, deleted } = stats; + if (added === 0 && changed === 0 && deleted === 0) return options?.empty ?? ''; + + const prefix = options?.prefix ?? ''; + const separator = options?.separator ?? ' '; + const suffix = options?.suffix ?? ''; + + if (options?.expand) { + let status = ''; + if (added) { + status += `${pluralize('file', added)} added`; + } + if (changed) { + status += `${status.length === 0 ? '' : separator}${pluralize('file', changed)} changed`; + } + if (deleted) { + status += `${status.length === 0 ? '' : separator}${pluralize('file', deleted)} deleted`; + } + return `${prefix}${status}${suffix}`; + } + + let status = ''; + if (options?.compact) { + if (added !== 0) { + status += `+${added}`; + } + if (changed !== 0) { + status += `${status.length === 0 ? '' : separator}~${changed}`; + } + if (deleted !== 0) { + status += `${status.length === 0 ? '' : separator}-${deleted}`; + } + } else { + status += `+${added}${separator}~${changed}${separator}-${deleted}`; + } + + return `${prefix}${status}${suffix}`; +} export function getUpstreamStatus( upstream: GitTrackingUpstream | undefined, diff --git a/src/plus/ai/anthropicProvider.ts b/src/plus/ai/anthropicProvider.ts index 88a638509398a..1a13bdf78c7bc 100644 --- a/src/plus/ai/anthropicProvider.ts +++ b/src/plus/ai/anthropicProvider.ts @@ -7,6 +7,20 @@ import { OpenAICompatibleProviderBase } from './openAICompatibleProviderBase'; type AnthropicModel = AIModel; const models: AnthropicModel[] = [ + { + id: 'claude-haiku-4-5', + name: 'Claude 4.5 Haiku', + maxTokens: { input: 204800, output: 32000 }, + provider: provider, + default: true, + }, + { + id: 'claude-haiku-4-5-20251001', + name: 'Claude 4.5 Haiku', + maxTokens: { input: 204800, output: 32000 }, + provider: provider, + hidden: true, + }, { id: 'claude-sonnet-4-5', name: 'Claude 4.5 Sonnet', @@ -25,19 +39,20 @@ const models: AnthropicModel[] = [ name: 'Claude 4.1 Opus', maxTokens: { input: 204800, output: 32000 }, provider: provider, - hidden: true, }, { id: 'claude-opus-4-1-20250805', name: 'Claude 4.1 Opus', maxTokens: { input: 204800, output: 32000 }, provider: provider, + hidden: true, }, { id: 'claude-opus-4-0', name: 'Claude 4 Opus', maxTokens: { input: 204800, output: 32000 }, provider: provider, + hidden: true, }, { id: 'claude-opus-4-20250514', @@ -64,6 +79,7 @@ const models: AnthropicModel[] = [ name: 'Claude 3.7 Sonnet', maxTokens: { input: 204800, output: 64000 }, provider: provider, + hidden: true, }, { id: 'claude-3-7-sonnet-20250219', @@ -77,6 +93,7 @@ const models: AnthropicModel[] = [ name: 'Claude 3.5 Sonnet', maxTokens: { input: 204800, output: 8192 }, provider: provider, + hidden: true, }, { id: 'claude-3-5-sonnet-20241022', @@ -97,7 +114,7 @@ const models: AnthropicModel[] = [ name: 'Claude 3.5 Haiku', maxTokens: { input: 204800, output: 8192 }, provider: provider, - default: true, + hidden: true, }, { id: 'claude-3-5-haiku-20241022', @@ -111,6 +128,7 @@ const models: AnthropicModel[] = [ name: 'Claude 3 Opus', maxTokens: { input: 204800, output: 4096 }, provider: provider, + hidden: true, }, { id: 'claude-3-opus-20240229', @@ -138,6 +156,7 @@ const models: AnthropicModel[] = [ name: 'Claude 3 Haiku', maxTokens: { input: 204800, output: 4096 }, provider: provider, + hidden: true, }, { id: 'claude-3-haiku-20240307', diff --git a/src/plus/gk/utils/-webview/mcp.utils.ts b/src/plus/gk/utils/-webview/mcp.utils.ts index 303d1e68b68f7..24ec3cea441fc 100644 --- a/src/plus/gk/utils/-webview/mcp.utils.ts +++ b/src/plus/gk/utils/-webview/mcp.utils.ts @@ -1,5 +1,5 @@ -import { lm, version } from 'vscode'; -import { isWeb } from '@env/platform'; +import { env, lm, version } from 'vscode'; +import { isOffline, isWeb } from '@env/platform'; import type { Container } from '../../../../container'; import { configuration } from '../../../../system/-webview/configuration'; import { satisfies } from '../../../../system/version'; @@ -13,8 +13,9 @@ export function isMcpBannerEnabled(container: Container, showAutoRegistration = return !container.storage.get('mcp:banner:dismissed', false); } +const supportedApps = ['Visual Studio Code', 'Visual Studio Code - Insiders', 'Visual Studio Code - Exploration']; export function supportsMcpExtensionRegistration(): boolean { - if (isWeb) { + if (isWeb || isOffline || !supportedApps.includes(env.appName)) { return false; } diff --git a/src/plus/gk/utils/subscription.utils.ts b/src/plus/gk/utils/subscription.utils.ts index dd3595cfe8897..82a75beecf339 100644 --- a/src/plus/gk/utils/subscription.utils.ts +++ b/src/plus/gk/utils/subscription.utils.ts @@ -83,7 +83,12 @@ export function computeSubscriptionState(subscription: Optional): PaidSubscriptionPlanIds { - const next = orderedPaidPlans.indexOf(subscription.plan.actual.id as PaidSubscriptionPlanIds) + 1; + let next = orderedPaidPlans.indexOf(subscription.plan.actual.id as PaidSubscriptionPlanIds) + 1; + // Skip the student plan since we cannot determine if the user is student-eligible or not + if (next === 0) { + next++; + } + if (next >= orderedPaidPlans.length) return 'enterprise'; // Not sure what to do here return orderedPaidPlans[next] ?? 'pro'; diff --git a/src/plus/integrations/providers/github/githubGitProvider.ts b/src/plus/integrations/providers/github/githubGitProvider.ts index 5f27fb718af34..94cc989b7f893 100644 --- a/src/plus/integrations/providers/github/githubGitProvider.ts +++ b/src/plus/integrations/providers/github/githubGitProvider.ts @@ -166,7 +166,7 @@ export class GitHubGitProvider implements GitProvider, Disposable { const workspaceUri = remotehub.getVirtualWorkspaceUri(uri); if (workspaceUri == null) return []; - return this.openRepository(undefined, workspaceUri, true, undefined, options?.silent); + return this.openRepository(undefined, workspaceUri, true, options?.silent); } catch (ex) { if (ex.message.startsWith('No provider registered with')) { Logger.error( @@ -218,13 +218,7 @@ export class GitHubGitProvider implements GitProvider, Disposable { void setContext('gitlens:hasVirtualFolders', this.container.git.hasOpenRepositories(this.descriptor.id)); } - openRepository( - folder: WorkspaceFolder | undefined, - uri: Uri, - root: boolean, - suspended?: boolean, - closed?: boolean, - ): Repository[] { + openRepository(folder: WorkspaceFolder | undefined, uri: Uri, root: boolean, closed?: boolean): Repository[] { return [ new Repository( this.container, @@ -236,7 +230,6 @@ export class GitHubGitProvider implements GitProvider, Disposable { folder ?? workspace.getWorkspaceFolder(uri), uri, root, - suspended ?? !window.state.focused, closed, ), ]; diff --git a/src/plus/integrations/providers/github/sub-providers/graph.ts b/src/plus/integrations/providers/github/sub-providers/graph.ts index 49b4a6f54383e..6e19df0cb68d7 100644 --- a/src/plus/integrations/providers/github/sub-providers/graph.ts +++ b/src/plus/integrations/providers/github/sub-providers/graph.ts @@ -27,6 +27,7 @@ import { getRemoteIconUri } from '../../../../../git/utils/-webview/icons'; import { getBranchId, getBranchNameWithoutRemote } from '../../../../../git/utils/branch.utils'; import { getChangedFilesCount } from '../../../../../git/utils/commit.utils'; import { createReference } from '../../../../../git/utils/reference.utils'; +import { isUncommitted } from '../../../../../git/utils/revision.utils'; import { getTagId } from '../../../../../git/utils/tag.utils'; import { configuration } from '../../../../../system/-webview/configuration'; import { log } from '../../../../../system/decorators/log'; @@ -66,7 +67,7 @@ export class GraphGitSubProvider implements GitGraphSubProvider { const [logResult, headBranchResult, branchesResult, remotesResult, tagsResult, currentUserResult] = await Promise.allSettled([ - this.provider.commits.getLog(repoPath, rev, { + this.provider.commits.getLog(repoPath, !rev || isUncommitted(rev) ? 'HEAD' : rev, { all: true, ordering: ordering, limit: defaultLimit, @@ -449,7 +450,7 @@ export class GraphGitSubProvider implements GitGraphSubProvider { worktrees: worktrees, worktreesByBranch: worktreesByBranch, rows: rows, - id: options?.ref, + id: options?.ref ?? first(log.commits.values())?.sha, paging: { limit: log.limit, diff --git a/src/plus/integrations/providers/github/sub-providers/remotes.ts b/src/plus/integrations/providers/github/sub-providers/remotes.ts index 68807042e7471..e72a001fc58b8 100644 --- a/src/plus/integrations/providers/github/sub-providers/remotes.ts +++ b/src/plus/integrations/providers/github/sub-providers/remotes.ts @@ -1,8 +1,7 @@ import { Uri } from 'vscode'; import { GitRemote } from '../../../../../git/models/remote'; -import { getRemoteProviderMatcher, loadRemoteProviders } from '../../../../../git/remotes/remoteProviders'; +import { getRemoteProviderMatcher, loadRemoteProvidersFromConfig } from '../../../../../git/remotes/remoteProviders'; import { RemotesGitProviderBase } from '../../../../../git/sub-providers/remotes'; -import { configuration } from '../../../../../system/-webview/configuration'; import { log } from '../../../../../system/decorators/log'; export class RemotesGitSubProvider extends RemotesGitProviderBase { @@ -13,7 +12,7 @@ export class RemotesGitSubProvider extends RemotesGitProviderBase { ): Promise { if (repoPath == null) return []; - const providers = loadRemoteProviders(configuration.get('remotes', null), undefined); + const providers = loadRemoteProvidersFromConfig(null, undefined); const uri = Uri.parse(repoPath, true); const [, owner, repo] = uri.path.split('/', 3); diff --git a/src/plus/integrations/providers/github/sub-providers/status.ts b/src/plus/integrations/providers/github/sub-providers/status.ts index 03df545ce5971..9d95ba9ef5ad4 100644 --- a/src/plus/integrations/providers/github/sub-providers/status.ts +++ b/src/plus/integrations/providers/github/sub-providers/status.ts @@ -1,6 +1,8 @@ import type { CancellationToken } from 'vscode'; import type { Container } from '../../../../../container'; -import type { GitStatusSubProvider } from '../../../../../git/gitProvider'; +import type { GitStatusSubProvider, GitWorkingChangesState } from '../../../../../git/gitProvider'; +import type { GitConflictFile } from '../../../../../git/models'; +import type { GitFile } from '../../../../../git/models/file'; import { GitStatus } from '../../../../../git/models/status'; import { gate } from '../../../../../system/decorators/gate'; import { log } from '../../../../../system/decorators/log'; @@ -35,4 +37,24 @@ export class StatusGitSubProvider implements GitStatusSubProvider { : undefined, ); } + + hasWorkingChanges(): Promise { + return Promise.resolve(false); + } + + getWorkingChangesState(): Promise { + return Promise.resolve({ staged: false, unstaged: false, untracked: false }); + } + + hasConflictingFiles(): Promise { + return Promise.resolve(false); + } + + getConflictingFiles(): Promise { + return Promise.resolve([]); + } + + getUntrackedFiles(): Promise { + return Promise.resolve([]); + } } diff --git a/src/system/decorators/__tests__/decorators.test.ts b/src/system/decorators/__tests__/decorators.test.ts new file mode 100644 index 0000000000000..7dac2551f5ec1 --- /dev/null +++ b/src/system/decorators/__tests__/decorators.test.ts @@ -0,0 +1,791 @@ +import * as assert from 'assert'; +import { gate } from '../gate'; +import { memoize } from '../memoize'; +import { sequentialize } from '../sequentialize'; + +suite('Decorator Test Suite', () => { + suite('sequentialize', () => { + test('should execute calls sequentially', async () => { + const executionOrder: number[] = []; + let counter = 0; + + class TestClass { + @sequentialize() + async method(delay: number): Promise { + const id = ++counter; + executionOrder.push(id); + await new Promise(resolve => setTimeout(resolve, delay)); + return id; + } + } + + const instance = new TestClass(); + + // Start three calls with different delays + const p1 = instance.method(50); // Should execute first + const p2 = instance.method(10); // Should execute second (even though faster) + const p3 = instance.method(5); // Should execute third + + const results = await Promise.all([p1, p2, p3]); + + // All should complete + assert.deepStrictEqual(results, [1, 2, 3]); + // Execution order should be sequential + assert.deepStrictEqual(executionOrder, [1, 2, 3]); + }); + + test('should deduplicate consecutive calls with same arguments', async () => { + let executionCount = 0; + const counterMap = new Map(); + + class TestClass { + @sequentialize() + async method(value: string): Promise { + executionCount++; + let counter = counterMap.get(value) || 0; + const id = ++counter; + counterMap.set(value, counter); + await new Promise(resolve => setTimeout(resolve, 10)); + return `${value}=${id}`; + } + } + + const instance = new TestClass(); + + const p1 = instance.method('msg1'); // Call 1 starts immediately + const p2 = instance.method('msg1'); // Call 2 chains and becomes waiting + const p3 = instance.method('msg1'); // Call 3 deduplicates with Call 2 (consecutive, same args) + const p4 = instance.method('msg2'); // Call 4 chains, doesn't deduplicate (different args) + const p5 = instance.method('msg1'); // Call 5 chains, doesn't deduplicate (not consecutive) + + const [r1, r2, r3, r4, r5] = await Promise.all([p1, p2, p3, p4, p5]); + + // Total executions: 4 (p1, p2 shared by calls 2&3, p4, p5) + assert.strictEqual(executionCount, 4); + + assert.strictEqual(r1, `msg1=1`); + // Calls 2 and 3 should share the same result + assert.strictEqual(r2, `msg1=2`); + assert.strictEqual(r3, `msg1=2`); + assert.strictEqual(r4, `msg2=1`); + assert.strictEqual(r5, `msg1=3`); + }); + + test('should not deduplicate non-consecutive calls', async () => { + let executionCount = 0; + const counterMap = new Map(); + + class TestClass { + @sequentialize() + async method(value: string): Promise { + executionCount++; + let counter = counterMap.get(value) || 0; + const id = ++counter; + counterMap.set(value, counter); + await new Promise(resolve => setTimeout(resolve, 10)); + return `${value}=${id}`; + } + } + + const instance = new TestClass(); + + const p1 = instance.method('msg1'); // Call 1 starts immediately + const p2 = instance.method('msg1'); // Call 2 chains and becomes waiting + const p3 = instance.method('msg2'); // Call 3 chains, doesn't deduplicate (different args) + const p4 = instance.method('msg1'); // Call 4 chains, doesn't deduplicate (not consecutive) + + const [r1, r2, r3, r4] = await Promise.all([p1, p2, p3, p4]); + + // Should execute 4 times (no deduplication) + assert.strictEqual(executionCount, 4); + + assert.strictEqual(r1, `msg1=1`); + assert.strictEqual(r2, `msg1=2`); + assert.strictEqual(r3, `msg2=1`); + assert.strictEqual(r4, `msg1=3`); + }); + + test('should work with custom resolver', async () => { + let executionCount = 0; + + class TestClass { + @sequentialize({ getDedupingKey: (obj: { id: number }) => obj.id.toString() }) + async method(obj: { id: number; data: string }): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 10)); + return `${obj.id}=${executionCount}`; + } + } + + const instance = new TestClass(); + + const p1 = instance.method({ id: 1, data: 'a' }); // Call 1 starts immediately + const p2 = instance.method({ id: 1, data: 'b' }); // Call 2 chains and becomes waiting + const p3 = instance.method({ id: 1, data: 'c' }); // Call 3 deduplicates with Call 2 (consecutive, same resolved args) + const p4 = instance.method({ id: 2, data: 'a' }); // Call 4 chains, doesn't deduplicate (not consecutive) + const p5 = instance.method({ id: 2, data: 'd' }); // Call 5 deduplicates with Call 4 (consecutive, same resolved args) + + const [r1, r2, r3, r4, r5] = await Promise.all([p1, p2, p3, p4, p5]); + + // Should execute 3 times (p1, p2 shared by calls 2&3, p4, p5 shared by calls 4&5) + assert.strictEqual(executionCount, 3); + + assert.strictEqual(r1, `1=1`); + assert.strictEqual(r2, `1=2`); + assert.strictEqual(r3, `1=2`); + assert.strictEqual(r4, `2=3`); + assert.strictEqual(r5, `2=3`); + }); + + test('should handle errors correctly', async () => { + let executionCount = 0; + + class TestClass { + @sequentialize() + async method(shouldFail: boolean): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 10)); + if (shouldFail) { + throw new Error('Test error'); + } + return executionCount; + } + } + + const instance = new TestClass(); + + const p1 = instance.method(true); // Will fail + const p2 = instance.method(false); // Should still execute after p1 fails + + await assert.rejects(p1, /Test error/); + const result = await p2; + + assert.strictEqual(executionCount, 2); + assert.strictEqual(result, 2); + }); + + test('should clean up state after all calls complete', async () => { + class TestClass { + @sequentialize() + async method(value: string): Promise { + await new Promise(resolve => setTimeout(resolve, 10)); + return value; + } + } + + const instance = new TestClass(); + const stateKey = '$sequentialize$method'; + + // Initially no state + assert.strictEqual((instance as any)[stateKey], undefined); + + const p1 = instance.method('test'); + // State should exist while call is pending + assert.notStrictEqual((instance as any)[stateKey], undefined); + + await p1; + // State should be cleaned up after completion + assert.strictEqual((instance as any)[stateKey], undefined); + }); + + test('should handle empty arguments', async () => { + let executionCount = 0; + + class TestClass { + @sequentialize() + async method(): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 10)); + return executionCount; + } + } + + const instance = new TestClass(); + + const p1 = instance.method(); + const p2 = instance.method(); // Should chain and become waiting + const p3 = instance.method(); // Should dedupe with p2 + + const [r1, r2, r3] = await Promise.all([p1, p2, p3]); + + // Should execute 2 times (p1, then p2 shared by calls 2&3) + assert.strictEqual(executionCount, 2); + assert.strictEqual(r1, 1); + assert.strictEqual(r2, 2); + assert.strictEqual(r3, 2); + }); + + test('should handle error in deduplicated waiting call', async () => { + let executionCount = 0; + + class TestClass { + @sequentialize() + async method(shouldFail: boolean): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 10)); + if (shouldFail) { + throw new Error('Test error'); + } + return executionCount; + } + } + + const instance = new TestClass(); + + const p1 = instance.method(false); // Succeeds + const p2 = instance.method(true); // Becomes waiting, will fail + const p3 = instance.method(true); // Dedupes with p2, should also fail + + await p1; // Wait for first to complete + + // Both p2 and p3 should reject with the same error + await assert.rejects(p2, /Test error/); + await assert.rejects(p3, /Test error/); + + // Should execute 2 times (p1, then p2 shared by p2&p3) + assert.strictEqual(executionCount, 2); + }); + + test('should handle null and undefined arguments', async () => { + let executionCount = 0; + + class TestClass { + @sequentialize() + async method(value: string | null | undefined): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 10)); + return executionCount; + } + } + + const instance = new TestClass(); + + const p1 = instance.method(null); // Execution 1 (runs immediately) + const p2 = instance.method(null); // Execution 2 (chains, becomes waiting) + const p3 = instance.method(undefined); // Dedupes with p2 (null and undefined both resolve to '') + const p4 = instance.method('test'); // Execution 3 (different arg) + + const [r1, r2, r3, r4] = await Promise.all([p1, p2, p3, p4]); + + // Should execute 3 times (p1, p2 shared by p2&p3, p4) + assert.strictEqual(executionCount, 3); + + assert.strictEqual(r1, 1); + assert.strictEqual(r2, 2); + assert.strictEqual(r3, 2); + assert.strictEqual(r4, 3); + }); + + test('should support parallel queues with getQueueKey', async () => { + let executionCount = 0; + const executionOrder: string[] = []; + + class TestClass { + @sequentialize({ + getQueueKey: (msg: { channel: string; id: string }) => msg.channel, + getDedupingKey: (msg: { channel: string; id: string }) => msg.id, + }) + async method(msg: { channel: string; id: string }): Promise { + const count = ++executionCount; + executionOrder.push(`${msg.channel}:${msg.id}:start`); + await new Promise(resolve => setTimeout(resolve, 10)); + executionOrder.push(`${msg.channel}:${msg.id}:end`); + return count; + } + } + + const instance = new TestClass(); + + // Queue A: 3 calls + const p1 = instance.method({ channel: 'A', id: '1' }); // Queue A, runs immediately + const p2 = instance.method({ channel: 'A', id: '1' }); // Queue A, chains, becomes waiting + const p3 = instance.method({ channel: 'A', id: '1' }); // Queue A, dedupes with p2 + + // Queue B: 2 calls (runs in parallel with Queue A) + const p4 = instance.method({ channel: 'B', id: '1' }); // Queue B, runs immediately + const p5 = instance.method({ channel: 'B', id: '2' }); // Queue B, chains (different id) + + // Queue A: 1 more call + const p6 = instance.method({ channel: 'A', id: '2' }); // Queue A, chains (different id) + + const results = await Promise.all([p1, p2, p3, p4, p5, p6]); + + // Should execute 5 times total (p1, p2 shared by p2&p3, p4, p5, p6) + assert.strictEqual(executionCount, 5); + + // p2 and p3 should share the same result (deduplicated) + assert.strictEqual(results[1], results[2]); + + // Verify execution order shows parallel execution + // Both queues should start before either finishes (parallel execution) + const aStartIndex = executionOrder.indexOf('A:1:start'); + const bStartIndex = executionOrder.indexOf('B:1:start'); + const aEndIndex = executionOrder.indexOf('A:1:end'); + assert.ok( + aStartIndex >= 0 && bStartIndex >= 0 && aEndIndex >= 0, + `Missing expected execution markers in: ${executionOrder.join(', ')}`, + ); + assert.ok( + bStartIndex < aEndIndex, + `Expected B to start before A ends (parallel), but order was: ${executionOrder.join(', ')}`, + ); + + // Verify sequential execution within each queue + const a1Start = executionOrder.indexOf('A:1:start'); + const a1End = executionOrder.indexOf('A:1:end'); + const a2Start = executionOrder.indexOf('A:2:start'); + assert.ok( + a1Start < a1End && a1End < a2Start, + `Expected A:1 to complete before A:2 starts (sequential in queue), but order was: ${executionOrder.join(', ')}`, + ); + + const b1Start = executionOrder.indexOf('B:1:start'); + const b1End = executionOrder.indexOf('B:1:end'); + const b2Start = executionOrder.indexOf('B:2:start'); + assert.ok( + b1Start < b1End && b1End < b2Start, + `Expected B:1 to complete before B:2 starts (sequential in queue), but order was: ${executionOrder.join(', ')}`, + ); + }); + + test('sequentialize should work with multiple instances', async () => { + let executionCount = 0; + + class TestClass { + @sequentialize() + async method(value: string): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 10)); + return executionCount; + } + } + + const instance1 = new TestClass(); + const instance2 = new TestClass(); + + // Calls on different instances should not interfere + const p1 = instance1.method('test'); + const p2 = instance2.method('test'); + const p3 = instance1.method('test'); + + await Promise.all([p1, p2, p3]); + + // Should execute 3 times (instance1: 2 sequential, instance2: 1) + assert.strictEqual(executionCount, 3); + }); + }); + + suite('gate', () => { + test('should deduplicate concurrent calls with same arguments', async () => { + let executionCount = 0; + + class TestClass { + @gate() + async method(value: string): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 50)); + return executionCount; + } + } + + const instance = new TestClass(); + + // All three calls happen concurrently with same args + const p1 = instance.method('test'); + const p2 = instance.method('test'); + const p3 = instance.method('test'); + + const results = await Promise.all([p1, p2, p3]); + + // Should only execute once + assert.strictEqual(executionCount, 1); + // All should get the same result + assert.strictEqual(results[0], 1); + assert.strictEqual(results[1], 1); + assert.strictEqual(results[2], 1); + }); + + test('should not deduplicate calls with different arguments', async () => { + let executionCount = 0; + + class TestClass { + @gate() + async method(value: string): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 10)); + return executionCount; + } + } + + const instance = new TestClass(); + + const p1 = instance.method('a'); + const p2 = instance.method('b'); + const p3 = instance.method('c'); + + await Promise.all([p1, p2, p3]); + + // Should execute three times (different args) + assert.strictEqual(executionCount, 3); + }); + + test('should allow new calls after promise resolves', async () => { + let executionCount = 0; + + class TestClass { + @gate() + async method(value: string): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 10)); + return executionCount; + } + } + + const instance = new TestClass(); + + const result1 = await instance.method('test'); + const result2 = await instance.method('test'); + + // Should execute twice (sequential, not concurrent) + assert.strictEqual(executionCount, 2); + assert.strictEqual(result1, 1); + assert.strictEqual(result2, 2); + }); + + test('should work with custom resolver', async () => { + let executionCount = 0; + const executionOrder: string[] = []; + + class TestClass { + @gate((obj: { id: number }) => obj.id.toString()) + async method(obj: { id: number; data: string }): Promise { + const count = ++executionCount; + executionOrder.push(`${obj.id}:start`); + await new Promise(resolve => setTimeout(resolve, 10)); + executionOrder.push(`${obj.id}:end`); + return count; + } + } + + const instance = new TestClass(); + + // Start all three calls at the same time + const p1 = instance.method({ id: 1, data: 'a' }); + const p2 = instance.method({ id: 1, data: 'b' }); // Same id, should dedupe + const p3 = instance.method({ id: 2, data: 'a' }); // Different id, runs in parallel + + const results = await Promise.all([p1, p2, p3]); + + // Should execute twice (p1&p2 share, p3 runs in parallel) + assert.strictEqual(executionCount, 2); + assert.strictEqual(results[0], results[1]); // p1 and p2 share result + assert.notStrictEqual(results[0], results[2]); // p3 has different result + + // Verify parallel execution: both should start before either finishes + const id1Start = executionOrder.indexOf('1:start'); + const id2Start = executionOrder.indexOf('2:start'); + const id1End = executionOrder.indexOf('1:end'); + assert.ok( + id1Start >= 0 && id2Start >= 0 && id1End >= 0, + `Missing expected execution markers in: ${executionOrder.join(', ')}`, + ); + assert.ok( + id2Start < id1End, + `Expected id:2 to start before id:1 ends (parallel), but order was: ${executionOrder.join(', ')}`, + ); + }); + + test('should handle non-promise return values', () => { + let executionCount = 0; + + class TestClass { + @gate() + method(value: string): number { + executionCount++; + return executionCount; + } + } + + const instance = new TestClass(); + + const result1 = instance.method('test'); + const result2 = instance.method('test'); + + // Non-promise values should not be gated + assert.strictEqual(executionCount, 2); + assert.strictEqual(result1, 1); + assert.strictEqual(result2, 2); + }); + + test('should handle errors in gated calls', async () => { + let executionCount = 0; + + class TestClass { + @gate() + async method(shouldFail: boolean): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 10)); + if (shouldFail) { + throw new Error('Test error'); + } + return executionCount; + } + } + + const instance = new TestClass(); + + const p1 = instance.method(true); + const p2 = instance.method(true); // Should share the same error + + await assert.rejects(p1, /Test error/); + await assert.rejects(p2, /Test error/); + + // Should only execute once (both share the same promise) + assert.strictEqual(executionCount, 1); + + // After error, new calls should work + const result = await instance.method(false); + assert.strictEqual(result, 2); + }); + + test('gate should work with multiple instances', async () => { + let executionCount = 0; + + class TestClass { + @gate() + async method(value: string): Promise { + const count = ++executionCount; + await new Promise(resolve => setTimeout(resolve, 50)); + return count; + } + } + + const instance1 = new TestClass(); + const instance2 = new TestClass(); + + // Concurrent calls on different instances should not deduplicate + const start = Date.now(); + const p1 = instance1.method('test'); + const p2 = instance2.method('test'); + const p3 = instance1.method('test'); // Should dedupe with p1 + + const results = await Promise.all([p1, p2, p3]); + const totalTime = Date.now() - start; + + // Should execute 2 times (instance1: 1, instance2: 1) + assert.strictEqual(executionCount, 2); + assert.strictEqual(results[0], results[2]); // p1 and p3 share result + assert.notStrictEqual(results[0], results[1]); // p1 and p2 different + // Should run in parallel (total time should be ~50ms, not ~100ms) + assert.ok(totalTime < 80, `Expected parallel execution (~50ms), but took ${totalTime}ms`); + }); + }); + + suite('memoize', () => { + test('should cache results for same arguments', () => { + let executionCount = 0; + + class TestClass { + @memoize() + method(value: string): number { + executionCount++; + return executionCount; + } + } + + const instance = new TestClass(); + + const result1 = instance.method('test'); + const result2 = instance.method('test'); + const result3 = instance.method('test'); + + // Should only execute once + assert.strictEqual(executionCount, 1); + // All results should be the same + assert.strictEqual(result1, 1); + assert.strictEqual(result2, 1); + assert.strictEqual(result3, 1); + }); + + test('should not cache results for different arguments', () => { + let executionCount = 0; + + class TestClass { + @memoize() + method(value: string): number { + executionCount++; + return executionCount; + } + } + + const instance = new TestClass(); + + const result1 = instance.method('a'); + const result2 = instance.method('b'); + const result3 = instance.method('c'); + + // Should execute three times + assert.strictEqual(executionCount, 3); + assert.strictEqual(result1, 1); + assert.strictEqual(result2, 2); + assert.strictEqual(result3, 3); + }); + + test('should work with custom resolver', () => { + let executionCount = 0; + + class TestClass { + @memoize((obj: { id: number }) => obj.id.toString()) + method(obj: { id: number; data: string }): number { + executionCount++; + return executionCount; + } + } + + const instance = new TestClass(); + + const result1 = instance.method({ id: 1, data: 'a' }); + const result2 = instance.method({ id: 1, data: 'b' }); // Same id, should use cache + const result3 = instance.method({ id: 2, data: 'a' }); // Different id, new execution + + // Should execute twice + assert.strictEqual(executionCount, 2); + assert.strictEqual(result1, 1); + assert.strictEqual(result2, 1); // Cached + assert.strictEqual(result3, 2); + }); + + test('should cache per instance', () => { + let executionCount = 0; + + class TestClass { + @memoize() + method(value: string): number { + executionCount++; + return executionCount; + } + } + + const instance1 = new TestClass(); + const instance2 = new TestClass(); + + const result1 = instance1.method('test'); + const result2 = instance2.method('test'); + const result3 = instance1.method('test'); // Should use cache from instance1 + + // Should execute twice (once per instance) + assert.strictEqual(executionCount, 2); + assert.strictEqual(result1, 1); + assert.strictEqual(result2, 2); + assert.strictEqual(result3, 1); // Cached from instance1 + }); + + test('should work with getters', () => { + let executionCount = 0; + + class TestClass { + @memoize() + get value(): number { + executionCount++; + return executionCount; + } + } + + const instance = new TestClass(); + + const result1 = instance.value; + const result2 = instance.value; + const result3 = instance.value; + + // Should only execute once + assert.strictEqual(executionCount, 1); + assert.strictEqual(result1, 1); + assert.strictEqual(result2, 1); + assert.strictEqual(result3, 1); + }); + + test('should cache complex return values', () => { + let executionCount = 0; + + class TestClass { + @memoize() + method(value: string): { count: number; value: string } { + executionCount++; + return { count: executionCount, value: value }; + } + } + + const instance = new TestClass(); + + const result1 = instance.method('test'); + const result2 = instance.method('test'); + + // Should only execute once + assert.strictEqual(executionCount, 1); + // Should return the exact same object reference + assert.strictEqual(result1, result2); + assert.strictEqual(result1.count, 1); + }); + + test('should work with async functions', async () => { + let executionCount = 0; + + class TestClass { + @memoize() + async method(value: string): Promise { + executionCount++; + await new Promise(resolve => setTimeout(resolve, 10)); + return executionCount; + } + } + + const instance = new TestClass(); + + // First call creates and caches the promise + const p1 = instance.method('test'); + // Second call should return the same cached promise + const p2 = instance.method('test'); + + // Should be the same promise reference + assert.strictEqual(p1, p2); + + const results = await Promise.all([p1, p2]); + + // Should only execute once + assert.strictEqual(executionCount, 1); + assert.strictEqual(results[0], 1); + assert.strictEqual(results[1], 1); + }); + + test('should NOT cache errors', () => { + let executionCount = 0; + + class TestClass { + @memoize() + method(shouldFail: boolean): number { + executionCount++; + if (shouldFail) { + throw new Error('Test error'); + } + return executionCount; + } + } + + const instance = new TestClass(); + + // First call throws + assert.throws(() => instance.method(true), /Test error/); + assert.strictEqual(executionCount, 1); + + // Second call with same args should execute again (error not cached) + assert.throws(() => instance.method(true), /Test error/); + assert.strictEqual(executionCount, 2); + + // Successful call should cache + const result1 = instance.method(false); + const result2 = instance.method(false); + assert.strictEqual(executionCount, 3); // Only one more execution + assert.strictEqual(result1, result2); + }); + }); +}); diff --git a/src/system/decorators/command.ts b/src/system/decorators/command.ts index eddc339feffcd..8b145ca983799 100644 --- a/src/system/decorators/command.ts +++ b/src/system/decorators/command.ts @@ -1,6 +1,15 @@ +import type { + GlCommands, + WebviewCommands, + WebviewCommandsOrCommandsWithSuffix, + WebviewViewCommands, + WebviewViewCommandsOrCommandsWithSuffix, +} from '../../constants.commands'; +import type { WebviewTypes, WebviewViewTypes } from '../../constants.views'; + interface Command< - THandler extends (...args: any[]) => any, - TCommand extends string = string, + TCommand extends string | GlCommands = GlCommands, + THandler extends (...args: any[]) => any = (...args: any[]) => any, TOptions extends object | void = void, > { command: TCommand; @@ -9,8 +18,8 @@ interface Command< } export function createCommandDecorator< + TCommand extends string | GlCommands = GlCommands, THandler extends (...args: any[]) => any = (...args: any[]) => any, - TCommand extends string = string, TOptions extends object | void = void, >(): { command: ( @@ -21,9 +30,9 @@ export function createCommandDecorator< contextOrKey?: string | ClassMethodDecoratorContext, descriptor?: PropertyDescriptor, ) => PropertyDescriptor | undefined; - getCommands: () => Iterable>; + getCommands: () => Iterable>; } { - const commands = new Map>(); + const commands = new Map>(); function command(command: TCommand, options?: TOptions) { return function ( @@ -66,3 +75,19 @@ export function createCommandDecorator< getCommands: () => commands.values(), }; } + +export function getWebviewCommand( + command: WebviewCommandsOrCommandsWithSuffix, + type: T, +): WebviewCommands { + return command.endsWith(':') ? (`${command}${type}` as WebviewCommands) : (command as WebviewCommands); +} + +export function getWebviewViewCommand( + command: WebviewViewCommandsOrCommandsWithSuffix, + type: T, +): WebviewViewCommands { + return command.endsWith(':') + ? (`${command}${type}` as WebviewViewCommands) + : (command as WebviewViewCommands); +} diff --git a/src/system/decorators/gate.ts b/src/system/decorators/gate.ts index 4cae13c3d1e3d..5158391230040 100644 --- a/src/system/decorators/gate.ts +++ b/src/system/decorators/gate.ts @@ -1,8 +1,10 @@ /* eslint-disable @typescript-eslint/no-unsafe-return */ +import { getTelementryService } from '@env/providers'; +import { Logger } from '../logger'; import { isPromise } from '../promise'; import { resolveProp } from './resolver'; -export function gate any>(resolver?: (...args: Parameters) => string) { +export function gate any>(getGroupingKey?: (...args: Parameters) => string) { return (_target: any, key: string, descriptor: PropertyDescriptor): void => { // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type let fn: Function | undefined; @@ -16,7 +18,7 @@ export function gate any>(resolver?: (...args: Parame const gateKey = `$gate$${key}`; descriptor.value = function (this: any, ...args: any[]) { - const prop = resolveProp(gateKey, resolver, ...(args as Parameters)); + const prop = resolveProp(gateKey, getGroupingKey, ...(args as Parameters)); if (!Object.prototype.hasOwnProperty.call(this, prop)) { Object.defineProperty(this, prop, { configurable: false, @@ -36,13 +38,36 @@ export function gate any>(resolver?: (...args: Parame this[prop] = promise; void promise.finally(() => (this[prop] = undefined)); - // if (DEBUG) { - // const timeout = setTimeout(() => { - // console.debug(`[gate] ${key} took too long to resolve`, this, ...args); - // debugger; - // }, 60000); - // void promise.finally(() => clearTimeout(timeout)); - // } + // Log if gate takes too long to resolve + let timeout = setTimeout(() => { + Logger.warn(`[gate] ${key} has been pending for 120+ seconds (possible deadlock)`, `prop=${prop}`); + getTelementryService()?.sendEvent('op/gate/deadlock', { key: key, prop: prop, timeout: 60000 }); + + timeout = setTimeout(() => { + Logger.warn( + `[gate] ${key} has still been pending for 420+ seconds (possible deadlock)`, + `prop=${prop}`, + ); + getTelementryService()?.sendEvent('op/gate/deadlock', { + key: key, + prop: prop, + timeout: 420000, + }); + + timeout = setTimeout(() => { + Logger.warn( + `[gate] ${key} has still been pending for 900+ seconds (possible deadlock)`, + `prop=${prop}`, + ); + getTelementryService()?.sendEvent('op/gate/deadlock', { + key: key, + prop: prop, + timeout: 900000, + }); + }, 480000); + }, 300000); + }, 120000); + void promise.finally(() => clearTimeout(timeout)); } return promise; diff --git a/src/system/decorators/sequentialize.ts b/src/system/decorators/sequentialize.ts new file mode 100644 index 0000000000000..ff02fd12899dc --- /dev/null +++ b/src/system/decorators/sequentialize.ts @@ -0,0 +1,116 @@ +import { defaultResolver } from '@env/resolver'; + +interface SequentializeState { + promise: Promise; + waiting?: { + key: string; + promise: Promise; + }; +} + +interface SequentializeOptions any> { + /** + * Optional function to resolve arguments into a deduplication key. + * Consecutive duplicate calls (same deduplication key) that haven't started yet are deduplicated and share the same result. + * If omitted, uses the default resolver which deduplicates based on argument values. + */ + getDedupingKey?: (...args: Parameters) => string; + + /** + * Optional function to resolve arguments into a queue key. + * Calls with the same queue key execute sequentially in that queue. + * Calls with different queue keys execute in parallel (different queues). + * If omitted, all calls share a single queue. + */ + getQueueKey?: (...args: Parameters) => string; +} + +/** + * Method decorator that ensures all calls to the decorated async method are executed sequentially. + * If the method is called multiple times before a previous invocation completes, subsequent calls are queued and executed one after another. + * + * Consecutive duplicate calls (same arguments) that haven't started yet are deduplicated and share the same result. + * + * @param options Optional options object: + * - getQueueKey: Groups calls into parallel queues + * - getDedupingKey: Deduplicates consecutive calls within each queue + * - If omitted: Uses default resolver for deduplication, single queue for all calls + */ +export function sequentialize any>( + options?: SequentializeOptions, +): (target: any, key: string, descriptor: PropertyDescriptor) => void { + const getQueueKey = options?.getQueueKey; + const getDedupingKey = options?.getDedupingKey; + + return (_target: any, key: string, descriptor: PropertyDescriptor) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type + let fn: Function | undefined; + if (typeof descriptor.value === 'function') { + fn = descriptor.value; + } else if (typeof descriptor.get === 'function') { + fn = descriptor.get; + } + if (fn === undefined) throw new Error('Not supported'); + + const serializeKey = `$sequentialize$${key}`; + + descriptor.value = function (this: any, ...args: any[]) { + // Compute queue key (if getQueueKey provided, otherwise use default queue) + const queueKey = getQueueKey?.(...(args as Parameters)) ?? ''; + const prop = queueKey ? `${serializeKey}$${queueKey}` : serializeKey; + + if (!Object.prototype.hasOwnProperty.call(this, prop)) { + Object.defineProperty(this, prop, { + configurable: false, + enumerable: false, + writable: true, + value: undefined, + }); + } + + const state: SequentializeState | undefined = this[prop]; + // eslint-disable-next-line no-return-await, @typescript-eslint/no-unsafe-return + const run = async () => await fn.apply(this, args); + + // Compute the dedupe key once + const dedupeKey = getDedupingKey?.(...(args as Parameters)) ?? defaultResolver(...(args as any)); + + // If there's a waiting call, check if we can deduplicate with it and return the same promise as the waiting call + if (state?.waiting != null && state.waiting.key === dedupeKey) return state.waiting.promise; + + // Chain this call after the current promise (or start fresh if no state) + let promise: Promise; + if (state == null) { + // No existing state, start fresh and don't set waiting (it starts immediately) + promise = run(); + this[prop] = { promise: promise }; + } else { + // Chain after existing promise with a single handler for both success and error + const clearWaitingAndRun = () => { + // Clear waiting status when this call starts running + const s = this[prop]; + if (s?.waiting?.promise === promise) { + s.waiting = undefined; + } + return run(); + }; + + promise = state.promise.then(clearWaitingAndRun, clearWaitingAndRun); + + // Update state with this call as the new waiting call + state.promise = promise; + state.waiting = { key: dedupeKey, promise: promise }; + } + + // Cleanup when done + void promise.finally(() => { + const s = this[prop]; + if (s?.promise === promise && s.waiting == null) { + this[prop] = undefined; + } + }); + + return promise; + }; + }; +} diff --git a/src/system/decorators/serialize.ts b/src/system/decorators/serialize.ts deleted file mode 100644 index 0b35bd3006d90..0000000000000 --- a/src/system/decorators/serialize.ts +++ /dev/null @@ -1,37 +0,0 @@ -export function sequentialize(): (target: any, key: string, descriptor: PropertyDescriptor) => void { - return (_target: any, key: string, descriptor: PropertyDescriptor) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type - let fn: Function | undefined; - if (typeof descriptor.value === 'function') { - fn = descriptor.value; - } else if (typeof descriptor.get === 'function') { - fn = descriptor.get; - } - if (fn === undefined) throw new Error('Not supported'); - - const serializeKey = `$sequentialize$${key}`; - - descriptor.value = function (this: any, ...args: any[]) { - if (!Object.prototype.hasOwnProperty.call(this, serializeKey)) { - Object.defineProperty(this, serializeKey, { - configurable: false, - enumerable: false, - writable: true, - value: undefined, - }); - } - - let promise: Promise | undefined = this[serializeKey]; - // eslint-disable-next-line no-return-await, @typescript-eslint/no-unsafe-return - const run = async () => await fn.apply(this, args); - if (promise == null) { - promise = run(); - } else { - promise = promise.then(run, run); - } - - this[serializeKey] = promise; - return promise; - }; - }; -} diff --git a/src/system/event.ts b/src/system/event.ts index 8a118be803ae6..c59b71101fb8d 100644 --- a/src/system/event.ts +++ b/src/system/event.ts @@ -1,4 +1,5 @@ import type { Disposable, Event } from 'vscode'; +import { Logger } from './logger'; import type { Deferred } from './promise'; export function once(event: Event): Event { @@ -112,21 +113,34 @@ export function weakEvent( ): Disposable { const ref = new WeakRef(thisArg); + let disposed = false; let disposable: Disposable; const d = event((e: T) => { const obj = ref.deref(); if (obj != null) { listener.call(obj, e); - } else { + } else if (!disposed) { + Logger.warn(`weakEvent GC'd; disposing listener`); disposable.dispose(); } }); if (alsoDisposeOnReleaseOrDispose == null) { - disposable = d; + disposable = { + dispose: () => { + disposed = true; + d.dispose(); + }, + }; } else { - disposable = disposableFrom(d, ...alsoDisposeOnReleaseOrDispose); + const wrapped = disposableFrom(d, ...alsoDisposeOnReleaseOrDispose); + disposable = { + dispose: () => { + disposed = true; + wrapped.dispose(); + }, + }; } return disposable; } diff --git a/src/system/ipcSerialize.ts b/src/system/ipcSerialize.ts new file mode 100644 index 0000000000000..03de80d8a83d5 --- /dev/null +++ b/src/system/ipcSerialize.ts @@ -0,0 +1,53 @@ +import type { Uri } from 'vscode'; +import { deserializeIpcJsonReviver, serializeIpcJsonReplacer } from '@env/json'; +import type { Container } from '../container'; +import type { IpcPromise } from '../webviews/ipc'; +import type { Branded } from './brand'; + +// prettier-ignore +export type IpcSerialized = + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type + T extends Error | Function | RegExp | Container + ? never + : T extends Date + ? Date + : T extends Uri + ? Uri + : T extends Promise + ? Promise> + : T extends Map + ? [IpcSerialized, IpcSerialized][] + : T extends Set + ? IpcSerialized[] + : T extends Branded + ? U + : T extends any[] + ? IpcSerialized[] + : T extends object + ? { [K in keyof T]: T[K] extends Date ? Date : IpcSerialized } + : T; + +export function serializeIpcData(obj: T, nextIpcId: () => string, pendingPromises: IpcPromise[]): string; +export function serializeIpcData( + obj: T | undefined, + nextIpcId: () => string, + pendingPromises: IpcPromise[], +): string | undefined; +export function serializeIpcData( + obj: T | undefined, + nextIpcId: () => string, + pendingPromises: IpcPromise[], +): string | undefined { + if (obj == null) return undefined; + + return JSON.stringify(obj, function (this: any, key: string, value: unknown) { + return serializeIpcJsonReplacer.call(this, key, value, nextIpcId, pendingPromises); + }); +} + +export function deserializeIpcData( + data: string, + promiseFactory: (value: IpcPromise['value']) => Promise, +): T { + return JSON.parse(data, (k, v) => deserializeIpcJsonReviver(k, v, promiseFactory)) as T; +} diff --git a/src/system/logger.scope.ts b/src/system/logger.scope.ts index c4a13e958332f..986eb3dffc45f 100644 --- a/src/system/logger.scope.ts +++ b/src/system/logger.scope.ts @@ -68,8 +68,17 @@ export function setLogScope(scopeId: number, scope: LogScope): LogScope { export function setLogScopeExit(scope: LogScope | undefined, details: string | undefined, failed?: string): void { if (scope == null) return; - scope.exitDetails = details; + if (scope.exitDetails != null && details != null) { + scope.exitDetails += details; + } else { + scope.exitDetails = details; + } + if (failed != null) { - scope.exitFailed = failed; + if (scope.exitFailed != null) { + scope.exitFailed += failed; + } else { + scope.exitFailed = failed; + } } } diff --git a/src/system/serialize.ts b/src/system/serialize.ts index 7697d2a4cba58..334d11a0e329c 100644 --- a/src/system/serialize.ts +++ b/src/system/serialize.ts @@ -6,7 +6,7 @@ import type { Branded } from './brand'; // prettier-ignore export type Serialized = // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type - T extends Function | Error | Container + T extends Error |Function | Container ? never : T extends Date ? TDate diff --git a/src/system/uri.ts b/src/system/uri.ts index 4de5693c4897c..2b6ed785d9e94 100644 --- a/src/system/uri.ts +++ b/src/system/uri.ts @@ -1,5 +1,13 @@ import type { Uri } from 'vscode'; +export interface UriComponents { + scheme: string; + authority: string; + path: string; + query: string; + fragment: string; +} + export function areUrisEqual(a: Uri | undefined, b: Uri | undefined): boolean { if (a === b) return true; if (a == null || b == null) return false; diff --git a/src/system/webview.ts b/src/system/webview.ts index 4be34e3cdcf9a..a27c46b868a9b 100644 --- a/src/system/webview.ts +++ b/src/system/webview.ts @@ -1,9 +1,9 @@ import type { PlusCommands, WebviewCommands, WebviewViewCommands } from '../constants.commands'; -import type { WebviewIds, WebviewViewIds } from '../constants.views'; +import type { CustomEditorIds, WebviewIds, WebviewViewIds } from '../constants.views'; export function createWebviewCommandLink( command: WebviewCommands | WebviewViewCommands | PlusCommands, - webviewId: WebviewIds | WebviewViewIds, + webviewId: WebviewIds | WebviewViewIds | CustomEditorIds, webviewInstanceId: string | undefined, args?: T, ): string { @@ -13,7 +13,7 @@ export function createWebviewCommandLink( } export interface WebviewContext { - webview: WebviewIds | WebviewViewIds; + webview: WebviewIds | WebviewViewIds | CustomEditorIds; webviewInstance: string | undefined; } diff --git a/src/views/nodes/UncommittedFilesNode.ts b/src/views/nodes/UncommittedFilesNode.ts index 6341b90055775..b6ba0176695b3 100644 --- a/src/views/nodes/UncommittedFilesNode.ts +++ b/src/views/nodes/UncommittedFilesNode.ts @@ -1,11 +1,10 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; import { GitUri } from '../../git/gitUri'; -import type { GitTrackingState } from '../../git/models/branch'; import type { GitFileWithCommit } from '../../git/models/file'; import type { GitStatus } from '../../git/models/status'; -import type { GitStatusFile } from '../../git/models/statusFile'; import { makeHierarchical } from '../../system/array'; import { flatMap, groupBy } from '../../system/iterable'; +import type { Lazy } from '../../system/lazy'; import { joinPaths, normalizePath } from '../../system/path'; import type { ViewsWithWorkingTree } from '../viewBase'; import { ContextValues, getViewNodeId, ViewNode } from './abstract/viewNode'; @@ -17,17 +16,11 @@ export class UncommittedFilesNode extends ViewNode<'uncommitted-files', ViewsWit constructor( view: ViewsWithWorkingTree, protected override readonly parent: ViewNode, - public readonly status: - | GitStatus - | { - readonly repoPath: string; - readonly files: GitStatusFile[]; - readonly state: GitTrackingState; - readonly upstream?: string; - }, + public readonly repoPath: string, + private readonly status: Lazy>, public readonly range: string | undefined, ) { - super('uncommitted-files', GitUri.fromRepoPath(status.repoPath), view, parent); + super('uncommitted-files', GitUri.fromRepoPath(repoPath), view, parent); this._uniqueId = getViewNodeId(this.type, this.context); } @@ -36,15 +29,14 @@ export class UncommittedFilesNode extends ViewNode<'uncommitted-files', ViewsWit return this._uniqueId; } - get repoPath(): string { - return this.status.repoPath; - } - - getChildren(): ViewNode[] { + async getChildren(): Promise { const repoPath = this.repoPath; + const status = await this.status.value; + if (status == null) return []; + const files: GitFileWithCommit[] = [ - ...flatMap(this.status.files, f => { + ...flatMap(status.files, f => { const commits = f.getPseudoCommits(this.view.container, undefined); return commits.map( c => diff --git a/src/views/nodes/abstract/subscribeableViewNode.ts b/src/views/nodes/abstract/subscribeableViewNode.ts index 4105e575613a9..a98cbb06846fc 100644 --- a/src/views/nodes/abstract/subscribeableViewNode.ts +++ b/src/views/nodes/abstract/subscribeableViewNode.ts @@ -5,6 +5,7 @@ import type { GitUri } from '../../../git/gitUri'; import { gate } from '../../../system/decorators/gate'; import { debug } from '../../../system/decorators/log'; import { weakEvent } from '../../../system/event'; +import { getLogScope, setLogScopeExit } from '../../../system/logger.scope'; import type { View } from '../../viewBase'; import { CacheableChildrenViewNode } from './cacheableChildrenViewNode'; import type { ViewNode } from './viewNode'; @@ -58,11 +59,35 @@ export abstract class SubscribeableViewNode< @debug() override async triggerChange(reset: boolean = false, force: boolean = false): Promise { - if (!this.loaded || this._disposed) return; + const scope = getLogScope(); + + // If the node has been disposed, nothing to do + if (this._disposed) { + setLogScopeExit(scope, ' \u2022 ignored; disposed'); + return; + } + + // If the node hasn't been loaded yet, don't trigger view refreshes now. + // If this is a reset, record it so it will be applied when the node becomes loaded/visible. + if (!this.loaded) { + if (reset) { + setLogScopeExit(scope, ' \u2022 ignored; pending reset'); + // If the view isn't visible, we'll persist the pending reset for application on visible. + // If the view is visible but the node isn't loaded, it's still safer to record the reset + // and let the normal load/visibility logic apply it rather than firing tree updates for + // a node that doesn't exist yet in the tree. + this._pendingReset = reset; + } else { + setLogScopeExit(scope, ' \u2022 ignored; not loaded'); + } + return; + } if (reset && !this.view.visible) { this._pendingReset = reset; } + + setLogScopeExit(scope, ' \u2022 refreshing view'); await super.triggerChange(reset, force); } @@ -144,8 +169,20 @@ export abstract class SubscribeableViewNode< @gate() @debug() async ensureSubscription(): Promise { - // We only need to subscribe if we are visible and if auto-refresh enabled (when supported) - if (!this.canSubscribe || !this.view.visible || (canAutoRefreshView(this.view) && !this.view.autoRefresh)) { + const scope = getLogScope(); + + // We only need to subscribe if we are visible and if auto-refresh isn't disabled + const { + canSubscribe, + view: { visible: isVisible }, + } = this; + const autoRefreshDisabled = canAutoRefreshView(this.view) && !this.view.autoRefresh; + + if (!canSubscribe || !isVisible || autoRefreshDisabled) { + setLogScopeExit( + scope, + ` \u2022 unsubscribed (subscription=${this.subscription != null}); canSubscribe=${canSubscribe}, viewVisible=${isVisible}, autoRefreshDisabled=${autoRefreshDisabled}`, + ); await this.unsubscribe(); return; @@ -154,6 +191,11 @@ export abstract class SubscribeableViewNode< // If we already have a subscription, just kick out if (this.subscription != null) return; + setLogScopeExit( + scope, + ` \u2022 subscribed; canSubscribe=${canSubscribe}, viewVisible=${isVisible}, autoRefreshDisabled=${autoRefreshDisabled}`, + ); + this.subscription = Promise.resolve(this.subscribe()); void (await this.subscription); } diff --git a/src/views/nodes/branchNode.ts b/src/views/nodes/branchNode.ts index 676662d49dc70..8a854bb3e4f9f 100644 --- a/src/views/nodes/branchNode.ts +++ b/src/views/nodes/branchNode.ts @@ -13,7 +13,7 @@ import { isStash } from '../../git/models/commit'; import type { GitLog } from '../../git/models/log'; import type { PullRequest, PullRequestState } from '../../git/models/pullRequest'; import type { GitBranchReference } from '../../git/models/reference'; -import type { Repository } from '../../git/models/repository'; +import type { Repository, RepositoryChangeEvent } from '../../git/models/repository'; import type { GitUser } from '../../git/models/user'; import type { GitWorktree } from '../../git/models/worktree'; import { getBranchAheadRange, getBranchMergeTargetName } from '../../git/utils/-webview/branch.utils'; @@ -231,7 +231,7 @@ export class BranchNode ] = await Promise.allSettled([ this.getLog(svc), svc.getBranchesAndTagsTipsLookup(branch.name), - this.options.showStatus && branch.current ? svc.status.getPausedOperationStatus?.() : undefined, + this.options.showStatus && branch.current ? svc.pausedOps?.getPausedOperationStatus?.() : undefined, !branch.remote ? getBranchAheadRange(svc, branch).then(range => range @@ -780,9 +780,7 @@ export class CommitsCurrentBranchNode extends SubscribeableViewNode<'commits-cur const interval = getLastFetchedUpdateInterval(lastFetched); if (lastFetched !== 0 && interval > 0) { return Disposable.from( - this.repo != null - ? weakEvent(this.repo.onDidChange, () => this.view.triggerNodeChange(this), this) - : emptyDisposable, + this.repo != null ? weakEvent(this.repo.onDidChange, this.onRepositoryChanged, this) : emptyDisposable, disposableInterval(() => { // Check if the interval should change, and if so, reset it if (interval !== getLastFetchedUpdateInterval(lastFetched)) { @@ -796,4 +794,9 @@ export class CommitsCurrentBranchNode extends SubscribeableViewNode<'commits-cur return undefined; } + + @debug({ args: { 0: e => e.toString() } }) + private onRepositoryChanged(_e: RepositoryChangeEvent) { + this.view.triggerNodeChange(this); + } } diff --git a/src/views/nodes/fileRevisionAsCommitNode.ts b/src/views/nodes/fileRevisionAsCommitNode.ts index 28ea941f36deb..6490187a14ccb 100644 --- a/src/views/nodes/fileRevisionAsCommitNode.ts +++ b/src/views/nodes/fileRevisionAsCommitNode.ts @@ -64,7 +64,7 @@ export class FileRevisionAsCommitNode extends ViewRefFileNode< const pausedOpStatus = await this.view.container.git .getRepositoryService(this.commit.repoPath) - .status.getPausedOperationStatus?.(); + .pausedOps?.getPausedOperationStatus?.(); if (pausedOpStatus == null) return []; return [ diff --git a/src/views/nodes/repositoryNode.ts b/src/views/nodes/repositoryNode.ts index 0b5a8989391b1..5beb6d6a80530 100644 --- a/src/views/nodes/repositoryNode.ts +++ b/src/views/nodes/repositoryNode.ts @@ -96,7 +96,7 @@ export class RepositoryNode extends SubscribeableViewNode<'repository', ViewsWit status.rebasing, ); - const pausedOpStatus = await this.repo.git.status.getPausedOperationStatus?.(); + const pausedOpStatus = await this.repo.git.pausedOps?.getPausedOperationStatus?.(); if (pausedOpStatus != null) { children.push(new PausedOperationStatusNode(this.view, this, branch, pausedOpStatus, true, status)); } else if (this.view.config.showUpstreamStatus) { diff --git a/src/views/nodes/resultsCommitsNode.ts b/src/views/nodes/resultsCommitsNode.ts index 3fe2c9108aa23..13a2e6061fb37 100644 --- a/src/views/nodes/resultsCommitsNode.ts +++ b/src/views/nodes/resultsCommitsNode.ts @@ -9,6 +9,8 @@ import type { AIGenerateChangelogChanges } from '../../plus/ai/aiProviderService import { configuration } from '../../system/-webview/configuration'; import { debug } from '../../system/decorators/log'; import { map } from '../../system/iterable'; +import { getLoggableName, Logger } from '../../system/logger'; +import { getNewLogScope } from '../../system/logger.scope'; import type { Deferred } from '../../system/promise'; import { defer, pauseOnCancelOrTimeout } from '../../system/promise'; import type { ViewsWithCommits } from '../viewBase'; @@ -182,11 +184,24 @@ export class ResultsCommitsNodeBase { + const scope = getNewLogScope(`${getLoggableName(this)}.getTreeItem`, true); try { - await this._onChildrenCompleted?.promise; + if (this._onChildrenCompleted?.promise != null) { + const timeout = new Promise(resolve => { + setTimeout(() => { + Logger.error(undefined, scope, 'onChildrenCompleted promise timed out after 30s'); + resolve(); + }, 30000); // 30 second timeout + }); + + await Promise.race([this._onChildrenCompleted.promise, timeout]); + } + void (await result.value); this.view.triggerNodeChange(this.parent); - } catch {} + } catch (ex) { + Logger.error(ex, scope, 'Failed awaiting children completion'); + } }); // Need to use Collapsed before we have results or the item won't show up in the view until the children are awaited diff --git a/src/views/nodes/worktreeNode.ts b/src/views/nodes/worktreeNode.ts index e6a88941dbdbb..9bda60c544bef 100644 --- a/src/views/nodes/worktreeNode.ts +++ b/src/views/nodes/worktreeNode.ts @@ -1,3 +1,4 @@ +import type { CancellationToken } from 'vscode'; import { MarkdownString, ThemeIcon, TreeItem, TreeItemCollapsibleState, window } from 'vscode'; import type { IconPath } from '../../@types/vscode.iconpath'; import { GlyphChars } from '../../constants'; @@ -17,6 +18,8 @@ import { getBestPath } from '../../system/-webview/path'; import { gate } from '../../system/decorators/gate'; import { debug, log } from '../../system/decorators/log'; import { map } from '../../system/iterable'; +import type { Lazy } from '../../system/lazy'; +import { lazy } from '../../system/lazy'; import { Logger } from '../../system/logger'; import type { Deferred } from '../../system/promise'; import { defer, getSettledValue, pauseOnCancelOrTimeout } from '../../system/promise'; @@ -43,6 +46,7 @@ export class WorktreeNode extends CacheableChildrenViewNode<'worktree', ViewsWit limit: number | undefined; private _branch: GitBranch | undefined; + private _lazyStatus: Lazy> | undefined; constructor( uri: GitUri, @@ -194,9 +198,12 @@ export class WorktreeNode extends CacheableChildrenViewNode<'worktree', ViewsWit children.push(new LoadMoreNode(this.view, this, children[children.length - 1])); } - const { status } = await this.getStatus(); - if (status?.hasChanges) { - children.unshift(new UncommittedFilesNode(this.view, this, status, undefined)); + const { hasChanges } = await this.hasWorkingChanges(); + if (hasChanges) { + this._lazyStatus ??= lazy(() => this.worktree.getStatus()); + children.unshift( + new UncommittedFilesNode(this.view, this, this.worktree.uri.fsPath, this._lazyStatus, undefined), + ); } this.children = children; @@ -209,28 +216,13 @@ export class WorktreeNode extends CacheableChildrenViewNode<'worktree', ViewsWit async getTreeItem(): Promise { let description = ''; let icon: IconPath | undefined; - let hasChanges = false; - const tooltip = new MarkdownString('', true); - tooltip.isTrusted = true; - - const indicators = - this.worktree.isDefault || this.worktree.opened - ? ` \u00a0(${ - this.worktree.isDefault - ? `_default${this.worktree.opened ? ', active_' : '_'}` - : this.worktree.opened - ? '_active_' - : '' - })` - : ''; - - let status: GitStatus | undefined; + let hasChanges: boolean | undefined; let missing = false; - const result = await pauseOnCancelOrTimeout(this.getStatus(), undefined, 1); + const result = await pauseOnCancelOrTimeout(this.hasWorkingChanges(), undefined, 1); if (!result.paused) { - ({ status, missing } = result.value); + ({ hasChanges, missing } = result.value); } else { queueMicrotask(() => { void result.value.then(() => { @@ -239,155 +231,70 @@ export class WorktreeNode extends CacheableChildrenViewNode<'worktree', ViewsWit }); } - const folder = `\\\n$(folder) [\`${ - this.worktree.friendlyPath - }\`](command:gitlens.views.revealWorktreeInExplorer?%22${this.worktree.uri.toString()}%22 "Reveal in Explorer")`; - const { viewAs } = this.view.config.worktrees; switch (this.worktree.type) { case 'bare': icon = new ThemeIcon('folder'); - tooltip.appendMarkdown( - `${this.worktree.isDefault ? '$(pass) ' : ''}Bare Worktree${indicators}${folder}`, - ); break; case 'branch': { const { branch } = this.worktree; this._branch = branch; - tooltip.appendMarkdown( - `${this.worktree.isDefault ? '$(pass) ' : ''}Worktree for $(git-branch) \`${ - branch?.getNameWithoutRemote() ?? branch?.name - }\`${indicators}${folder}`, - ); icon = getBranchIconPath(this.view.container, branch); - if (branch != null) { - if (!branch.remote) { - if (branch.upstream != null) { - let arrows = GlyphChars.Dash; - - const remote = await branch.getRemote(); - if (!branch.upstream.missing) { - if (remote != null) { - let left; - let right; - for (const { type } of remote.urls) { - if (type === 'fetch') { - left = true; - - if (right) break; - } else if (type === 'push') { - right = true; - - if (left) break; - } - } - - if (left && right) { - arrows = GlyphChars.ArrowsRightLeft; - } else if (right) { - arrows = GlyphChars.ArrowRight; - } else if (left) { - arrows = GlyphChars.ArrowLeft; - } + if (branch != null && !branch.remote && branch.upstream != null) { + let arrows = GlyphChars.Dash; + + const remote = await branch.getRemote(); + if (!branch.upstream.missing) { + if (remote != null) { + let left; + let right; + for (const { type } of remote.urls) { + if (type === 'fetch') { + left = true; + + if (right) break; + } else if (type === 'push') { + right = true; + + if (left) break; } - } else { - arrows = GlyphChars.Warning; } - description = `${branch.getTrackingStatus({ - empty: `${viewAs !== 'name' ? ` ${branch.getNameWithoutRemote()}` : ''}${pad( - arrows, - viewAs !== 'name' ? 2 : 0, - 2, - )}`, - suffix: `${viewAs !== 'name' ? ` ${branch.getNameWithoutRemote()}` : ''}${pad( - arrows, - 2, - 2, - )}`, - })}${branch.upstream.name}`; - - tooltip.appendMarkdown( - `\n\nBranch is ${branch.getTrackingStatus({ - empty: `${ - branch.upstream.missing ? 'missing upstream' : 'up to date with' - } \\\n $(git-branch) \`${branch.upstream.name}\`${ - remote?.provider?.name ? ` on ${remote.provider.name}` : '' - }`, - expand: true, - icons: true, - separator: ', ', - suffix: `\\\n$(git-branch) \`${branch.upstream.name}\`${ - remote?.provider?.name ? ` on ${remote.provider.name}` : '' - }`, - })}`, - ); - } else { - const providerName = getHighlanderProviderName( - await this.view.container.git - .getRepositoryService(branch.repoPath) - .remotes.getRemotesWithProviders(), - ); - - tooltip.appendMarkdown( - `\n\nLocal branch, hasn't been published to ${providerName ?? 'a remote'}`, - ); + if (left && right) { + arrows = GlyphChars.ArrowsRightLeft; + } else if (right) { + arrows = GlyphChars.ArrowRight; + } else if (left) { + arrows = GlyphChars.ArrowLeft; + } } + } else { + arrows = GlyphChars.Warning; } - } - if (status != null) { - hasChanges = status.hasChanges; - tooltip.appendMarkdown( - `\n\n${status.getFormattedDiffStatus({ - prefix: 'Has Uncommitted Changes\\\n', - empty: 'No Uncommitted Changes', - expand: true, - })}`, - ); + description = `${branch.getTrackingStatus({ + empty: `${viewAs !== 'name' ? ` ${branch.getNameWithoutRemote()}` : ''}${pad( + arrows, + viewAs !== 'name' ? 2 : 0, + 2, + )}`, + suffix: `${viewAs !== 'name' ? ` ${branch.getNameWithoutRemote()}` : ''}${pad(arrows, 2, 2)}`, + })}${branch.upstream.name}`; } break; } case 'detached': { icon = new ThemeIcon('git-commit'); - tooltip.appendMarkdown( - `${this.worktree.isDefault ? '$(pass) ' : ''}Detached Worktree at $(git-commit) ${shortenRevision( - this.worktree.sha, - )}${indicators}${folder}`, - ); - - if (status != null) { - hasChanges = status.hasChanges; - tooltip.appendMarkdown( - `\n\n${status.getFormattedDiffStatus({ - prefix: 'Has Uncommitted Changes', - empty: 'No Uncommitted Changes', - expand: true, - })}`, - ); - } - break; } } const pendingPullRequest = this.getState('pendingPullRequest'); - if (pendingPullRequest != null) { - tooltip.appendMarkdown(`\n\n$(loading~spin) Loading associated pull request${GlyphChars.Ellipsis}`); - } - - if (missing) { - tooltip.appendMarkdown(`\n\n${GlyphChars.Warning} Unable to locate worktree path`); - } - - if (this.worktree.branch?.starred) { - tooltip.appendMarkdown('\n\n$(star-full) Favorited'); - } let label: string; switch (viewAs) { @@ -421,7 +328,7 @@ export class WorktreeNode extends CacheableChildrenViewNode<'worktree', ViewsWit : this.worktree.opened ? new ThemeIcon('check') : icon; - item.tooltip = tooltip; + // Tooltip will be set lazily in resolveTreeItem item.resourceUri = createViewDecorationUri('worktree', { hasChanges: hasChanges, missing: missing, @@ -431,6 +338,124 @@ export class WorktreeNode extends CacheableChildrenViewNode<'worktree', ViewsWit return item; } + override async resolveTreeItem(item: TreeItem, _token: CancellationToken): Promise { + if (item.tooltip != null) return item; + + const tooltip = new MarkdownString('', true); + tooltip.isTrusted = true; + + const indicators = + this.worktree.isDefault || this.worktree.opened + ? ` \u00a0(${ + this.worktree.isDefault + ? `_default${this.worktree.opened ? ', active_' : '_'}` + : this.worktree.opened + ? '_active_' + : '' + })` + : ''; + + const folder = `\\\n$(folder) [\`${ + this.worktree.friendlyPath + }\`](command:gitlens.views.revealWorktreeInExplorer?%22${this.worktree.uri.toString()}%22 "Reveal in Explorer")`; + + switch (this.worktree.type) { + case 'bare': + tooltip.appendMarkdown( + `${this.worktree.isDefault ? '$(pass) ' : ''}Bare Worktree${indicators}${folder}`, + ); + break; + + case 'branch': { + const { branch } = this.worktree; + tooltip.appendMarkdown( + `${this.worktree.isDefault ? '$(pass) ' : ''}Worktree for $(git-branch) \`${ + branch?.getNameWithoutRemote() ?? branch?.name + }\`${indicators}${folder}`, + ); + + if (branch != null && !branch.remote) { + if (branch.upstream != null) { + const remote = await branch.getRemote(); + tooltip.appendMarkdown( + `\n\nBranch is ${branch.getTrackingStatus({ + empty: `${ + branch.upstream.missing ? 'missing upstream' : 'up to date with' + } \\\n $(git-branch) \`${branch.upstream.name}\`${ + remote?.provider?.name ? ` on ${remote.provider.name}` : '' + }`, + expand: true, + icons: true, + separator: ', ', + suffix: `\\\n$(git-branch) \`${branch.upstream.name}\`${ + remote?.provider?.name ? ` on ${remote.provider.name}` : '' + }`, + })}`, + ); + } else { + const providerName = getHighlanderProviderName( + await this.view.container.git + .getRepositoryService(branch.repoPath) + .remotes.getRemotesWithProviders(), + ); + tooltip.appendMarkdown( + `\n\nLocal branch, hasn't been published to ${providerName ?? 'a remote'}`, + ); + } + } + + break; + } + + case 'detached': + tooltip.appendMarkdown( + `${this.worktree.isDefault ? '$(pass) ' : ''}Detached Worktree at $(git-commit) ${shortenRevision( + this.worktree.sha, + )}${indicators}${folder}`, + ); + + break; + } + + switch (this.worktree.type) { + case 'branch': + case 'detached': { + this._lazyStatus ??= lazy(() => this.worktree.getStatus()); + const status = await this._lazyStatus.value; + const stats = status?.getFormattedDiffStatus({ + prefix: 'Has Uncommitted Changes\\\n', + empty: 'No Uncommitted Changes', + expand: true, + }); + if (stats != null) { + tooltip.appendMarkdown(`\n\n${stats}`); + } + + break; + } + } + + // Add pending pull request indicator + const pendingPullRequest = this.getState('pendingPullRequest'); + if (pendingPullRequest != null) { + tooltip.appendMarkdown(`\n\n$(loading~spin) Loading associated pull request${GlyphChars.Ellipsis}`); + } + + // Add missing worktree warning + const { missing } = await this.hasWorkingChanges(); + if (missing) { + tooltip.appendMarkdown(`\n\n${GlyphChars.Warning} Unable to locate worktree path`); + } + + // Add favorited indicator + if (this.worktree.branch?.starred) { + tooltip.appendMarkdown('\n\n$(star-full) Favorited'); + } + + item.tooltip = tooltip; + return item; + } + @debug() override refresh(reset?: boolean): void | { cancel: boolean } | Promise { if (reset) { @@ -492,19 +517,19 @@ export class WorktreeNode extends CacheableChildrenViewNode<'worktree', ViewsWit return this._log; } - private _status: { status: GitStatus | undefined; missing: boolean } | undefined; - private async getStatus() { - if (this._status == null) { + private _hasWorkingChanges: { hasChanges: boolean | undefined; missing: boolean } | undefined; + private async hasWorkingChanges() { + if (this._hasWorkingChanges == null) { try { - const status = await this.worktree.getStatus(); - this._status = { status: status, missing: false }; + const hasChanges = await this.worktree.hasWorkingChanges(); + this._hasWorkingChanges = { hasChanges: hasChanges, missing: false }; } catch (ex) { - Logger.error(ex, `Worktree status failed: ${this.worktree.uri.toString(true)}`); - this._status = { status: undefined, missing: true }; + Logger.error(ex, `Worktree hasWorkingChanges failed: ${this.worktree.uri.toString(true)}`); + this._hasWorkingChanges = { hasChanges: undefined, missing: true }; } } - return this._status; + return this._hasWorkingChanges; } get hasMore(): boolean { diff --git a/src/views/viewCommands.ts b/src/views/viewCommands.ts index f67a4841faf0f..cd9f7dfff1627 100644 --- a/src/views/viewCommands.ts +++ b/src/views/viewCommands.ts @@ -51,7 +51,7 @@ import { registerCommand, } from '../system/-webview/command'; import { configuration } from '../system/-webview/configuration'; -import { setContext } from '../system/-webview/context'; +import { getContext, setContext } from '../system/-webview/context'; import { revealInFileExplorer } from '../system/-webview/vscode'; import type { MergeEditorInputs } from '../system/-webview/vscode/editors'; import { editorLineToDiffRange, openMergeEditor } from '../system/-webview/vscode/editors'; @@ -111,8 +111,8 @@ import type { WorktreeNode } from './nodes/worktreeNode'; import type { WorktreesNode } from './nodes/worktreesNode'; const { command, getCommands } = createCommandDecorator< - (...args: any[]) => unknown, GlCommands, + (...args: any[]) => unknown, { multiselect?: boolean | 'sequential'; args?: (...args: unknown[]) => unknown[]; @@ -1318,36 +1318,31 @@ export class ViewCommands implements Disposable { @command('gitlens.views.compareFileWithSelected') @log() private compareFileWithSelected(node: ViewRefFileNode) { - if (this._selectedFile == null || !(node instanceof ViewRefFileNode) || node.ref == null) { + const selectedFile = getContext('gitlens:views:canCompare:file'); + if (selectedFile == null || !(node instanceof ViewRefFileNode) || node.ref == null) { return Promise.resolve(); } - if (this._selectedFile.repoPath !== node.repoPath) { + void setContext('gitlens:views:canCompare:file', undefined); + + if (selectedFile.repoPath !== node.repoPath) { this.selectFileForCompare(node); return Promise.resolve(); } - const selected = this._selectedFile; - - this._selectedFile = undefined; - void setContext('gitlens:views:canCompare:file', false); - - return this.compareFileWith(selected.repoPath!, selected.uri!, selected.ref, node.uri, node.ref.ref); + return this.compareFileWith(selectedFile.repoPath, selectedFile.uri, selectedFile.ref, node.uri, node.ref.ref); } - private _selectedFile: CompareSelectedInfo | undefined; - @command('gitlens.views.selectFileForCompare') @log() private selectFileForCompare(node: ViewRefFileNode) { if (!(node instanceof ViewRefFileNode) || node.ref == null) return; - this._selectedFile = { + void setContext('gitlens:views:canCompare:file', { ref: node.ref.ref, repoPath: node.repoPath, uri: node.uri, - }; - void setContext('gitlens:views:canCompare:file', true); + }); } @command('gitlens.views.openChangedFileDiffs', { args: (n, o) => [n, o] }) @@ -1830,12 +1825,6 @@ export class ViewCommands implements Disposable { } } -interface CompareSelectedInfo { - ref: string; - repoPath: string | undefined; - uri?: Uri; -} - export function registerViewCommand( command: GlCommands, callback: (...args: any[]) => unknown, diff --git a/src/webviews/apps/commitDetails/commitDetails.ts b/src/webviews/apps/commitDetails/commitDetails.ts index 68631efdf7969..5b68717fe5cb1 100644 --- a/src/webviews/apps/commitDetails/commitDetails.ts +++ b/src/webviews/apps/commitDetails/commitDetails.ts @@ -3,7 +3,7 @@ import { customElement, state } from 'lit/decorators.js'; import { when } from 'lit/directives/when.js'; import type { ViewFilesLayout } from '../../../config'; import type { GlCommands } from '../../../constants.commands'; -import type { Serialized } from '../../../system/serialize'; +import type { IpcSerialized } from '../../../system/ipcSerialize'; import { pluralize } from '../../../system/string'; import type { DraftState, ExecuteCommitActionsParams, Mode, State } from '../../commitDetails/protocol'; import { @@ -40,6 +40,7 @@ import type { CreatePatchMetadataEventDetail } from '../plus/patchDetails/compon import { GlAppHost } from '../shared/appHost'; import type { IssuePullRequest } from '../shared/components/rich/issue-pull-request'; import type { WebviewPane, WebviewPaneExpandedChangeEventDetail } from '../shared/components/webview-pane'; +import type { LoggerContext } from '../shared/contexts/logger'; import { DOM } from '../shared/dom'; import type { HostIpc } from '../shared/ipc'; import type { GlCommitDetails } from './components/gl-commit-details'; @@ -67,17 +68,17 @@ interface ExplainState { } @customElement('gl-commit-details-app') -export class GlCommitDetailsApp extends GlAppHost> { +export class GlCommitDetailsApp extends GlAppHost> { protected override createRenderRoot(): HTMLElement { return this; } - protected override createStateProvider(state: Serialized, ipc: HostIpc): CommitDetailsStateProvider { - return new CommitDetailsStateProvider(this, state, ipc); - } - - protected override onPersistState(state: Serialized): void { - this._ipc.setPersistedState({ mode: state.mode, pinned: state.pinned, preferences: state.preferences }); + protected override createStateProvider( + bootstrap: string, + ipc: HostIpc, + logger: LoggerContext, + ): CommitDetailsStateProvider { + return new CommitDetailsStateProvider(this, bootstrap, ipc, logger); } @state() diff --git a/src/webviews/apps/commitDetails/components/gl-commit-details.ts b/src/webviews/apps/commitDetails/components/gl-commit-details.ts index 387321d381947..611b4b28acba8 100644 --- a/src/webviews/apps/commitDetails/components/gl-commit-details.ts +++ b/src/webviews/apps/commitDetails/components/gl-commit-details.ts @@ -7,8 +7,9 @@ import type { ConnectCloudIntegrationsCommandArgs } from '../../../../commands/c import type { IssueOrPullRequest } from '../../../../git/models/issueOrPullRequest'; import type { PullRequestShape } from '../../../../git/models/pullRequest'; import { createCommandLink } from '../../../../system/commands'; -import type { Serialized } from '../../../../system/serialize'; -import type { State } from '../../../commitDetails/protocol'; +import type { IpcSerialized } from '../../../../system/ipcSerialize'; +import { serializeWebviewItemContext } from '../../../../system/webview'; +import type { State as _State, DetailsItemContext, DetailsItemTypedContext } from '../../../commitDetails/protocol'; import { messageHeadlineSplitterToken } from '../../../commitDetails/protocol'; import type { TreeItemAction, TreeItemBase } from '../../shared/components/tree/base'; import { uncommittedSha } from '../commitDetails'; @@ -25,6 +26,7 @@ import '../../shared/components/markdown/markdown'; import '../../shared/components/panes/pane-group'; import '../../shared/components/rich/issue-pull-request'; +type State = IpcSerialized<_State>; interface ExplainState { cancelled?: boolean; error?: { message: string }; @@ -36,7 +38,7 @@ export class GlCommitDetails extends GlDetailsBase { override readonly tab = 'commit'; @property({ type: Object }) - state?: Serialized; + state?: State; @state() get isStash(): boolean { @@ -54,6 +56,35 @@ export class GlCommitDetails extends GlDetailsBase { @property({ type: Object }) explain?: ExplainState; + private _commit: State['commit']; + get commit(): State['commit'] { + return this._commit; + } + set commit(value: State['commit']) { + this._commit = value; + this.enrichedPromise = value?.enriched; + } + + @state() + private _enriched!: Awaited['enriched']>; + get enriched(): Awaited['enriched']> { + return this._enriched; + } + + private _enrichedPromise!: NonNullable['enriched']; + get enrichedPromise(): NonNullable['enriched'] { + return this._enrichedPromise; + } + set enrichedPromise(value: NonNullable['enriched']) { + if (this._enrichedPromise === value) return; + + this._enrichedPromise = value; + void this._enrichedPromise?.then( + r => (this._enriched = r), + () => (this._enriched = undefined), + ); + } + get navigation() { if (this.state?.navigationStack == null) { return { @@ -86,6 +117,10 @@ export class GlCommitDetails extends GlDetailsBase { this.explainBusy = false; this.querySelector('[data-region="commit-explanation"]')?.scrollIntoView(); } + + if (changedProperties.has('state')) { + this.commit = this.state?.commit; + } } private renderEmptyContent() { @@ -145,7 +180,8 @@ export class GlCommitDetails extends GlDetailsBase { const details = this.state?.commit; if (details == null) return undefined; - const message = details.message; + // Use formatted message from promise if available, otherwise use basic message + const message = this._enriched?.formattedMessage ?? details.message; const index = message.indexOf(messageHeadlineSplitterToken); return html`
@@ -185,7 +221,7 @@ export class GlCommitDetails extends GlDetailsBase { !this.isStash, () => html` } - | { type: 'issue'; value: Serialized } - | { type: 'pr'; value: Serialized } + | { type: 'autolink'; value: Autolink } + | { type: 'issue'; value: IssueOrPullRequest } + | { type: 'pr'; value: PullRequestShape } >(); const autolinkIdsByUrl = new Map(); @@ -217,8 +253,10 @@ export class GlCommitDetails extends GlDetailsBase { } } - if (this.state?.autolinkedIssues != null) { - for (const issue of this.state.autolinkedIssues) { + // Use resolved enriched autolinks from promise + const enrichedAutolinks = this._enriched?.autolinkedIssues ?? this.state?.autolinkedIssues; + if (enrichedAutolinks != null) { + for (const issue of enrichedAutolinks) { if (issue.url != null) { const autoLinkId = autolinkIdsByUrl.get(issue.url); if (autoLinkId != null) { @@ -229,19 +267,21 @@ export class GlCommitDetails extends GlDetailsBase { } } - if (this.state?.pullRequest != null) { - if (this.state.pullRequest.url != null) { - const autoLinkId = autolinkIdsByUrl.get(this.state.pullRequest.url); + // Use resolved pull request from promise + const pullRequest = this._enriched?.associatedPullRequest ?? this.state?.pullRequest; + if (pullRequest != null) { + if (pullRequest.url != null) { + const autoLinkId = autolinkIdsByUrl.get(pullRequest.url); if (autoLinkId != null) { deduped.delete(autoLinkId); } } - deduped.set(this.state.pullRequest.id, { type: 'pr', value: this.state.pullRequest }); + deduped.set(pullRequest.id, { type: 'pr', value: pullRequest }); } - const autolinks: Serialized[] = []; - const issues: Serialized[] = []; - const prs: Serialized[] = []; + const autolinks: Autolink[] = []; + const issues: IssueOrPullRequest[] = []; + const prs: PullRequestShape[] = []; for (const item of deduped.values()) { switch (item.type) { @@ -427,11 +467,36 @@ export class GlCommitDetails extends GlDetailsBase { action: 'file-open-on-remote', }); } - actions.push({ - icon: 'ellipsis', - label: 'Show more actions', - action: 'file-more-actions', - }); return actions; } + + override getFileContextData(file: File): string | undefined { + if (!this.state?.commit) return undefined; + + // Build webviewItem with modifiers matching view context values + // Pattern: gitlens:file+committed[+current][+HEAD][+unpublished] + const commit = this.state.commit; + const isStash = commit.stashNumber != null; + + let webviewItem: DetailsItemContext['webviewItem']; + if (isStash) { + webviewItem = 'gitlens:file+stashed'; + } else { + webviewItem = 'gitlens:file+committed'; + } + + const context: DetailsItemTypedContext = { + webviewItem: webviewItem, + webviewItemValue: { + type: 'file', + path: file.path, + repoPath: commit.repoPath, + sha: commit.sha, + stashNumber: commit.stashNumber, + status: file.status, + }, + }; + + return serializeWebviewItemContext(context); + } } diff --git a/src/webviews/apps/commitDetails/components/gl-details-base.ts b/src/webviews/apps/commitDetails/components/gl-details-base.ts index f4a2b9aa30294..bd1b2eba28815 100644 --- a/src/webviews/apps/commitDetails/components/gl-details-base.ts +++ b/src/webviews/apps/commitDetails/components/gl-details-base.ts @@ -152,13 +152,13 @@ export class GlDetailsBase extends LitElement { } } - if (staged.length === 0 && unstaged.length === 0) { + if (!staged.length && !unstaged.length) { children.push(...this.createFileTreeModel(mode, files, isTree, compact)); } else { if (staged.length) { children.push({ label: 'Staged Changes', - path: '', + path: '/:staged:/', level: 1, // isMulti ? 2 : 1, branch: true, checkable: false, @@ -174,7 +174,7 @@ export class GlDetailsBase extends LitElement { if (unstaged.length) { children.push({ label: 'Unstaged Changes', - path: '', + path: '/:unstaged:/', level: 1, // isMulti ? 2 : 1, branch: true, checkable: false, @@ -314,6 +314,11 @@ export class GlDetailsBase extends LitElement { return []; } + protected getFileContextData(_file: File): string | undefined { + // To be overridden by subclasses + return undefined; + } + protected fileToTreeModel( file: File, options?: Partial, @@ -336,6 +341,7 @@ export class GlDetailsBase extends LitElement { description: `${flat === true ? filePath : ''}${file.status === 'R' ? ` ← ${file.originalPath}` : ''}`, context: [file], actions: this.getFileActions(file, options), + contextData: this.getFileContextData(file), // decorations: [{ type: 'text', label: file.status }], ...options, }; diff --git a/src/webviews/apps/commitDetails/components/gl-wip-details.ts b/src/webviews/apps/commitDetails/components/gl-wip-details.ts index 0e28e0c1a8017..eeace883acb73 100644 --- a/src/webviews/apps/commitDetails/components/gl-wip-details.ts +++ b/src/webviews/apps/commitDetails/components/gl-wip-details.ts @@ -7,7 +7,8 @@ import { when } from 'lit/directives/when.js'; import { uncommitted } from '../../../../git/models/revision'; import { createCommandLink } from '../../../../system/commands'; import { equalsIgnoreCase } from '../../../../system/string'; -import type { DraftState, Wip } from '../../../commitDetails/protocol'; +import { serializeWebviewItemContext } from '../../../../system/webview'; +import type { DetailsItemTypedContext, DraftState, Wip } from '../../../commitDetails/protocol'; import type { ComposerCommandArgs } from '../../../plus/composer/registration'; import type { Change } from '../../../plus/patchDetails/protocol'; import type { TreeItemAction, TreeItemBase } from '../../shared/components/tree/base'; @@ -418,6 +419,24 @@ export class GlWipDetails extends GlDetailsBase { return [openFile, { icon: 'plus', label: 'Stage changes', action: 'file-stage' }]; } + override getFileContextData(file: File): string | undefined { + if (!this.wip?.repo?.path) return undefined; + + const context: DetailsItemTypedContext = { + webviewItem: file.staged ? 'gitlens:file+staged' : 'gitlens:file+unstaged', + webviewItemValue: { + type: 'file', + path: file.path, + repoPath: this.wip.repo.path, + sha: uncommitted, + staged: file.staged, + status: file.status, + }, + }; + + return serializeWebviewItemContext(context); + } + private onDataActionClick(name: string) { void this.dispatchEvent(new CustomEvent('data-action', { detail: { name: name } })); } diff --git a/src/webviews/apps/commitDetails/context.ts b/src/webviews/apps/commitDetails/context.ts index d96e0238a3946..45b7c04cbf400 100644 --- a/src/webviews/apps/commitDetails/context.ts +++ b/src/webviews/apps/commitDetails/context.ts @@ -1,5 +1,5 @@ import { createContext } from '@lit/context'; -import type { Serialized } from '../../../system/serialize'; +import type { IpcSerialized } from '../../../system/ipcSerialize'; import type { State } from '../../commitDetails/protocol'; -export const stateContext = createContext>('state'); +export const stateContext = createContext>('state'); diff --git a/src/webviews/apps/commitDetails/stateProvider.ts b/src/webviews/apps/commitDetails/stateProvider.ts index a89599b3e1554..f1ddbe4767308 100644 --- a/src/webviews/apps/commitDetails/stateProvider.ts +++ b/src/webviews/apps/commitDetails/stateProvider.ts @@ -1,6 +1,6 @@ import { ContextProvider } from '@lit/context'; -import type { Serialized } from '../../../system/serialize'; -import type { State, UpdateablePreferences } from '../../commitDetails/protocol'; +import type { IpcSerialized } from '../../../system/ipcSerialize'; +import type { State as _State, UpdateablePreferences } from '../../commitDetails/protocol'; import { ChangeReviewModeCommand, DidChangeDraftStateNotification, @@ -11,93 +11,52 @@ import { SwitchModeCommand, UpdatePreferencesCommand, } from '../../commitDetails/protocol'; -import type { ReactiveElementHost, StateProvider } from '../shared/appHost'; -import type { Disposable } from '../shared/events'; -import type { HostIpc } from '../shared/ipc'; -import { assertsSerialized } from '../shared/ipc'; +import type { IpcMessage } from '../../protocol'; +import type { ReactiveElementHost } from '../shared/appHost'; +import { StateProviderBase } from '../shared/stateProviderBase'; import { stateContext } from './context'; -export class CommitDetailsStateProvider implements StateProvider> { - private readonly disposable: Disposable; - private readonly provider: ContextProvider<{ __context__: Serialized }, ReactiveElementHost>; +type State = IpcSerialized<_State>; - private _state: Serialized; - get state(): Serialized { - return this._state; +export class CommitDetailsStateProvider extends StateProviderBase { + protected override get deferBootstrap(): boolean { + return true; } - private _host: ReactiveElementHost; - - constructor( - host: ReactiveElementHost, - state: Serialized, - private readonly _ipc: HostIpc, - ) { - this._host = host; - this._state = state; - this.provider = new ContextProvider(host, { context: stateContext, initialValue: state }); - - this.disposable = this._ipc.onReceiveMessage(msg => { - switch (true) { - // case DidChangeRichStateNotificationType.method: - // onIpc(DidChangeRichStateNotificationType, msg, params => { - // if (this._state.selected == null) return; - - // assertsSerialized(params); - - // const newState = { ...this._state }; - // if (params.formattedMessage != null) { - // newState.selected!.message = params.formattedMessage; - // } - // // if (params.pullRequest != null) { - // newState.pullRequest = params.pullRequest; - // // } - // // if (params.formattedMessage != null) { - // newState.autolinkedIssues = params.autolinkedIssues; - // // } - - // this._state = newState; - // this.provider.setValue(this._state, true); - - // this.renderRichContent(); - // }); - // break; - - case DidChangeNotification.is(msg): - assertsSerialized(msg.params.state); - - this._state = { ...msg.params.state, timestamp: Date.now() }; - this.provider.setValue(this._state, true); - host.requestUpdate(); - break; - - case DidChangeWipStateNotification.is(msg): - this._state = { ...this._state, wip: msg.params.wip, inReview: msg.params.inReview }; - this.provider.setValue(this._state, true); - host.requestUpdate(); - break; - - case DidChangeDraftStateNotification.is(msg): - this.onDraftStateChanged(host, msg.params.inReview, true); - break; - - case DidChangeHasAccountNotification.is(msg): - this._state = { ...this._state, hasAccount: msg.params.hasAccount }; - this.provider.setValue(this._state, true); - host.requestUpdate(); - break; - - case DidChangeIntegrationsNotification.is(msg): - this._state = { ...this._state, hasIntegrationsConnected: msg.params.hasIntegrationsConnected }; - this.provider.setValue(this._state, true); - host.requestUpdate(); - break; - } - }); + protected override createContextProvider(state: State): ContextProvider { + return new ContextProvider(this.host, { context: stateContext, initialValue: state }); } - dispose(): void { - this.disposable.dispose(); + protected override onMessageReceived(msg: IpcMessage): void { + switch (true) { + case DidChangeNotification.is(msg): + this._state = { ...(msg.params.state as State), timestamp: Date.now() }; + this.provider.setValue(this._state, true); + this.host.requestUpdate(); + break; + + case DidChangeWipStateNotification.is(msg): + this._state = { ...this._state, wip: msg.params.wip, inReview: msg.params.inReview }; + this.provider.setValue(this._state, true); + this.host.requestUpdate(); + break; + + case DidChangeDraftStateNotification.is(msg): + this.onDraftStateChanged(this.host, msg.params.inReview, true); + break; + + case DidChangeHasAccountNotification.is(msg): + this._state = { ...this._state, hasAccount: msg.params.hasAccount }; + this.provider.setValue(this._state, true); + this.host.requestUpdate(); + break; + + case DidChangeIntegrationsNotification.is(msg): + this._state = { ...this._state, hasIntegrationsConnected: msg.params.hasIntegrationsConnected }; + this.provider.setValue(this._state, true); + this.host.requestUpdate(); + break; + } } private onDraftStateChanged(host: ReactiveElementHost, inReview: boolean, silent = false) { @@ -106,23 +65,23 @@ export class CommitDetailsStateProvider implements StateProvider { private badgeSource = { source: 'home', detail: 'badge' }; - protected override createStateProvider(state: State, ipc: HostIpc): HomeStateProvider { + protected override createStateProvider(bootstrap: string, ipc: HostIpc, logger: LoggerContext): HomeStateProvider { this.disposables.push((this._activeOverviewState = new ActiveOverviewState(ipc))); this.disposables.push((this._inactiveOverviewState = new InactiveOverviewState(ipc))); - return new HomeStateProvider(this, state, ipc); + return new HomeStateProvider(this, bootstrap, ipc, logger); } override connectedCallback(): void { diff --git a/src/webviews/apps/home/stateProvider.ts b/src/webviews/apps/home/stateProvider.ts index 75a96ddef68d1..aede1b40c19c9 100644 --- a/src/webviews/apps/home/stateProvider.ts +++ b/src/webviews/apps/home/stateProvider.ts @@ -11,104 +11,87 @@ import { DidChangeWalkthroughProgress, DidCompleteDiscoveringRepositories, } from '../../home/protocol'; -import type { ReactiveElementHost, StateProvider } from '../shared/appHost'; -import type { Disposable } from '../shared/events'; -import type { HostIpc } from '../shared/ipc'; +import type { IpcMessage } from '../../protocol'; +import type { ReactiveElementHost } from '../shared/appHost'; +import { StateProviderBase } from '../shared/stateProviderBase'; import { stateContext } from './context'; -export class HomeStateProvider implements StateProvider { - private readonly disposable: Disposable; - private readonly provider: ContextProvider<{ __context__: State }, ReactiveElementHost>; - - private readonly _state: State; - get state(): State { - return this._state; - } - - constructor( - host: ReactiveElementHost, - state: State, - private readonly _ipc: HostIpc, - ) { - this._state = state; - this.provider = new ContextProvider(host, { context: stateContext, initialValue: state }); - - this.disposable = this._ipc.onReceiveMessage(msg => { - switch (true) { - case DidChangeRepositories.is(msg): - this._state.repositories = msg.params; - this._state.timestamp = Date.now(); - - this.provider.setValue(this._state, true); - break; - case DidCompleteDiscoveringRepositories.is(msg): - this._state.repositories = msg.params.repositories; - this._state.discovering = msg.params.discovering; - this._state.timestamp = Date.now(); - - this.provider.setValue(this._state, true); - break; - case DidChangeWalkthroughProgress.is(msg): - this._state.walkthroughProgress = msg.params; - this._state.timestamp = Date.now(); - - this.provider.setValue(this._state, true); - break; - case DidChangeSubscription.is(msg): - this._state.subscription = msg.params.subscription; - this._state.avatar = msg.params.avatar; - this._state.organizationsCount = msg.params.organizationsCount; - this._state.timestamp = Date.now(); - - this.provider.setValue(this._state, true); - break; - case DidChangeOrgSettings.is(msg): - this._state.orgSettings = msg.params.orgSettings; - this._state.timestamp = Date.now(); - - this.provider.setValue(this._state, true); - break; - - case DidChangeIntegrationsConnections.is(msg): - this._state.hasAnyIntegrationConnected = msg.params.hasAnyIntegrationConnected; - this._state.integrations = msg.params.integrations; - this._state.ai = msg.params.ai; - this._state.timestamp = Date.now(); - - this.provider.setValue(this._state, true); - break; - - case DidChangePreviewEnabled.is(msg): - this._state.previewEnabled = msg.params.previewEnabled; - this._state.previewCollapsed = msg.params.previewCollapsed; - this._state.aiEnabled = msg.params.aiEnabled; - this._state.experimentalComposerEnabled = msg.params.experimentalComposerEnabled; - this._state.timestamp = Date.now(); - - this.provider.setValue(this._state, true); - host.requestUpdate(); - break; - - case DidChangeAiAllAccessBanner.is(msg): - this._state.aiAllAccessBannerCollapsed = msg.params; - this._state.timestamp = Date.now(); - - this.provider.setValue(this._state, true); - host.requestUpdate(); - break; - case DidChangeMcpBanner.is(msg): - this._state.mcpBannerCollapsed = msg.params.mcpBannerCollapsed; - this._state.mcpCanAutoRegister = msg.params.mcpCanAutoRegister; - this._state.timestamp = Date.now(); - - this.provider.setValue(this._state, true); - host.requestUpdate(); - break; - } - }); +export class HomeStateProvider extends StateProviderBase { + protected override createContextProvider(state: State): ContextProvider { + return new ContextProvider(this.host, { context: stateContext, initialValue: state }); } - dispose(): void { - this.disposable.dispose(); + protected override onMessageReceived(msg: IpcMessage): void { + switch (true) { + case DidChangeRepositories.is(msg): + this._state.repositories = msg.params; + this._state.timestamp = Date.now(); + + this.provider.setValue(this._state, true); + break; + case DidCompleteDiscoveringRepositories.is(msg): + this._state.repositories = msg.params.repositories; + this._state.discovering = msg.params.discovering; + this._state.timestamp = Date.now(); + + this.provider.setValue(this._state, true); + break; + case DidChangeWalkthroughProgress.is(msg): + this._state.walkthroughProgress = msg.params; + this._state.timestamp = Date.now(); + + this.provider.setValue(this._state, true); + break; + case DidChangeSubscription.is(msg): + this._state.subscription = msg.params.subscription; + this._state.avatar = msg.params.avatar; + this._state.organizationsCount = msg.params.organizationsCount; + this._state.timestamp = Date.now(); + + this.provider.setValue(this._state, true); + break; + case DidChangeOrgSettings.is(msg): + this._state.orgSettings = msg.params.orgSettings; + this._state.timestamp = Date.now(); + + this.provider.setValue(this._state, true); + break; + + case DidChangeIntegrationsConnections.is(msg): + this._state.hasAnyIntegrationConnected = msg.params.hasAnyIntegrationConnected; + this._state.integrations = msg.params.integrations; + this._state.ai = msg.params.ai; + this._state.timestamp = Date.now(); + + this.provider.setValue(this._state, true); + break; + + case DidChangePreviewEnabled.is(msg): + this._state.previewEnabled = msg.params.previewEnabled; + this._state.previewCollapsed = msg.params.previewCollapsed; + this._state.aiEnabled = msg.params.aiEnabled; + this._state.experimentalComposerEnabled = msg.params.experimentalComposerEnabled; + this._state.timestamp = Date.now(); + + this.provider.setValue(this._state, true); + this.host.requestUpdate(); + break; + + case DidChangeAiAllAccessBanner.is(msg): + this._state.aiAllAccessBannerCollapsed = msg.params; + this._state.timestamp = Date.now(); + + this.provider.setValue(this._state, true); + this.host.requestUpdate(); + break; + case DidChangeMcpBanner.is(msg): + this._state.mcpBannerCollapsed = msg.params.mcpBannerCollapsed; + this._state.mcpCanAutoRegister = msg.params.mcpCanAutoRegister; + this._state.timestamp = Date.now(); + + this.provider.setValue(this._state, true); + this.host.requestUpdate(); + break; + } } } diff --git a/src/webviews/apps/plus/composer/components/app.ts b/src/webviews/apps/plus/composer/components/app.ts index 26dd71ed431f8..cb1bf236f650b 100644 --- a/src/webviews/apps/plus/composer/components/app.ts +++ b/src/webviews/apps/plus/composer/components/app.ts @@ -27,7 +27,7 @@ import { OpenOnboardingCommand, ReloadComposerCommand, } from '../../../../plus/composer/protocol'; -import { createCombinedDiffForCommit, updateHunkAssignments } from '../../../../plus/composer/utils'; +import { updateHunkAssignments } from '../../../../plus/composer/utils/composer.utils'; import type { RepoButtonGroupClickEvent } from '../../../shared/components/repo-button-group'; import { focusableBaseStyles } from '../../../shared/components/styles/lit/a11y.css'; import { boxSizingBase } from '../../../shared/components/styles/lit/base.css'; @@ -402,7 +402,6 @@ export class ComposerApp extends LitElement { @state() private onboardingStepNumber: number = 0; - private commitsSortable?: Sortable; private hunksSortable?: Sortable; private isDragging = false; private lastMouseEvent?: MouseEvent; @@ -460,7 +459,6 @@ export class ComposerApp extends LitElement { override disconnectedCallback() { super.disconnectedCallback?.(); - this.commitsSortable?.destroy(); this.hunksSortable?.destroy(); if (this.commitMessageDebounceTimer) { clearTimeout(this.commitMessageDebounceTimer); @@ -470,33 +468,6 @@ export class ComposerApp extends LitElement { } private initializeSortable() { - // Initialize commits sortable - const commitsContainer = this.shadowRoot?.querySelector('.commits-list'); - if (commitsContainer) { - this.commitsSortable = Sortable.create(commitsContainer as HTMLElement, { - animation: 150, - ghostClass: 'sortable-ghost', - chosenClass: 'sortable-chosen', - dragClass: 'sortable-drag', - handle: '.drag-handle', // Only allow dragging by the handle - filter: '.new-commit-drop-zone', - onMove: evt => { - // Only allow moving within the commits list, not into drop zones - const target = evt.related; - return ( - target.tagName.toLowerCase() === 'gl-commit-item' && - !target.closest('.drop-zone') && - !target.closest('.new-commit-drop-zone') - ); - }, - onEnd: evt => { - if (evt.oldIndex !== undefined && evt.newIndex !== undefined && evt.oldIndex !== evt.newIndex) { - this.reorderCommits(evt.oldIndex, evt.newIndex); - } - }, - }); - } - // Initialize hunks sortable (will be re-initialized when commit is selected) this.initializeHunksSortable(); @@ -742,8 +713,6 @@ export class ComposerApp extends LitElement { } private reorderCommits(oldIndex: number, newIndex: number) { - if (!this.canReorderCommits) return; - this.saveToHistory(); const newCommits = [...this.state.commits]; @@ -1214,10 +1183,6 @@ export class ComposerApp extends LitElement { return this.state?.mode === 'preview'; } - private get canReorderCommits(): boolean { - return !this.isPreviewMode; - } - private get canCombineCommits(): boolean { return !this.isPreviewMode; } @@ -1271,9 +1236,7 @@ export class ComposerApp extends LitElement { private finishAndCommit() { this._ipc.sendCommand(FinishAndCommitCommand, { commits: this.state.commits, - hunks: this.hunksWithAssignments, baseCommit: this.state.baseCommit, - safetyState: this.state.safetyState, }); } @@ -1288,7 +1251,6 @@ export class ComposerApp extends LitElement { private handleReloadComposer() { this.resetHistory(); this._ipc.sendCommand(ReloadComposerCommand, { - repoPath: this.state.safetyState.repoPath, mode: this.state.mode, }); } @@ -1480,11 +1442,8 @@ export class ComposerApp extends LitElement { this.saveToHistory(); this._ipc.sendCommand(GenerateCommitsCommand, { - hunks: hunksToGenerate, - // In preview mode, send empty commits array to overwrite existing commits - // In interactive mode, send existing commits to preserve them + hunkIndices: hunksToGenerate.map(hunk => hunk.index), commits: this.isPreviewMode ? [] : this.state.commits, - hunkMap: this.state.hunkMap, baseCommit: this.state.baseCommit, customInstructions: customInstructions || undefined, }); @@ -1499,15 +1458,9 @@ export class ComposerApp extends LitElement { return; } - // Create combined diff for the commit - const { patch } = createCombinedDiffForCommit(commit, this.hunksWithAssignments); - if (!patch) { - return; - } - this._ipc.sendCommand(GenerateCommitMessageCommand, { commitId: commitId, - diff: patch, + commitHunkIndices: commit.hunkIndices, overwriteExistingMessage: commit.message.trim() !== '', }); } @@ -1624,12 +1577,12 @@ export class ComposerApp extends LitElement { .committing=${this.state.committing} .aiEnabled=${this.aiEnabled} .aiDisabledReason=${this.aiDisabledReason} - .canReorderCommits=${this.canReorderCommits} .canCombineCommits=${this.canCombineCommits} .canMoveHunks=${this.canMoveHunks} .canGenerateCommitsWithAI=${this.canGenerateCommitsWithAI} .isPreviewMode=${this.isPreviewMode} .baseCommit=${this.state.baseCommit} + .repoName=${this.state.baseCommit?.repoName ?? this.state.repositoryState?.current.name} .customInstructions=${this.customInstructions} .hasUsedAutoCompose=${this.state.hasUsedAutoCompose} .hasChanges=${this.state.hasChanges} diff --git a/src/webviews/apps/plus/composer/components/commit-item.ts b/src/webviews/apps/plus/composer/components/commit-item.ts index ba6a141a3542a..fe7ae54219d31 100644 --- a/src/webviews/apps/plus/composer/components/commit-item.ts +++ b/src/webviews/apps/plus/composer/components/commit-item.ts @@ -86,6 +86,9 @@ export class CommitItem extends LitElement { @property({ type: Boolean }) first = false; + @property({ type: Boolean }) + last = false; + override connectedCallback() { super.connectedCallback?.(); // Set the data attribute for sortable access @@ -120,7 +123,7 @@ export class CommitItem extends LitElement {
0 ? this.message : 'Draft commit (add a commit message)'; - const isPlaceholder = !this.message || this.message.trim().length === 0; + let displayMessage = 'Draft commit (add a commit message)'; + let isPlaceholder = true; + if (this.message && this.message.trim().length > 0) { + displayMessage = this.message.replace(/\n/g, '
'); + isPlaceholder = false; + } - return html`

- ${displayMessage} + return html`

+ ${unsafeHTML(displayMessage)}

`; } diff --git a/src/webviews/apps/plus/composer/components/commits-panel.ts b/src/webviews/apps/plus/composer/components/commits-panel.ts index 3adc1ea07dce8..ef554f209800c 100644 --- a/src/webviews/apps/plus/composer/components/commits-panel.ts +++ b/src/webviews/apps/plus/composer/components/commits-panel.ts @@ -11,13 +11,14 @@ import { getFileCountForCommit, getUnassignedHunks, getUniqueFileNames, -} from '../../../../plus/composer/utils'; +} from '../../../../plus/composer/utils/composer.utils'; import { focusableBaseStyles } from '../../../shared/components/styles/lit/a11y.css'; import { boxSizingBase, inlineCode, scrollableBase } from '../../../shared/components/styles/lit/base.css'; import { ruleStyles } from '../../shared/components/vscode.css'; import { composerItemCommitStyles, composerItemContentStyles, composerItemStyles } from './composer.css'; import '../../../shared/components/button'; import '../../../shared/components/button-container'; +import '../../../shared/components/overlays/popover'; import './commit-item'; @customElement('gl-commits-panel') @@ -285,7 +286,15 @@ export class CommitsPanel extends LitElement { } .auto-compose__instructions-info { - --gl-tooltip-max-width: 37rem; + --max-width: 37rem; + + a:has(.inline-code) { + text-decoration: none; + white-space: nowrap; + } + .inline-code code-icon { + vertical-align: middle; + } } .auto-compose__instructions-input { width: 100%; @@ -362,6 +371,9 @@ export class CommitsPanel extends LitElement { @property({ type: Object }) baseCommit: ComposerBaseCommit | null = null; + @property({ type: String }) + repoName: string | null = null; + @property({ type: String }) customInstructions: string = ''; @@ -426,11 +438,6 @@ export class CommitsPanel extends LitElement { } private initializeSortable() { - // Don't initialize sortable in AI preview mode - if (this.isPreviewMode) { - return; - } - const commitsContainer = this.shadowRoot?.querySelector('.commits-only'); if (commitsContainer) { this.commitsSortable = Sortable.create(commitsContainer as HTMLElement, { @@ -1059,9 +1066,11 @@ export class CommitsPanel extends LitElement { @input=${this.handleCustomInstructionsChange} ?disabled=${disabled} > - - -
+ + + + +
Providing additional instructions can help steer the AI composition for this session.

Potential instructions include: @@ -1073,9 +1082,15 @@ export class CommitsPanel extends LitElement {
You can also specify custom instructions that apply to all composer sessions with the following setting: - gitlens.ai.generateCommits.customInstructions + + gitlens.ai.generateCommits.customInstructions
- +
@@ -1220,13 +1235,19 @@ export class CommitsPanel extends LitElement {
-
+
-
${this.baseCommit?.message || 'HEAD'}
+
+ ${this.baseCommit?.message || 'No commits yet'} +
- ${this.baseCommit?.repoName || 'Repository'} - / - ${this.baseCommit?.branchName || 'main'} + ${this.repoName || 'Repository'} + ${this.baseCommit?.branchName + ? html`/${this.baseCommit.branchName}` + : ''}
@@ -1279,6 +1300,7 @@ export class CommitsPanel extends LitElement { .multiSelected=${this.selectedCommitIds.has(commit.id)} .isPreviewMode=${this.isPreviewMode} ?first=${i === 0} + ?last=${i === this.commits.length - 1 && !this.baseCommit} @click=${(e: MouseEvent) => this.dispatchCommitSelect(commit.id, e)} @keydown=${(e: KeyboardEvent) => this.dispatchCommitSelect(commit.id, e)} > @@ -1289,13 +1311,17 @@ export class CommitsPanel extends LitElement {
-
+
-
${this.baseCommit?.message || 'HEAD'}
+
+ ${this.baseCommit?.message || 'No commits yet'} +
- ${this.baseCommit?.repoName || 'Repository'} - / - ${this.baseCommit?.branchName || 'main'} + ${this.repoName || 'Repository'} + ${this.baseCommit?.branchName + ? html`/${this.baseCommit.branchName}` + : ''}
diff --git a/src/webviews/apps/plus/composer/components/composer.css.ts b/src/webviews/apps/plus/composer/components/composer.css.ts index 8011465b1a501..6d943fd238d0a 100644 --- a/src/webviews/apps/plus/composer/components/composer.css.ts +++ b/src/webviews/apps/plus/composer/components/composer.css.ts @@ -148,6 +148,10 @@ export const composerItemCommitStyles = css` height: 50%; } + .composer-item.is-last .composer-item__commit::before { + display: none; + } + .composer-item__commit::after { content: ''; position: absolute; @@ -168,6 +172,11 @@ export const composerItemCommitStyles = css` .composer-item.is-base .composer-item__commit::before { border-left-style: solid; } + + .composer-item__commit.is-empty::before, + .composer-item__commit.is-empty::after { + display: none; + } `; export const composerItemContentStyles = css` diff --git a/src/webviews/apps/plus/composer/components/details-panel.ts b/src/webviews/apps/plus/composer/components/details-panel.ts index 0e202950c20eb..9853d89669350 100644 --- a/src/webviews/apps/plus/composer/components/details-panel.ts +++ b/src/webviews/apps/plus/composer/components/details-panel.ts @@ -10,7 +10,7 @@ import { getUnassignedHunks, getUniqueFileNames, groupHunksByFile, -} from '../../../../plus/composer/utils'; +} from '../../../../plus/composer/utils/composer.utils'; import { focusableBaseStyles } from '../../../shared/components/styles/lit/a11y.css'; import { boxSizingBase, scrollableBase } from '../../../shared/components/styles/lit/base.css'; import type { CommitMessage } from './commit-message'; diff --git a/src/webviews/apps/plus/composer/composer.ts b/src/webviews/apps/plus/composer/composer.ts index d5ab11acb5999..df2e3be7c8ab5 100644 --- a/src/webviews/apps/plus/composer/composer.ts +++ b/src/webviews/apps/plus/composer/composer.ts @@ -2,15 +2,20 @@ import { html } from 'lit'; import { customElement } from 'lit/decorators.js'; import type { State } from '../../../plus/composer/protocol'; import { GlAppHost } from '../../shared/appHost'; +import type { LoggerContext } from '../../shared/contexts/logger'; import type { HostIpc } from '../../shared/ipc'; +import { ComposerStateProvider } from './stateProvider'; import './components/app'; import './composer.scss'; -import { ComposerStateProvider } from './stateProvider'; @customElement('gl-composer-apphost') export class ComposerAppHost extends GlAppHost { - protected override createStateProvider(state: State, ipc: HostIpc): ComposerStateProvider { - return new ComposerStateProvider(this, state, ipc); + protected override createStateProvider( + bootstrap: string, + ipc: HostIpc, + logger: LoggerContext, + ): ComposerStateProvider { + return new ComposerStateProvider(this, bootstrap, ipc, logger); } override render() { diff --git a/src/webviews/apps/plus/composer/stateProvider.ts b/src/webviews/apps/plus/composer/stateProvider.ts index 6e45c2d34a55a..3987934815c57 100644 --- a/src/webviews/apps/plus/composer/stateProvider.ts +++ b/src/webviews/apps/plus/composer/stateProvider.ts @@ -19,269 +19,250 @@ import { DidStartGeneratingNotification, DidWorkingDirectoryChangeNotification, } from '../../../plus/composer/protocol'; -import type { ReactiveElementHost, StateProvider } from '../../shared/appHost'; -import type { Disposable } from '../../shared/events'; -import type { HostIpc } from '../../shared/ipc'; +import type { IpcMessage } from '../../../protocol'; +import type { ReactiveElementHost } from '../../shared/appHost'; +import { StateProviderBase } from '../../shared/stateProviderBase'; import { stateContext } from './context'; -export class ComposerStateProvider implements StateProvider { - private readonly disposable: Disposable; - private readonly provider: ContextProvider<{ __context__: State }, ReactiveElementHost>; - - private readonly _state: State; - get state(): State { - return this._state; +export class ComposerStateProvider extends StateProviderBase { + protected override createContextProvider(state: State): ContextProvider { + return new ContextProvider(this.host, { context: stateContext, initialValue: state }); } - constructor( - host: ReactiveElementHost, - state: State, - private readonly _ipc: HostIpc, - ) { - this._state = state; - this.provider = new ContextProvider(host, { context: stateContext, initialValue: this._state }); - - this.disposable = this._ipc.onReceiveMessage(msg => { - switch (true) { - case DidStartGeneratingNotification.is(msg): { - const updatedState = { - ...this._state, - generatingCommits: true, - timestamp: Date.now(), - }; - - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidStartGeneratingCommitMessageNotification.is(msg): { - const updatedState = { - ...this._state, - generatingCommitMessage: msg.params.commitId, - timestamp: Date.now(), - }; + protected override onMessageReceived(msg: IpcMessage): void { + switch (true) { + case DidStartGeneratingNotification.is(msg): { + const updatedState = { + ...this._state, + generatingCommits: true, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidGenerateCommitsNotification.is(msg): { - const updatedState = { - ...this._state, - generatingCommits: false, - commits: msg.params.commits, - hunks: this._state.hunks.map(hunk => ({ - ...hunk, - assigned: true, - })), - hasUsedAutoCompose: true, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidStartGeneratingCommitMessageNotification.is(msg): { + const updatedState = { + ...this._state, + generatingCommitMessage: msg.params.commitId, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidGenerateCommitMessageNotification.is(msg): { - const updatedCommits = this._state.commits.map(commit => - commit.id === msg.params.commitId ? { ...commit, message: msg.params.message } : commit, - ); + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidGenerateCommitsNotification.is(msg): { + const updatedState = { + ...this._state, + generatingCommits: false, + commits: msg.params.commits, + hunks: this._state.hunks.map(hunk => ({ + ...hunk, + assigned: true, + })), + hasUsedAutoCompose: true, + timestamp: Date.now(), + }; - const updatedState = { - ...this._state, - generatingCommitMessage: null, - commits: updatedCommits, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidGenerateCommitMessageNotification.is(msg): { + const updatedCommits = this._state.commits.map(commit => + commit.id === msg.params.commitId ? { ...commit, message: msg.params.message } : commit, + ); - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidStartCommittingNotification.is(msg): { - const updatedState = { - ...this._state, - committing: true, - timestamp: Date.now(), - }; + const updatedState = { + ...this._state, + generatingCommitMessage: null, + commits: updatedCommits, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidFinishCommittingNotification.is(msg): { - const updatedState = { - ...this._state, - committing: false, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidStartCommittingNotification.is(msg): { + const updatedState = { + ...this._state, + committing: true, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidSafetyErrorNotification.is(msg): { - const updatedState = { - ...this._state, - safetyError: msg.params.error, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidFinishCommittingNotification.is(msg): { + const updatedState = { + ...this._state, + committing: false, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidReloadComposerNotification.is(msg): { - const updatedState = { - ...this._state, - hunks: msg.params.hunks, - commits: msg.params.commits, - hunkMap: msg.params.hunkMap, - baseCommit: msg.params.baseCommit, - safetyState: msg.params.safetyState, - loadingError: msg.params.loadingError, - hasChanges: msg.params.hasChanges, - safetyError: null, // Clear any existing safety errors - // Reset UI state to defaults - selectedCommitId: null, - selectedCommitIds: new Set(), - selectedUnassignedSection: null, - selectedHunkIds: new Set(), - // Clear any ongoing operations - generatingCommits: false, - generatingCommitMessage: null, - committing: false, - // Reset working directory change flag on reload - workingDirectoryHasChanged: false, - indexHasChanged: false, - timestamp: Date.now(), - hasUsedAutoCompose: false, - repositoryState: msg.params.repositoryState, - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidSafetyErrorNotification.is(msg): { + const updatedState = { + ...this._state, + safetyError: msg.params.error, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidWorkingDirectoryChangeNotification.is(msg): { - const updatedState = { - ...this._state, - workingDirectoryHasChanged: true, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidReloadComposerNotification.is(msg): { + const updatedState = { + ...this._state, + hunks: msg.params.hunks, + commits: msg.params.commits, + baseCommit: msg.params.baseCommit, + loadingError: msg.params.loadingError, + hasChanges: msg.params.hasChanges, + safetyError: null, // Clear any existing safety errors + // Reset UI state to defaults + selectedCommitId: null, + selectedCommitIds: new Set(), + selectedUnassignedSection: null, + selectedHunkIds: new Set(), + // Clear any ongoing operations + generatingCommits: false, + generatingCommitMessage: null, + committing: false, + // Reset working directory change flag on reload + workingDirectoryHasChanged: false, + indexHasChanged: false, + timestamp: Date.now(), + hasUsedAutoCompose: false, + repositoryState: msg.params.repositoryState, + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidIndexChangeNotification.is(msg): { - const updatedState = { - ...this._state, - indexHasChanged: true, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidWorkingDirectoryChangeNotification.is(msg): { + const updatedState = { + ...this._state, + workingDirectoryHasChanged: true, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidLoadingErrorNotification.is(msg): { - const updatedState = { - ...this._state, - loadingError: msg.params.error, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidIndexChangeNotification.is(msg): { + const updatedState = { + ...this._state, + indexHasChanged: true, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidErrorAIOperationNotification.is(msg): { - const updatedState = { - ...this._state, - aiOperationError: { - operation: msg.params.operation, - error: msg.params.error, - }, - // Clear any loading states since the operation failed - generatingCommits: false, - generatingCommitMessage: null, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidLoadingErrorNotification.is(msg): { + const updatedState = { + ...this._state, + loadingError: msg.params.error, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidClearAIOperationErrorNotification.is(msg): { - const updatedState = { - ...this._state, - aiOperationError: null, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidErrorAIOperationNotification.is(msg): { + const updatedState = { + ...this._state, + aiOperationError: { + operation: msg.params.operation, + error: msg.params.error, + }, + // Clear any loading states since the operation failed + generatingCommits: false, + generatingCommitMessage: null, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidCancelGenerateCommitsNotification.is(msg): { - // Clear loading state and reset to pre-generation state - const updatedState = { - ...this._state, - generatingCommits: false, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidClearAIOperationErrorNotification.is(msg): { + const updatedState = { + ...this._state, + aiOperationError: null, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidCancelGenerateCommitMessageNotification.is(msg): { - // Clear loading state for commit message generation - const updatedState = { - ...this._state, - generatingCommitMessage: null, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidCancelGenerateCommitsNotification.is(msg): { + // Clear loading state and reset to pre-generation state + const updatedState = { + ...this._state, + generatingCommits: false, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidChangeAiEnabledNotification.is(msg): { - const updatedState = { - ...this._state, - aiEnabled: { - ...this._state.aiEnabled, - ...(msg.params.org !== undefined && { org: msg.params.org }), - ...(msg.params.config !== undefined && { config: msg.params.config }), - }, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidCancelGenerateCommitMessageNotification.is(msg): { + // Clear loading state for commit message generation + const updatedState = { + ...this._state, + generatingCommitMessage: null, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } - case DidChangeAiModelNotification.is(msg): { - const updatedState = { - ...this._state, - ai: { - ...this._state.ai, - model: msg.params.model, - }, - timestamp: Date.now(), - }; + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + case DidChangeAiEnabledNotification.is(msg): { + const updatedState = { + ...this._state, + aiEnabled: { + ...this._state.aiEnabled, + ...(msg.params.org !== undefined && { org: msg.params.org }), + ...(msg.params.config !== undefined && { config: msg.params.config }), + }, + timestamp: Date.now(), + }; - (this as any)._state = updatedState; - this.provider.setValue(this._state, true); - break; - } + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; } - }); - } + case DidChangeAiModelNotification.is(msg): { + const updatedState = { + ...this._state, + ai: { + ...this._state.ai, + model: msg.params.model, + }, + timestamp: Date.now(), + }; - dispose(): void { - this.disposable.dispose(); + (this as any)._state = updatedState; + this.provider.setValue(this._state, true); + break; + } + } } } diff --git a/src/webviews/apps/plus/graph/context.ts b/src/webviews/apps/plus/graph/context.ts new file mode 100644 index 0000000000000..3d2085984c2bc --- /dev/null +++ b/src/webviews/apps/plus/graph/context.ts @@ -0,0 +1,27 @@ +import { createContext } from '@lit/context'; +import type { SearchQuery } from '../../../../constants.search'; +import type { + GraphSearchResults, + GraphSearchResultsError, + GraphSelectedRows, + State, +} from '../../../plus/graph/protocol'; + +export interface AppState extends State { + state: State; + activeDay: number | undefined; + activeRow: string | undefined; + filter: SearchQuery; + isBusy: boolean; + loading: boolean; + mcpBannerCollapsed?: boolean | undefined; + searching: boolean; + searchResultsHidden: boolean; + searchResultsResponse: GraphSearchResults | GraphSearchResultsError | undefined; + searchResults: GraphSearchResults | undefined; + searchResultsError: GraphSearchResultsError | undefined; + selectedRows: GraphSelectedRows | undefined; + visibleDays: { top: number; bottom: number } | undefined; +} + +export const graphStateContext = createContext('graph-state-context'); diff --git a/src/webviews/apps/plus/graph/gate.ts b/src/webviews/apps/plus/graph/gate.ts index c4e50e13eb5d3..842fecd779a9d 100644 --- a/src/webviews/apps/plus/graph/gate.ts +++ b/src/webviews/apps/plus/graph/gate.ts @@ -6,7 +6,7 @@ import { ifDefined } from 'lit/directives/if-defined.js'; import { createWebviewCommandLink } from '../../../../system/webview'; import { GlElement } from '../../shared/components/element'; import { linkStyles } from '../shared/components/vscode.css'; -import { graphStateContext } from './stateProvider'; +import { graphStateContext } from './context'; import '../../shared/components/feature-badge'; import '../../shared/components/feature-gate'; diff --git a/src/webviews/apps/plus/graph/graph-app.ts b/src/webviews/apps/plus/graph/graph-app.ts index bbdbdc2f853d2..8bb6ad6a9da4a 100644 --- a/src/webviews/apps/plus/graph/graph-app.ts +++ b/src/webviews/apps/plus/graph/graph-app.ts @@ -13,11 +13,11 @@ import { ipcContext } from '../../shared/contexts/ipc'; import type { TelemetryContext } from '../../shared/contexts/telemetry'; import { telemetryContext } from '../../shared/contexts/telemetry'; import { emitTelemetrySentEvent } from '../../shared/telemetry'; +import { graphStateContext } from './context'; import type { GlGraphWrapper } from './graph-wrapper/graph-wrapper'; import type { GlGraphHover } from './hover/graphHover'; import type { GraphMinimapDaySelectedEventDetail } from './minimap/minimap'; import type { GlGraphMinimapContainer } from './minimap/minimap-container'; -import { graphStateContext } from './stateProvider'; import './gate'; import './graph-header'; import './graph-wrapper/graph-wrapper'; diff --git a/src/webviews/apps/plus/graph/graph-header.ts b/src/webviews/apps/plus/graph/graph-header.ts index b03f6b1e67ba3..196ed8a3b8dcb 100644 --- a/src/webviews/apps/plus/graph/graph-header.ts +++ b/src/webviews/apps/plus/graph/graph-header.ts @@ -48,7 +48,7 @@ import type { TelemetryContext } from '../../shared/contexts/telemetry'; import { telemetryContext } from '../../shared/contexts/telemetry'; import { emitTelemetrySentEvent } from '../../shared/telemetry'; import { ruleStyles } from '../shared/components/vscode.css'; -import { graphStateContext } from './stateProvider'; +import { graphStateContext } from './context'; import { actionButton, linkBase } from './styles/graph.css'; import { graphHeaderControlStyles, progressStyles, repoHeaderStyles, titlebarStyles } from './styles/header.css'; import '@shoelace-style/shoelace/dist/components/option/option.js'; diff --git a/src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper.ts b/src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper.ts index 7673cfaa1e14c..af8240ec83b8d 100644 --- a/src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper.ts +++ b/src/webviews/apps/plus/graph/graph-wrapper/graph-wrapper.ts @@ -26,7 +26,7 @@ import { telemetryContext } from '../../../shared/contexts/telemetry'; import type { Disposable } from '../../../shared/events'; import type { ThemeChangeEvent } from '../../../shared/theme'; import { onDidChangeTheme } from '../../../shared/theme'; -import { graphStateContext } from '../stateProvider'; +import { graphStateContext } from '../context'; import type { GlGraph } from './gl-graph'; import type { GraphWrapperTheming } from './gl-graph.react'; import './gl-graph'; @@ -140,6 +140,7 @@ export class GlGraphWrapper extends SignalWatcher(LitElement) { .refsMetadata=${graphState.refsMetadata} .rows=${graphState.rows} .rowsStats=${graphState.rowsStats} + ?rowsStatsLoading=${graphState.rowsStatsLoading} .searchResults=${graphState.searchResults} .selectedRows=${graphState.selectedRows} .theming=${this.theming} diff --git a/src/webviews/apps/plus/graph/graph.scss b/src/webviews/apps/plus/graph/graph.scss index 346a8c10e815c..06fabdc2c5118 100644 --- a/src/webviews/apps/plus/graph/graph.scss +++ b/src/webviews/apps/plus/graph/graph.scss @@ -1129,6 +1129,10 @@ web-graph { margin-top: 0.1rem; } + .columns-btn.spinner { + margin-right: 0.6rem; + } + .button { background-color: var(--color-graph-actionbar-background); color: var(--color-graph-text-disabled, hsla(0deg, 0%, 100%, 0.4)); @@ -1465,3 +1469,5 @@ web-graph { height: 100%; } } + +@import '../../shared/codicons'; diff --git a/src/webviews/apps/plus/graph/graph.ts b/src/webviews/apps/plus/graph/graph.ts index a65dca0ad2bb5..8a92a82e10602 100644 --- a/src/webviews/apps/plus/graph/graph.ts +++ b/src/webviews/apps/plus/graph/graph.ts @@ -33,8 +33,8 @@ export class GraphAppHost extends GlAppHost { return html``; } - protected override createStateProvider(state: State, ipc: HostIpc): GraphStateProvider { - return new GraphStateProvider(this, state, ipc, this._logger, { + protected override createStateProvider(bootstrap: string, ipc: HostIpc): GraphStateProvider { + return new GraphStateProvider(this, bootstrap, ipc, this._logger, { onStateUpdate: partial => { if ('rows' in partial) { this.appElement.resetHover(); diff --git a/src/webviews/apps/plus/graph/sidebar/sidebar.ts b/src/webviews/apps/plus/graph/sidebar/sidebar.ts index 51379dd775f44..20e4559370320 100644 --- a/src/webviews/apps/plus/graph/sidebar/sidebar.ts +++ b/src/webviews/apps/plus/graph/sidebar/sidebar.ts @@ -9,7 +9,7 @@ import { ipcContext } from '../../../shared/contexts/ipc'; import type { Disposable } from '../../../shared/events'; import type { HostIpc } from '../../../shared/ipc'; import { emitTelemetrySentEvent } from '../../../shared/telemetry'; -import { graphStateContext } from '../stateProvider'; +import { graphStateContext } from '../context'; import '../../../shared/components/code-icon'; import '../../../shared/components/overlays/tooltip'; diff --git a/src/webviews/apps/plus/graph/stateProvider.ts b/src/webviews/apps/plus/graph/stateProvider.ts index 29d87d8bdd288..e6a6abb2b6b69 100644 --- a/src/webviews/apps/plus/graph/stateProvider.ts +++ b/src/webviews/apps/plus/graph/stateProvider.ts @@ -1,14 +1,7 @@ -import { ContextProvider, createContext } from '@lit/context'; -import type { ReactiveControllerHost } from 'lit'; -import type { SearchQuery } from '../../../../constants.search'; +import { ContextProvider } from '@lit/context'; import { debounce } from '../../../../system/function/debounce'; import { getLogScope, setLogScopeExit } from '../../../../system/logger.scope'; -import type { - GraphSearchResults, - GraphSearchResultsError, - GraphSelectedRows, - State, -} from '../../../plus/graph/protocol'; +import type { GraphSearchResults, GraphSearchResultsError, State } from '../../../plus/graph/protocol'; import { DidChangeAvatarsNotification, DidChangeBranchStateNotification, @@ -30,20 +23,21 @@ import { DidSearchNotification, DidStartFeaturePreviewNotification, } from '../../../plus/graph/protocol'; +import type { IpcMessage, WebviewState } from '../../../protocol'; import { DidChangeHostWindowFocusNotification } from '../../../protocol'; -import type { StateProvider } from '../../shared/appHost'; +import type { ReactiveElementHost } from '../../shared/appHost'; import { signalObjectState, signalState } from '../../shared/components/signal-utils'; import type { LoggerContext } from '../../shared/contexts/logger'; -import type { Disposable } from '../../shared/events'; import type { HostIpc } from '../../shared/ipc'; +import { StateProviderBase } from '../../shared/stateProviderBase'; +import type { AppState } from './context'; +import { graphStateContext } from './context'; -type ReactiveElementHost = Partial & HTMLElement; - -interface AppState { - activeDay?: number; - activeRow?: string; - visibleDays?: { top: number; bottom: number }; -} +const BaseWebviewStateKeys = [ + 'timestamp', + 'webviewId', + 'webviewInstanceId', +] as const satisfies readonly (keyof WebviewState)[] as readonly string[]; function getSearchResultModel(searchResults: State['searchResults']): { results: undefined | GraphSearchResults; @@ -61,44 +55,13 @@ function getSearchResultModel(searchResults: State['searchResults']): { return { results: results, resultsError: resultsError }; } -export const graphStateContext = createContext('graph-state-context'); - -export class GraphStateProvider implements StateProvider, State, AppState { - private readonly disposable: Disposable; - private readonly provider: ContextProvider<{ __context__: GraphStateProvider }, ReactiveElementHost>; - - private readonly _state: State; - get state() { - return this._state; - } - - get webviewId() { - return this._state.webviewId; - } - - get webviewInstanceId() { - return this._state.webviewInstanceId; - } - - get timestamp() { - return this._state.timestamp; - } - +export class GraphStateProvider extends StateProviderBase { // App state members moved from GraphAppState @signalState() - accessor activeDay: number | undefined; + accessor activeDay: AppState['activeDay']; @signalState() - accessor activeRow: string | undefined = undefined; - - @signalState(false) - accessor loading = false; - - @signalState(false) - accessor searching = false; - - @signalObjectState() - accessor visibleDays: AppState['visibleDays']; + accessor activeRow: AppState['activeRow']; @signalObjectState( { query: '' }, @@ -108,10 +71,20 @@ export class GraphStateProvider implements StateProvider, State, AppState }, }, ) - accessor filter!: SearchQuery; + accessor filter!: AppState['filter']; + + get isBusy(): AppState['isBusy'] { + return this.loading || this.searching || this.rowsStatsLoading || false; + } + + @signalState(false) + accessor loading: AppState['loading'] = false; + + @signalState(false) + accessor searching: AppState['searching'] = false; @signalState(false) - accessor searchResultsHidden = false; + accessor searchResultsHidden: AppState['searchResultsHidden'] = false; @signalState(undefined, { afterChange: (target, value) => { @@ -120,16 +93,19 @@ export class GraphStateProvider implements StateProvider, State, AppState target.searchResultsError = resultsError; }, }) - accessor searchResultsResponse: GraphSearchResults | GraphSearchResultsError | undefined; + accessor searchResultsResponse: AppState['searchResultsResponse']; @signalState() - accessor searchResults: GraphSearchResults | undefined; + accessor searchResults: AppState['searchResults']; @signalState() - accessor searchResultsError: GraphSearchResultsError | undefined; + accessor searchResultsError: AppState['searchResultsError']; @signalState() - accessor selectedRows: undefined | GraphSelectedRows; + accessor selectedRows: AppState['selectedRows']; + + @signalObjectState() + accessor visibleDays: AppState['visibleDays']; // State accessors for all top-level State properties @signalState() @@ -142,7 +118,7 @@ export class GraphStateProvider implements StateProvider, State, AppState accessor repositories: State['repositories']; @signalState() - accessor selectedRepository: string | undefined; + accessor selectedRepository: State['selectedRepository']; @signalState() accessor selectedRepositoryVisibility: State['selectedRepositoryVisibility']; @@ -157,13 +133,13 @@ export class GraphStateProvider implements StateProvider, State, AppState accessor branchState: State['branchState']; @signalState() - accessor lastFetched: Date | undefined; + accessor lastFetched: State['lastFetched']; @signalState() accessor subscription: State['subscription']; @signalState() - accessor allowed: boolean = false; + accessor allowed: State['allowed'] = false; @signalState() accessor avatars: State['avatars']; @@ -178,7 +154,7 @@ export class GraphStateProvider implements StateProvider, State, AppState accessor rowsStats: State['rowsStats']; @signalState() - accessor rowsStatsLoading: boolean | undefined; + accessor rowsStatsLoading: State['rowsStatsLoading'] | undefined; @signalState() accessor downstreams: State['downstreams']; @@ -196,7 +172,7 @@ export class GraphStateProvider implements StateProvider, State, AppState accessor context: State['context']; @signalState() - accessor nonce: string | undefined; + accessor nonce: State['nonce']; @signalState() accessor workingTreeStats: State['workingTreeStats']; @@ -205,7 +181,7 @@ export class GraphStateProvider implements StateProvider, State, AppState accessor defaultSearchMode: State['defaultSearchMode']; @signalState() - accessor useNaturalLanguageSearch: boolean | undefined; + accessor useNaturalLanguageSearch: State['useNaturalLanguageSearch'] | undefined; @signalState() accessor excludeRefs: State['excludeRefs']; @@ -222,258 +198,252 @@ export class GraphStateProvider implements StateProvider, State, AppState @signalState() accessor orgSettings: State['orgSettings']; - get isBusy() { - return this.loading || this.searching || this.rowsStatsLoading || false; - } - - private updateState(partial: Partial, silent?: boolean) { - for (const key in partial) { - const value = partial[key as keyof State]; - // @ts-expect-error key is a key of State - this._state[key] = value; - - if (['timestamp', 'webviewId', 'webviewInstanceId'].includes(key)) continue; - - // Update corresponding accessors - switch (key) { - case 'allowed': - this.allowed = partial.allowed ?? false; - break; - case 'loading': - this.loading = partial.loading ?? false; - break; - default: - // @ts-expect-error key is a key of State - this[key as keyof Omit] = value; - break; - } - } - - if (silent) return; - - this.options.onStateUpdate?.(partial); - this.fireProviderUpdate(); - } - - private fireProviderUpdate = debounce(() => this.provider.setValue(this, true), 100); + mcpBannerCollapsed?: boolean | undefined; constructor( host: ReactiveElementHost, - state: State, - private readonly _ipc: HostIpc, - private readonly _logger: LoggerContext, + bootstrap: string, + ipc: HostIpc, + logger: LoggerContext, private readonly options: { onStateUpdate?: (partial: Partial) => void } = {}, ) { - this._state = state; - this.provider = new ContextProvider(host, { context: graphStateContext, initialValue: this }); - this.updateState(state, true); - - this.disposable = this._ipc.onReceiveMessage(msg => { - const scope = getLogScope(); - - const updates: Partial = {}; - switch (true) { - case DidChangeNotification.is(msg): - this.updateState(msg.params.state); - break; - - case DidFetchNotification.is(msg): - this._state.lastFetched = msg.params.lastFetched; - this.updateState({ lastFetched: msg.params.lastFetched }); - break; - - case DidChangeAvatarsNotification.is(msg): - this.updateState({ avatars: msg.params.avatars }); - break; - case DidStartFeaturePreviewNotification.is(msg): - this._state.featurePreview = msg.params.featurePreview; - this._state.allowed = msg.params.allowed; - this.updateState({ - featurePreview: msg.params.featurePreview, - allowed: msg.params.allowed, - }); - break; - case DidChangeBranchStateNotification.is(msg): - this.updateState({ - branchState: msg.params.branchState, - }); - break; - - case DidChangeHostWindowFocusNotification.is(msg): - this.updateState({ - windowFocused: msg.params.focused, - }); - break; + super(host, bootstrap, ipc, logger); + } - case DidChangeColumnsNotification.is(msg): - this.updateState({ - columns: msg.params.columns, - context: { - ...this._state.context, - header: msg.params.context, - settings: msg.params.settingsContext, - }, - }); - break; + protected override createContextProvider( + _state: State, + ): ContextProvider { + return new ContextProvider(this.host, { context: graphStateContext, initialValue: this }); + } - case DidChangeRefsVisibilityNotification.is(msg): - this.updateState({ - branchesVisibility: msg.params.branchesVisibility, - excludeRefs: msg.params.excludeRefs, - excludeTypes: msg.params.excludeTypes, - includeOnlyRefs: msg.params.includeOnlyRefs, - }); - break; + protected override async initializeState(): Promise { + await super.initializeState(); - case DidChangeRefsMetadataNotification.is(msg): - this.updateState({ - refsMetadata: msg.params.metadata, - }); - break; + this.updateState(this._state, true); + } - case DidChangeRowsNotification.is(msg): { - let rows; - if ( - msg.params.rows.length && - msg.params.paging?.startingCursor != null && - this._state.rows != null - ) { - const previousRows = this._state.rows; - const lastId = previousRows[previousRows.length - 1]?.sha; - - let previousRowsLength = previousRows.length; - const newRowsLength = msg.params.rows.length; - - this._logger.log( - scope, - `paging in ${newRowsLength} rows into existing ${previousRowsLength} rows at ${msg.params.paging.startingCursor} (last existing row: ${lastId})`, - ); - - rows = []; - // Preallocate the array to avoid reallocations - rows.length = previousRowsLength + newRowsLength; - - if (msg.params.paging.startingCursor !== lastId) { - this._logger.log( - scope, - `searching for ${msg.params.paging.startingCursor} in existing rows`, - ); - - let i = 0; - let row; - for (row of previousRows) { - rows[i++] = row; - if (row.sha === msg.params.paging.startingCursor) { - this._logger.log( - scope, - `found ${msg.params.paging.startingCursor} in existing rows`, - ); - - previousRowsLength = i; - - if (previousRowsLength !== previousRows.length) { - // If we stopped before the end of the array, we need to trim it - rows.length = previousRowsLength + newRowsLength; - } - - break; + protected onMessageReceived(msg: IpcMessage): void { + const scope = getLogScope(); + + const updates: Partial = {}; + switch (true) { + case DidChangeNotification.is(msg): + this.updateState(msg.params.state); + break; + + case DidFetchNotification.is(msg): + this._state.lastFetched = msg.params.lastFetched; + this.updateState({ lastFetched: msg.params.lastFetched }); + break; + + case DidChangeAvatarsNotification.is(msg): + this.updateState({ avatars: msg.params.avatars }); + break; + case DidStartFeaturePreviewNotification.is(msg): + this._state.featurePreview = msg.params.featurePreview; + this._state.allowed = msg.params.allowed; + this.updateState({ + featurePreview: msg.params.featurePreview, + allowed: msg.params.allowed, + }); + break; + case DidChangeBranchStateNotification.is(msg): + this.updateState({ + branchState: msg.params.branchState, + }); + break; + + case DidChangeHostWindowFocusNotification.is(msg): + this.updateState({ + windowFocused: msg.params.focused, + }); + break; + + case DidChangeColumnsNotification.is(msg): + this.updateState({ + columns: msg.params.columns, + context: { + ...this._state.context, + header: msg.params.context, + settings: msg.params.settingsContext, + }, + }); + break; + + case DidChangeRefsVisibilityNotification.is(msg): + this.updateState({ + branchesVisibility: msg.params.branchesVisibility, + excludeRefs: msg.params.excludeRefs, + excludeTypes: msg.params.excludeTypes, + includeOnlyRefs: msg.params.includeOnlyRefs, + }); + break; + + case DidChangeRefsMetadataNotification.is(msg): + this.updateState({ + refsMetadata: msg.params.metadata, + }); + break; + + case DidChangeRowsNotification.is(msg): { + let rows; + if (msg.params.rows.length && msg.params.paging?.startingCursor != null && this._state.rows != null) { + const previousRows = this._state.rows; + const lastId = previousRows[previousRows.length - 1]?.sha; + + let previousRowsLength = previousRows.length; + const newRowsLength = msg.params.rows.length; + + this.logger.log( + scope, + `paging in ${newRowsLength} rows into existing ${previousRowsLength} rows at ${msg.params.paging.startingCursor} (last existing row: ${lastId})`, + ); + + rows = []; + // Preallocate the array to avoid reallocations + rows.length = previousRowsLength + newRowsLength; + + if (msg.params.paging.startingCursor !== lastId) { + this.logger.log(scope, `searching for ${msg.params.paging.startingCursor} in existing rows`); + + let i = 0; + let row; + for (row of previousRows) { + rows[i++] = row; + if (row.sha === msg.params.paging.startingCursor) { + this.logger.log(scope, `found ${msg.params.paging.startingCursor} in existing rows`); + + previousRowsLength = i; + + if (previousRowsLength !== previousRows.length) { + // If we stopped before the end of the array, we need to trim it + rows.length = previousRowsLength + newRowsLength; } - } - } else { - for (let i = 0; i < previousRowsLength; i++) { - rows[i] = previousRows[i]; - } - } - for (let i = 0; i < newRowsLength; i++) { - rows[previousRowsLength + i] = msg.params.rows[i]; + break; + } } } else { - this._logger.log(scope, `setting to ${msg.params.rows.length} rows`); - - if (msg.params.rows.length === 0) { - rows = this._state.rows; - } else { - rows = msg.params.rows; + for (let i = 0; i < previousRowsLength; i++) { + rows[i] = previousRows[i]; } } - updates.avatars = msg.params.avatars; - updates.downstreams = msg.params.downstreams; - if (msg.params.refsMetadata !== undefined) { - updates.refsMetadata = msg.params.refsMetadata; - } - updates.rows = rows; - updates.paging = msg.params.paging; - if (msg.params.rowsStats != null) { - updates.rowsStats = { ...this._state.rowsStats, ...msg.params.rowsStats }; + for (let i = 0; i < newRowsLength; i++) { + rows[previousRowsLength + i] = msg.params.rows[i]; } - updates.rowsStatsLoading = msg.params.rowsStatsLoading; - if (msg.params.searchResults != null) { - updates.searchResults = msg.params.searchResults; - } - if (msg.params.selectedRows != null) { - updates.selectedRows = msg.params.selectedRows; - } - updates.loading = false; - this.updateState(updates); - setLogScopeExit(scope, ` \u2022 rows=${this._state.rows?.length ?? 0}`); - break; - } - case DidChangeRowsStatsNotification.is(msg): - this.updateState({ - rowsStats: { ...this._state.rowsStats, ...msg.params.rowsStats }, - rowsStatsLoading: msg.params.rowsStatsLoading, - }); - break; - - case DidChangeScrollMarkersNotification.is(msg): - this.updateState({ context: { ...this._state.context, settings: msg.params.context } }); - break; + } else { + this.logger.log(scope, `setting to ${msg.params.rows.length} rows`); - case DidSearchNotification.is(msg): - if (msg.params.selectedRows != null) { - updates.selectedRows = msg.params.selectedRows; + if (msg.params.rows.length === 0) { + rows = this._state.rows; + } else { + rows = msg.params.rows; } - updates.searchResults = msg.params.results; - this.updateState(updates); - break; + } - case DidChangeSelectionNotification.is(msg): - this.updateState({ selectedRows: msg.params.selection }); - break; + updates.avatars = msg.params.avatars; + updates.downstreams = msg.params.downstreams; + if (msg.params.refsMetadata !== undefined) { + updates.refsMetadata = msg.params.refsMetadata; + } + updates.rows = rows; + updates.paging = msg.params.paging; + if (msg.params.rowsStats != null) { + updates.rowsStats = { ...this._state.rowsStats, ...msg.params.rowsStats }; + } + updates.rowsStatsLoading = msg.params.rowsStatsLoading; + if (msg.params.searchResults != null) { + updates.searchResults = msg.params.searchResults; + } + if (msg.params.selectedRows != null) { + updates.selectedRows = msg.params.selectedRows; + } + updates.loading = false; + this.updateState(updates); + setLogScopeExit(scope, ` \u2022 rows=${this._state.rows?.length ?? 0}`); + break; + } + case DidChangeRowsStatsNotification.is(msg): + this.updateState({ + rowsStats: { ...this._state.rowsStats, ...msg.params.rowsStats }, + rowsStatsLoading: msg.params.rowsStatsLoading, + }); + break; + + case DidChangeScrollMarkersNotification.is(msg): + this.updateState({ context: { ...this._state.context, settings: msg.params.context } }); + break; + + case DidSearchNotification.is(msg): + if (msg.params.selectedRows != null) { + updates.selectedRows = msg.params.selectedRows; + } + updates.searchResults = msg.params.results; + this.updateState(updates); + break; + + case DidChangeSelectionNotification.is(msg): + this.updateState({ selectedRows: msg.params.selection }); + break; + + case DidChangeGraphConfigurationNotification.is(msg): + this.updateState({ config: msg.params.config }); + break; + + case DidChangeSubscriptionNotification.is(msg): + this.updateState({ + subscription: msg.params.subscription, + allowed: msg.params.allowed, + }); + break; + + case DidChangeOrgSettings.is(msg): + this.updateState({ orgSettings: msg.params.orgSettings }); + break; + + case DidChangeMcpBanner.is(msg): + this.updateState({ mcpBannerCollapsed: msg.params }); + break; + + case DidChangeWorkingTreeNotification.is(msg): + this.updateState({ workingTreeStats: msg.params.stats }); + break; + + case DidChangeRepoConnectionNotification.is(msg): + this.updateState({ repositories: msg.params.repositories }); + break; + } + } - case DidChangeGraphConfigurationNotification.is(msg): - this.updateState({ config: msg.params.config }); - break; + private fireProviderUpdate = debounce(() => this.provider.setValue(this, true), 100); - case DidChangeSubscriptionNotification.is(msg): - this.updateState({ - subscription: msg.params.subscription, - allowed: msg.params.allowed, - }); - break; + protected updateState(partial: Partial, silent?: boolean) { + for (const key in partial) { + const value = partial[key as keyof State]; + // @ts-expect-error key is a key of State + this._state[key] = value; - case DidChangeOrgSettings.is(msg): - this.updateState({ orgSettings: msg.params.orgSettings }); - break; + if (BaseWebviewStateKeys.includes(key)) continue; - case DidChangeMcpBanner.is(msg): - this.updateState({ mcpBannerCollapsed: msg.params }); + // Update corresponding accessors + switch (key) { + case 'allowed': + this.allowed = partial.allowed ?? false; break; - - case DidChangeWorkingTreeNotification.is(msg): - this.updateState({ workingTreeStats: msg.params.stats }); + case 'loading': + this.loading = partial.loading ?? false; break; - - case DidChangeRepoConnectionNotification.is(msg): - this.updateState({ repositories: msg.params.repositories }); + default: + // @ts-expect-error key is a key of State + this[key as keyof Omit] = value; break; } - }); - } + } - dispose(): void { - this.disposable.dispose(); + if (silent) return; + + this.options.onStateUpdate?.(partial); + this.fireProviderUpdate(); } } diff --git a/src/webviews/apps/plus/shared/components/home-header.ts b/src/webviews/apps/plus/shared/components/home-header.ts index ef6710d07abcc..d78d2e5c78f4a 100644 --- a/src/webviews/apps/plus/shared/components/home-header.ts +++ b/src/webviews/apps/plus/shared/components/home-header.ts @@ -6,11 +6,11 @@ import type { GlAccountChip } from './account-chip'; import './account-chip'; import './integrations-chip'; import '../../../home/components/onboarding'; +import '../../../home/components/promo-banner'; import '../../../shared/components/button'; import '../../../shared/components/button-container'; import '../../../shared/components/code-icon'; import '../../../shared/components/overlays/popover'; -import '../../../shared/components/promo'; // import '../../../shared/components/snow'; @customElement('gl-home-header') diff --git a/src/webviews/apps/plus/shared/components/merge-rebase-status.ts b/src/webviews/apps/plus/shared/components/merge-rebase-status.ts index f5de7178996d0..08076a5724169 100644 --- a/src/webviews/apps/plus/shared/components/merge-rebase-status.ts +++ b/src/webviews/apps/plus/shared/components/merge-rebase-status.ts @@ -15,6 +15,7 @@ export class GlMergeConflictWarning extends LitElement { static override styles = [ css` .status { + --action-item-foreground: #000; box-sizing: border-box; display: flex; align-items: center; @@ -29,6 +30,7 @@ export class GlMergeConflictWarning extends LitElement { } :host([conflicts]) .status { + --action-item-foreground: #fff; background-color: var(--vscode-gitlens-decorations\\.statusMergingOrRebasingConflictForegroundColor); color: #fff; } diff --git a/src/webviews/apps/plus/timeline/components/chart.ts b/src/webviews/apps/plus/timeline/components/chart.ts index 3207290ecb4fe..abca6d8fa95a5 100644 --- a/src/webviews/apps/plus/timeline/components/chart.ts +++ b/src/webviews/apps/plus/timeline/components/chart.ts @@ -173,7 +173,11 @@ export class GlTimelineChart extends GlElement { this.emit('gl-loading', this._loading.promise); } - if (this.dataPromise == null) return; + if (this.dataPromise == null) { + // Fulfill the loading promise since there's no data to load + this._loading?.fulfill(); + return; + } this._chartAborter?.abort(); this._chartAborter = new AbortController(); diff --git a/src/webviews/apps/plus/timeline/stateProvider.ts b/src/webviews/apps/plus/timeline/stateProvider.ts index d58e5addcc977..70c14ae96a7f2 100644 --- a/src/webviews/apps/plus/timeline/stateProvider.ts +++ b/src/webviews/apps/plus/timeline/stateProvider.ts @@ -1,41 +1,28 @@ import { ContextProvider } from '@lit/context'; import type { State } from '../../../plus/timeline/protocol'; import { DidChangeNotification } from '../../../plus/timeline/protocol'; -import type { ReactiveElementHost, StateProvider } from '../../shared/appHost'; -import type { Disposable } from '../../shared/events'; -import type { HostIpc } from '../../shared/ipc'; +import type { IpcMessage } from '../../../protocol'; +import type { ReactiveElementHost } from '../../shared/appHost'; +import { StateProviderBase } from '../../shared/stateProviderBase'; import { stateContext } from './context'; -export class TimelineStateProvider implements StateProvider { - private readonly disposable: Disposable; - private readonly provider: ContextProvider<{ __context__: State }, ReactiveElementHost>; - - private _state: State; - get state(): State { - return this._state; +export class TimelineStateProvider extends StateProviderBase { + protected override createContextProvider(state: State): ContextProvider { + return new ContextProvider(this.host, { context: stateContext, initialValue: state }); } - constructor( - host: ReactiveElementHost, - state: State, - private readonly _ipc: HostIpc, - ) { - this._state = state; - this.provider = new ContextProvider(host, { context: stateContext, initialValue: state }); - - this.disposable = this._ipc.onReceiveMessage(msg => { - switch (true) { - case DidChangeNotification.is(msg): - this._state = { ...msg.params.state, timestamp: Date.now() }; + protected override onMessageReceived(msg: IpcMessage): void { + switch (true) { + case DidChangeNotification.is(msg): + this._state = { ...msg.params.state, timestamp: Date.now() }; - this.provider.setValue(this._state, true); - host.requestUpdate(); - break; - } - }); + this.provider.setValue(this._state, true); + this.host.requestUpdate(); + break; + } } - dispose(): void { - this.disposable.dispose(); + protected override onPersistState(state: State): void { + this.ipc.setPersistedState({ config: state.config, scope: state.scope }); } } diff --git a/src/webviews/apps/plus/timeline/timeline.ts b/src/webviews/apps/plus/timeline/timeline.ts index 8cb1b47ade7c6..4ea1145892ae7 100644 --- a/src/webviews/apps/plus/timeline/timeline.ts +++ b/src/webviews/apps/plus/timeline/timeline.ts @@ -19,6 +19,7 @@ import { import { GlAppHost } from '../../shared/appHost'; import type { Checkbox } from '../../shared/components/checkbox/checkbox'; import type { GlRefButton } from '../../shared/components/ref-button'; +import type { LoggerContext } from '../../shared/contexts/logger'; import type { HostIpc } from '../../shared/ipc'; import { linkStyles, ruleStyles } from '../shared/components/vscode.css'; import type { CommitEventDetail, GlTimelineChart } from './components/chart'; @@ -51,12 +52,12 @@ export class GlTimelineApp extends GlAppHost { @query('#chart') private _chart?: GlTimelineChart; - protected override createStateProvider(state: State, ipc: HostIpc): TimelineStateProvider { - return new TimelineStateProvider(this, state, ipc); - } - - protected override onPersistState(state: State): void { - this._ipc.setPersistedState({ config: state.config, scope: state.scope }); + protected override createStateProvider( + bootstrap: string, + ipc: HostIpc, + logger: LoggerContext, + ): TimelineStateProvider { + return new TimelineStateProvider(this, bootstrap, ipc, logger); } override connectedCallback(): void { diff --git a/src/webviews/apps/shared/__tests__/ipc.test.ts b/src/webviews/apps/shared/__tests__/ipc.test.ts new file mode 100644 index 0000000000000..4080587f7e232 --- /dev/null +++ b/src/webviews/apps/shared/__tests__/ipc.test.ts @@ -0,0 +1,223 @@ +import * as assert from 'assert'; +import { URI } from 'vscode-uri'; +import { deserializeIpcData } from '../../../../system/ipcSerialize'; +import type { IpcPromise } from '../../../ipc'; + +suite('IPC Deserialization Test Suite', () => { + suite('deserializeIpcData (pure function)', () => { + const mockPromiseFactory = (_value: IpcPromise['value']): Promise => Promise.resolve(); + + test('should be exported and callable', () => { + assert.strictEqual(typeof deserializeIpcData, 'function'); + }); + + suite('IpcDate deserialization', () => { + test('should deserialize IpcDate to Date', () => { + const timestamp = new Date('2024-01-15T10:30:00.000Z').getTime(); + const input = { + date: { __ipc: 'date', value: timestamp }, + }; + const jsonString = JSON.stringify(input); + + const result: any = deserializeIpcData(jsonString, mockPromiseFactory); + + assert.ok(result.date instanceof Date); + assert.strictEqual(result.date.getTime(), timestamp); + }); + + test('should deserialize nested IpcDate objects', () => { + const timestamp1 = new Date('2024-01-15T10:30:00.000Z').getTime(); + const timestamp2 = new Date('2024-01-16T14:45:00.000Z').getTime(); + const input = { + commit: { + author: { + name: 'John Doe', + date: { __ipc: 'date', value: timestamp1 }, + }, + committer: { + name: 'Jane Doe', + date: { __ipc: 'date', value: timestamp2 }, + }, + }, + }; + const jsonString = JSON.stringify(input); + + const result: any = deserializeIpcData(jsonString, mockPromiseFactory); + + assert.ok(result.commit.author.date instanceof Date); + assert.strictEqual(result.commit.author.date.getTime(), timestamp1); + assert.ok(result.commit.committer.date instanceof Date); + assert.strictEqual(result.commit.committer.date.getTime(), timestamp2); + }); + + test('should deserialize array of IpcDate objects', () => { + const timestamps = [ + new Date('2024-01-15T10:30:00.000Z').getTime(), + new Date('2024-01-16T14:45:00.000Z').getTime(), + new Date('2024-01-17T08:15:00.000Z').getTime(), + ]; + const input = { + dates: timestamps.map(t => ({ __ipc: 'date', value: t })), + }; + const jsonString = JSON.stringify(input); + + const result: any = deserializeIpcData(jsonString, mockPromiseFactory); + + assert.strictEqual(result.dates.length, 3); + result.dates.forEach((date: Date, index: number) => { + assert.ok(date instanceof Date); + assert.strictEqual(date.getTime(), timestamps[index]); + }); + }); + }); + + suite('IpcUri deserialization', () => { + test('should deserialize IpcUri to URI', () => { + const input = { + uri: { + __ipc: 'uri', + value: { + scheme: 'file', + authority: '', + path: '/path/to/file.ts', + query: '', + fragment: '', + }, + }, + }; + const jsonString = JSON.stringify(input); + + const result: any = deserializeIpcData(jsonString, mockPromiseFactory); + + assert.ok(URI.isUri(result.uri)); + assert.strictEqual(result.uri.scheme, 'file'); + assert.strictEqual(result.uri.path, '/path/to/file.ts'); + }); + + test('should deserialize IpcUri with all components', () => { + const input = { + uri: { + __ipc: 'uri', + value: { + scheme: 'https', + authority: 'example.com:8080', + path: '/path/to/file', + query: 'query=value', + fragment: 'fragment', + }, + }, + }; + const jsonString = JSON.stringify(input); + + const result: any = deserializeIpcData(jsonString, mockPromiseFactory); + + assert.ok(URI.isUri(result.uri)); + assert.strictEqual(result.uri.scheme, 'https'); + assert.strictEqual(result.uri.authority, 'example.com:8080'); + assert.strictEqual(result.uri.path, '/path/to/file'); + assert.strictEqual(result.uri.query, 'query=value'); + assert.strictEqual(result.uri.fragment, 'fragment'); + }); + }); + + suite('IpcPromise deserialization', () => { + test('should deserialize IpcPromise to Promise', () => { + const input = { + promise: { + __ipc: 'promise', + value: { + id: 'test-id-1', + method: 'core/ipc/promise/settled', + }, + }, + }; + const jsonString = JSON.stringify(input); + + const result: any = deserializeIpcData(jsonString, mockPromiseFactory); + + assert.ok(result.promise instanceof Promise); + }); + }); + + suite('Mixed types deserialization', () => { + test('should deserialize object with multiple IPC types', () => { + const timestamp = new Date('2024-01-15T10:30:00.000Z').getTime(); + const input = { + date: { __ipc: 'date', value: timestamp }, + uri: { + __ipc: 'uri', + value: { + scheme: 'file', + authority: '', + path: '/path/to/file.ts', + query: '', + fragment: '', + }, + }, + promise: { + __ipc: 'promise', + value: { + id: 'test-id-1', + method: 'core/ipc/promise/settled', + }, + }, + normal: 'string', + number: 42, + boolean: true, + }; + const jsonString = JSON.stringify(input); + + const result: any = deserializeIpcData(jsonString, mockPromiseFactory); + + assert.ok(result.date instanceof Date); + assert.ok(URI.isUri(result.uri)); + assert.ok(result.promise instanceof Promise); + assert.strictEqual(result.normal, 'string'); + assert.strictEqual(result.number, 42); + assert.strictEqual(result.boolean, true); + }); + }); + + suite('Edge cases', () => { + test('should handle empty object', () => { + const input = {}; + const jsonString = JSON.stringify(input); + + const result: any = deserializeIpcData(jsonString, mockPromiseFactory); + + assert.deepStrictEqual(result, {}); + }); + + test('should handle primitive values', () => { + const input = { + string: 'test', + number: 42, + boolean: true, + null: null, + }; + const jsonString = JSON.stringify(input); + + const result: any = deserializeIpcData(jsonString, mockPromiseFactory); + + assert.strictEqual(result.string, 'test'); + assert.strictEqual(result.number, 42); + assert.strictEqual(result.boolean, true); + assert.strictEqual(result.null, null); + }); + + test('should handle JSON string input', () => { + const timestamp = new Date('2024-01-15T10:30:00.000Z').getTime(); + const jsonString = JSON.stringify({ + date: { __ipc: 'date', value: timestamp }, + value: 'test', + }); + + const result: any = deserializeIpcData(jsonString, mockPromiseFactory); + + assert.ok(result.date instanceof Date); + assert.strictEqual(result.date.getTime(), timestamp); + assert.strictEqual(result.value, 'test'); + }); + }); + }); +}); diff --git a/src/webviews/apps/shared/appBase.ts b/src/webviews/apps/shared/appBase.ts index 9b948275ec997..92c8e191558d7 100644 --- a/src/webviews/apps/shared/appBase.ts +++ b/src/webviews/apps/shared/appBase.ts @@ -15,7 +15,7 @@ import { DidChangeWebviewFocusNotification, DidChangeWebviewVisibilityNotification, WebviewFocusChangedCommand, - WebviewReadyCommand, + WebviewReadyRequest, } from '../../protocol'; import { ipcContext } from './contexts/ipc'; import { loggerContext, LoggerContext } from './contexts/logger'; @@ -126,7 +126,7 @@ export abstract class App< ); } - this.sendCommand(WebviewReadyCommand, undefined); + void this.sendRequest(WebviewReadyRequest, { bootstrap: false }); this.onInitialized?.(); } finally { diff --git a/src/webviews/apps/shared/appHost.ts b/src/webviews/apps/shared/appHost.ts index 07e3121be0d1c..4ad886e2d48b4 100644 --- a/src/webviews/apps/shared/appHost.ts +++ b/src/webviews/apps/shared/appHost.ts @@ -2,7 +2,6 @@ import { provide } from '@lit/context'; import type { ReactiveControllerHost } from 'lit'; import { html, LitElement } from 'lit'; import { property } from 'lit/decorators.js'; -import { fromBase64ToString } from '@env/base64'; import type { CustomEditorIds, WebviewIds, WebviewViewIds } from '../../../constants.views'; import type { Deferrable } from '../../../system/function/debounce'; import { debounce } from '../../../system/function/debounce'; @@ -11,7 +10,6 @@ import { DidChangeWebviewFocusNotification, DidChangeWebviewVisibilityNotification, WebviewFocusChangedCommand, - WebviewReadyCommand, } from '../../protocol'; import { GlElement } from './components/element'; import { ipcContext } from './contexts/ipc'; @@ -70,8 +68,7 @@ export abstract class GlAppHost< private _sendWebviewFocusChangedCommandDebounced!: Deferrable<(params: WebviewFocusChangedParams) => void>; protected _stateProvider!: Provider; - protected abstract createStateProvider(state: State, ipc: HostIpc): Provider; - protected onPersistState?(state: State): void; + protected abstract createStateProvider(bootstrap: string, ipc: HostIpc, logger: LoggerContext): Provider; protected onWebviewFocusChanged?(focused: boolean): void; protected onWebviewVisibilityChanged?(visible: boolean): void; @@ -82,12 +79,11 @@ export abstract class GlAppHost< this._logger.log('connected'); this._ipc = new HostIpc(this.name); - this._ipc.sendCommand(WebviewReadyCommand, undefined); - const state: State = JSON.parse(fromBase64ToString(this.bootstrap)); + const bootstrap = this.bootstrap; this.bootstrap = undefined!; - this._ipc.replaceIpcPromisesWithPromises(state); - this.onPersistState?.(state); + + this._stateProvider = this.createStateProvider(bootstrap, this._ipc, this._logger); const themeEvent = computeThemeColors(); if (this.onThemeUpdated != null) { @@ -97,7 +93,7 @@ export abstract class GlAppHost< } this.disposables.push( - (this._stateProvider = this.createStateProvider(state, this._ipc)), + this._stateProvider, this._ipc.onReceiveMessage(msg => { switch (true) { case DidChangeWebviewFocusNotification.is(msg): diff --git a/src/webviews/apps/shared/components/actions/action-item.ts b/src/webviews/apps/shared/components/actions/action-item.ts index c3ecbd6c3f234..6f6657e585517 100644 --- a/src/webviews/apps/shared/components/actions/action-item.ts +++ b/src/webviews/apps/shared/components/actions/action-item.ts @@ -21,7 +21,7 @@ export class ActionItem extends LitElement { width: 2rem; height: 2rem; border-radius: 0.5rem; - color: var(--vscode-icon-foreground); + color: var(--action-item-foreground, var(--vscode-icon-foreground)); padding: 0.2rem; vertical-align: text-bottom; text-decoration: none; @@ -53,10 +53,14 @@ export class ActionItem extends LitElement { justify-content: center; width: 100%; height: 100%; + text-decoration: none; } a:focus { outline: none; } + a:is(:hover, :focus, :active) { + text-decoration: none; + } `; @property() diff --git a/src/webviews/apps/shared/components/converters/date-converter.ts b/src/webviews/apps/shared/components/converters/date-converter.ts index c5f742936df65..7badc4ed73baa 100644 --- a/src/webviews/apps/shared/components/converters/date-converter.ts +++ b/src/webviews/apps/shared/components/converters/date-converter.ts @@ -6,6 +6,9 @@ export const dateConverter = (): ComplexAttributeConverter => { return date.getTime(); }, fromAttribute: (value: string, _type?: number) => { + const date = new Date(value); + if (!isNaN(date.getTime())) return date; + return new Date(parseInt(value, 10)); }, }; diff --git a/src/webviews/apps/shared/components/formatted-date.ts b/src/webviews/apps/shared/components/formatted-date.ts index 2e730e420f4e9..9a5b87606e9d5 100644 --- a/src/webviews/apps/shared/components/formatted-date.ts +++ b/src/webviews/apps/shared/components/formatted-date.ts @@ -12,7 +12,7 @@ export class FormattedDate extends LitElement { @property({ attribute: 'date-style' }) dateStyle: 'relative' | 'absolute' = 'relative'; - @property({ converter: dateConverter(), reflect: true }) + @property({ converter: dateConverter(), reflect: true, attribute: false }) date = new Date(); @property() diff --git a/src/webviews/apps/shared/components/tree/tree-generator.ts b/src/webviews/apps/shared/components/tree/tree-generator.ts index 40f9b5c312392..241a157882b12 100644 --- a/src/webviews/apps/shared/components/tree/tree-generator.ts +++ b/src/webviews/apps/shared/components/tree/tree-generator.ts @@ -20,6 +20,7 @@ import '../actions/action-item'; import '../status/git-status'; import '../code-icon'; import './tree-item'; +import type { GlTreeItem } from './tree-item'; @customElement('gl-tree-generator') export class GlTreeGenerator extends GlElement { @@ -101,6 +102,10 @@ export class GlTreeGenerator extends GlElement { this.addEventListener('keydown', this.handleKeydown, { capture: true }); this.addEventListener('focusin', this.handleFocusIn, { capture: true }); this.addEventListener('focusout', this.handleFocusOut, { capture: true }); + + // Listen for contextmenu events from tree items and re-dispatch them + // so they can cross the shadow DOM boundary with the context data + this.addEventListener('contextmenu', this.handleContextMenu); } override disconnectedCallback(): void { @@ -109,6 +114,7 @@ export class GlTreeGenerator extends GlElement { this.removeEventListener('keydown', this.handleKeydown, { capture: true }); this.removeEventListener('focusin', this.handleFocusIn, { capture: true }); this.removeEventListener('focusout', this.handleFocusOut, { capture: true }); + this.removeEventListener('contextmenu', this.handleContextMenu); // Clean up type-ahead timer and reset state if (this._typeAheadTimer) { @@ -231,6 +237,7 @@ export class GlTreeGenerator extends GlElement { .focused=${isFocused && this._containerHasFocus && !this._actionButtonHasFocus} .focusedInactive=${isFocused && (!this._containerHasFocus || this._actionButtonHasFocus)} .tabIndex=${-1} + .vscodeContext=${model.contextData as string | undefined} @gl-tree-item-select=${() => this.onBeforeTreeItemSelected(model)} @gl-tree-item-selected=${(e: CustomEvent) => this.onTreeItemSelected(e, model)} @gl-tree-item-checked=${(e: CustomEvent) => this.onTreeItemChecked(e, model)} @@ -407,6 +414,49 @@ export class GlTreeGenerator extends GlElement { } }; + private handleContextMenu = (e: MouseEvent) => { + // Find the tree-item element that triggered the context menu + const path = e.composedPath(); + const treeItem = path.find(el => (el as HTMLElement).tagName === 'GL-TREE-ITEM') as GlTreeItem | undefined; + if (!treeItem) return; + + // Get the context data from the tree-item + const contextData = treeItem.vscodeContext; + if (!contextData) return; + + // Prevent the original event from bubbling + e.preventDefault(); + e.stopPropagation(); + + // Copy the context data to this element (tree-generator host) + // so VS Code's injected library can read it + this.dataset.vscodeContext = contextData; + + // Re-dispatch the event from this element so it can cross the shadow DOM boundary + const evt = new MouseEvent('contextmenu', { + bubbles: true, + composed: true, + cancelable: true, + clientX: e.clientX, + clientY: e.clientY, + button: e.button, + buttons: e.buttons, + ctrlKey: e.ctrlKey, + shiftKey: e.shiftKey, + altKey: e.altKey, + metaKey: e.metaKey, + }); + + // Dispatch the new event + this.dispatchEvent(evt); + + // Clean up the context data after a short delay + // (VS Code should have read it by then) + setTimeout(() => { + delete this.dataset.vscodeContext; + }, 100); + }; + private handleKeydown = (e: KeyboardEvent) => { if (e.key !== 'Tab') return; diff --git a/src/webviews/apps/shared/components/tree/tree-item.ts b/src/webviews/apps/shared/components/tree/tree-item.ts index 9c316b8460482..5e2408a88df62 100644 --- a/src/webviews/apps/shared/components/tree/tree-item.ts +++ b/src/webviews/apps/shared/components/tree/tree-item.ts @@ -54,6 +54,9 @@ export class GlTreeItem extends GlElement { @property({ type: Number }) override tabIndex = -1; + @property({ type: String, attribute: 'vscode-context' }) + vscodeContext?: string; + // state @state() selected = false; @@ -183,6 +186,7 @@ export class GlTreeItem extends GlElement { tabindex=${this.tabIndex} @click=${this.onButtonClick} @dblclick=${this.onButtonDblClick} + @contextmenu=${this.onButtonContextMenu} > ${when(this.showIcon, () => html``)} @@ -244,6 +248,29 @@ export class GlTreeItem extends GlElement { }); } + private onButtonContextMenu(e: MouseEvent) { + e.preventDefault(); + e.stopPropagation(); + + // Create a new contextmenu event that can cross shadow DOM boundaries + const evt = new MouseEvent('contextmenu', { + bubbles: true, + composed: true, // This is key - allows event to cross shadow DOM boundaries + cancelable: true, + clientX: e.clientX, + clientY: e.clientY, + button: e.button, + buttons: e.buttons, + ctrlKey: e.ctrlKey, + shiftKey: e.shiftKey, + altKey: e.altKey, + metaKey: e.metaKey, + }); + + // Dispatch from the host element (outside shadow DOM) + this.dispatchEvent(evt); + } + private onCheckboxClick(e: Event) { e.stopPropagation(); } diff --git a/src/webviews/apps/shared/ipc.ts b/src/webviews/apps/shared/ipc.ts index 93cf1051086cd..8abec1ba37027 100644 --- a/src/webviews/apps/shared/ipc.ts +++ b/src/webviews/apps/shared/ipc.ts @@ -1,12 +1,14 @@ /*global window */ +import { inflateSync, strFromU8 } from 'fflate'; import { getScopedCounter } from '../../../system/counter'; import { debug, logName } from '../../../system/decorators/log'; +import { deserializeIpcData } from '../../../system/ipcSerialize'; import { Logger } from '../../../system/logger'; -import { getLogScope, getNewLogScope } from '../../../system/logger.scope'; +import { getLogScope, getNewLogScope, setLogScopeExit } from '../../../system/logger.scope'; import type { Serialized } from '../../../system/serialize'; import { maybeStopWatch } from '../../../system/stopwatch'; import type { IpcCallParamsType, IpcCallResponseParamsType, IpcCommand, IpcMessage, IpcRequest } from '../../protocol'; -import { ipcPromiseSettled, isIpcPromise } from '../../protocol'; +import { IpcPromiseSettled } from '../../protocol'; import { DOM } from './dom'; import type { Disposable, Event } from './events'; import { Emitter } from './events'; @@ -41,7 +43,6 @@ export class HostIpc implements Disposable { private readonly _api: HostIpcApi; private readonly _disposable: Disposable; private _pendingHandlers = new Map(); - private _textDecoder: TextDecoder | undefined; constructor(private readonly appName: string) { this._api = getHostIpcApi(); @@ -52,22 +53,42 @@ export class HostIpc implements Disposable { this._disposable.dispose(); } - @debug({ args: { 0: e => `${e.data.id}, method=${e.data.method}` } }) + @debug({ args: { 0: e => `${e.data.id}|${e.data.method}` } }) private onMessageReceived(e: MessageEvent) { const scope = getLogScope(); const msg = e.data as IpcMessage; - if (msg.packed && msg.params instanceof Uint8Array) { - const sw = maybeStopWatch(getNewLogScope(` deserializing msg=${e.data.method}`, scope), { - log: false, - logLevel: 'debug', - }); - this._textDecoder ??= new TextDecoder(); - msg.params = JSON.parse(this._textDecoder.decode(msg.params)); - sw?.stop(); + const sw = maybeStopWatch(getNewLogScope(`(e=${msg.id}|${msg.method})`, scope), { + log: false, + logLevel: 'debug', + }); + + if (msg.compressed && msg.params instanceof Uint8Array) { + if (msg.compressed === 'deflate') { + try { + msg.params = strFromU8(inflateSync(msg.params)); + } catch (ex) { + debugger; + console.warn('IPC deflate decompression failed, assuming uncompressed', ex); + msg.params = strFromU8(msg.params as Uint8Array); + } + } else { + msg.params = strFromU8(msg.params); + } + sw?.restart({ message: `\u2022 decompressed (${msg.compressed}) serialized params` }); } - this.replaceIpcPromisesWithPromises(msg.params); + if (typeof msg.params === 'string') { + msg.params = deserializeIpcData(msg.params, v => this.getResponsePromise(v.method, v.id)); + sw?.stop({ message: `\u2022 deserialized params` }); + } else if (msg.params == null) { + sw?.stop({ message: `\u2022 no params` }); + } else { + sw?.stop({ message: `\u2022 invalid params` }); + debugger; + } + + setLogScopeExit(scope, ` \u2022 ipc (host -> webview) duration=${Date.now() - msg.timestamp}ms`); // If we have a completionId, then this is a response to a request and it should be handled directly if (msg.completionId != null) { @@ -80,17 +101,8 @@ export class HostIpc implements Disposable { this._onReceiveMessage.fire(msg); } - replaceIpcPromisesWithPromises(data: unknown): void { - if (data == null || typeof data !== 'object') return; - - for (const key in data) { - const value = (data as Record)[key]; - if (isIpcPromise(value)) { - (data as Record)[key] = this.getResponsePromise(value.method, value.id); - } else { - this.replaceIpcPromisesWithPromises(value); - } - } + deserializeIpcData(data: string): T { + return deserializeIpcData(data, v => this.getResponsePromise(v.method, v.id)); } sendCommand(commandType: T, params?: never): void; @@ -105,6 +117,8 @@ export class HostIpc implements Disposable { scope: commandType.scope, method: commandType.method, params: params, + compressed: false, + timestamp: Date.now(), } satisfies IpcMessage>); } @@ -122,6 +136,8 @@ export class HostIpc implements Disposable { scope: requestType.scope, method: requestType.method, params: params, + compressed: false, + timestamp: Date.now(), completionId: id, } satisfies IpcMessage>); return promise; @@ -150,7 +166,7 @@ export class HostIpc implements Disposable { this._pendingHandlers.set(queueKey, msg => { dispose.call(this); - if (msg.method === ipcPromiseSettled.method) { + if (msg.method === IpcPromiseSettled.method) { const params = msg.params as PromiseSettledResult; if (params.status === 'rejected') { queueMicrotask(() => reject(new Error(params.reason))); diff --git a/src/webviews/apps/shared/stateProviderBase.ts b/src/webviews/apps/shared/stateProviderBase.ts new file mode 100644 index 0000000000000..c2eb06197bd0c --- /dev/null +++ b/src/webviews/apps/shared/stateProviderBase.ts @@ -0,0 +1,89 @@ +import type { Context, ContextProvider, ContextType } from '@lit/context'; +import { fromBase64ToString } from '@env/base64'; +import type { CustomEditorIds, WebviewIds, WebviewViewIds } from '../../../constants.views'; +import { isPromise } from '../../../system/promise'; +import type { IpcMessage, WebviewState } from '../../protocol'; +import { WebviewReadyRequest } from '../../protocol'; +import type { ReactiveElementHost } from './appHost'; +import type { LoggerContext } from './contexts/logger'; +import type { Disposable } from './events'; +import type { HostIpc } from './ipc'; + +/** + * Base class for webview state providers that handles bootstrap initialization. + * + * Subclasses declare their bootstrap strategy ('sync' or 'async') and implement + * message handling. The base class automatically handles state initialization: + * - Sync: Uses bootstrap state from HTML + * - Async: Requests full state from extension after connection + */ +export abstract class StateProviderBase< + ID extends WebviewIds | WebviewViewIds | CustomEditorIds, + State extends WebviewState, + TContext extends Context, +> implements Disposable +{ + protected readonly disposable: Disposable; + protected readonly provider: ContextProvider; + + protected _state: State; + get state(): State { + return this._state; + } + + get webviewId() { + return this._state.webviewId; + } + + get webviewInstanceId() { + return this._state.webviewInstanceId; + } + + get timestamp() { + return this._state.timestamp; + } + + constructor( + protected host: ReactiveElementHost, + bootstrap: string, + protected ipc: HostIpc, + protected logger: LoggerContext, + ) { + // Deserialize bootstrap from base64 + this._state = this.ipc.deserializeIpcData(fromBase64ToString(bootstrap)); + this.logger?.log(`bootstrap duration=${Date.now() - this._state.timestamp}ms`); + + this.provider = this.createContextProvider(this._state); + this.onPersistState?.(this._state); + + this.disposable = this.ipc.onReceiveMessage(this.onMessageReceived.bind(this)); + void this.initializeState(); + } + + dispose(): void { + this.disposable.dispose(); + } + + protected get deferBootstrap(): boolean { + return false; + } + + protected abstract createContextProvider(state: State): ContextProvider; + + protected async initializeState(): Promise { + if (this.deferBootstrap) { + const response = await this.ipc.sendRequest(WebviewReadyRequest, { bootstrap: true }); + if (response.state != null) { + const state: State = (isPromise(response.state) ? await response.state : response.state) as State; + this._state = { ...state, timestamp: Date.now() }; + this.provider.setValue(this._state as ContextType, true); + this.host.requestUpdate(); + } + } else { + void this.ipc.sendRequest(WebviewReadyRequest, { bootstrap: false }); + } + } + + protected abstract onMessageReceived(msg: IpcMessage): void; + protected onPersistState?(state: State): void; +} diff --git a/src/webviews/apps/tsconfig.json b/src/webviews/apps/tsconfig.json index 3844c9cad6bba..8e8975fe8f58e 100644 --- a/src/webviews/apps/tsconfig.json +++ b/src/webviews/apps/tsconfig.json @@ -12,6 +12,7 @@ // Keep in sync with `src/eslint.config.mjs` "include": [ "**/*", + "../ipc.ts", "../**/protocol.ts", "../../**/models/**/*.ts", "../../**/utils/**/*.ts", @@ -21,10 +22,8 @@ "../../constants.*.ts", "../../env/browser/**/*", "../../features.ts", - "../../git/parsers/diffParser.ts", "../../system/**/*.ts", - "../../**/webview/**/*", - "../plus/composer/utils.ts" + "../../**/webview/**/*" ], "exclude": ["src/**/__tests__/**/*", "src/**/-webview/**/*"] } diff --git a/src/webviews/commitDetails/commitDetailsWebview.ts b/src/webviews/commitDetails/commitDetailsWebview.ts index d5d13ef81d2b9..666c0a4cb0dba 100644 --- a/src/webviews/commitDetails/commitDetailsWebview.ts +++ b/src/webviews/commitDetails/commitDetailsWebview.ts @@ -1,15 +1,21 @@ import { EntityIdentifierUtils } from '@gitkraken/provider-apis/entity-identifiers'; -import type { CancellationToken, ConfigurationChangeEvent, TextDocumentShowOptions } from 'vscode'; +import type { ConfigurationChangeEvent, TextDocumentShowOptions } from 'vscode'; import { CancellationTokenSource, Disposable, env, Uri, window } from 'vscode'; import type { MaybeEnrichedAutolink } from '../../autolinks/models/autolinks'; import { serializeAutolink } from '../../autolinks/utils/-webview/autolinks.utils'; import { getAvatarUri } from '../../avatars'; +import type { CopyDeepLinkCommandArgs, CopyFileDeepLinkCommandArgs } from '../../commands/copyDeepLink'; import type { CopyMessageToClipboardCommandArgs } from '../../commands/copyMessageToClipboard'; import type { CopyShaToClipboardCommandArgs } from '../../commands/copyShaToClipboard'; +import type { DiffWithCommandArgs } from '../../commands/diffWith'; import type { ExplainCommitCommandArgs } from '../../commands/explainCommit'; import type { ExplainStashCommandArgs } from '../../commands/explainStash'; import type { ExplainWipCommandArgs } from '../../commands/explainWip'; +import type { OpenFileOnRemoteCommandArgs } from '../../commands/openFileOnRemote'; +import type { OpenOnRemoteCommandArgs } from '../../commands/openOnRemote'; import type { OpenPullRequestOnRemoteCommandArgs } from '../../commands/openPullRequestOnRemote'; +import type { CreatePatchCommandArgs } from '../../commands/patches'; +import type { WebviewViewCommandsOrCommandsWithSuffix } from '../../constants.commands'; import type { ContextKeys } from '../../constants.context'; import { isSupportedCloudIntegrationId } from '../../constants.integrations'; import type { InspectTelemetryContext, Sources } from '../../constants.telemetry'; @@ -17,11 +23,14 @@ import type { Container } from '../../container'; import type { CommitSelectedEvent } from '../../eventBus'; import { executeGitCommand } from '../../git/actions'; import { + applyChanges, openChanges, openChangesWithWorking, openComparisonChanges, openFile, + openFileAtRevision, openFileOnRemote, + restoreFile, showDetailsQuickPick, } from '../../git/actions/commit'; import * as RepoActions from '../../git/actions/repository'; @@ -34,10 +43,13 @@ import type { IssueOrPullRequest } from '../../git/models/issueOrPullRequest'; import type { PullRequest } from '../../git/models/pullRequest'; import type { GitRevisionReference } from '../../git/models/reference'; import type { GitRemote } from '../../git/models/remote'; +import { RemoteResourceType } from '../../git/models/remoteResource'; import type { Repository } from '../../git/models/repository'; import { RepositoryChange, RepositoryChangeComparisonMode } from '../../git/models/repository'; import { uncommitted, uncommittedStaged } from '../../git/models/revision'; +import type { RemoteProvider } from '../../git/remotes/remoteProvider'; import { getReferenceFromRevision } from '../../git/utils/-webview/reference.utils'; +import { splitCommitMessage } from '../../git/utils/commit.utils'; import { serializeIssueOrPullRequest } from '../../git/utils/issueOrPullRequest.utils'; import { getComparisonRefsForPullRequest, serializePullRequest } from '../../git/utils/pullRequest.utils'; import { createReference } from '../../git/utils/reference.utils'; @@ -55,10 +67,13 @@ import { executeCommand, executeCoreCommand, executeCoreGitCommand, - registerCommand, + registerWebviewCommand, } from '../../system/-webview/command'; import { configuration } from '../../system/-webview/configuration'; -import { getContext, onDidChangeContext } from '../../system/-webview/context'; +import { getContext, onDidChangeContext, setContext } from '../../system/-webview/context'; +import type { MergeEditorInputs } from '../../system/-webview/vscode/editors'; +import { openMergeEditor } from '../../system/-webview/vscode/editors'; +import { createCommandDecorator, getWebviewViewCommand } from '../../system/decorators/command'; import { debug } from '../../system/decorators/log'; import type { Deferrable } from '../../system/function/debounce'; import { debounce } from '../../system/function/debounce'; @@ -67,20 +82,23 @@ import { Logger } from '../../system/logger'; import { getLogScope } from '../../system/logger.scope'; import { MRU } from '../../system/mru'; import { getSettledValue, pauseOnCancelOrTimeoutMapTuplePromise } from '../../system/promise'; -import type { Serialized } from '../../system/serialize'; -import { serialize } from '../../system/serialize'; import type { LinesChangeEvent } from '../../trackers/lineTracker'; import type { ShowInCommitGraphCommandArgs } from '../plus/graph/registration'; import type { Change } from '../plus/patchDetails/protocol'; import type { IpcCallMessageType, IpcMessage } from '../protocol'; -import { updatePendingContext } from '../webviewController'; import type { WebviewHost, WebviewProvider, WebviewShowingArgs } from '../webviewProvider'; import type { WebviewShowOptions } from '../webviewsController'; import { isSerializedState } from '../webviewsController'; +import { + getFileCommitFromContext, + getUriFromContext, + isDetailsFileContext, + isDetailsItemContext, +} from './commitDetailsWebview.utils'; import type { CommitDetails, CreatePatchFromWipParams, - DidChangeWipStateParams, + DetailsItemContext, DidExplainParams, DidGenerateParams, ExecuteFileActionParams, @@ -102,6 +120,7 @@ import { DidChangeHasAccountNotification, DidChangeIntegrationsNotification, DidChangeNotification, + DidChangeOrgSettingsNotification, DidChangeWipStateNotification, ExecuteCommitActionCommand, ExecuteFileActionCommand, @@ -134,6 +153,9 @@ import { } from './protocol'; import type { CommitDetailsWebviewShowingArgs } from './registration'; +const { command, getCommands } = + createCommandDecorator>(); + type RepositorySubscription = { repo: Repository; subscription: Disposable }; // interface WipContext extends Wip @@ -159,7 +181,6 @@ interface Context { commit: GitCommit | undefined; autolinksEnabled: boolean; experimentalComposerEnabled: boolean; - richStateLoaded: boolean; formattedMessage: string | undefined; autolinkedIssues: IssueOrPullRequest[] | undefined; pullRequest: PullRequest | undefined; @@ -171,14 +192,9 @@ interface Context { hasIntegrationsConnected: boolean | undefined; } -export class CommitDetailsWebviewProvider - implements WebviewProvider, CommitDetailsWebviewShowingArgs> -{ - private _bootstraping = true; +export class CommitDetailsWebviewProvider implements WebviewProvider { /** The context the webview has */ private _context: Context; - /** The context the webview should have */ - private _pendingContext: Partial | undefined; private readonly _disposable: Disposable; private _pinned = false; private _focused = false; @@ -202,7 +218,6 @@ export class CommitDetailsWebviewProvider commit: undefined, autolinksEnabled: configuration.get('views.commitDetails.autolinks.enabled'), experimentalComposerEnabled: configuration.get('ai.experimental.composer.enabled', undefined, false), - richStateLoaded: false, formattedMessage: undefined, autolinkedIssues: undefined, pullRequest: undefined, @@ -268,7 +283,7 @@ export class CommitDetailsWebviewProvider async onShowing( _loading: boolean, options?: WebviewShowOptions, - ...args: WebviewShowingArgs> + ...args: WebviewShowingArgs ): Promise<[boolean, InspectTelemetryContext]> { const [arg] = args; if ((arg as ShowWipArgs)?.type === 'wip') { @@ -282,15 +297,15 @@ export class CommitDetailsWebviewProvider } private get inReview(): boolean { - return this._pendingContext?.inReview ?? this._context.inReview; + return this._context.inReview; } async onShowingWip(arg: ShowWipArgs, options?: WebviewShowOptions): Promise { - this.updatePendingContext({ source: arg.source }); + this._context.source = arg.source; const shouldChangeReview = arg.inReview != null && this.inReview !== arg.inReview; if (this.mode !== 'wip' || (arg.repository != null && this._context.wip?.repo !== arg.repository)) { - if (shouldChangeReview) { - this.updatePendingContext({ inReview: arg.inReview }); + if (shouldChangeReview && arg.inReview != null) { + this._context.inReview = arg.inReview; } await this.setMode('wip', arg.repository); if (shouldChangeReview && arg.inReview === true) { @@ -316,7 +331,7 @@ export class CommitDetailsWebviewProvider ): Promise { let data: Partial | undefined; - if (isSerializedState>(arg)) { + if (isSerializedState(arg)) { const { commit: selected } = arg.state; if (selected?.repoPath != null && selected?.sha != null) { if (selected.stashNumber != null) { @@ -390,17 +405,27 @@ export class CommitDetailsWebviewProvider }); } - includeBootstrap(): Promise> { - this._bootstraping = true; - - this._context = { ...this._context, ...this._pendingContext }; - this._pendingContext = undefined; - + includeBootstrap(deferrable?: boolean): Promise { + if (deferrable) { + return Promise.resolve({ + webviewId: this.host.id, + webviewInstanceId: this.host.instanceId, + timestamp: Date.now(), + } as State); + } return this.getState(this._context); } registerCommands(): Disposable[] { - return [registerCommand(`${this.host.id}.refresh`, () => this.host.refresh(true))]; + const subscriptions: Disposable[] = [ + registerWebviewCommand(`${this.host.id}.refresh`, () => this.host.refresh(true)), + ]; + + for (const { command, handler } of getCommands()) { + subscriptions.push(registerWebviewCommand(getWebviewViewCommand(command, this.host.type), handler, this)); + } + + return subscriptions; } onFocusChanged(focused: boolean): void { @@ -423,11 +448,11 @@ export class CommitDetailsWebviewProvider break; case OpenFileCompareWorkingCommand.is(e): - void this.openFileComparisonWithWorking(e.params); + void this.openFileChangesWithWorking(e.params); break; case OpenFileComparePreviousCommand.is(e): - void this.openFileComparisonWithPrevious(e.params); + void this.openChanges(e.params); break; case ExecuteFileActionCommand.is(e): @@ -831,7 +856,7 @@ export class CommitDetailsWebviewProvider this.container.git.getBestRepositoryOrFirst(uri != null ? Uri.parse(uri) : undefined), ); } else { - const commit = this._pendingContext?.commit ?? this.getBestCommitOrStash(); + const commit = this.getBestCommitOrStash(); void this.updateCommit(commit, { immediate: false }); } } @@ -849,19 +874,10 @@ export class CommitDetailsWebviewProvider this._skipNextRefreshOnVisibilityChange = false; } - // Since this gets called even the first time the webview is shown, avoid sending an update, because the bootstrap has the data - if (this._bootstraping) { - this._bootstraping = false; - - if (this._pendingContext == null) return; - - this.updateState(); - } else { - if (!skipRefresh) { - this.onRefresh(); - } - this.updateState(true); + if (!skipRefresh) { + this.onRefresh(); } + void this.notifyDidChangeState(true); } private onAnyConfigurationChanged(e: ConfigurationChangeEvent) { @@ -876,14 +892,8 @@ export class CommitDetailsWebviewProvider configuration.changedCore(e, 'workbench.tree.renderIndentGuides') || configuration.changedCore(e, 'workbench.tree.indent') ) { - this.updatePendingContext({ - preferences: { - ...this._context.preferences, - ...this._pendingContext?.preferences, - ...this.getPreferences(), - }, - }); - this.updateState(); + this._context.preferences = this.getPreferences(); + void this.notifyDidChangeState(); } if ( @@ -891,7 +901,6 @@ export class CommitDetailsWebviewProvider configuration.changed(e, ['views.commitDetails.autolinks', 'views.commitDetails.pullRequests']) ) { void this.updateCommit(this._context.commit, { force: true }); - this.updateState(); } } @@ -904,8 +913,7 @@ export class CommitDetailsWebviewProvider const hasAccount = subscription.account != null; if (this._context.hasAccount === hasAccount) return; - this._context.hasAccount = hasAccount; - void this.host.notify(DidChangeHasAccountNotification, { hasAccount: hasAccount }); + this.notifyDidChangeHasAccount(hasAccount); } async getHasAccount(force = false): Promise { @@ -921,9 +929,7 @@ export class CommitDetailsWebviewProvider const current = await this.getHasIntegrationsConnected(true); if (previous === current) return; - void this.host.notify(DidChangeIntegrationsNotification, { - hasIntegrationsConnected: current, - }); + this.notifyDidChangeIntegrations(current); } async getHasIntegrationsConnected(force = false): Promise { @@ -956,8 +962,7 @@ export class CommitDetailsWebviewProvider private onContextChanged(key: keyof ContextKeys) { if (['gitlens:gk:organization:ai:enabled', 'gitlens:gk:organization:drafts:enabled'].includes(key)) { - this.updatePendingContext({ orgSettings: this.getOrgSettings() }); - this.updateState(); + this.notifyDidChangeOrgSettings(); } } @@ -1096,14 +1101,13 @@ export class CommitDetailsWebviewProvider private _wipSubscription: RepositorySubscription | undefined; private get mode(): Mode { - return this._pendingContext?.mode ?? this._context.mode; + return this._context.mode; } private async setMode(mode: Mode, repository?: Repository): Promise { - this.updatePendingContext({ mode: mode }); - if (mode === 'commit') { - this.updateState(true); - } else { + this._context.mode = mode; + void this.notifyDidChangeState(true); + if (mode === 'wip') { await this.updateWipState(repository ?? this.container.git.getBestRepositoryOrFirst()); } @@ -1211,7 +1215,7 @@ export class CommitDetailsWebviewProvider private _cancellationTokenSource: CancellationTokenSource | undefined = undefined; @debug({ args: false }) - protected async getState(current: Context): Promise> { + protected async getState(current: Context): Promise { if (this._cancellationTokenSource != null) { this._cancellationTokenSource.cancel(); this._cancellationTokenSource = undefined; @@ -1220,16 +1224,6 @@ export class CommitDetailsWebviewProvider let details; if (current.commit != null) { details = await this.getDetailsModel(current.commit, current.formattedMessage); - - if (!current.richStateLoaded) { - this._cancellationTokenSource = new CancellationTokenSource(); - - const cancellation = this._cancellationTokenSource.token; - setTimeout(() => { - if (cancellation.isCancellationRequested) return; - void this.updateRichState(current, cancellation); - }, 100); - } } const wip = current.wip; @@ -1244,32 +1238,26 @@ export class CommitDetailsWebviewProvider }, 100); } - if (current.hasAccount == null) { - current.hasAccount = await this.getHasAccount(); - } + current.hasAccount ??= await this.getHasAccount(); + current.hasIntegrationsConnected ??= await this.getHasIntegrationsConnected(); - if (current.hasIntegrationsConnected == null) { - current.hasIntegrationsConnected = await this.getHasIntegrationsConnected(); - } - - const state = serialize({ + const state: State = { ...this.host.baseWebviewState, mode: current.mode, commit: details, navigationStack: current.navigationStack, pinned: current.pinned, preferences: current.preferences, - includeRichContent: current.richStateLoaded, autolinksEnabled: current.autolinksEnabled, experimentalComposerEnabled: current.experimentalComposerEnabled, - autolinkedIssues: current.autolinkedIssues?.map(serializeIssueOrPullRequest), - pullRequest: current.pullRequest != null ? serializePullRequest(current.pullRequest) : undefined, + autolinkedIssues: current.autolinkedIssues, //?.map(serializeIssueOrPullRequest), + pullRequest: current.pullRequest, // != null ? serializePullRequest(current.pullRequest) : undefined, wip: serializeWipContext(wip), orgSettings: current.orgSettings, inReview: current.inReview, hasAccount: current.hasAccount, hasIntegrationsConnected: current.hasIntegrationsConnected, - }); + }; return state; } @@ -1318,30 +1306,26 @@ export class CommitDetailsWebviewProvider if ( this._shouldRefreshPullRequestDetails && wip.pullRequest != null && - (this._context.source === 'launchpad' || this._pendingContext?.source === 'launchpad') + this._context.source === 'launchpad' ) { void this.container.views.pullRequest.showPullRequest(wip.pullRequest, wip.branch ?? repository.path); this._shouldRefreshPullRequestDetails = false; } - if (this._pendingContext == null) { - const success = await this.host.notify( - DidChangeWipStateNotification, - serialize({ - wip: serializeWipContext(wip), - inReview: inReview, - }) as DidChangeWipStateParams, - ); - if (success) { - this._context.wip = wip; - this._context.inReview = inReview; - return; - } + const success = await this.host.notify(DidChangeWipStateNotification, { + wip: serializeWipContext(wip), + inReview: inReview, + }); + if (success) { + this._context.wip = wip; + this._context.inReview = inReview; + return; } } - this.updatePendingContext({ wip: wip, inReview: inReview }); - this.updateState(true); + this._context.wip = wip; + this._context.inReview = inReview; + void this.notifyDidChangeState(true); } private async getWipBranchDetails( @@ -1417,75 +1401,14 @@ export class CommitDetailsWebviewProvider ? await this.getCodeSuggestions(pullRequest!, repo) : []; - if (this._pendingContext == null) { - const success = await this.host.notify( - DidChangeWipStateNotification, - serialize({ - wip: serializeWipContext(wip), - }) as DidChangeWipStateParams, - ); - if (success) { - this._context.wip = wip; - return; - } + const success = await this.host.notify(DidChangeWipStateNotification, { wip: serializeWipContext(wip) }); + if (success) { + this._context.wip = wip; + return; } - this.updatePendingContext({ wip: wip }); - this.updateState(true); - } - - @debug({ args: false }) - private async updateRichState(current: Context, cancellation: CancellationToken): Promise { - const { commit } = current; - if (commit == null) return; - - const remote = await this.container.git - .getRepositoryService(commit.repoPath) - .remotes.getBestRemoteWithIntegration(); - - if (cancellation.isCancellationRequested) return; - - const [enrichedAutolinksResult, prResult] = - remote?.provider != null && current.autolinksEnabled - ? await Promise.allSettled([ - configuration.get('views.commitDetails.autolinks.enhanced') - ? pauseOnCancelOrTimeoutMapTuplePromise(commit.getEnrichedAutolinks(remote)) - : undefined, - configuration.get('views.commitDetails.pullRequests.enabled') - ? commit.getAssociatedPullRequest(remote) - : undefined, - ]) - : []; - - if (cancellation.isCancellationRequested) return; - - const enrichedAutolinks = getSettledValue(enrichedAutolinksResult)?.value; - const pr = getSettledValue(prResult); - - const formattedMessage = this.getFormattedMessage(commit, remote, enrichedAutolinks); - - this.updatePendingContext({ - autolinksEnabled: current.autolinksEnabled, - experimentalComposerEnabled: current.experimentalComposerEnabled, - richStateLoaded: true, - formattedMessage: formattedMessage, - autolinkedIssues: - enrichedAutolinks != null - ? [...filterMap(enrichedAutolinks.values(), ([issueOrPullRequest]) => issueOrPullRequest?.value)] - : undefined, - pullRequest: pr, - }); - - this.updateState(); - - // return { - // formattedMessage: formattedMessage, - // pullRequest: pr, - // autolinkedIssues: - // autolinkedIssuesAndPullRequests != null - // ? [...autolinkedIssuesAndPullRequests.values()].filter((i: T | undefined): i is T => i != null) - // : undefined, - // }; + this._context.wip = wip; + void this.notifyDidChangeState(true); } private _repositorySubscription: RepositorySubscription | undefined; @@ -1511,7 +1434,7 @@ export class CommitDetailsWebviewProvider } } - let wip = this._pendingContext?.wip ?? this._context.wip; + let wip = this._context.wip; if (this._repositorySubscription != null) { const { repo, subscription } = this._repositorySubscription; @@ -1535,23 +1458,17 @@ export class CommitDetailsWebviewProvider } } - this.updatePendingContext( - { - commit: commit, - autolinksEnabled: configuration.get('views.commitDetails.autolinks.enabled'), - experimentalComposerEnabled: configuration.get('ai.experimental.composer.enabled', undefined, false), - richStateLoaded: - Boolean(commit?.isUncommitted) || - (commit != null - ? !getContext('gitlens:repos:withHostingIntegrationsConnected')?.includes(commit.repoPath) - : !getContext('gitlens:repos:withHostingIntegrationsConnected')), - formattedMessage: undefined, - autolinkedIssues: undefined, - pullRequest: undefined, - wip: wip, - }, - options?.force, + this._context.commit = commit; + this._context.autolinksEnabled = configuration.get('views.commitDetails.autolinks.enabled'); + this._context.experimentalComposerEnabled = configuration.get( + 'ai.experimental.composer.enabled', + undefined, + false, ); + this._context.formattedMessage = undefined; + this._context.autolinkedIssues = undefined; + this._context.pullRequest = undefined; + this._context.wip = wip; if (options?.pinned != null) { this.updatePinned(options?.pinned); @@ -1568,7 +1485,7 @@ export class CommitDetailsWebviewProvider this.updateNavigation(); } - this.updateState(options?.immediate ?? true); + this.notifyDidChangeCommit(options?.immediate ?? true); this.updateTitle(); } @@ -1625,8 +1542,8 @@ export class CommitDetailsWebviewProvider this._pinned = pinned; this.ensureTrackers(); - this.updatePendingContext({ pinned: pinned }); - this.updateState(immediate); + this._context.pinned = pinned; + this.notifyDidChangeCommit(immediate); } private updatePreferences(preferences: UpdateablePreferences) { @@ -1642,7 +1559,6 @@ export class CommitDetailsWebviewProvider const changes: Preferences = { ...this._context.preferences, - ...this._pendingContext?.preferences, }; if ( @@ -1673,32 +1589,39 @@ export class CommitDetailsWebviewProvider changes.files = preferences.files; } - this.updatePendingContext({ preferences: changes }); - this.updateState(); + this._context.preferences = changes; + this.notifyDidChangeCommit(); } - private updatePendingContext(context: Partial, force: boolean = false): boolean { - const [changed, pending] = updatePendingContext(this._context, this._pendingContext, context, force); - if (changed) { - this._pendingContext = pending; - } - - return changed; - } + private _notifyDidChangeCommitDebounced: Deferrable<() => void> | undefined = undefined; - private _notifyDidChangeStateDebounced: Deferrable<() => void> | undefined = undefined; - - private updateState(immediate: boolean = false) { + private notifyDidChangeCommit(immediate: boolean = false) { if (immediate) { void this.notifyDidChangeState(); return; } - if (this._notifyDidChangeStateDebounced == null) { - this._notifyDidChangeStateDebounced = debounce(this.notifyDidChangeState.bind(this), 500); - } + this._notifyDidChangeCommitDebounced ??= debounce(this.notifyDidChangeState.bind(this), 500); + this._notifyDidChangeCommitDebounced(); + } - this._notifyDidChangeStateDebounced(); + private notifyDidChangeOrgSettings() { + this._context.orgSettings = this.getOrgSettings(); + void this.host.notify(DidChangeOrgSettingsNotification, { + orgSettings: this._context.orgSettings, + }); + } + + private notifyDidChangeHasAccount(hasAccount: boolean) { + this._context.hasAccount = hasAccount; + void this.host.notify(DidChangeHasAccountNotification, { hasAccount: hasAccount }); + } + + private notifyDidChangeIntegrations(hasIntegrationsConnected: boolean) { + this._context.hasIntegrationsConnected = hasIntegrationsConnected; + void this.host.notify(DidChangeIntegrationsNotification, { + hasIntegrationsConnected: hasIntegrationsConnected, + }); } private updateNavigation() { @@ -1706,53 +1629,43 @@ export class CommitDetailsWebviewProvider if (sha != null) { sha = shortenRevision(sha); } - this.updatePendingContext({ - navigationStack: { - count: this._commitStack.count, - position: this._commitStack.position, - hint: sha, - }, - }); - this.updateState(); + this._context.navigationStack = { + count: this._commitStack.count, + position: this._commitStack.position, + hint: sha, + }; + this.notifyDidChangeCommit(); } private async setInReview(inReview: boolean, source?: ShowWipArgs['source']) { if (this.inReview === inReview) return; - if (this._pendingContext == null) { - const success = await this.host.notify(DidChangeDraftStateNotification, { inReview: inReview }); - if (success) { - this._context.inReview = inReview; + const success = await this.host.notify(DidChangeDraftStateNotification, { inReview: inReview }); + if (success) { + this._context.inReview = inReview; + if (inReview) { + void this.trackOpenReviewMode(source); } + return; } - this.updatePendingContext({ inReview: inReview }); - this.updateState(true); + this._context.inReview = inReview; + void this.notifyDidChangeState(true); if (inReview) { void this.trackOpenReviewMode(source); } } - private async notifyDidChangeState(force: boolean = false) { + private async notifyDidChangeState(_force?: boolean) { const scope = getLogScope(); - this._notifyDidChangeStateDebounced?.cancel(); - if (!force && this._pendingContext == null) return false; - - let context: Context; - if (this._pendingContext != null) { - context = { ...this._context, ...this._pendingContext }; - this._context = context; - this._pendingContext = undefined; - } else { - context = this._context; - } + this._notifyDidChangeCommitDebounced?.cancel(); return window.withProgress({ location: { viewId: this.host.id } }, async () => { try { await this.host.notify(DidChangeNotification, { - state: await this.getState(context), + state: await this.getState(this._context), }); } catch (ex) { Logger.error(ex, scope); @@ -1764,7 +1677,7 @@ export class CommitDetailsWebviewProvider private getBestCommitOrStash(): GitCommit | GitRevisionReference | undefined { if (this._pinned) return undefined; - let commit; + let commit: GitCommit | GitRevisionReference | undefined; if (this.options.attachedTo !== 'graph' && window.activeTextEditor != null) { const { lineTracker } = this.container; @@ -1772,9 +1685,15 @@ export class CommitDetailsWebviewProvider if (line != null) { commit = lineTracker.getState(line)?.commit; } - } else { - commit = this._pendingContext?.commit; - if (commit == null) { + } + + if (commit == null) { + // For graphDetails, use source-specific cache to avoid stale data from other contexts + if (this.options.attachedTo === 'graph') { + const args = this.container.events.getCachedEventArgsBySource('commit:selected', 'gitlens.views.graph'); + commit = args?.commit; + } else { + // For commitDetails, use the general cache (for backward compatibility) const args = this.container.events.getCachedEventArgs('commit:selected'); commit = args?.commit; } @@ -1785,7 +1704,9 @@ export class CommitDetailsWebviewProvider private async getDetailsModel(commit: GitCommit, formattedMessage?: string): Promise { const [commitResult, avatarUriResult, remoteResult] = await Promise.allSettled([ - !commit.hasFullDetails() ? commit.ensureFullDetails().then(() => commit) : commit, + !commit.hasFullDetails() + ? commit.ensureFullDetails({ include: { uncommittedFiles: true } }).then(() => commit) + : commit, commit.author.getAvatarUri(commit, { size: 32 }), this.container.git .getRepositoryService(commit.repoPath) @@ -1795,10 +1716,7 @@ export class CommitDetailsWebviewProvider commit = getSettledValue(commitResult, commit); const avatarUri = getSettledValue(avatarUriResult); const remote = getSettledValue(remoteResult); - - if (formattedMessage == null) { - formattedMessage = this.getFormattedMessage(commit, remote); - } + formattedMessage ??= this.getFormattedMessage(commit, remote); const autolinks = commit.message != null ? await this.container.autolinks.getAutolinks(commit.message, remote) : undefined; @@ -1812,9 +1730,52 @@ export class CommitDetailsWebviewProvider message: formattedMessage, parents: commit.parents, stashNumber: commit.refType === 'stash' ? commit.stashNumber : undefined, - files: commit.fileset?.files, + files: commit.isUncommitted ? commit.anyFiles : commit.fileset?.files, stats: commit.stats, autolinks: autolinks != null ? [...map(autolinks.values(), serializeAutolink)] : undefined, + + enriched: this.getEnrichedState(commit, remote), + }; + } + + @debug({ args: false }) + private async getEnrichedState( + commit: GitCommit, + remote: GitRemote | undefined, + ): Promise['enriched']>>> { + const [enrichedAutolinksResult, prResult] = + remote?.provider != null + ? await Promise.allSettled([ + configuration.get('views.commitDetails.autolinks.enabled') && + configuration.get('views.commitDetails.autolinks.enhanced') + ? pauseOnCancelOrTimeoutMapTuplePromise( + commit.getEnrichedAutolinks(remote as GitRemote), + ) + : undefined, + configuration.get('views.commitDetails.pullRequests.enabled') + ? commit.getAssociatedPullRequest(remote as GitRemote) + : undefined, + ]) + : []; + + const enrichedAutolinks = getSettledValue(enrichedAutolinksResult)?.value; + const pr = getSettledValue(prResult); + + const issues = + enrichedAutolinks != null + ? [ + ...filterMap(enrichedAutolinks.values(), ([issueOrPullRequest]) => + issueOrPullRequest?.value != null + ? serializeIssueOrPullRequest(issueOrPullRequest.value) + : undefined, + ), + ] + : []; + + return { + formattedMessage: this.getFormattedMessage(commit, remote, enrichedAutolinks), + associatedPullRequest: pr != null ? serializePullRequest(pr) : undefined, + autolinkedIssues: issues, }; } @@ -1839,13 +1800,27 @@ export class CommitDetailsWebviewProvider ); } + private async getFileCommitFromContextOrParams( + item: DetailsItemContext | ExecuteFileActionParams | undefined, + ): Promise<[commit: GitCommit, file: GitFileChange] | [commit?: undefined, file?: undefined]> { + if (item == null) return []; + + if (isDetailsItemContext(item)) { + if (!isDetailsFileContext(item)) return []; + + return getFileCommitFromContext(this.container, item.webviewItemValue); + } + + return this.getFileCommitFromParams(item); + } + private async getFileCommitFromParams( params: ExecuteFileActionParams, - ): Promise<[commit: GitCommit, file: GitFileChange] | undefined> { + ): Promise<[commit: GitCommit, file: GitFileChange] | [commit?: undefined, file?: undefined]> { let commit: GitCommit | undefined; if (this.mode === 'wip') { const uri = this._context.wip?.changes?.repository.uri; - if (uri == null) return; + if (uri == null) return []; commit = await this.container.git.getRepositoryService(Uri.parse(uri)).commits.getCommit(uncommitted); } else { @@ -1853,7 +1828,7 @@ export class CommitDetailsWebviewProvider } commit = await commit?.getCommitForFile(params.path, params.staged); - return commit != null ? [commit, commit.file!] : undefined; + return commit != null ? [commit, commit.file!] : []; } private showCommitPicker() { @@ -1878,10 +1853,8 @@ export class CommitDetailsWebviewProvider } private async showFileActions(params: ExecuteFileActionParams) { - const result = await this.getFileCommitFromParams(params); - if (result == null) return; - - const [commit, file] = result; + const [commit, file] = await this.getFileCommitFromParams(params); + if (commit == null) return; this.suspendLineTracker(); void showDetailsQuickPick(commit, file); @@ -1917,81 +1890,434 @@ export class CommitDetailsWebviewProvider ); } - private async openFileComparisonWithWorking(params: ExecuteFileActionParams) { - const result = await this.getFileCommitFromParams(params); - if (result == null) return; + @command('gitlens.views.openChanges:') + private async openChanges(item: DetailsItemContext | ExecuteFileActionParams | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; - const [commit, file] = result; + this.suspendLineTracker(); + void openChanges(file, commit, { preserveFocus: true, preview: true, ...this.getShowOptions(item) }); + this.container.events.fire('file:selected', { uri: file.uri }, { source: this.host.id }); + } + + @command('gitlens.views.openChangesWithWorking:') + private async openFileChangesWithWorking(item: DetailsItemContext | ExecuteFileActionParams | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; this.suspendLineTracker(); void openChangesWithWorking(file, commit, { preserveFocus: true, preview: true, - ...this.getShowOptions(params), + ...this.getShowOptions(item), }); } - private async openFileComparisonWithPrevious(params: ExecuteFileActionParams) { - const result = await this.getFileCommitFromParams(params); - if (result == null) return; - - const [commit, file] = result; + @command('gitlens.views.openPreviousChangesWithWorking:') + private async openPreviousFileChangesWithWorking(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; this.suspendLineTracker(); - void openChanges(file, commit, { - preserveFocus: true, - preview: true, - ...this.getShowOptions(params), - }); + void openChangesWithWorking( + file, + { repoPath: commit.repoPath, ref: commit.unresolvedPreviousSha }, + { preserveFocus: true, preview: true, ...this.getShowOptions(item) }, + ); this.container.events.fire('file:selected', { uri: file.uri }, { source: this.host.id }); } - private async openFile(params: ExecuteFileActionParams) { - const result = await this.getFileCommitFromParams(params); - if (result == null) return; + @command('gitlens.views.openFile:') + private async openFile(item: DetailsItemContext | ExecuteFileActionParams | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + this.suspendLineTracker(); + void openFile(file, commit, { preserveFocus: true, preview: true }); + } + + @command('gitlens.openFileOnRemote:') + private async openFileOnRemote(item: DetailsItemContext | ExecuteFileActionParams | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void openFileOnRemote(file, commit); + } + + @command('gitlens.views.stageFile:') + private async stageFile(item: DetailsItemContext | ExecuteFileActionParams | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + await this.container.git.getRepositoryService(commit.repoPath).staging?.stageFile(file.uri); + } + + @command('gitlens.views.unstageFile:') + private async unstageFile(item: DetailsItemContext | ExecuteFileActionParams | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + await this.container.git.getRepositoryService(commit.repoPath).staging?.unstageFile(file.uri); + } - const [commit, file] = result; + private getShowOptions( + item: DetailsItemContext | ExecuteFileActionParams | undefined, + ): TextDocumentShowOptions | undefined { + return isDetailsItemContext(item) ? undefined : item?.showOptions; + + // return getContext('gitlens:webview:graph:active') || getContext('gitlens:webview:rebase:active') + // ? { ...params.showOptions, viewColumn: ViewColumn.Beside } : params.showOptions; + } + + @command('gitlens.views.copy:') + private async copy(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void env.clipboard.writeText(file.path); + } + + @command('gitlens.copyRelativePathToClipboard:') + private async copyRelativePath(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + const path = this.container.git.getRelativePath(file.uri, commit.repoPath); + void env.clipboard.writeText(path); + } + + @command('gitlens.copyPatchToClipboard:') + private async copyPatch(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + if (commit.message == null) { + await commit.ensureFullDetails(); + } + + const { summary: title, body: description } = splitCommitMessage(commit.message); + + void executeCommand('gitlens.copyPatchToClipboard', { + repoPath: commit.repoPath, + to: commit.ref, + from: `${commit.ref}^`, + title: title, + description: description, + uris: [file.uri], + }); + } + + @command('gitlens.views.openFileRevision:') + private async openFileRevision(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; this.suspendLineTracker(); - void openFile(file, commit, { - preserveFocus: true, - preview: true, - ...this.getShowOptions(params), + void openFileAtRevision(file, commit, { preserveFocus: true, preview: false }); + } + + @command('gitlens.openFileHistory:') + private async openFileHistory(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void executeCommand('gitlens.openFileHistory', file.uri); + } + + @command('gitlens.quickOpenFileHistory:') + private async quickOpenFileHistory(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void executeCommand('gitlens.quickOpenFileHistory', file.uri); + } + + @command('gitlens.visualizeHistory.file:') + private async visualizeFileHistory(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void executeCommand('gitlens.visualizeHistory.file', file.uri); + } + + @command('gitlens.restore.file:') + private async restoreFile(item: DetailsItemContext | undefined) { + if (!isDetailsFileContext(item)) return; + + const { path, repoPath, sha } = item.webviewItemValue; + if (sha == null || sha === uncommitted) return; + + await this.container.git.getRepositoryService(repoPath).ops?.checkout(sha, { path: path }); + } + + @command('gitlens.restorePrevious.file:') + private async restorePreviousFile(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void restoreFile(file, commit, true); + } + + @command('gitlens.views.selectFileForCompare:') + private selectFileForCompare(item: DetailsItemContext | undefined) { + if (!isDetailsFileContext(item)) return; + + const { repoPath, sha } = item.webviewItemValue; + const uri = getUriFromContext(this.container, item.webviewItemValue); + if (uri == null) return; + + void setContext('gitlens:views:canCompare:file', { ref: sha ?? uncommitted, repoPath: repoPath, uri: uri }); + } + + @command('gitlens.views.compareFileWithSelected:') + private async compareFileWithSelected(item: DetailsItemContext | undefined) { + const selectedFile = getContext('gitlens:views:canCompare:file'); + if (selectedFile == null || !isDetailsFileContext(item)) return; + + void setContext('gitlens:views:canCompare:file', undefined); + + const { repoPath, sha } = item.webviewItemValue; + if (selectedFile.repoPath !== repoPath) { + this.selectFileForCompare(item); + return; + } + + const uri = getUriFromContext(this.container, item.webviewItemValue); + if (uri == null) return; + + await this.compareFileWith(selectedFile.repoPath, selectedFile.uri, selectedFile.ref, uri, sha ?? uncommitted); + } + + private async compareFileWith( + repoPath: string, + lhsUri: Uri, + lhsRef: string, + rhsUri: Uri | undefined, + rhsRef: string, + ) { + rhsUri ??= await this.container.git.getRepositoryService(repoPath).getWorkingUri(lhsUri); + + return executeCommand('gitlens.diffWith', { + repoPath: repoPath, + lhs: { sha: lhsRef, uri: lhsUri }, + rhs: { sha: rhsRef, uri: rhsUri ?? lhsUri }, }); } - private async openFileOnRemote(params: ExecuteFileActionParams) { - const result = await this.getFileCommitFromParams(params); - if (result == null) return; + @command('gitlens.views.applyChanges:') + private async applyChanges(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; - const [commit, file] = result; + void applyChanges(file, commit); + } - void openFileOnRemote(file, commit); + @command('gitlens.views.mergeChangesWithWorking:') + private async mergeChangesWithWorking(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + const svc = this.container.git.getRepositoryService(commit.repoPath); + if (svc == null) return; + + const nodeUri = await svc.getBestRevisionUri(file.path, commit.ref); + if (nodeUri == null) return; + + const input1: MergeEditorInputs['input1'] = { + uri: nodeUri, + title: `Incoming`, + detail: ` ${commit.shortSha}`, + }; + + const [mergeBaseResult, workingUriResult] = await Promise.allSettled([ + svc.refs.getMergeBase(commit.ref, 'HEAD'), + svc.getWorkingUri(file.uri), + ]); + + const workingUri = getSettledValue(workingUriResult); + if (workingUri == null) { + void window.showWarningMessage('Unable to open the merge editor, no working file found'); + return; + } + const input2: MergeEditorInputs['input2'] = { + uri: workingUri, + title: 'Current', + detail: ' Working Tree', + }; + + const headUri = await svc.getBestRevisionUri(file.path, 'HEAD'); + if (headUri != null) { + const branch = await svc.branches.getBranch?.(); + + input2.uri = headUri; + input2.detail = ` ${branch?.name || 'HEAD'}`; + } + + const mergeBase = getSettledValue(mergeBaseResult); + const baseUri = mergeBase != null ? await svc.getBestRevisionUri(file.path, mergeBase) : undefined; + + return openMergeEditor({ + base: baseUri ?? nodeUri, + input1: input1, + input2: input2, + output: workingUri, + }); } - private async stageFile(params: ExecuteFileActionParams) { - const result = await this.getFileCommitFromParams(params); - if (result == null) return; + @command('gitlens.diffWithRevision:') + private diffWithRevision(item: DetailsItemContext | undefined) { + if (!isDetailsFileContext(item)) return; - const [commit, file] = result; + const uri = getUriFromContext(this.container, item.webviewItemValue); + if (uri == null) return; - await this.container.git.getRepositoryService(commit.repoPath).staging?.stageFile(file.path); + void executeCommand('gitlens.diffWithRevision', uri); } - private async unstageFile(params: ExecuteFileActionParams) { - const result = await this.getFileCommitFromParams(params); - if (result == null) return; + @command('gitlens.diffWithRevisionFrom:') + private diffWithRevisionFrom(item: DetailsItemContext | undefined) { + if (!isDetailsFileContext(item)) return; - const [commit, file] = result; + const uri = getUriFromContext(this.container, item.webviewItemValue); + if (uri == null) return; - await this.container.git.getRepositoryService(commit.repoPath).staging?.unstageFile(file.path); + void executeCommand('gitlens.diffWithRevisionFrom', uri); } - private getShowOptions(params: ExecuteFileActionParams): TextDocumentShowOptions | undefined { - return params.showOptions; + @command('gitlens.externalDiff:') + private async externalDiff(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; - // return getContext('gitlens:webview:graph:active') || getContext('gitlens:webview:rebase:active') - // ? { ...params.showOptions, viewColumn: ViewColumn.Beside } : params.showOptions; + void executeCommand('gitlens.externalDiff', { + files: [ + { + uri: file.uri, + staged: false, + ref1: `${commit.ref}^`, + ref2: commit.ref, + }, + ], + }); + } + + @command('gitlens.views.highlightChanges:') + private async highlightChanges(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + this.suspendLineTracker(); + await openFile(file, commit, { preserveFocus: true, preview: true }); + void (await this.container.fileAnnotations.toggle( + window.activeTextEditor, + 'changes', + { sha: commit.ref }, + true, + )); + } + + @command('gitlens.views.highlightRevisionChanges:') + private async highlightRevisionChanges(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + this.suspendLineTracker(); + await openFile(file, commit, { preserveFocus: true, preview: true }); + void (await this.container.fileAnnotations.toggle( + window.activeTextEditor, + 'changes', + { sha: commit.ref, only: true }, + true, + )); + } + + @command('gitlens.copyDeepLinkToCommit:') + private async copyDeepLinkToCommit(item: DetailsItemContext | undefined) { + const [commit] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void executeCommand('gitlens.copyDeepLinkToCommit', { refOrRepoPath: commit }); + } + + @command('gitlens.copyDeepLinkToFile:') + private async copyDeepLinkToFile(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void executeCommand('gitlens.copyDeepLinkToFile', { + ref: commit, + filePath: file.path, + repoPath: commit.repoPath, + }); + } + + @command('gitlens.copyDeepLinkToFileAtRevision:') + private async copyDeepLinkToFileAtRevision(item: DetailsItemContext | undefined) { + const [commit, file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void executeCommand('gitlens.copyDeepLinkToFileAtRevision', { + ref: commit, + filePath: file.path, + repoPath: commit.repoPath, + chooseRef: true, + }); + } + + @command('gitlens.views.copyRemoteCommitUrl:') + private async copyRemoteCommitUrl(item: DetailsItemContext | undefined) { + const [commit] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void executeCommand('gitlens.openOnRemote', { + repoPath: commit.repoPath, + resource: { type: RemoteResourceType.Commit, sha: commit.ref }, + clipboard: true, + }); + } + + @command('gitlens.shareAsCloudPatch:') + private async shareAsCloudPatch(item: DetailsItemContext | undefined) { + const [commit] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + if (commit.message == null) { + await commit.ensureFullDetails(); + } + + const { summary: title, body: description } = splitCommitMessage(commit.message); + + void executeCommand('gitlens.createCloudPatch', { + to: commit.ref, + repoPath: commit.repoPath, + title: title, + description: description, + }); + } + + @command('gitlens.copyRemoteFileUrlFrom:') + private async copyRemoteFileUrlFrom(item: DetailsItemContext | undefined) { + const [commit, _file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void executeCommand('gitlens.copyRemoteFileUrlFrom', { + sha: commit.ref, + clipboard: true, + pickBranchOrTag: true, + range: false, + }); + } + + @command('gitlens.copyRemoteFileUrlWithoutRange:') + private async copyRemoteFileUrlWithoutRange(item: DetailsItemContext | undefined) { + const [commit, _file] = await this.getFileCommitFromContextOrParams(item); + if (commit == null) return; + + void executeCommand('gitlens.copyRemoteFileUrlWithoutRange', { + sha: commit.ref, + clipboard: true, + range: false, + }); } } @@ -2034,14 +2360,9 @@ function serializeWipContext(wip?: WipContext): Wip | undefined { // type: wip.repo.provider.name, }, pullRequest: wip.pullRequest != null ? serializePullRequest(wip.pullRequest) : undefined, - codeSuggestions: wip.codeSuggestions?.map(draft => serializeDraft(draft)), + codeSuggestions: wip.codeSuggestions?.map(draft => ({ + ...draft, + changesets: undefined, // Inspect doesn't need changesets for the draft list + })), }; } - -function serializeDraft(draft: Draft): Serialized { - // Inspect doesn't need changesets for the draft list - return serialize({ - ...draft, - changesets: undefined, - }); -} diff --git a/src/webviews/commitDetails/commitDetailsWebview.utils.ts b/src/webviews/commitDetails/commitDetailsWebview.utils.ts new file mode 100644 index 0000000000000..78a5f55455cc9 --- /dev/null +++ b/src/webviews/commitDetails/commitDetailsWebview.utils.ts @@ -0,0 +1,82 @@ +import type { Uri } from 'vscode'; +import type { Container } from '../../container'; +import type { GitCommit } from '../../git/models/commit'; +import type { GitFileChange } from '../../git/models/fileChange'; +import { uncommitted } from '../../git/models/revision'; +import { isUncommitted } from '../../git/utils/revision.utils'; +import { isWebviewItemContext } from '../../system/webview'; +import type { + DetailsFileContextValue, + DetailsItemContext, + DetailsItemTypedContext, + DetailsItemTypedContextValue, +} from './protocol'; + +export function isDetailsItemContext(item: unknown): item is DetailsItemContext { + if (item == null) return false; + + return ( + isWebviewItemContext(item) && + (item.webview === 'gitlens.views.commitDetails' || item.webview === 'gitlens.views.graphDetails') + ); +} + +export function isDetailsItemTypedContext(item: unknown, type: 'file'): item is DetailsItemTypedContext; +export function isDetailsItemTypedContext( + item: unknown, + type: DetailsItemTypedContextValue['type'], +): item is DetailsItemTypedContext { + if (item == null) return false; + + return ( + isDetailsItemContext(item) && typeof item.webviewItemValue === 'object' && item.webviewItemValue.type === type + ); +} + +export function isDetailsFileContext(item: unknown): item is DetailsItemTypedContext { + if (item == null) return false; + + return isDetailsItemTypedContext(item, 'file'); +} + +export function getUriFromContext(container: Container, context: DetailsFileContextValue): Uri | undefined { + const { path, repoPath, sha } = context; + const svc = container.git.getRepositoryService(repoPath); + + let uri: Uri | undefined; + if (sha != null && !isUncommitted(sha)) { + uri = svc.getRevisionUri(sha, path); + } else { + uri = svc.getAbsoluteUri(path, repoPath); + } + return uri; +} + +export async function getFileCommitFromContext( + container: Container, + context: DetailsFileContextValue, +): Promise<[commit: GitCommit, file: GitFileChange] | [commit?: undefined, file?: undefined]> { + const { path, repoPath, sha, staged, stashNumber } = context; + const svc = container.git.getRepositoryService(repoPath); + + if (stashNumber != null) { + const stash = await svc.stash?.getStash(); + const commit = stash?.stashes.get(sha!); + if (commit == null) return []; + + const file = await commit.findFile(path); + return commit != null && file != null ? [commit, file] : []; + } + + if (isUncommitted(sha)) { + let commit = await svc.commits.getCommit(uncommitted); + commit = await commit?.getCommitForFile(path, staged); + return commit?.file != null ? [commit, commit.file] : []; + } + + const uri = getUriFromContext(container, context); + if (uri == null) return []; + + const commit = await svc.commits.getCommitForFile(uri, sha); + return commit?.file != null ? [commit, commit.file] : []; +} diff --git a/src/webviews/commitDetails/protocol.ts b/src/webviews/commitDetails/protocol.ts index 6df244858d7d2..c1147feea6466 100644 --- a/src/webviews/commitDetails/protocol.ts +++ b/src/webviews/commitDetails/protocol.ts @@ -4,12 +4,13 @@ import type { Config, DateStyle } from '../../config'; import type { Sources } from '../../constants.telemetry'; import type { GitCommitIdentityShape, GitCommitStats } from '../../git/models/commit'; import type { GitFileChangeShape } from '../../git/models/fileChange'; +import type { GitFileStatus } from '../../git/models/fileStatus'; import type { IssueOrPullRequest } from '../../git/models/issueOrPullRequest'; import type { PullRequestShape } from '../../git/models/pullRequest'; import type { Repository } from '../../git/models/repository'; import type { Draft, DraftVisibility } from '../../plus/drafts/models/drafts'; import type { DateTimeFormat } from '../../system/date'; -import type { Serialized } from '../../system/serialize'; +import type { WebviewItemContext } from '../../system/webview'; import type { Change, DraftUserSelection } from '../plus/patchDetails/protocol'; import type { IpcScope, WebviewState } from '../protocol'; import { IpcCommand, IpcNotification, IpcRequest } from '../protocol'; @@ -36,6 +37,12 @@ export interface CommitDetails extends CommitSummary { autolinks?: Autolink[]; files?: readonly GitFileChangeShape[]; stats?: GitCommitStats; + + enriched?: Promise<{ + formattedMessage: string; + associatedPullRequest: PullRequestShape | undefined; + autolinkedIssues: IssueOrPullRequest[]; + }>; } export interface Preferences { @@ -73,7 +80,7 @@ export interface Wip { repositoryCount: number; branch?: GitBranchShape; pullRequest?: PullRequestShape; - codeSuggestions?: Serialized[]; + codeSuggestions?: Omit[]; repo: { uri: string; name: string; @@ -85,7 +92,7 @@ export interface DraftState { inReview: boolean; } -export interface State extends WebviewState { +export interface State extends WebviewState<'gitlens.views.commitDetails' | 'gitlens.views.graphDetails'> { mode: Mode; pinned: boolean; @@ -99,7 +106,6 @@ export interface State extends WebviewState { ai: boolean; drafts: boolean; }; - includeRichContent?: boolean; commit?: CommitDetails; autolinksEnabled: boolean; @@ -223,14 +229,14 @@ export const GenerateRequest = new IpcRequest(scope, 'g // NOTIFICATIONS export interface DidChangeParams { - state: Serialized; + state: State; } export const DidChangeNotification = new IpcNotification(scope, 'didChange', true); -export type DidChangeWipStateParams = Pick, 'wip' | 'inReview'>; +export type DidChangeWipStateParams = Pick; export const DidChangeWipStateNotification = new IpcNotification(scope, 'didChange/wip'); -export type DidChangeOrgSettings = Pick, 'orgSettings'>; +export type DidChangeOrgSettings = Pick; export const DidChangeOrgSettingsNotification = new IpcNotification( scope, 'org/settings/didChange', @@ -256,3 +262,21 @@ export const DidChangeIntegrationsNotification = new IpcNotification; +export type DetailsItemContextValue = DetailsItemTypedContextValue; + +export type DetailsItemTypedContext = WebviewItemContext; +export type DetailsItemTypedContextValue = DetailsFileContextValue; + +export interface DetailsFileContextValue { + type: 'file'; + path: string; + repoPath: string; + sha?: string; + stashNumber?: string; + staged?: boolean; + status?: GitFileStatus; +} diff --git a/src/webviews/commitDetails/registration.ts b/src/webviews/commitDetails/registration.ts index 98e0bdc6e8705..77c34ec643db0 100644 --- a/src/webviews/commitDetails/registration.ts +++ b/src/webviews/commitDetails/registration.ts @@ -1,5 +1,4 @@ import type { CommitSelectedEvent } from '../../eventBus'; -import type { Serialized } from '../../system/serialize'; import type { WebviewsController, WebviewViewProxy } from '../webviewsController'; import type { ShowWipArgs, State } from './protocol'; @@ -7,13 +6,8 @@ export type CommitDetailsWebviewShowingArgs = [Partial> { - return controller.registerWebviewView< - 'gitlens.views.commitDetails', - State, - Serialized, - CommitDetailsWebviewShowingArgs - >( +): WebviewViewProxy<'gitlens.views.commitDetails', CommitDetailsWebviewShowingArgs, State> { + return controller.registerWebviewView<'gitlens.views.commitDetails', State, State, CommitDetailsWebviewShowingArgs>( { id: 'gitlens.views.commitDetails', fileName: 'commitDetails.html', @@ -37,13 +31,8 @@ export function registerCommitDetailsWebviewView( export function registerGraphDetailsWebviewView( controller: WebviewsController, -): WebviewViewProxy<'gitlens.views.graphDetails', CommitDetailsWebviewShowingArgs, Serialized> { - return controller.registerWebviewView< - 'gitlens.views.graphDetails', - State, - Serialized, - CommitDetailsWebviewShowingArgs - >( +): WebviewViewProxy<'gitlens.views.graphDetails', CommitDetailsWebviewShowingArgs, State> { + return controller.registerWebviewView<'gitlens.views.graphDetails', State, State, CommitDetailsWebviewShowingArgs>( { id: 'gitlens.views.graphDetails', fileName: 'commitDetails.html', diff --git a/src/webviews/home/homeWebview.ts b/src/webviews/home/homeWebview.ts index 45d68f831dd96..d1d94f03441f5 100644 --- a/src/webviews/home/homeWebview.ts +++ b/src/webviews/home/homeWebview.ts @@ -445,7 +445,7 @@ export class HomeWebviewProvider implements WebviewProvider { + includeBootstrap(_deferrable?: boolean): Promise { return this.getState(); } @@ -1397,7 +1397,7 @@ export class HomeWebviewProvider implements WebviewProvider `${r.branchId}, upstream: ${r.branchUpstreamName}` }, }) private pushBranch(ref: BranchRef) { - void this.container.git.getRepositoryService(ref.repoPath).push({ + void this.container.git.getRepositoryService(ref.repoPath).ops?.push({ reference: { name: ref.branchName, ref: ref.branchId, @@ -1991,7 +1991,9 @@ async function getWipInfo( const [statusResult, pausedOpStatusResult] = await Promise.allSettled([ statusPromise, - active ? container.git.getRepositoryService(branch.repoPath).status.getPausedOperationStatus?.() : undefined, + active + ? container.git.getRepositoryService(branch.repoPath).pausedOps?.getPausedOperationStatus?.() + : undefined, ]); const status = getSettledValue(statusResult); diff --git a/src/webviews/home/protocol.ts b/src/webviews/home/protocol.ts index 14cced16e3489..6323628262fec 100644 --- a/src/webviews/home/protocol.ts +++ b/src/webviews/home/protocol.ts @@ -21,7 +21,7 @@ import { IpcCommand, IpcNotification, IpcRequest } from '../protocol'; export const scope: IpcScope = 'home'; -export interface State extends WebviewState { +export interface State extends WebviewState<'gitlens.views.home'> { discovering: boolean; repositories: DidChangeRepositoriesParams; webroot?: string; diff --git a/src/webviews/ipc.ts b/src/webviews/ipc.ts new file mode 100644 index 0000000000000..a215113c33741 --- /dev/null +++ b/src/webviews/ipc.ts @@ -0,0 +1,71 @@ +import type { UriComponents } from '../system/uri'; + +// Unified IPC Tagged Types System - allows transparent serialization/deserialization of special types across the IPC boundary + +/** Tagged type for Dates that get serialized as timestamps */ +export interface IpcDate { + __ipc: 'date'; + value: number; +} + +/** Tagged type for Promises that get resolved asynchronously over IPC */ +export interface IpcPromise { + __ipc: 'promise'; + value: { + id: string; + method: string; + }; + __promise: Promise; +} + +/** Tagged type for Uris that get serialized as UriComponents */ +export interface IpcUri { + __ipc: 'uri'; + value: UriComponents; +} + +export type IpcTaggedType = IpcPromise | IpcDate | IpcUri; + +/** + * @returns the IPC tagged type if the value is one, otherwise undefined + * More efficient than calling multiple isIpc* functions when you need to handle different types + */ +export function getIpcTaggedType(value: unknown): IpcTaggedType | undefined { + if (typeof value !== 'object' || value == null) return undefined; + + const ipc = (value as any).__ipc; + if (ipc == null) return undefined; + + switch (ipc) { + case 'date': + return typeof (value as IpcDate).value === 'number' ? (value as IpcDate) : undefined; + case 'promise': + return typeof (value as IpcPromise).value === 'object' && + typeof (value as IpcPromise).value.id === 'string' && + typeof (value as IpcPromise).value.method === 'string' + ? (value as IpcPromise) + : undefined; + case 'uri': + return typeof (value as IpcUri).value === 'object' && typeof (value as IpcUri).value?.scheme === 'string' + ? (value as IpcUri) + : undefined; + default: + return undefined; + } +} + +export function isIpcTaggedType(value: unknown): value is IpcTaggedType { + return getIpcTaggedType(value) != null; +} + +export function isIpcDate(value: unknown): value is IpcDate { + return getIpcTaggedType(value)?.__ipc === 'date'; +} + +export function isIpcPromise(value: unknown): value is IpcPromise { + return getIpcTaggedType(value)?.__ipc === 'promise'; +} + +export function isIpcUri(value: unknown): value is IpcUri { + return getIpcTaggedType(value)?.__ipc === 'uri'; +} diff --git a/src/webviews/plus/composer/composerWebview.ts b/src/webviews/plus/composer/composerWebview.ts index 00a89ad1f4d60..d28d922279a1e 100644 --- a/src/webviews/plus/composer/composerWebview.ts +++ b/src/webviews/plus/composer/composerWebview.ts @@ -10,6 +10,7 @@ import type { RepositoryFileSystemChangeEvent, } from '../../../git/models/repository'; import { RepositoryChange, RepositoryChangeComparisonMode } from '../../../git/models/repository'; +import { rootSha } from '../../../git/models/revision'; import { sendFeedbackEvent, showUnhelpfulFeedbackPicker } from '../../../plus/ai/aiFeedbackUtils'; import type { AIModelChangeEvent } from '../../../plus/ai/aiProviderService'; import { getRepositoryPickerTitleAndPlaceholder, showRepositoryPicker } from '../../../quickpicks/repositoryPicker'; @@ -25,7 +26,9 @@ import type { ComposerContext, ComposerGenerateCommitMessageEventData, ComposerGenerateCommitsEventData, + ComposerHunk, ComposerLoadedErrorData, + ComposerSafetyState, ComposerTelemetryEvent, FinishAndCommitParams, GenerateCommitMessageParams, @@ -76,14 +79,16 @@ import { ReloadComposerCommand, } from './protocol'; import type { ComposerWebviewShowingArgs } from './registration'; +import type { WorkingTreeDiffs } from './utils/composer.utils'; import { convertToComposerDiffInfo, + createCombinedDiffForCommit, createHunksFromDiffs, createSafetyState, getWorkingTreeDiffs, validateResultingDiff, validateSafetyState, -} from './utils'; +} from './utils/composer.utils'; export class ComposerWebviewProvider implements WebviewProvider { private readonly _disposable: Disposable; @@ -98,9 +103,16 @@ export class ComposerWebviewProvider implements WebviewProvider, @@ -111,6 +123,15 @@ export class ComposerWebviewProvider implements WebviewProvider { + includeBootstrap(_deferrable?: boolean): Promise { return this._cache.get('bootstrap', () => this.getBootstrapState()); } @@ -283,6 +304,16 @@ export class ComposerWebviewProvider implements WebviewProvider { + // Stop repo change subscription so we can deal with untracked files + this._repositorySubscription?.dispose(); + const untrackedPaths = (await repo.git.status?.getUntrackedFiles())?.map(f => f.path); + if (untrackedPaths?.length) { + try { + await repo.git.staging?.stageFiles(untrackedPaths, { intentToAdd: true }); + this._ignoreIndexChange = true; + } catch {} + } + const [diffsResult, commitResult, branchResult] = await Promise.allSettled([ // Handle baseCommit - could be string (old format) or ComposerBaseCommit (new format) getWorkingTreeDiffs(repo), @@ -290,6 +321,10 @@ export class ComposerWebviewProvider implements WebviewProvider { if (e.repository.id !== this._currentRepository?.id) return; - + const ignoreIndexChange = this._ignoreIndexChange; + this._ignoreIndexChange = false; // Only care about index changes (staged/unstaged changes) - if (!e.changed(RepositoryChange.Index, RepositoryChangeComparisonMode.Any)) { + if ( + !e.changed(RepositoryChange.Index, RepositoryChangeComparisonMode.Any) || + (ignoreIndexChange && e.changed(RepositoryChange.Index, RepositoryChangeComparisonMode.Exclusive)) + ) { return; } @@ -788,14 +804,10 @@ export class ComposerWebviewProvider implements WebviewProvider ({ - index: hunk.index, - fileName: hunk.fileName, - diffHeader: hunk.diffHeader || `diff --git a/${hunk.fileName} b/${hunk.fileName}`, - hunkHeader: hunk.hunkHeader, - content: hunk.content, - source: hunk.source, - })); + const hunks = []; + for (const index of params.hunkIndices) { + hunks.push({ ...this._hunks.find(m => m.index === index)!, assigned: true }); + } const existingCommits = params.commits.map(commit => ({ id: commit.id, @@ -808,7 +820,7 @@ export class ComposerWebviewProvider implements WebviewProvider ({ index: m.index, hunkHeader: m.hunkHeader })), { source: 'composer', correlationId: this.host.instanceId }, { cancellation: this._generateCommitsCancellation.token, @@ -942,9 +954,28 @@ export class ComposerWebviewProvider implements WebviewProvider params.commitHunkIndices.includes(h.index)), + ); + if (!patch) { + this._context.operations.generateCommitMessage.errorCount++; + this._context.errors.operation.count++; + // Send error notification for failure (not cancellation) + this.sendTelemetryEvent('composer/action/generateCommitMessage/failed', { + ...eventData, + 'failure.reason': 'error', + 'failure.error.message': 'Failed to create diff for commit', + }); + await this.host.notify(DidErrorAIOperationNotification, { + operation: 'generate commit message', + error: 'Failed to create diff for commit', + }); + } + // Call the AI service to generate commit message const result = await this.container.ai.generateCommitMessage( - params.diff, + patch, { source: 'composer', correlationId: this.host.instanceId }, { cancellation: this._generateCommitMessageCancellation.token, @@ -1032,7 +1063,7 @@ export class ComposerWebviewProvider implements WebviewProvider + const commitHunkIndices = params.commits.flatMap(c => c.hunkIndices); + const hunks: ComposerHunk[] = []; + for (const hunk of commitHunkIndices) { + hunks.push({ ...this._hunks.find(m => m.index === hunk)!, assigned: true }); + } + + const hunksBeingCommitted = hunks.filter(hunk => params.commits.some(c => c.hunkIndices.includes(hunk.index)), ); // Validate repository safety state before proceeding - const validation = await validateSafetyState(repo, params.safetyState, hunksBeingCommitted); + // Stop repo change subscription so we can deal with untracked files + let workingTreeDiffs: WorkingTreeDiffs | undefined; + if (this._context.diff.unstagedIncluded) { + this._repositorySubscription?.dispose(); + const untrackedPaths = (await repo.git.status?.getUntrackedFiles())?.map(f => f.path); + if (untrackedPaths?.length) { + try { + workingTreeDiffs = await getWorkingTreeDiffs(repo); + await repo.git.staging?.stageFiles(untrackedPaths); + } catch {} + } + } + + const validation = await validateSafetyState( + repo, + this._safetyState, + hunksBeingCommitted, + workingTreeDiffs, + ); if (!validation.isValid) { // Clear loading state and show safety error await this.host.notify(DidFinishCommittingNotification, undefined); @@ -1073,8 +1127,7 @@ export class ComposerWebviewProvider implements WebviewProvider { // data model hunks: ComposerHunk[]; - hunkMap: ComposerHunkMap[]; commits: ComposerCommit[]; - baseCommit: ComposerBaseCommit; - safetyState: ComposerSafetyState; + baseCommit: ComposerBaseCommit | null; // UI state selectedCommitId: string | null; @@ -115,25 +111,10 @@ export interface State extends WebviewState { }; } -export const initialState: Omit = { +export const initialState: Omit> = { hunks: [], commits: [], - hunkMap: [], - baseCommit: { - sha: '', - message: '', - repoName: '', - branchName: '', - }, - safetyState: { - repoPath: '', - headSha: '', - hashes: { - staged: null, - unstaged: null, - unified: null, - }, - }, + baseCommit: null, selectedCommitId: null, selectedCommitIds: new Set(), selectedUnassignedSection: null, @@ -361,7 +342,7 @@ export interface GenerateWithAIParams { export interface DidChangeComposerDataParams { hunks: ComposerHunk[]; commits: ComposerCommit[]; - baseCommit: ComposerBaseCommit; + baseCommit: ComposerBaseCommit | null; } // IPC Commands and Notifications @@ -404,7 +385,6 @@ export const OnRedoCommand = new IpcCommand(ipcScope, 'onRedo'); export const OnResetCommand = new IpcCommand(ipcScope, 'onReset'); // Notifications sent from host to webview -export const DidChangeNotification = new IpcNotification(ipcScope, 'didChange'); export const DidStartGeneratingNotification = new IpcNotification(ipcScope, 'didStartGenerating'); export const DidStartGeneratingCommitMessageNotification = new IpcNotification<{ commitId: string }>( ipcScope, @@ -450,25 +430,22 @@ export const DidChangeAiModelNotification = new IpcNotification commit.hunkIndices.includes(hunk.index)); @@ -82,22 +82,17 @@ export function getFileChanges(hunks: ComposerHunk[]): { additions: number; dele ); } -export function createCombinedDiffForCommit( - commit: ComposerCommit, - hunks: ComposerHunk[], -): { patch: string; filePatches: Map } { - // Get hunks for this commit - const commitHunks = commit.hunkIndices - .map(index => hunks.find(hunk => hunk.index === index)) - .filter((hunk): hunk is ComposerHunk => hunk !== undefined); - - if (commitHunks.length === 0) { +export function createCombinedDiffForCommit(hunks: ComposerHunk[]): { + patch: string; + filePatches: Map; +} { + if (hunks.length === 0) { return { patch: '', filePatches: new Map() }; } // Group hunks by file (diffHeader) const filePatches = new Map(); - for (const hunk of commitHunks) { + for (const hunk of hunks) { const diffHeader = hunk.diffHeader || `diff --git a/${hunk.fileName} b/${hunk.fileName}`; let array = filePatches.get(diffHeader); @@ -137,7 +132,7 @@ export function convertToComposerDiffInfo( hunks: ComposerHunk[], ): Array<{ message: string; explanation?: string; filePatches: Map; patch: string }> { return commits.map(commit => { - const { patch, filePatches } = createCombinedDiffForCommit(commit, hunks); + const { patch, filePatches } = createCombinedDiffForCommit(getHunksForCommit(commit, hunks)); return { message: commit.message, @@ -174,34 +169,27 @@ export function generateComposerMarkdown( return markdown; } -export function createHunksFromDiffs( - stagedDiffContent?: string, - unstagedDiffContent?: string, -): { hunkMap: ComposerHunkMap[]; hunks: ComposerHunk[] } { - const allHunkMaps: ComposerHunkMap[] = []; +export function createHunksFromDiffs(stagedDiffContent?: string, unstagedDiffContent?: string): ComposerHunk[] { const allHunks: ComposerHunk[] = []; let count = 0; - let hunkMap: ComposerHunkMap[] = []; let hunks: ComposerHunk[] = []; if (stagedDiffContent) { const stagedDiff = parseGitDiff(stagedDiffContent); - ({ hunkMap, hunks, count } = convertDiffToComposerHunks(stagedDiff, 'staged', count)); + ({ hunks, count } = convertDiffToComposerHunks(stagedDiff, 'staged', count)); - allHunkMaps.push(...hunkMap); allHunks.push(...hunks); } if (unstagedDiffContent) { const unstagedDiff = parseGitDiff(unstagedDiffContent); - ({ hunkMap, hunks, count } = convertDiffToComposerHunks(unstagedDiff, 'unstaged', count)); + ({ hunks, count } = convertDiffToComposerHunks(unstagedDiff, 'unstaged', count)); - allHunkMaps.push(...hunkMap); allHunks.push(...hunks); } - return { hunkMap: allHunkMaps, hunks: allHunks }; + return allHunks; } /** Converts @type {ParsedGitDiff} output to @type {ComposerHunk}'s */ @@ -209,8 +197,7 @@ function convertDiffToComposerHunks( diff: ParsedGitDiff, source: 'staged' | 'unstaged', startingCount: number, -): { hunkMap: ComposerHunkMap[]; hunks: ComposerHunk[]; count: number } { - const hunkMap: ComposerHunkMap[] = []; +): { hunks: ComposerHunk[]; count: number } { const hunks: ComposerHunk[] = []; let counter = startingCount; @@ -238,8 +225,6 @@ function convertDiffToComposerHunks( content = file.header.split('\n').slice(1).join('\n'); // Skip the diff --git line } - hunkMap.push({ index: hunkIndex, hunkHeader: hunkHeader }); - const composerHunk: ComposerHunk = { index: hunkIndex, fileName: file.path, @@ -260,8 +245,6 @@ function convertDiffToComposerHunks( for (const hunk of file.hunks) { const hunkIndex = ++counter; - hunkMap.push({ index: hunkIndex, hunkHeader: hunk.header }); - // Calculate additions and deletions from the hunk content const { additions, deletions } = calculateHunkStats(hunk.content); @@ -284,7 +267,7 @@ function convertDiffToComposerHunks( } } - return { hunkMap: hunkMap, hunks: hunks, count: counter }; + return { hunks: hunks, count: counter }; } function calculateHunkStats(content: string): { additions: number; deletions: number } { @@ -335,15 +318,11 @@ export async function getWorkingTreeDiffs(repo: Repository): Promise { - if (!headSha) { - throw new Error('Cannot create safety state: no HEAD commit found'); - } - return { repoPath: repo.path, - headSha: headSha, + headSha: headSha ?? null, hashes: { staged: diffs.staged?.contents ? await sha256(diffs.staged.contents) : null, unstaged: diffs.unstaged?.contents ? await sha256(diffs.unstaged.contents) : null, @@ -360,6 +339,7 @@ export async function validateSafetyState( repo: Repository, safetyState: ComposerSafetyState, hunksBeingCommitted?: ComposerHunk[], + workingTreeDiffs?: WorkingTreeDiffs, ): Promise<{ isValid: boolean; errors: string[] }> { const errors: string[] = []; @@ -371,14 +351,14 @@ export async function validateSafetyState( // 2. Check HEAD SHA const currentHeadCommit = await repo.git.commits.getCommit('HEAD'); - const currentHeadSha = currentHeadCommit?.sha ?? 'unknown'; + const currentHeadSha = currentHeadCommit?.sha ?? null; if (currentHeadSha !== safetyState.headSha) { errors.push(`HEAD commit changed from "${safetyState.headSha}" to "${currentHeadSha}"`); } // 2. Smart diff validation - only check diffs for sources being committed if (hunksBeingCommitted?.length) { - const { staged, unstaged /*, unified*/ } = await getWorkingTreeDiffs(repo); + const { staged, unstaged /*, unified*/ } = workingTreeDiffs ?? (await getWorkingTreeDiffs(repo)); const hashes = { staged: staged?.contents ? await sha256(staged.contents) : null, diff --git a/src/webviews/plus/graph/graphWebview.ts b/src/webviews/plus/graph/graphWebview.ts index f3c45cd5cd79e..9b81388c2063b 100644 --- a/src/webviews/plus/graph/graphWebview.ts +++ b/src/webviews/plus/graph/graphWebview.ts @@ -487,7 +487,7 @@ export class GraphWebviewProvider implements WebviewProvider { + includeBootstrap(_deferrable?: boolean): Promise { return this.getState(true); } @@ -734,7 +734,11 @@ export class GraphWebviewProvider implements WebviewProvider { + private async getWorkingTreeStats( + hasWorkingChanges?: boolean, + cancellation?: CancellationToken, + ): Promise { if (this.repository == null || !this.container.git.repositoryCount) return undefined; const svc = this.container.git.getRepositoryService(this.repository.path); + hasWorkingChanges ??= await svc.status.hasWorkingChanges( + { staged: true, unstaged: true, untracked: false }, + cancellation, + ); + const [statusResult, pausedOpStatusResult] = await Promise.allSettled([ - svc.status.getStatus(cancellation), - svc.status.getPausedOperationStatus?.(cancellation), + hasWorkingChanges ? svc.status.getStatus(cancellation) : undefined, + svc.pausedOps?.getPausedOperationStatus?.(cancellation), ]); const status = getSettledValue(statusResult); @@ -2615,14 +2618,30 @@ export class GraphWebviewProvider implements WebviewProvider this.host.asWebviewUri(uri), { include: { @@ -2639,7 +2658,7 @@ export class GraphWebviewProvider implements WebviewProvider { windowFocused?: boolean; webroot?: string; repositories?: GraphRepository[]; @@ -383,7 +383,7 @@ export const DidChangeRepoConnectionNotification = new IpcNotification(scope, 'didChange', true, true); +export const DidChangeNotification = new IpcNotification(scope, 'didChange', true); export interface DidChangeGraphConfigurationParams { config: GraphComponentConfig; @@ -467,12 +467,7 @@ export interface DidChangeRowsParams { searchResults?: GraphSearchResults; selectedRows?: GraphSelectedRows; } -export const DidChangeRowsNotification = new IpcNotification( - scope, - 'rows/didChange', - undefined, - true, -); +export const DidChangeRowsNotification = new IpcNotification(scope, 'rows/didChange'); export interface DidChangeRowsStatsParams { rowsStats: Record; diff --git a/src/webviews/plus/patchDetails/patchDetailsWebview.ts b/src/webviews/plus/patchDetails/patchDetailsWebview.ts index b0cf50092683d..172ecd7223381 100644 --- a/src/webviews/plus/patchDetails/patchDetailsWebview.ts +++ b/src/webviews/plus/patchDetails/patchDetailsWebview.ts @@ -212,7 +212,7 @@ export class PatchDetailsWebviewProvider return [true, undefined]; } - includeBootstrap(): Promise> { + includeBootstrap(_deferrable?: boolean): Promise> { return this.getState(this._context); } diff --git a/src/webviews/plus/patchDetails/protocol.ts b/src/webviews/plus/patchDetails/protocol.ts index 8eebeb2c57b5e..b11d3feb79816 100644 --- a/src/webviews/plus/patchDetails/protocol.ts +++ b/src/webviews/plus/patchDetails/protocol.ts @@ -151,7 +151,7 @@ export interface CreatePatchState { userSelections?: DraftUserSelection[]; } -export interface State extends WebviewState { +export interface State extends WebviewState<'gitlens.patchDetails' | 'gitlens.views.patchDetails'> { mode: Mode; preferences: Preferences; diff --git a/src/webviews/plus/timeline/protocol.ts b/src/webviews/plus/timeline/protocol.ts index 9e0136a84fcbc..57bc16e6d075c 100644 --- a/src/webviews/plus/timeline/protocol.ts +++ b/src/webviews/plus/timeline/protocol.ts @@ -8,7 +8,7 @@ import { IpcCommand, IpcNotification, IpcRequest } from '../../protocol'; export const scope: IpcScope = 'timeline'; -export interface State extends WebviewState { +export interface State extends WebviewState<'gitlens.timeline' | 'gitlens.views.timeline'> { dataset?: Promise; config: { showAllBranches: boolean; diff --git a/src/webviews/plus/timeline/timelineWebview.ts b/src/webviews/plus/timeline/timelineWebview.ts index 745f1f669b69d..12caf689dd6e9 100644 --- a/src/webviews/plus/timeline/timelineWebview.ts +++ b/src/webviews/plus/timeline/timelineWebview.ts @@ -223,7 +223,7 @@ export class TimelineWebviewProvider implements WebviewProvider { + includeBootstrap(_deferrable?: boolean): Promise { return this._cache.get('bootstrap', () => this.getState(this._context, false)); } diff --git a/src/webviews/protocol.ts b/src/webviews/protocol.ts index 56d7eba739396..e910aea12b7ff 100644 --- a/src/webviews/protocol.ts +++ b/src/webviews/protocol.ts @@ -15,12 +15,15 @@ import type { ConfigPath, ConfigPathValue, Path, PathValue } from '../system/-we export type IpcScope = 'core' | CustomEditorTypes | WebviewTypes | WebviewViewTypes; +type IpcCompression = 'deflate' | 'utf8' | false; export interface IpcMessage { id: string; scope: IpcScope; method: string; - packed?: boolean; params: T; + compressed: IpcCompression; + timestamp: number; + completionId?: string; } @@ -31,7 +34,6 @@ abstract class IpcCall { public readonly scope: IpcScope, method: string, public readonly reset: boolean = false, - public readonly pack: boolean = false, ) { this.method = `${scope}/${method}`; } @@ -58,10 +60,10 @@ export class IpcCommand extends IpcCall {} export class IpcRequest extends IpcCall { public readonly response: IpcNotification; - constructor(scope: IpcScope, method: string, reset?: boolean, pack?: boolean) { - super(scope, method, reset, pack); + constructor(scope: IpcScope, method: string, reset?: boolean) { + super(scope, method, reset); - this.response = new IpcNotification(this.scope, `${method}/completion`, this.reset, this.pack); + this.response = new IpcNotification(this.scope, `${method}/completion`, this.reset); } } @@ -70,9 +72,16 @@ export class IpcRequest extends IpcCall extends IpcCall {} -// COMMANDS +// COMMANDS & REQUESTS + +export interface WebviewReadyParams { + bootstrap?: boolean; +} -export const WebviewReadyCommand = new IpcCommand('core', 'webview/ready'); +export interface WebviewReadyResponse { + state?: unknown | Promise; +} +export const WebviewReadyRequest = new IpcRequest('core', 'webview/ready'); export interface WebviewFocusChangedParams { focused: boolean; @@ -119,27 +128,7 @@ export const TelemetrySendEventCommand = new IpcCommand; - id: string; - method: string; -} - -export function isIpcPromise(value: unknown): value is IpcPromise { - return ( - value != null && - typeof value === 'object' && - '__ipc' in value && - value.__ipc === 'promise' && - 'id' in value && - typeof value.id === 'string' && - 'method' in value && - typeof value.method === 'string' - ); -} - -export const ipcPromiseSettled = new IpcNotification>('core', 'ipc/promise/settled'); +export const IpcPromiseSettled = new IpcNotification>('core', 'ipc/promise/settled'); export interface DidChangeHostWindowFocusParams { focused: boolean; @@ -202,7 +191,7 @@ export function assertsConfigKeyValue( // Noop } -export interface WebviewState { +export interface WebviewState { webviewId: Id; webviewInstanceId: string | undefined; timestamp: number; diff --git a/src/webviews/rebase/protocol.ts b/src/webviews/rebase/protocol.ts index 70826f4c2664b..93c2fcdac04ee 100644 --- a/src/webviews/rebase/protocol.ts +++ b/src/webviews/rebase/protocol.ts @@ -1,10 +1,9 @@ -import type { CustomEditorIds } from '../../constants.views'; import type { IpcScope, WebviewState } from '../protocol'; import { IpcCommand, IpcNotification } from '../protocol'; export const scope: IpcScope = 'rebase'; -export interface State extends WebviewState { +export interface State extends WebviewState<'gitlens.rebase'> { branch: string; onto: { sha: string; commit?: Commit } | undefined; diff --git a/src/webviews/rebase/rebaseEditor.ts b/src/webviews/rebase/rebaseEditor.ts index 56c9e12c1747c..3768ab35b0c32 100644 --- a/src/webviews/rebase/rebaseEditor.ts +++ b/src/webviews/rebase/rebaseEditor.ts @@ -513,6 +513,8 @@ export class RebaseEditorProvider implements CustomTextEditorProvider, Disposabl scope: DidChangeNotification.scope, method: DidChangeNotification.method, params: { state: state }, + compressed: false, + timestamp: Date.now(), }); } diff --git a/src/webviews/settings/protocol.ts b/src/webviews/settings/protocol.ts index 865c903756abd..926321b1e669c 100644 --- a/src/webviews/settings/protocol.ts +++ b/src/webviews/settings/protocol.ts @@ -5,7 +5,7 @@ import { IpcNotification, IpcRequest } from '../protocol'; export const scope: IpcScope = 'settings'; -export interface State extends WebviewState { +export interface State extends WebviewState<'gitlens.settings'> { version: string; config: Config; customSettings?: Record; diff --git a/src/webviews/settings/registration.ts b/src/webviews/settings/registration.ts index 6274cc56ff27a..38f613b96983e 100644 --- a/src/webviews/settings/registration.ts +++ b/src/webviews/settings/registration.ts @@ -53,7 +53,6 @@ export function registerSettingsWebviewCommands( 'gitlens.showSettingsPage!stashes-view', 'gitlens.showSettingsPage!tags-view', 'gitlens.showSettingsPage!worktrees-view', - 'gitlens.showSettingsPage!views', 'gitlens.showSettingsPage!commit-graph', 'gitlens.showSettingsPage!autolinks', ] satisfies GlCommands[] diff --git a/src/webviews/settings/settingsWebview.ts b/src/webviews/settings/settingsWebview.ts index 82be14a63c520..7dd1e07e30768 100644 --- a/src/webviews/settings/settingsWebview.ts +++ b/src/webviews/settings/settingsWebview.ts @@ -88,7 +88,7 @@ export class SettingsWebviewProvider implements WebviewProvider { + async includeBootstrap(_deferrable?: boolean): Promise { const scopes: ['user' | 'workspace', string][] = [['user', 'User']]; if (workspace.workspaceFolders?.length) { scopes.push(['workspace', 'Workspace']); diff --git a/src/webviews/webviewController.ts b/src/webviews/webviewController.ts index d0cba656ebb8f..af82bb01db3fb 100644 --- a/src/webviews/webviewController.ts +++ b/src/webviews/webviewController.ts @@ -1,10 +1,18 @@ +import { deflateSync, strFromU8, strToU8 } from 'fflate'; import type { Event, ViewBadge, Webview, WebviewPanel, WebviewView, WindowState } from 'vscode'; import { CancellationTokenSource, Disposable, EventEmitter, Uri, ViewColumn, window, workspace } from 'vscode'; import { base64 } from '@env/base64'; import { getNonce } from '@env/crypto'; import type { WebviewCommands, WebviewViewCommands } from '../constants.commands'; import type { WebviewTelemetryContext } from '../constants.telemetry'; -import type { CustomEditorTypes, WebviewIds, WebviewTypes, WebviewViewIds, WebviewViewTypes } from '../constants.views'; +import type { + CustomEditorTypes, + WebviewIds, + WebviewOrWebviewViewTypeFromId, + WebviewTypes, + WebviewViewIds, + WebviewViewTypes, +} from '../constants.views'; import type { Container } from '../container'; import { isCancellationError } from '../errors'; import { getSubscriptionNextPaidPlanId } from '../plus/gk/utils/subscription.utils'; @@ -13,19 +21,20 @@ import { setContext } from '../system/-webview/context'; import { getViewFocusCommand } from '../system/-webview/vscode/views'; import { getScopedCounter } from '../system/counter'; import { debug, logName } from '../system/decorators/log'; -import { sequentialize } from '../system/decorators/serialize'; +import { sequentialize } from '../system/decorators/sequentialize'; +import { serializeIpcData } from '../system/ipcSerialize'; import { getLoggableName, Logger } from '../system/logger'; import { getLogScope, getNewLogScope, setLogScopeExit } from '../system/logger.scope'; import { pauseOnCancelOrTimeout } from '../system/promise'; import { maybeStopWatch, Stopwatch } from '../system/stopwatch'; import type { WebviewContext } from '../system/webview'; +import type { IpcPromise } from './ipc'; import type { IpcCallMessageType, IpcCallParamsType, IpcCallResponseParamsType, IpcMessage, IpcNotification, - IpcPromise, IpcRequest, WebviewFocusChangedParams, WebviewState, @@ -36,19 +45,16 @@ import { DidChangeWebviewFocusNotification, DidChangeWebviewVisibilityNotification, ExecuteCommand, - ipcPromiseSettled, - isIpcPromise, + IpcPromiseSettled, TelemetrySendEventCommand, WebviewFocusChangedCommand, - WebviewReadyCommand, + WebviewReadyRequest, } from './protocol'; import type { WebviewCommandCallback, WebviewCommandRegistrar } from './webviewCommandRegistrar'; import type { WebviewHost, WebviewProvider, WebviewShowingArgs } from './webviewProvider'; import type { WebviewPanelDescriptor, WebviewShowOptions, WebviewViewDescriptor } from './webviewsController'; const ipcSequencer = getScopedCounter(); -const utf8TextDecoder = new TextDecoder('utf8'); -const utf8TextEncoder = new TextEncoder(); type GetWebviewDescriptor = T extends WebviewIds ? WebviewPanelDescriptor @@ -153,6 +159,10 @@ export class WebviewController< readonly id: ID; + get type(): WebviewOrWebviewViewTypeFromId { + return this.descriptor.type as WebviewOrWebviewViewTypeFromId; + } + private _ready: boolean = false; get ready(): boolean { return this._ready; @@ -409,7 +419,7 @@ export class WebviewController< }); } - get baseWebviewState(): WebviewState { + get baseWebviewState(): WebviewState { return { webviewId: this.id, webviewInstanceId: this.instanceId, @@ -479,9 +489,15 @@ export class WebviewController< private async onMessageReceivedCore(e: IpcMessage) { if (e == null) return; + const scope = getLogScope(); + setLogScopeExit(scope, ` \u2022 ipc (webview -> host) duration=${Date.now() - e.timestamp}ms`); + switch (true) { - case WebviewReadyCommand.is(e): + case WebviewReadyRequest.is(e): this._ready = true; + void this.respond(WebviewReadyRequest, e, { + state: e.params.bootstrap ? this.provider.includeBootstrap?.(false) : undefined, + }); this.sendPendingIpcNotifications(); void this.provider.onReady?.(); @@ -606,22 +622,27 @@ export class WebviewController< return this._webRootUri; } + @debug({ args: false }) private async getHtml(webview: Webview): Promise { + const scope = getLogScope(); + const webRootUri = this.getWebRootUri(); const uri = Uri.joinPath(webRootUri, this.descriptor.fileName); const [bytes, bootstrap, head, body, endOfBody] = await Promise.all([ workspace.fs.readFile(uri), - this.provider.includeBootstrap?.(), + this.provider.includeBootstrap?.(true), this.provider.includeHead?.(), this.provider.includeBody?.(), this.provider.includeEndOfBody?.(), ]); - this.replacePromisesWithIpcPromises(bootstrap); + const sw = maybeStopWatch(scope, { log: false, logLevel: 'debug' }); + const serialized = this.serializeIpcData(bootstrap); + sw?.stop({ message: `\u2022 serialized bootstrap; length=${serialized.length}` }); const html = replaceWebviewHtmlTokens( - utf8TextDecoder.decode(bytes), + strFromU8(bytes), this.id, this.instanceId, webview.cspSource, @@ -629,7 +650,7 @@ export class WebviewController< this.asWebviewUri(this.getRootUri()).toString(), this.getWebRoot(), this.is('editor') ? 'editor' : 'view', - bootstrap, + serialized, head, body, endOfBody, @@ -646,34 +667,56 @@ export class WebviewController< params: IpcCallParamsType, completionId?: string, ): Promise { - this.replacePromisesWithIpcPromises(params); - - let packed; - if (notificationType.pack && params != null) { - const sw = maybeStopWatch( - getNewLogScope(`${getLoggableName(this)}.notify serializing msg=${notificationType.method}`, true), - { - log: false, - logLevel: 'debug', - }, - ); - packed = utf8TextEncoder.encode(JSON.stringify(params)); - sw?.stop(); + const id = this.nextIpcId(); + const timestamp = Date.now(); + + const scope = getNewLogScope(`${getLoggableName(this)}.notify(${id}|${notificationType.method})`, true); + const sw = maybeStopWatch(scope, { log: false, logLevel: 'debug' }); + + const serializedParams = params != null ? this.serializeIpcData(params) : undefined; + + sw?.restart({ message: `\u2022 serialized params; length=${serializedParams?.length ?? 0}` }); + + let bytes: Uint8Array | undefined; + let compression: IpcMessage['compressed'] = false; + if (serializedParams != null && serializedParams.length > 1024) { + bytes = strToU8(serializedParams); + compression = 'utf8'; + + const originalSize = bytes.byteLength; + + try { + bytes = deflateSync(bytes, { level: 1 }); + compression = 'deflate'; + + sw?.stop({ + message: `\u2022 compressed (${compression}) serialized params (${Math.round((1 - bytes.byteLength / originalSize) * 100)}% reduction) ${originalSize} → ${bytes.byteLength} bytes`, + }); + } catch (ex) { + debugger; + // Compression failed, keep uncompressed data + Logger.error(ex, scope, 'IPC deflate compression failed'); + sw?.stop({ + message: `\u2022 failed deflate compression, using uncompressed data`, + suffix: `failed`, + }); + } } const msg: IpcMessage | Uint8Array> = { - id: this.nextIpcId(), + id: id, scope: notificationType.scope, method: notificationType.method, - params: packed ?? params, - packed: packed != null, + params: bytes ?? serializedParams, + compressed: compression, + timestamp: timestamp, completionId: completionId, }; const success = await this.postMessage(msg); if (success) { this._pendingIpcNotifications.clear(); - } else if (notificationType === ipcPromiseSettled) { + } else if (notificationType === IpcPromiseSettled) { this._pendingIpcPromiseNotifications.add({ msg: msg, timestamp: Date.now() }); } else { this.addPendingIpcNotificationCore(notificationType, msg); @@ -689,63 +732,48 @@ export class WebviewController< return this.notify(requestType.response, params, msg.completionId); } - private replacePromisesWithIpcPromises(data: unknown) { + private serializeIpcData(data: unknown): string { const pendingPromises: IpcPromise[] = []; - this.replacePromisesWithIpcPromisesCore(data, pendingPromises); - if (!pendingPromises.length) return; - - const cancellation = this.cancellation?.token; - queueMicrotask(() => { - for (const ipcPromise of pendingPromises) { - ipcPromise.__promise.then( - r => { - if (cancellation?.isCancellationRequested) { - debugger; - return; - } - return this.notify(ipcPromiseSettled, { status: 'fulfilled', value: r }, ipcPromise.id); - }, - (ex: unknown) => { - if (cancellation?.isCancellationRequested) { - debugger; - return; - } - return this.notify(ipcPromiseSettled, { status: 'rejected', reason: ex }, ipcPromise.id); - }, - ); - } - }); - } - - private replacePromisesWithIpcPromisesCore(data: unknown, pendingPromises: IpcPromise[]) { - if (data == null || typeof data !== 'object') return; - - for (const key in data) { - if (key === '__promise') continue; - - const value = (data as Record)[key]; - if (value instanceof Promise) { - const ipcPromise: IpcPromise = { - __ipc: 'promise', - __promise: value, - id: this.nextIpcId(), - method: ipcPromiseSettled.method, - }; - (data as Record)[key] = ipcPromise; - pendingPromises.push(ipcPromise); - } else if (isIpcPromise(value)) { - value.id = this.nextIpcId(); - pendingPromises.push(value); - } else { - this.replacePromisesWithIpcPromisesCore(value, pendingPromises); - } + const serialized = serializeIpcData(data, () => this.nextIpcId(), pendingPromises); + + if (pendingPromises.length) { + const cancellation = this.cancellation?.token; + queueMicrotask(() => { + for (const ipcPromise of pendingPromises) { + ipcPromise.__promise.then( + r => { + if (cancellation?.isCancellationRequested) { + debugger; + return; + } + return this.notify( + IpcPromiseSettled, + { status: 'fulfilled', value: r }, + ipcPromise.value.id, + ); + }, + (ex: unknown) => { + if (cancellation?.isCancellationRequested) { + debugger; + return; + } + return this.notify( + IpcPromiseSettled, + { status: 'rejected', reason: ex }, + ipcPromise.value.id, + ); + }, + ); + } + }); } + + return serialized; } @sequentialize() @debug['postMessage']>({ - args: false, - enter: m => `(${m.id}|${m.method}${m.completionId ? `+${m.completionId}` : ''})`, + args: { 0: m => `${m.id}|${m.method}${m.completionId ? `+${m.completionId}` : ''}` }, }) private async postMessage(message: IpcMessage): Promise { if (!this._ready) return Promise.resolve(false); @@ -859,7 +887,7 @@ export function replaceWebviewHtmlTokens( root: string, webRoot: string, placement: 'editor' | 'view', - bootstrap?: SerializedState, + bootstrap?: SerializedState | string, head?: string, body?: string, endOfBody?: string, @@ -873,13 +901,15 @@ export function replaceWebviewHtmlTokens( case 'body': return body ?? ''; case 'state': - return bootstrap != null ? base64(JSON.stringify(bootstrap)) : ''; + return bootstrap != null + ? base64(typeof bootstrap === 'string' ? bootstrap : JSON.stringify(bootstrap)) + : ''; case 'endOfBody': return `${ bootstrap != null - ? `` + ? `` : '' }${endOfBody ?? ''}`; case 'webviewId': @@ -914,37 +944,3 @@ export function setContextKeys( ): void { void setContext(`${contextKeyPrefix}:visible`, true); } - -export function updatePendingContext( - current: Context, - pending: Partial | undefined, - update: Partial, - force: boolean = false, -): [changed: boolean, pending: Partial | undefined] { - let changed = false; - for (const [key, value] of Object.entries(update)) { - const currentValue = (current as unknown as Record)[key]; - if ( - !force && - (currentValue instanceof Uri || value instanceof Uri) && - (currentValue as any)?.toString() === value?.toString() - ) { - continue; - } - - if (!force && currentValue === value) { - if ((value !== undefined || key in current) && (pending == null || !(key in pending))) { - continue; - } - } - - if (pending == null) { - pending = {}; - } - - (pending as Record)[key] = value; - changed = true; - } - - return [changed, pending]; -} diff --git a/src/webviews/webviewProvider.ts b/src/webviews/webviewProvider.ts index ec884abe094cf..a1327f689d66f 100644 --- a/src/webviews/webviewProvider.ts +++ b/src/webviews/webviewProvider.ts @@ -1,7 +1,7 @@ import type { Disposable, Uri, ViewBadge, ViewColumn } from 'vscode'; import type { WebviewCommands, WebviewViewCommands } from '../constants.commands'; import type { WebviewTelemetryContext } from '../constants.telemetry'; -import type { WebviewIds, WebviewViewIds } from '../constants.views'; +import type { WebviewIds, WebviewOrWebviewViewTypeFromId, WebviewViewIds } from '../constants.views'; import type { WebviewContext } from '../system/webview'; import type { IpcCallMessageType, @@ -35,7 +35,7 @@ export interface WebviewProvider | undefined]>; registerCommands?(): Disposable[]; - includeBootstrap?(): SerializedState | Promise; + includeBootstrap?(deferrable?: boolean): SerializedState | Promise; includeHead?(): string | Promise; includeBody?(): string | Promise; includeEndOfBody?(): string | Promise; @@ -58,6 +58,7 @@ export interface WebviewStateProvier { readonly id: ID; readonly instanceId: string; + readonly type: WebviewOrWebviewViewTypeFromId; readonly originalTitle: string; title: string; @@ -68,7 +69,7 @@ export interface WebviewHost { readonly ready: boolean; readonly viewColumn: ViewColumn | undefined; readonly visible: boolean; - readonly baseWebviewState: WebviewState; + readonly baseWebviewState: WebviewState; readonly cspNonce: string; getWebRoot(): string; diff --git a/src/webviews/webviewsController.ts b/src/webviews/webviewsController.ts index 7df9a5335fab1..a13c24d1d7175 100644 --- a/src/webviews/webviewsController.ts +++ b/src/webviews/webviewsController.ts @@ -10,7 +10,7 @@ import { Disposable, Uri, ViewColumn, window } from 'vscode'; import { uuid } from '@env/crypto'; import type { GlCommands } from '../constants.commands'; import type { TrackedUsageFeatures } from '../constants.telemetry'; -import type { WebviewIds, WebviewTypes, WebviewViewIds, WebviewViewTypes } from '../constants.views'; +import type { WebviewIds, WebviewTypeFromId, WebviewViewIds, WebviewViewTypeFromId } from '../constants.views'; import type { Container } from '../container'; import { ensurePlusFeaturesEnabled } from '../plus/gk/utils/-webview/plus.utils'; import { executeCoreCommand, registerCommand } from '../system/-webview/command'; @@ -28,9 +28,9 @@ export interface WebviewPanelDescriptor { readonly fileName: string; readonly iconPath: string; readonly title: string; - readonly contextKeyPrefix: `gitlens:webview:${WebviewTypes}`; + readonly contextKeyPrefix: `gitlens:webview:${WebviewTypeFromId}`; readonly trackingFeature: TrackedUsageFeatures; - readonly type: WebviewTypes; + readonly type: WebviewTypeFromId; readonly plusFeature: boolean; readonly column?: ViewColumn; readonly webviewOptions?: WebviewOptions; @@ -88,9 +88,9 @@ export interface WebviewViewDescriptor}`; readonly trackingFeature: TrackedUsageFeatures; - readonly type: WebviewViewTypes; + readonly type: WebviewViewTypeFromId; readonly plusFeature: boolean; readonly webviewOptions?: WebviewOptions; readonly webviewHostOptions?: { diff --git a/webpack.config.mjs b/webpack.config.mjs index 0961d31163cf0..8dd21bd9ae1f6 100644 --- a/webpack.config.mjs +++ b/webpack.config.mjs @@ -41,6 +41,7 @@ const eslintOptions = { // concurrency: 'auto', }; +const useAsyncTypeChecking = false; const useNpm = Boolean(process.env.GL_USE_NPM); if (useNpm) { console.log('Using npm to run scripts'); @@ -87,6 +88,25 @@ const stats = { timings: true, }; +/** + * @param {string} name + * @param { 'node' | 'webworker' } target + * @param { 'production' | 'development' | 'none' } mode + * @returns { WebpackConfig['cache'] } + */ +function getCacheConfig(name, target, mode) { + return undefined; + // Attempt at caching to improve build times, but it doesn't seem to help much if at all + // return { + // type: 'filesystem', + // cacheDirectory: path.join(__dirname, '.webpack-cache'), + // buildDependencies: { + // config: [__filename], + // }, + // name: `${name}-${target}-${mode}`, // Unique per config + // }; +} + /** * @param { 'production' | 'development' | 'none' } mode * @param {{ analyzeBundle?: boolean; analyzeDeps?: boolean; esbuild?: boolean; skipLint?: boolean }} env @@ -133,6 +153,7 @@ function getCommonConfig(mode, env) { plugins: plugins, infrastructureLogging: mode === 'production' ? undefined : { level: 'log' }, // enables logging required for problem matchers stats: stats, + cache: getCacheConfig('common', 'node', mode), }; } @@ -154,10 +175,11 @@ function getExtensionConfig(target, mode, env) { DEBUG: mode === 'development', }), new ForkTsCheckerPlugin({ - async: false, + async: useAsyncTypeChecking, formatter: 'basic', typescript: { configFile: tsConfigPath, + memoryLimit: 4096, }, }), ]; @@ -322,6 +344,7 @@ function getExtensionConfig(target, mode, env) { plugins: plugins, infrastructureLogging: mode === 'production' ? undefined : { level: 'log' }, // enables logging required for problem matchers stats: stats, + cache: getCacheConfig('extension', target, mode), }; } @@ -440,6 +463,7 @@ function getWebviewsCommonConfig(mode, env) { plugins: plugins, infrastructureLogging: mode === 'production' ? undefined : { level: 'log' }, // enables logging required for problem matchers stats: stats, + cache: getCacheConfig('webviews-common', 'webworker', mode), }; } @@ -460,10 +484,11 @@ function getWebviewConfig(webviews, overrides, mode, env) { DEBUG: mode === 'development', }), new ForkTsCheckerPlugin({ - async: false, + async: useAsyncTypeChecking, formatter: 'basic', typescript: { configFile: tsConfigPath, + memoryLimit: 4096, }, }), new WebpackRequireFromPlugin({ @@ -485,6 +510,19 @@ function getWebviewConfig(webviews, overrides, mode, env) { ); } + if (!env.skipLint) { + plugins.push( + new ESLintLitePlugin({ + files: path.join(basePath, '**', '*.ts?(x)'), + worker: eslintWorker, + eslintOptions: { + ...eslintOptions, + cacheLocation: path.join(__dirname, '.eslintcache', 'webviews/'), + }, + }), + ); + } + let name = ''; let filePrefix = ''; if (Object.keys(webviews).length > 1) { @@ -660,6 +698,7 @@ function getWebviewConfig(webviews, overrides, mode, env) { plugins: plugins, infrastructureLogging: mode === 'production' ? undefined : { level: 'log' }, // enables logging required for problem matchers stats: stats, + cache: getCacheConfig(name, 'webworker', mode), }; } @@ -749,52 +788,52 @@ function getHtmlPlugin(name, plus, mode, env) { }); } -class InlineChunkHtmlPlugin { - constructor(htmlPlugin, patterns) { - this.htmlPlugin = htmlPlugin; - this.patterns = patterns; - } - - getInlinedTag(publicPath, assets, tag) { - if ( - (tag.tagName !== 'script' || !(tag.attributes && tag.attributes.src)) && - (tag.tagName !== 'link' || !(tag.attributes && tag.attributes.href)) - ) { - return tag; - } - - let chunkName = tag.tagName === 'link' ? tag.attributes.href : tag.attributes.src; - if (publicPath) { - chunkName = chunkName.replace(publicPath, ''); - } - if (!this.patterns.some(pattern => chunkName.match(pattern))) { - return tag; - } - - const asset = assets[chunkName]; - if (asset == null) { - return tag; - } - - return { tagName: tag.tagName === 'link' ? 'style' : tag.tagName, innerHTML: asset.source(), closeTag: true }; - } - - apply(compiler) { - let publicPath = compiler.options.output.publicPath || ''; - if (publicPath && !publicPath.endsWith('/')) { - publicPath += '/'; - } - - compiler.hooks.compilation.tap('InlineChunkHtmlPlugin', compilation => { - const getInlinedTagFn = tag => this.getInlinedTag(publicPath, compilation.assets, tag); - const sortFn = (a, b) => (a.tagName === 'script' ? 1 : -1) - (b.tagName === 'script' ? 1 : -1); - this.htmlPlugin.getHooks(compilation).alterAssetTagGroups.tap('InlineChunkHtmlPlugin', assets => { - assets.headTags = assets.headTags.map(getInlinedTagFn).sort(sortFn); - assets.bodyTags = assets.bodyTags.map(getInlinedTagFn).sort(sortFn); - }); - }); - } -} +// class InlineChunkHtmlPlugin { +// constructor(htmlPlugin, patterns) { +// this.htmlPlugin = htmlPlugin; +// this.patterns = patterns; +// } + +// getInlinedTag(publicPath, assets, tag) { +// if ( +// (tag.tagName !== 'script' || !(tag.attributes && tag.attributes.src)) && +// (tag.tagName !== 'link' || !(tag.attributes && tag.attributes.href)) +// ) { +// return tag; +// } + +// let chunkName = tag.tagName === 'link' ? tag.attributes.href : tag.attributes.src; +// if (publicPath) { +// chunkName = chunkName.replace(publicPath, ''); +// } +// if (!this.patterns.some(pattern => chunkName.match(pattern))) { +// return tag; +// } + +// const asset = assets[chunkName]; +// if (asset == null) { +// return tag; +// } + +// return { tagName: tag.tagName === 'link' ? 'style' : tag.tagName, innerHTML: asset.source(), closeTag: true }; +// } + +// apply(compiler) { +// let publicPath = compiler.options.output.publicPath || ''; +// if (publicPath && !publicPath.endsWith('/')) { +// publicPath += '/'; +// } + +// compiler.hooks.compilation.tap('InlineChunkHtmlPlugin', compilation => { +// const getInlinedTagFn = tag => this.getInlinedTag(publicPath, compilation.assets, tag); +// const sortFn = (a, b) => (a.tagName === 'script' ? 1 : -1) - (b.tagName === 'script' ? 1 : -1); +// this.htmlPlugin.getHooks(compilation).alterAssetTagGroups.tap('InlineChunkHtmlPlugin', assets => { +// assets.headTags = assets.headTags.map(getInlinedTagFn).sort(sortFn); +// assets.bodyTags = assets.bodyTags.map(getInlinedTagFn).sort(sortFn); +// }); +// }); +// } +// } const schema = { type: 'object', @@ -845,6 +884,9 @@ class FileGeneratorPlugin { return changed; } + /** + * @param {import("webpack").Compiler} compiler + */ apply(compiler) { let pendingGeneration = false; @@ -980,6 +1022,9 @@ class LicensesPlugin extends FileGeneratorPlugin { class FantasticonPlugin { alreadyRun = false; + /** + * @param {{config?: { [key:string]: any }; configPath?: string; onBefore?: Function; onComplete?: Function }} options + */ constructor(options = {}) { this.pluginName = 'fantasticon'; this.options = options; @@ -1069,7 +1114,9 @@ class FantasticonPlugin { } const generateFn = generate.bind(this); + // @ts-ignore compiler.hooks.beforeRun.tapPromise(this.pluginName, generateFn); + // @ts-ignore compiler.hooks.watchRun.tapPromise(this.pluginName, generateFn); } }