瀏覽代碼

Updates the list-tree toggle in commit details

main
Keith Daulton 2 年之前
父節點
當前提交
322f9153ad
共有 6 個文件被更改,包括 147 次插入17 次删除
  1. +3
    -10
      src/webviews/apps/commitDetails/commitDetails.html
  2. +12
    -7
      src/webviews/apps/commitDetails/commitDetails.ts
  3. +48
    -0
      src/webviews/apps/shared/components/actions/action-item.ts
  4. +73
    -0
      src/webviews/apps/shared/components/actions/action-nav.ts
  5. +4
    -0
      src/webviews/apps/shared/components/list/list-container.ts
  6. +7
    -0
      src/webviews/apps/shared/components/webview-pane.ts

+ 3
- 10
src/webviews/apps/commitDetails/commitDetails.html 查看文件

@ -133,17 +133,10 @@
<webview-pane class="commit-details__files" collapsable expanded>
<span slot="title">Files changed </span>
<span slot="subtitle" data-region="stats"></span>
<action-nav slot="actions">
<action-item data-switch-value="list-tree" label="Show tree" icon="list-tree"></action-item>
</action-nav>
<div style="text-align: center">
<div class="switch">
<button type="button" class="switch__option" data-switch-value="list">
<code-icon icon="list-flat"></code-icon> Path
</button>
<button type="button" class="switch__option" data-switch-value="list-tree">
<code-icon icon="list-tree"></code-icon> Tree
</button>
</div>
</div>
<ul class="change-list" data-region="files">
<li class="change-list__item commit-details__item-skeleton">
<skeleton-loader></skeleton-loader>

+ 12
- 7
src/webviews/apps/commitDetails/commitDetails.ts 查看文件

