diff --git a/src/system/color.ts b/src/system/color.ts index b5daa52d18b49..d2b8f5c912844 100644 --- a/src/system/color.ts +++ b/src/system/color.ts @@ -805,3 +805,11 @@ function _parseHexDigit(charCode: CharCode): number { } return 0; } + +export function getCssMixedColorValue(color1: string, color2: string, percent: number): string { + return `color-mix(in srgb, ${color1} ${percent}%, ${color2})`; +} + +export function getCssOpacityColorValue(color: string, percent: number): string { + return getCssMixedColorValue(color, 'transparent', percent); +} diff --git a/src/webviews/apps/plus/graph/graph-app.ts b/src/webviews/apps/plus/graph/graph-app.ts index 11af6583b8ceb..8f8b1f10dcf10 100644 --- a/src/webviews/apps/plus/graph/graph-app.ts +++ b/src/webviews/apps/plus/graph/graph-app.ts @@ -13,7 +13,6 @@ 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 { stateContext } from './context'; import type { GlGraphWrapper } from './graph-wrapper/graph-wrapper'; import type { GlGraphHover } from './hover/graphHover'; import type { GraphMinimapDaySelectedEventDetail } from './minimap/minimap'; @@ -36,11 +35,8 @@ export class GraphApp extends SignalWatcher(LitElement) { return this; } - @consume({ context: stateContext, subscribe: true }) - state!: typeof stateContext.__context__; - @consume({ context: graphStateContext, subscribe: true }) - graphApp!: typeof graphStateContext.__context__; + graphState!: typeof graphStateContext.__context__; @consume({ context: ipcContext }) private readonly _ipc!: typeof ipcContext.__context__; @@ -76,27 +72,27 @@ export class GraphApp extends SignalWatcher(LitElement) { @gl-select-commits=${this.handleHeaderSearchNavigation} >
- ${when(!this.state.allowed, () => html``)} + ${when(!this.graphState.allowed, () => html``)}
${when( - this.state.config?.minimap !== false, + this.graphState.config?.minimap !== false, () => html` `, )} - ${when(this.state.config?.sidebar, () => html``)} + ${when(this.graphState.config?.sidebar, () => html``)} ) { - if (!this.state.rows) return; + if (!this.graphState.rows) return; let { sha } = e.detail; if (sha == null) { @@ -127,7 +123,7 @@ export class GraphApp extends SignalWatcher(LitElement) { if (date == null) return; // Find closest row to the date - const closest = this.state.rows.reduce((prev, curr) => { + const closest = this.graphState.rows.reduce((prev, curr) => { return Math.abs(curr.date - date) < Math.abs(prev.date - date) ? curr : prev; }); sha = closest.sha; @@ -161,7 +157,7 @@ export class GraphApp extends SignalWatcher(LitElement) { } private handleGraphVisibleDaysChanged({ detail }: CustomEventType<'gl-graph-change-visible-days'>) { - this.graphApp.visibleDays = detail; + this.graphState.visibleDays = detail; } private handleGraphRowContextMenu(_e: CustomEventType<'gl-graph-row-context-menu'>) { diff --git a/src/webviews/apps/plus/graph/graph-header.ts b/src/webviews/apps/plus/graph/graph-header.ts index ef0fe24ef7210..3f6568266eb0b 100644 --- a/src/webviews/apps/plus/graph/graph-header.ts +++ b/src/webviews/apps/plus/graph/graph-header.ts @@ -48,7 +48,6 @@ 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 { stateContext } from './context'; import { graphStateContext } from './stateProvider'; import { actionButton, linkBase } from './styles/graph.css'; import { graphHeaderControlStyles, progressStyles, repoHeaderStyles, titlebarStyles } from './styles/header.css'; @@ -129,27 +128,24 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { @consume({ context: telemetryContext as { __context__: TelemetryContext } }) _telemetry!: TelemetryContext; - @consume({ context: stateContext, subscribe: true }) - hostState!: typeof stateContext.__context__; - - @consume({ context: graphStateContext }) - appState!: typeof graphStateContext.__context__; + @consume({ context: graphStateContext, subscribe: true }) + graphState!: typeof graphStateContext.__context__; @state() private aiAllowed = true; get hasFilters() { - if (this.hostState.config?.onlyFollowFirstParent) return true; - if (this.hostState.excludeTypes == null) return false; + if (this.graphState.config?.onlyFollowFirstParent) return true; + if (this.graphState.excludeTypes == null) return false; - return Object.values(this.hostState.excludeTypes).includes(true); + return Object.values(this.graphState.excludeTypes).includes(true); } get excludeRefs() { - return Object.values(this.hostState.excludeRefs ?? {}).sort(compareGraphRefOpts); + return Object.values(this.graphState.excludeRefs ?? {}).sort(compareGraphRefOpts); } override updated(changedProperties: PropertyValues): void { - this.aiAllowed = (this.hostState.config?.aiEnabled ?? true) && (this.hostState.orgSettings?.ai ?? true); + this.aiAllowed = (this.graphState.config?.aiEnabled ?? true) && (this.graphState.orgSettings?.ai ?? true); super.updated(changedProperties); } @@ -179,7 +175,7 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { } private onSearchOpenInView() { - this._ipc.sendCommand(SearchOpenInViewCommand, { search: { ...this.appState.filter } }); + this._ipc.sendCommand(SearchOpenInViewCommand, { search: { ...this.graphState.filter } }); } private onExcludeTypesChanged(key: keyof GraphExcludeTypes, value: boolean) { @@ -193,7 +189,7 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { private _activeRowInfoCache: { row: string; info: { date: number; id: string } } | undefined; private getActiveRowInfo(): { date: number; id: string } | undefined { - const { activeRow } = this.appState; + const { activeRow } = this.graphState; if (activeRow == null) return undefined; if (this._activeRowInfoCache?.row === activeRow) return this._activeRowInfoCache?.info; @@ -293,13 +289,13 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { } private _searchPositionSignal = computed(() => { - const { searchResults } = this.appState; - if (searchResults?.ids == null || !this.appState.filter.query) return 0; + const { searchResults } = this.graphState; + if (searchResults?.ids == null || !this.graphState.filter.query) return 0; const id = this.getActiveRowInfo()?.id; let searchIndex = id ? searchResults.ids[id]?.i : undefined; if (searchIndex == null) { - ({ index: searchIndex } = this.getClosestSearchResultIndex(searchResults, { ...this.appState.filter })); + ({ index: searchIndex } = this.getClosestSearchResultIndex(searchResults, { ...this.graphState.filter })); } return searchIndex < 1 ? 1 : searchIndex + 1; }); @@ -309,7 +305,7 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { } get searchValid() { - return this.appState.filter.query.length > 2; + return this.graphState.filter.query.length > 2; } handleFilterChange(e: CustomEvent) { @@ -331,7 +327,7 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { case 'stashes': case 'tags': { const key = $el.value satisfies keyof GraphExcludeTypes; - const currentFilter = this.hostState.excludeTypes?.[key]; + const currentFilter = this.graphState.excludeTypes?.[key]; if ((currentFilter == null && checked) || (currentFilter != null && currentFilter !== checked)) { this.onExcludeTypesChanged(key, checked); } @@ -351,33 +347,33 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { } async handleSearch() { - this.appState.searching = this.searchValid; + this.graphState.searching = this.searchValid; if (!this.searchValid) { - this.appState.searchResultsResponse = undefined; + this.graphState.searchResultsResponse = undefined; } try { const rsp = await this._ipc.sendRequest(SearchRequest, { - search: this.searchValid ? { ...this.appState.filter } : undefined /*limit: options?.limit*/, + search: this.searchValid ? { ...this.graphState.filter } : undefined /*limit: options?.limit*/, }); if (rsp.search && rsp.results) { this.searchEl.logSearch(rsp.search); } - this.appState.searchResultsResponse = rsp.results; + this.graphState.searchResultsResponse = rsp.results; if (rsp.selectedRows != null) { - this.appState.selectedRows = rsp.selectedRows; + this.graphState.selectedRows = rsp.selectedRows; } } catch { - this.appState.searchResultsResponse = undefined; + this.graphState.searchResultsResponse = undefined; } - this.appState.searching = false; + this.graphState.searching = false; } @debounce(250) private handleSearchInput(e: CustomEvent) { - this.appState.filter = e.detail; + this.graphState.filter = e.detail; void this.handleSearch(); } @@ -389,9 +385,9 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { more: options?.more, }); - this.appState.searchResultsResponse = rsp.results; + this.graphState.searchResultsResponse = rsp.results; if (rsp.selectedRows != null) { - this.appState.selectedRows = rsp.selectedRows; + this.graphState.selectedRows = rsp.selectedRows; } return rsp; @@ -401,7 +397,7 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { } private async handleSearchNavigation(e: CustomEvent) { - let { searchResults } = this.appState; + let { searchResults } = this.graphState; if (searchResults == null) return; const direction = e.detail?.direction ?? 'next'; @@ -422,7 +418,7 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { next = direction === 'next'; ({ index: searchIndex, id } = this.getClosestSearchResultIndex( searchResults, - { ...this.appState.filter }, + { ...this.graphState.filter }, next, )); } @@ -435,13 +431,13 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { // Indicates a boundary and we need to load more results if (searchIndex === -1) { if (next) { - if (this.appState.filter.query && searchResults?.paging?.hasMore) { - this.appState.searching = true; + if (this.graphState.filter.query && searchResults?.paging?.hasMore) { + this.graphState.searching = true; let moreResults; try { - moreResults = await this.onSearchPromise?.({ ...this.appState.filter }, { more: true }); + moreResults = await this.onSearchPromise?.({ ...this.graphState.filter }, { more: true }); } finally { - this.appState.searching = false; + this.graphState.searching = false; } if (moreResults?.results != null && !('error' in moreResults.results)) { if (count < moreResults.results.count) { @@ -457,14 +453,17 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { } else { searchIndex = 0; } - // this.appState.filter != null seems noop - } else if (direction === 'last' && this.appState.filter != null && searchResults?.paging?.hasMore) { - this.appState.searching = true; + // this.graphState.filter != null seems noop + } else if (direction === 'last' && this.graphState.filter != null && searchResults?.paging?.hasMore) { + this.graphState.searching = true; let moreResults; try { - moreResults = await this.onSearchPromise({ ...this.appState.filter }, { limit: 0, more: true }); + moreResults = await this.onSearchPromise( + { ...this.graphState.filter }, + { limit: 0, more: true }, + ); } finally { - this.appState.searching = false; + this.graphState.searching = false; } if (moreResults?.results != null && !('error' in moreResults.results)) { if (count < moreResults.results.count) { @@ -484,10 +483,10 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { if (id != null) break; } - this.appState.searchResultsHidden = true; + this.graphState.searchResultsHidden = true; searchIndex = this.getNextOrPreviousSearchResultIndex(searchIndex, next, searchResults, { - ...this.appState.filter, + ...this.graphState.filter, }); } @@ -516,13 +515,13 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { if (promise == null) { let timeout: ReturnType | undefined = setTimeout(() => { timeout = undefined; - this.appState.loading = true; + this.graphState.loading = true; }, 500); const ensureCore = async () => { const e = await this.onEnsureRowPromise(id, false); if (timeout == null) { - this.appState.loading = false; + this.graphState.loading = false; } else { clearTimeout(timeout); } @@ -555,7 +554,7 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { } handleMinimapToggled() { - this.changeGraphConfiguration({ minimap: !this.hostState.config?.minimap }); + this.changeGraphConfiguration({ minimap: !this.graphState.config?.minimap }); } private changeGraphConfiguration(changes: UpdateGraphConfigurationParams['changes']) { @@ -563,30 +562,30 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { } private handleMinimapDataTypeChanged(e: Event) { - if (this.hostState.config == null) return; + if (this.graphState.config == null) return; const $el = e.target as RadioGroup; const minimapDataType = $el.value === 'lines' ? 'lines' : 'commits'; - if (this.hostState.config.minimapDataType === minimapDataType) return; + if (this.graphState.config.minimapDataType === minimapDataType) return; this.changeGraphConfiguration({ minimapDataType: minimapDataType }); } private handleMinimapAdditionalTypesChanged(e: Event) { - if (this.hostState.config?.minimapMarkerTypes == null) return; + if (this.graphState.config?.minimapMarkerTypes == null) return; const $el = e.target as HTMLInputElement; const value = $el.value as GraphMinimapMarkerTypes; if ($el.checked) { - if (!this.hostState.config.minimapMarkerTypes.includes(value)) { - const minimapMarkerTypes = [...this.hostState.config.minimapMarkerTypes, value]; + if (!this.graphState.config.minimapMarkerTypes.includes(value)) { + const minimapMarkerTypes = [...this.graphState.config.minimapMarkerTypes, value]; this.changeGraphConfiguration({ minimapMarkerTypes: minimapMarkerTypes }); } } else { - const index = this.hostState.config.minimapMarkerTypes.indexOf(value); + const index = this.graphState.config.minimapMarkerTypes.indexOf(value); if (index !== -1) { - const minimapMarkerTypes = [...this.hostState.config.minimapMarkerTypes]; + const minimapMarkerTypes = [...this.graphState.config.minimapMarkerTypes]; minimapMarkerTypes.splice(index, 1); this.changeGraphConfiguration({ minimapMarkerTypes: minimapMarkerTypes }); } @@ -613,17 +612,17 @@ export class GlGraphHeader extends SignalWatcher(LitElement) { private readonly searchEl!: GlSearchBox; override render() { - const repo = this.hostState.repositories?.find(repo => repo.id === this.hostState.selectedRepository); - const { searchResults } = this.appState; + const repo = this.graphState.repositories?.find(repo => repo.id === this.graphState.selectedRepository); + const { searchResults } = this.graphState; - const hasMultipleRepositories = (this.hostState.repositories?.length ?? 0) > 1; + const hasMultipleRepositories = (this.graphState.repositories?.length ?? 0) > 1; return cache( html`
${when( - this.hostState.allowed && repo, + this.graphState.allowed && repo, () => html` ${when( - this.hostState.branchState?.pr, + this.graphState.branchState?.pr, pr => html`
${when( - this.hostState.allowed && - this.hostState.workingTreeStats != null && - (this.hostState.workingTreeStats.hasConflicts || - this.hostState.workingTreeStats.pausedOpStatus), + this.graphState.allowed && + this.graphState.workingTreeStats != null && + (this.graphState.workingTreeStats.hasConflicts || + this.graphState.workingTreeStats.pausedOpStatus), () => html`
`, )} ${when( - this.hostState.allowed, + this.graphState.allowed, () => html`
@@ -861,7 +860,7 @@ export class GlGraphHeader extends SignalWatcher(LitElement) {