@ -36,6 +36,8 @@ import '../shared/components/progress';
import '../shared/components/list/list-container';
import '../shared/components/list/list-item';
import '../shared/components/list/file-change-list-item';
import '../shared/components/actions/action-item';
import '../shared/components/actions/action-nav';
const uncommittedSha = '0000000000000000000000000000000000000000';
@ -126,13 +128,13 @@ export class CommitDetailsApp extends App> {
private onTreeSetting(e: MouseEvent) {
const isTree = (e.target as HTMLElement)?.getAttribute('data-switch-value') === 'list-tree';
if (isTree === this.state.preferences?.filesAsTree) return;
if (!isTree === this.state.preferences?.filesAsTree) return;
this.state.preferences = { ...this.state.preferences, filesAsTree: isTree };
this.state.preferences = { ...this.state.preferences, filesAsTree: !isTree };
this.renderFiles(this.state as CommitState);
this.sendCommand(PreferencesCommandType, { filesAsTree: isTree });
this.sendCommand(PreferencesCommandType, { filesAsTree: !isTree });
}
private onExpandedChange(e: WebviewPaneExpandedChangeEventDetail) {
@ -330,15 +332,18 @@ export class CommitDetailsApp extends App> {
const $el = document.querySelector<HTMLElement>('[data-region="files"]');
if ($el == null) return;
const isTree = state.preferences?.filesAsTree === true;
const $toggle = document.querySelector('[data-switch-value]');
if ($toggle) {
$toggle.setAttribute('data-switch-value', isTree ? 'list-tree' : 'list');
$toggle.setAttribute('icon', isTree ? 'list-tree' : 'list-flat');
}
if (!state.selected.files?.length) {
$el.innerHTML = '';
return;
}
const isTree = state.preferences?.filesAsTree === true;
document.querySelector('[data-switch-value="list"]')?.classList.toggle('is-selected', !isTree);
document.querySelector('[data-switch-value="list-tree"]')?.classList.toggle('is-selected', isTree);
const stashAttr = state.selected.isStash
? 'stash '
: state.selected.sha === uncommittedSha

+ 48
- 0
src/webviews/apps/shared/components/actions/action-item.ts 查看文件

@ -0,0 +1,48 @@
import { attr, css, customElement, FASTElement, html } from '@microsoft/fast-element';
const template = html<ActionItem>`<a
role="${x => (!x.href ? 'button' : null)}"
type="${x => (!x.href ? 'button' : null)}"
aria-label="${x => x.label}"
title="${x => x.label}"
><code-icon icon="${x => x.icon}"></code-icon
></a>`;
const styles = css`
:host {
box-sizing: border-box;
display: inline-flex;
justify-content: center;
align-items: center;
width: 2rem;
height: 2rem;
border-radius: 0.5rem;
color: inherit;
padding: 0.2rem;
vertical-align: text-bottom;
text-decoration: none;
cursor: pointer;
}
:host(:focus) {
outline: 1px solid var(--vscode-focusBorder);
outline-offset: -1px;
}
:host(:hover) {
background-color: var(--vscode-toolbar-hoverBackground);
}
:host(:active) {
background-color: var(--vscode-toolbar-activeBackground);
}
`;
@customElement({ name: 'action-item', template: template, styles: styles })
export class ActionItem extends FASTElement {
@attr
href?: string;
@attr
label: string = '';
@attr
icon: string = '';
}

+ 73
- 0
src/webviews/apps/shared/components/actions/action-nav.ts 查看文件

@ -0,0 +1,73 @@
import { css, customElement, FASTElement, html, observable, slotted } from '@microsoft/fast-element';
import '../codicon';
const template = html<ActionNav>`<template role="navigation"><slot ${slotted('actionNodes')}></slot></template>`;
const styles = css`
:host {
display: flex;
align-items: center;
user-select: none;
}
`;
@customElement({ name: 'action-nav', template: template, styles: styles })
export class ActionNav extends FASTElement {
@observable
actionNodes?: HTMLElement[];
actionNodesDisposer?: () => void;
actionNodesChanged(_oldValue?: HTMLElement[], newValue?: HTMLElement[]) {
this.actionNodesDisposer?.();
if (!newValue?.length) {
return;
}
const handleKeydown = this.handleKeydown.bind(this);
const nodeEvents = newValue
?.filter(node => node.nodeType === 1)
.map((node, i) => {
node.setAttribute('tabindex', i === 0 ? '0' : '-1');
node.addEventListener('keydown', handleKeydown, false);
return {
dispose: () => {
node?.removeEventListener('keydown', handleKeydown, false);
},
};
});
this.actionNodesDisposer = () => {
nodeEvents?.forEach(({ dispose }) => dispose());
};
}
override disconnectedCallback() {
this.actionNodesDisposer?.();
}
handleKeydown(e: KeyboardEvent) {
if (!e.target || this.actionNodes == null || this.actionNodes.length < 2) return;
const target = e.target as HTMLElement;
let $next: HTMLElement | null = null;
if (e.key === 'ArrowLeft') {
$next = target.previousElementSibling as HTMLElement;
if ($next == null) {
const filteredNodes = this.actionNodes.filter(node => node.nodeType === 1);
$next = filteredNodes[filteredNodes.length - 1] ?? null;
}
} else if (e.key === 'ArrowRight') {
$next = target.nextElementSibling as HTMLElement;
if ($next == null) {
$next = this.actionNodes.find(node => node.nodeType === 1) ?? null;
}
}
if ($next == null || $next === target) {
return;
}
target.setAttribute('tabindex', '-1');
$next.setAttribute('tabindex', '0');
$next.focus();
}
}

+ 4
- 0
src/webviews/apps/shared/components/list/list-container.ts 查看文件

@ -55,6 +55,10 @@ export class ListContainer extends FASTElement {
};
}
override disconnectedCallback() {
this.itemNodesDisposer?.();
}
handleBeforeSelected(e: Event) {
if (!e.target) return;

+ 7
- 0
src/webviews/apps/shared/components/webview-pane.ts 查看文件

@ -1,6 +1,7 @@
import { css, html, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import './codicon';
import './actions/action-nav';
export interface WebviewPaneExpandedChangeEventDetail {
expanded: boolean;
@ -81,6 +82,11 @@ export class WebviewPane extends LitElement {
:host([collapsable][expanded='false']) .content {
display: none;
}
slot[name='actions']::slotted(*) {
flex: none;
margin-left: auto;
}
`;
@property({ type: Boolean, reflect: true })
@ -116,6 +122,7 @@ export class WebviewPane extends LitElement {
return html`
<header class="header">
${this.renderTitle()}
<slot name="actions"></slot>
<progress-indicator active="${this.loading}"></progress-indicator>
</header>
<div id="content" role="region" class="content">

Loading…
取消
儲存