Merge remote-tracking branch 'origin/master' into hotfix-1.2.3-minification

This commit is contained in:
Markus Olsson 2018-06-07 18:49:26 +02:00
commit 6305ffeb2b
31 changed files with 253 additions and 252 deletions

View file

@ -323,18 +323,11 @@ export enum RepositorySectionTab {
History,
}
export type RepositorySection =
| { selectedTab: RepositorySectionTab.Changes }
| {
selectedTab: RepositorySectionTab.History
shouldShowBranchesList?: boolean
}
export interface IRepositoryState {
readonly historyState: IHistoryState
readonly changesState: IChangesState
readonly compareState: ICompareState
readonly selectedSection: RepositorySection
readonly selectedSection: RepositorySectionTab
/**
* The name and email that will be used for the author info
@ -635,6 +628,12 @@ export interface ICompareState {
/** The current state of the compare form, based on user input */
readonly formState: IDisplayHistory | ICompareBranch
/** Whether the branch list should be expanded or hidden */
readonly showBranchList: boolean
/** The text entered into the compare branch filter text box */
readonly filterText: string
/** The SHAs of commits to render in the compare list */
readonly commitSHAs: ReadonlyArray<string>
@ -662,6 +661,14 @@ export interface ICompareState {
readonly aheadBehindCache: ComparisonCache
}
export interface ICompareFormUpdate {
/** The updated filter text to set */
readonly filterText: string
/** Thew new state of the branches list */
readonly showBranchList: boolean
}
export enum CompareActionKind {
History = 'History',
Branch = 'Branch',

View file

@ -11,13 +11,14 @@ import {
} from '../../models/status'
import { DiffSelection } from '../../models/diff'
import {
RepositorySection,
RepositorySectionTab,
Popup,
PopupType,
Foldout,
FoldoutType,
ImageDiffType,
CompareAction,
ICompareFormUpdate,
} from '../app-state'
import { AppStore } from '../stores/app-store'
import { CloningRepository } from '../../models/cloning-repository'
@ -179,7 +180,7 @@ export class Dispatcher {
/** Change the selected section in the repository. */
public changeRepositorySection(
repository: Repository,
section: RepositorySection
section: RepositorySectionTab
): Promise<void> {
return this.appStore._changeRepositorySection(repository, section)
}
@ -1184,6 +1185,14 @@ export class Dispatcher {
return this.appStore._executeCompare(repository, action)
}
/** Update the compare form state for the current repository */
public updateCompareForm<K extends keyof ICompareFormUpdate>(
repository: Repository,
newState: Pick<ICompareFormUpdate, K>
) {
return this.appStore._updateCompareForm(repository, newState)
}
/**
* Increments the `mergeIntoCurrentBranchMenuCount` metric
*/

View file

@ -171,7 +171,9 @@ async function findHyper(): Promise<string | null> {
const path = commandPieces
? commandPieces[2]
: localAppData != null ? localAppData.concat('\\hyper\\Hyper.exe') : null // fall back to the launcher in install root
: localAppData != null
? localAppData.concat('\\hyper\\Hyper.exe')
: null // fall back to the launcher in install root
if (path == null) {
log.debug(

View file

@ -23,7 +23,7 @@ import {
CompareActionKind,
IDisplayHistory,
ICompareBranch,
RepositorySection,
ICompareFormUpdate,
} from '../app-state'
import { Account } from '../../models/account'
import { Repository } from '../../models/repository'
@ -255,7 +255,7 @@ export class AppStore extends TypedBaseStore<IAppState> {
| ((repository: Repository | null) => void)
| null = null
private selectedCloneRepositoryTab: CloneRepositoryTab = CloneRepositoryTab.DotCom
private selectedCloneRepositoryTab = CloneRepositoryTab.DotCom
private selectedBranchesTab = BranchesTab.Branches
@ -422,7 +422,7 @@ export class AppStore extends TypedBaseStore<IAppState> {
coAuthors: [],
showCoAuthoredBy: false,
},
selectedSection: { selectedTab: RepositorySectionTab.Changes },
selectedSection: RepositorySectionTab.Changes,
branchesState: {
tip: { kind: TipState.Unknown },
defaultBranch: null,
@ -434,6 +434,8 @@ export class AppStore extends TypedBaseStore<IAppState> {
},
compareState: {
formState: { kind: ComparisonView.None },
showBranchList: false,
filterText: '',
commitSHAs: [],
aheadBehindCache: new ComparisonCache(),
allBranches: new Array<Branch>(),
@ -861,6 +863,18 @@ export class AppStore extends TypedBaseStore<IAppState> {
}
}
/** This shouldn't be called directly. See `Dispatcher`. */
public _updateCompareForm<K extends keyof ICompareFormUpdate>(
repository: Repository,
newState: Pick<ICompareFormUpdate, K>
) {
this.updateCompareState(repository, state => {
return merge(state, newState)
})
this.emitUpdate()
}
/** This shouldn't be called directly. See `Dispatcher`. */
public _loadNextHistoryBatch(repository: Repository): Promise<void> {
const gitStore = this.getGitStore(repository)
@ -1482,14 +1496,14 @@ export class AppStore extends TypedBaseStore<IAppState> {
/** This shouldn't be called directly. See `Dispatcher`. */
public async _changeRepositorySection(
repository: Repository,
selectedSection: RepositorySection
selectedSection: RepositorySectionTab
): Promise<void> {
this.updateRepositoryState(repository, state => ({ selectedSection }))
this.emitUpdate()
if (selectedSection.selectedTab === RepositorySectionTab.History) {
if (selectedSection === RepositorySectionTab.History) {
return this.refreshHistorySection(repository)
} else if (selectedSection.selectedTab === RepositorySectionTab.Changes) {
} else if (selectedSection === RepositorySectionTab.Changes) {
return this.refreshChangesSection(repository, {
includingStatus: true,
clearPartialState: false,
@ -1729,9 +1743,9 @@ export class AppStore extends TypedBaseStore<IAppState> {
const section = state.selectedSection
let refreshSectionPromise: Promise<void>
if (section.selectedTab === RepositorySectionTab.History) {
if (section === RepositorySectionTab.History) {
refreshSectionPromise = this.refreshHistorySection(repository)
} else if (section.selectedTab === RepositorySectionTab.Changes) {
} else if (section === RepositorySectionTab.Changes) {
refreshSectionPromise = this.refreshChangesSection(repository, {
includingStatus: false,
clearPartialState: false,
@ -2156,7 +2170,7 @@ export class AppStore extends TypedBaseStore<IAppState> {
const refreshWeight = 0.1
// Scale pull and fetch weights to be between 0 and 0.9.
const scale = 1 / (pushWeight + fetchWeight) * (1 - refreshWeight)
const scale = (1 / (pushWeight + fetchWeight)) * (1 - refreshWeight)
pushWeight *= scale
fetchWeight *= scale
@ -2340,7 +2354,7 @@ export class AppStore extends TypedBaseStore<IAppState> {
const refreshWeight = 0.1
// Scale pull and fetch weights to be between 0 and 0.9.
const scale = 1 / (pullWeight + fetchWeight) * (1 - refreshWeight)
const scale = (1 / (pullWeight + fetchWeight)) * (1 - refreshWeight)
pullWeight *= scale
fetchWeight *= scale

View file

@ -358,7 +358,9 @@ export function buildDefaultMenu(
const showLogsLabel = __DARWIN__
? 'Show Logs in Finder'
: __WIN32__ ? 'S&how logs in Explorer' : 'S&how logs in your File Manager'
: __WIN32__
? 'S&how logs in Explorer'
: 'S&how logs in your File Manager'
const showLogsItem: Electron.MenuItemConstructorOptions = {
label: showLogsLabel,

View file

@ -490,7 +490,7 @@ export class App extends React.Component<IAppProps, IAppState> {
this.props.dispatcher.showPopup({ type: PopupType.About })
}
private async showHistory(shouldShowBranchesList: boolean = false) {
private async showHistory(showBranchList: boolean = false) {
const state = this.state.selectedState
if (state == null || state.type !== SelectionType.Repository) {
return
@ -502,9 +502,14 @@ export class App extends React.Component<IAppProps, IAppState> {
kind: CompareActionKind.History,
})
await this.props.dispatcher.changeRepositorySection(state.repository, {
selectedTab: RepositorySectionTab.History,
shouldShowBranchesList,
await this.props.dispatcher.changeRepositorySection(
state.repository,
RepositorySectionTab.History
)
await this.props.dispatcher.updateCompareForm(state.repository, {
filterText: '',
showBranchList,
})
}
@ -515,9 +520,10 @@ export class App extends React.Component<IAppProps, IAppState> {
}
this.props.dispatcher.closeCurrentFoldout()
this.props.dispatcher.changeRepositorySection(state.repository, {
selectedTab: RepositorySectionTab.Changes,
})
this.props.dispatcher.changeRepositorySection(
state.repository,
RepositorySectionTab.Changes
)
}
private chooseRepository() {

View file

@ -31,7 +31,9 @@ export class BranchListItem extends React.Component<IBranchListItemProps, {}> {
const icon = isCurrentBranch ? OcticonSymbol.check : OcticonSymbol.gitBranch
const infoTitle = isCurrentBranch
? 'Current branch'
: lastCommitDate ? lastCommitDate.toString() : ''
: lastCommitDate
? lastCommitDate.toString()
: ''
return (
<div className="branches-list-item">
<Octicon className="icon" symbol={icon} />

View file

@ -20,14 +20,6 @@ import {
} from './group-branches'
import { NoBranches } from './no-branches'
/**
* TS can't parse generic specialization in JSX, so we have to alias it here
* with the generic type. See https://github.com/Microsoft/TypeScript/issues/6395.
*/
const BranchesFilterList: new () => FilterList<
IBranchListItem
> = FilterList as any
const RowHeight = 30
interface IBranchListProps {
@ -172,7 +164,7 @@ export class BranchList extends React.Component<
public render() {
return (
<BranchesFilterList
<FilterList<IBranchListItem>
ref={this.onBranchesFilterListRef}
className="branches-list"
rowHeight={RowHeight}

View file

@ -17,14 +17,6 @@ interface IPullRequestListItem extends IFilterListItem {
readonly pullRequest: PullRequest
}
/**
* TS can't parse generic specialization in JSX, so we have to alias it here
* with the generic type. See https://github.com/Microsoft/TypeScript/issues/6395.
*/
const PullRequestFilterList: new () => FilterList<
IPullRequestListItem
> = FilterList as any
export const RowHeight = 47
interface IPullRequestListProps {
@ -128,7 +120,7 @@ export class PullRequestList extends React.Component<
public render() {
return (
<PullRequestFilterList
<FilterList<IPullRequestListItem>
className="pull-request-list"
rowHeight={RowHeight}
groups={this.state.groupedItems}

View file

@ -8,14 +8,6 @@ import { RowHeight } from './pull-request-list'
const FacadeCount = 6
/**
* TS can't parse generic specialization in JSX, so we have to alias it here
* with the generic type. See https://github.com/Microsoft/TypeScript/issues/6395.
*/
const PullRequestsLoadingList: new () => FilterList<
IFilterListItem
> = FilterList as any
const prLoadingItemProps: IPullRequestListItemProps = {
loading: true,
author: '',
@ -51,7 +43,7 @@ export class PullRequestsLoading extends React.Component<{}, {}> {
]
return (
<PullRequestsLoadingList
<FilterList<IFilterListItem>
className="pull-request-list"
rowHeight={RowHeight}
groups={groups}

View file

@ -47,6 +47,7 @@ interface IChangesListProps {
trailers?: ReadonlyArray<ITrailer>
) => Promise<boolean>
readonly onDiscardChanges: (file: WorkingDirectoryFileChange) => void
readonly askForConfirmationOnDiscardChanges: boolean
readonly onDiscardAllChanges: (
files: ReadonlyArray<WorkingDirectoryFileChange>
) => void
@ -160,7 +161,9 @@ export class ChangesList extends React.Component<
const includeAll =
selection === DiffSelectionType.All
? true
: selection === DiffSelectionType.None ? false : null
: selection === DiffSelectionType.None
? false
: null
return (
<ChangedFile
@ -217,6 +220,19 @@ export class ChangesList extends React.Component<
}
}
private getDiscardChangesMenuItemLabel = (files: ReadonlyArray<string>) => {
const label =
files.length === 1
? __DARWIN__
? `Discard Changes`
: `Discard changes`
: __DARWIN__
? `Discard ${files.length} Selected Changes`
: `Discard ${files.length} selected changes`
return this.props.askForConfirmationOnDiscardChanges ? `${label}` : label
}
private onContextMenu = (event: React.MouseEvent<any>) => {
event.preventDefault()
@ -264,12 +280,7 @@ export class ChangesList extends React.Component<
const items: IMenuItem[] = [
{
label:
paths.length === 1
? __DARWIN__ ? `Discard Changes…` : `Discard changes…`
: __DARWIN__
? `Discard ${paths.length} Selected Changes…`
: `Discard ${paths.length} selected changes…`,
label: this.getDiscardChangesMenuItemLabel(paths),
action: () => this.onDiscardChanges(paths),
},
{

View file

@ -343,8 +343,12 @@ export class CommitMessage extends React.Component<
private get toggleCoAuthorsText(): string {
return this.props.showCoAuthoredBy
? __DARWIN__ ? 'Remove Co-Authors' : 'Remove co-authors'
: __DARWIN__ ? 'Add Co-Authors' : 'Add co-authors'
? __DARWIN__
? 'Remove Co-Authors'
: 'Remove co-authors'
: __DARWIN__
? 'Add Co-Authors'
: 'Add co-authors'
}
private getAddRemoveCoAuthorsMenuItem(): IMenuItem {

View file

@ -19,7 +19,9 @@ export class NoChanges extends React.Component<INoChangesProps, {}> {
public render() {
const opener = __DARWIN__
? 'Finder'
: __WIN32__ ? 'Explorer' : 'your File Manager'
: __WIN32__
? 'Explorer'
: 'your File Manager'
return (
<div className="panel blankslate" id="no-changes">
<img src={BlankSlateImage} className="blankslate-image" />

View file

@ -295,6 +295,9 @@ export class ChangesSidebar extends React.Component<IChangesSidebarProps, {}> {
onIncludeChanged={this.onIncludeChanged}
onSelectAll={this.onSelectAll}
onDiscardChanges={this.onDiscardChanges}
askForConfirmationOnDiscardChanges={
this.props.askForConfirmationOnDiscardChanges
}
onDiscardAllChanges={this.onDiscardAllChanges}
onOpenItem={this.onOpenItem}
onRowClick={this.onChangedItemClick}

View file

@ -30,7 +30,7 @@ export class TwoUp extends React.Component<ITwoUpProps, {}> {
maxHeight: this.props.maxSize.height - ControlsHeight,
}
const percentDiff = (previous: number, current: number) => {
const diff = Math.round(100 * (current - previous) / previous)
const diff = Math.round((100 * (current - previous)) / previous)
const sign = diff > 0 ? '+' : ''
return sign + diff + '%'
}

View file

@ -33,12 +33,6 @@ interface ICompareSidebarProps {
readonly localCommitSHAs: ReadonlyArray<string>
readonly dispatcher: Dispatcher
readonly currentBranch: Branch | null
readonly sidebarHasFocusWithin: boolean
/**
* A flag from the application to indicate the branches list should be expanded.
*/
readonly shouldShowBranchesList: boolean
readonly onRevertCommit: (commit: Commit) => void
readonly onViewCommitOnGitHub: (sha: string) => void
}
@ -50,8 +44,6 @@ interface ICompareSidebarState {
* For all other cases, use the prop
*/
readonly focusedBranch: Branch | null
readonly filterText: string
readonly showBranchList: boolean
readonly selectedCommit: Commit | null
}
@ -71,8 +63,6 @@ export class CompareSidebar extends React.Component<
this.state = {
focusedBranch: null,
filterText: '',
showBranchList: props.shouldShowBranchesList,
selectedCommit: null,
}
}
@ -81,28 +71,31 @@ export class CompareSidebar extends React.Component<
const newFormState = nextProps.compareState.formState
const oldFormState = this.props.compareState.formState
if (this.textbox !== null) {
if (
!this.props.compareState.showBranchList &&
nextProps.compareState.showBranchList
) {
// showBranchList changes from false -> true
// -> ensure the textbox has focus
this.textbox.focus()
} else if (
this.props.compareState.showBranchList &&
!nextProps.compareState.showBranchList
) {
// showBranchList changes from true -> false
// -> ensure the textbox no longer has focus
this.textbox.blur()
}
}
if (
newFormState.kind !== oldFormState.kind &&
newFormState.kind === ComparisonView.None
) {
// reset form to it's default state
this.setState(
{
filterText: '',
focusedBranch: null,
showBranchList: nextProps.shouldShowBranchesList,
},
() => {
// ensure filter text behaviour matches the prop value
if (this.textbox !== null) {
if (nextProps.shouldShowBranchesList) {
this.textbox.focus()
} else {
this.textbox.blur()
}
}
}
)
this.setState({
focusedBranch: null,
})
return
}
@ -114,27 +107,12 @@ export class CompareSidebar extends React.Component<
const newBranch = newFormState.comparisonBranch
if (oldBranch.name !== newBranch.name) {
// ensure the filter text is in sync with the comparison branch
// ensure the focused branch is in sync with the chosen branch
this.setState({
filterText: newBranch.name,
focusedBranch: newBranch,
})
}
}
if (
this.props.shouldShowBranchesList !== nextProps.shouldShowBranchesList
) {
if (nextProps.shouldShowBranchesList === true) {
this.setState({ showBranchList: true })
}
}
if (nextProps.sidebarHasFocusWithin !== this.props.sidebarHasFocusWithin) {
if (nextProps.sidebarHasFocusWithin === false) {
this.setState({ showBranchList: false })
}
}
}
public componentWillMount() {
@ -145,14 +123,8 @@ export class CompareSidebar extends React.Component<
this.textbox = null
}
public componentDidMount() {
if (this.textbox !== null && this.state.showBranchList) {
this.textbox.focus()
}
}
public render() {
const { allBranches } = this.props.compareState
const { allBranches, filterText, showBranchList } = this.props.compareState
const placeholderText = getPlaceholderText(this.props.compareState)
return (
@ -163,26 +135,20 @@ export class CompareSidebar extends React.Component<
type="search"
placeholder={placeholderText}
onFocus={this.onTextBoxFocused}
value={this.state.filterText}
value={filterText}
disabled={allBranches.length <= 1}
onRef={this.onTextBoxRef}
onValueChanged={this.onBranchFilterTextChanged}
onKeyDown={this.onBranchFilterKeyDown}
onSearchCleared={this.onSearchCleared}
onSearchCleared={this.handleEscape}
/>
</div>
{this.state.showBranchList
? this.renderFilterList()
: this.renderCommits()}
{showBranchList ? this.renderFilterList() : this.renderCommits()}
</div>
)
}
private onSearchCleared = () => {
this.handleEscape()
}
private onBranchesListRef = (branchList: BranchList | null) => {
this.branchList = branchList
}
@ -202,22 +168,24 @@ export class CompareSidebar extends React.Component<
this.props.dispatcher.executeCompare(this.props.repository, {
kind: CompareActionKind.History,
})
this.props.dispatcher.updateCompareForm(this.props.repository, {
showBranchList: false,
})
}
private renderCommitList() {
const compareState = this.props.compareState
const { formState, commitSHAs } = this.props.compareState
const selectedCommit = this.state.selectedCommit
const commitSHAs = compareState.commitSHAs
let emptyListMessage: string | JSX.Element
if (compareState.formState.kind === ComparisonView.None) {
if (formState.kind === ComparisonView.None) {
emptyListMessage = 'No history'
} else {
const currentlyComparedBranchName =
compareState.formState.comparisonBranch.name
const currentlyComparedBranchName = formState.comparisonBranch.name
emptyListMessage =
compareState.formState.kind === ComparisonView.Ahead ? (
formState.kind === ComparisonView.Ahead ? (
<p>
The compared branch (<Ref>{currentlyComparedBranchName}</Ref>) is up
to date with your branch
@ -262,15 +230,21 @@ export class CompareSidebar extends React.Component<
}
private renderFilterList() {
const compareState = this.props.compareState
const {
defaultBranch,
allBranches,
recentBranches,
filterText,
} = this.props.compareState
return (
<BranchList
ref={this.onBranchesListRef}
defaultBranch={compareState.defaultBranch}
defaultBranch={defaultBranch}
currentBranch={this.props.currentBranch}
allBranches={compareState.allBranches}
recentBranches={compareState.recentBranches}
filterText={this.state.filterText}
allBranches={allBranches}
recentBranches={recentBranches}
filterText={filterText}
textbox={this.textbox!}
selectedBranch={this.state.focusedBranch}
canCreateNewBranch={false}
@ -388,7 +362,7 @@ export class CompareSidebar extends React.Component<
const key = event.key
if (key === 'Enter') {
if (this.state.filterText.length === 0) {
if (this.props.compareState.filterText.length === 0) {
this.handleEscape()
} else {
if (this.state.focusedBranch == null) {
@ -402,7 +376,9 @@ export class CompareSidebar extends React.Component<
mode: ComparisonView.Behind,
})
this.setState({ filterText: branch.name })
this.props.dispatcher.updateCompareForm(this.props.repository, {
filterText: branch.name,
})
}
if (this.textbox) {
@ -418,7 +394,7 @@ export class CompareSidebar extends React.Component<
}
}
private handleEscape() {
private handleEscape = () => {
this.clearFilterState()
if (this.textbox) {
this.textbox.blur()
@ -470,26 +446,27 @@ export class CompareSidebar extends React.Component<
)
await this.viewHistoryForBranch()
this.setState({ filterText: '' })
this.props.dispatcher.updateCompareForm(this.props.repository, {
filterText: '',
})
}
private onBranchFilterTextChanged = (filterText: string) => {
if (filterText.length === 0) {
this.setState({ focusedBranch: null, filterText })
if (this.props.compareState.formState.kind !== ComparisonView.None) {
// ensure any previous filter branch selection is cleared
this.props.dispatcher.executeCompare(this.props.repository, {
kind: CompareActionKind.History,
})
}
} else {
this.setState({ filterText })
this.setState({ focusedBranch: null })
}
this.props.dispatcher.updateCompareForm(this.props.repository, {
filterText,
})
}
private clearFilterState = () => {
this.setState({
focusedBranch: null,
})
this.props.dispatcher.updateCompareForm(this.props.repository, {
filterText: '',
})
@ -504,8 +481,11 @@ export class CompareSidebar extends React.Component<
})
this.setState({
filterText: branch.name,
focusedBranch: null,
})
this.props.dispatcher.updateCompareForm(this.props.repository, {
filterText: branch.name,
showBranchList: false,
})
}
@ -528,7 +508,9 @@ export class CompareSidebar extends React.Component<
}
private onTextBoxFocused = () => {
this.setState({ showBranchList: true })
this.props.dispatcher.updateCompareForm(this.props.repository, {
showBranchList: true,
})
}
private onTextBoxRef = (textbox: TextBox) => {

View file

@ -174,17 +174,6 @@ function scanUntil(
return scanWhile(doc, start, (doc, pos) => !predicate(doc, pos), iter)
}
/**
* Given a cursor position, expand it into a range covering as
* long of an autocompletable string as possible.
*/
function getHintRangeFromCursor(doc: Doc, cursor: Position) {
return {
from: scanUntil(doc, cursor, isMarkOrWhitespace, prevPosition),
to: scanUntil(doc, cursor, isMarkOrWhitespace, nextPosition),
}
}
function appendTextMarker(
cm: Editor,
text: string,
@ -635,7 +624,10 @@ export class AuthorInput extends React.Component<IAuthorInputProps, {}> {
const doc = cm.getDoc()
const cursor = doc.getCursor() as Readonly<Position>
const { from, to } = getHintRangeFromCursor(doc, cursor)
// expand the current cursor position into a range covering as
// long of an autocompletable string as possible.
const from = scanUntil(doc, cursor, isMarkOrWhitespace, prevPosition)
const to = scanUntil(doc, cursor, isMarkOrWhitespace, nextPosition)
const word = doc.getRange(from, to)

View file

@ -5,7 +5,9 @@ export const DefaultEditorLabel = __DARWIN__
export const RevealInFileManagerLabel = __DARWIN__
? 'Reveal in Finder'
: __WIN32__ ? 'Show in Explorer' : 'Show in your File Manager'
: __WIN32__
? 'Show in Explorer'
: 'Show in your File Manager'
export const OpenWithDefaultProgramLabel = __DARWIN__
? 'Open with Default Program'

View file

@ -17,9 +17,10 @@ export class MergeConflictsWarning extends React.Component<
{}
> {
private onSubmit = () => {
this.props.dispatcher.changeRepositorySection(this.props.repository, {
selectedTab: RepositorySectionTab.Changes,
})
this.props.dispatcher.changeRepositorySection(
this.props.repository,
RepositorySectionTab.Changes
)
this.props.onDismissed()
}

View file

@ -11,14 +11,6 @@ import { FilterList } from '../lib/filter-list'
import { IMatches } from '../../lib/fuzzy-find'
import { assertNever } from '../../lib/fatal-error'
/**
* TS can't parse generic specialization in JSX, so we have to alias it here
* with the generic type. See https://github.com/Microsoft/TypeScript/issues/6395.
*/
const RepositoryFilterList: new () => FilterList<
IRepositoryListItem
> = FilterList as any
interface IRepositoriesListProps {
readonly selectedRepository: Repositoryish | null
readonly repositories: ReadonlyArray<Repositoryish>
@ -127,7 +119,7 @@ export class RepositoriesList extends React.Component<
return (
<div className="repository-list">
<RepositoryFilterList
<FilterList<IRepositoryListItem>
rowHeight={RowHeight}
selectedItem={selectedItem}
filterText={this.props.filterText}

View file

@ -102,7 +102,9 @@ export class RepositoryListItem extends React.Component<
const showRepositoryLabel = __DARWIN__
? 'Show in Finder'
: __WIN32__ ? 'Show in Explorer' : 'Show in your File Manager'
: __WIN32__
? 'Show in Explorer'
: 'Show in your File Manager'
const items: ReadonlyArray<IMenuItem> = [
{

View file

@ -13,7 +13,6 @@ import {
IRepositoryState,
RepositorySectionTab,
ImageDiffType,
RepositorySection,
} from '../lib/app-state'
import { Dispatcher } from '../lib/dispatcher'
import { IssuesStore, GitHubUserStore } from '../lib/stores'
@ -77,8 +76,7 @@ export class RepositoryView extends React.Component<
const hasChanges =
this.props.state.changesState.workingDirectory.files.length > 0
const selectedTab =
this.props.state.selectedSection.selectedTab ===
RepositorySectionTab.Changes
this.props.state.selectedSection === RepositorySectionTab.Changes
? Tab.Changes
: Tab.History
@ -157,11 +155,6 @@ export class RepositoryView extends React.Component<
private renderCompareSidebar(): JSX.Element {
const tip = this.props.state.branchesState.tip
const currentBranch = tip.kind === TipState.Valid ? tip.branch : null
const selectedSection = this.props.state.selectedSection
const shouldShowBranchesList =
selectedSection.selectedTab === RepositorySectionTab.History
? selectedSection.shouldShowBranchesList || false
: false
return (
<CompareSidebar
@ -175,8 +168,6 @@ export class RepositoryView extends React.Component<
dispatcher={this.props.dispatcher}
onRevertCommit={this.onRevertCommit}
onViewCommitOnGitHub={this.props.onViewCommitOnGitHub}
sidebarHasFocusWithin={this.state.sidebarHasFocusWithin}
shouldShowBranchesList={shouldShowBranchesList}
/>
)
}
@ -184,9 +175,9 @@ export class RepositoryView extends React.Component<
private renderSidebarContents(): JSX.Element {
const selectedSection = this.props.state.selectedSection
if (selectedSection.selectedTab === RepositorySectionTab.Changes) {
if (selectedSection === RepositorySectionTab.Changes) {
return this.renderChangesSidebar()
} else if (selectedSection.selectedTab === RepositorySectionTab.History) {
} else if (selectedSection === RepositorySectionTab.History) {
return enableCompareSidebar()
? this.renderCompareSidebar()
: this.renderHistorySidebar()
@ -223,12 +214,21 @@ export class RepositoryView extends React.Component<
private onSidebarFocusWithinChanged = (sidebarHasFocusWithin: boolean) => {
// this lets us know that focus is somewhere within the sidebar
this.setState({ sidebarHasFocusWithin })
if (
sidebarHasFocusWithin === false &&
this.props.state.selectedSection === RepositorySectionTab.History
) {
this.props.dispatcher.updateCompareForm(this.props.repository, {
showBranchList: false,
})
}
}
private renderContent(): JSX.Element | null {
const selectedSection = this.props.state.selectedSection
if (selectedSection.selectedTab === RepositorySectionTab.Changes) {
if (selectedSection === RepositorySectionTab.Changes) {
const changesState = this.props.state.changesState
const selectedFileIDs = changesState.selectedFileIDs
@ -260,7 +260,7 @@ export class RepositoryView extends React.Component<
/>
)
}
} else if (selectedSection.selectedTab === RepositorySectionTab.History) {
} else if (selectedSection === RepositorySectionTab.History) {
return (
<History
repository={this.props.repository}
@ -298,14 +298,10 @@ export class RepositoryView extends React.Component<
// about the shift key here, we can get away with that as long
// as there's only two tabs.
if (e.ctrlKey && e.key === 'Tab') {
const section: RepositorySection =
this.props.state.selectedSection.selectedTab ===
RepositorySectionTab.History
? { selectedTab: RepositorySectionTab.Changes }
: {
selectedTab: RepositorySectionTab.History,
shouldShowBranchesList: false,
}
const section =
this.props.state.selectedSection === RepositorySectionTab.History
? RepositorySectionTab.Changes
: RepositorySectionTab.History
this.props.dispatcher.changeRepositorySection(
this.props.repository,
@ -316,13 +312,10 @@ export class RepositoryView extends React.Component<
}
private onTabClicked = (tab: Tab) => {
const section: RepositorySection =
const section =
tab === Tab.History
? {
selectedTab: RepositorySectionTab.History,
shouldShowBranchesList: false,
}
: { selectedTab: RepositorySectionTab.Changes }
? RepositorySectionTab.History
: RepositorySectionTab.Changes
this.props.dispatcher.changeRepositorySection(
this.props.repository,

View file

@ -1,4 +1,4 @@
import { expect } from 'chai'
import { expect, AssertionError } from 'chai'
import * as Path from 'path'
import * as FSE from 'fs-extra'
@ -89,15 +89,15 @@ describe('AppStore', () => {
describe('undo first commit', () => {
function getAppState(appStore: AppStore): IRepositoryState {
const selectedState = appStore.getState().selectedState
if (!selectedState) {
throw new chai.AssertionError('No selected state for AppStore')
if (selectedState == null) {
throw new AssertionError('No selected state for AppStore')
}
switch (selectedState.type) {
case SelectionType.Repository:
return selectedState.state
default:
throw new chai.AssertionError(
throw new AssertionError(
`Got selected state of type ${
selectedState.type
} which is not supported.`
@ -131,9 +131,10 @@ describe('AppStore', () => {
// select the repository and show the changes view
await appStore._selectRepository(repository)
await appStore._changeRepositorySection(repository, {
selectedTab: RepositorySectionTab.Changes,
})
await appStore._changeRepositorySection(
repository,
RepositorySectionTab.Changes
)
let state = getAppState(appStore)
expect(state.localCommitSHAs.length).to.equal(1)

View file

@ -36,21 +36,21 @@ describe('CloneProgressParser', () => {
'remote: Compressing objects: 45% (10/22)'
)
expect(compressing.kind).to.equal('progress')
expect(compressing.percent).to.be.closeTo(10 / 22 * 0.1, 0.01)
expect(compressing.percent).to.be.closeTo((10 / 22) * 0.1, 0.01)
const receiving = parser.parse(
'Receiving objects: 17% (4808/28282), 3.30 MiB | 1.29 MiB/s'
)
expect(receiving.kind).to.equal('progress')
expect(receiving.percent).to.be.closeTo(0.1 + 4808 / 28282 * 0.6, 0.01)
expect(receiving.percent).to.be.closeTo(0.1 + (4808 / 28282) * 0.6, 0.01)
const resolving = parser.parse('Resolving deltas: 89% (18063/20263)')
expect(resolving.kind).to.equal('progress')
expect(resolving.percent).to.be.closeTo(0.7 + 18063 / 20263 * 0.1, 0.01)
expect(resolving.percent).to.be.closeTo(0.7 + (18063 / 20263) * 0.1, 0.01)
const checkingOut = parser.parse('Checking out files: 100% (579/579)')
expect(checkingOut.kind).to.equal('progress')
expect(checkingOut.percent).to.be.closeTo(0.8 + 579 / 579 * 0.2, 0.01)
expect(checkingOut.percent).to.be.closeTo(0.8 + (579 / 579) * 0.2, 0.01)
})
it('ignores wrong order', () => {

View file

@ -8,6 +8,9 @@
"[Fixed] No autocomplete when searching for co-authors - #4847",
"[Fixed] Error when checking out a PR from a fork - #4842"
],
"1.2.3-test1": [
"Confirming switch from uglify-es to babel-minify addresses minification issue - #4871"
],
"1.2.2": [
"[Fixed] Make cURL/schannel default to using the Windows certificate store - #4817",
"[Fixed] Restore text selection highlighting in diffs - #4818"

View file

@ -166,19 +166,9 @@ problems.
## Running tests
- `yarn test` - Runs all unit and integration tests
- `yarn test:unit` - Runs all unit tests
- `yarn test:unit` - Runs all unit tests (add `--debug` to open Chrome Dev Tools while running tests)
- `yarn test:integration` - Runs all integration tests
**Pro Tip:** If you're only interested in the results of a single test and don't
wish to run the entire test suite to see it you can pass along a search string
in order to only run the tests that match that string.
```shellsession
$ yarn test:unit -- --grep CloneProgressParser
```
This example will run all test names containing `CloneProgressParser`.
## Debugging
Electron ships with Chrome Dev Tools to assist with debugging, profiling and

View file

@ -119,7 +119,7 @@ changes here to handle a new shell.
## macOS
The source for the macOS shell integration is found in [`app/src/lib/shells/darwin.ts`](https://github.com/desktop/desktop/blob/master/app/src/lib/shell/darwin.ts).
The source for the macOS shell integration is found in [`app/src/lib/shells/darwin.ts`](https://github.com/desktop/desktop/blob/master/app/src/lib/shells/darwin.ts).
These shells are currently supported:
@ -204,7 +204,7 @@ export function launch(
## Linux
The source for the Linux shell integration is found in [`app/src/lib/shells/linux.ts`](https://github.com/desktop/desktop/blob/master/app/src/lib/shell/linux.ts).
The source for the Linux shell integration is found in [`app/src/lib/shells/linux.ts`](https://github.com/desktop/desktop/blob/master/app/src/lib/shells/linux.ts).
These shells are currently supported:

View file

@ -70,7 +70,7 @@
"eslint-plugin-json": "^1.2.0",
"eslint-plugin-prettier": "^2.6.0",
"eslint-plugin-react": "^7.7.0",
"eslint-plugin-typescript": "^0.10.0",
"eslint-plugin-typescript": "^0.12.0",
"express": "^4.15.0",
"front-matter": "^2.3.0",
"fs-extra": "^6.0.0",
@ -83,7 +83,7 @@
"node-sass": "^4.7.2",
"octicons": "^7.0.1",
"parallel-webpack": "^2.3.0",
"prettier": "1.11.1",
"prettier": "1.13.0",
"request": "^2.72.0",
"rimraf": "^2.5.2",
"sass-loader": "^7.0.1",
@ -96,7 +96,7 @@
"tslint-config-prettier": "^1.10.0",
"tslint-microsoft-contrib": "^5.0.3",
"tslint-react": "^3.5.1",
"typescript": "^2.8.3",
"typescript": "^2.9.1",
"typescript-eslint-parser": "^15.0.0",
"webpack": "^4.8.3",
"webpack-bundle-analyzer": "^2.13.0",

View file

@ -11,7 +11,12 @@ const root = Path.dirname(__dirname)
const prettier = process.platform === 'win32' ? 'prettier.cmd' : 'prettier'
const prettierPath = Path.join(root, 'node_modules', '.bin', prettier)
const args = ['**/*.scss', '--list-different']
const args = [
'**/*.scss',
'app/**/*.{ts,tsx}',
'script/**/*.ts',
'--list-different',
]
if (shouldFix) {
args.push('--write')

View file

@ -52,6 +52,12 @@ const electronMochaArgs = [
'app/test/unit/**/*.{ts,tsx}',
]
const shouldDebug = process.argv.indexOf('--debug') > -1
if (shouldDebug) {
electronMochaArgs.push('--debug')
}
let exitCode = -1
if (process.platform === 'linux') {

View file

@ -126,13 +126,7 @@
"@types/prop-types" "*"
"@types/react" "*"
"@types/react@*":
version "16.3.14"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.3.14.tgz#f90ac6834de172e13ecca430dcb6814744225d36"
dependencies:
csstype "^2.2.0"
"@types/react@16.3.14":
"@types/react@*", "@types/react@16.3.14":
version "16.3.14"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.3.14.tgz#f90ac6834de172e13ecca430dcb6814744225d36"
dependencies:
@ -2675,9 +2669,9 @@ eslint-plugin-react@^7.7.0:
jsx-ast-utils "^2.0.1"
prop-types "^15.6.0"
eslint-plugin-typescript@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-typescript/-/eslint-plugin-typescript-0.10.0.tgz#009a8fcaf0ec7bf68f6fb71576df0d84ebd0b114"
eslint-plugin-typescript@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-typescript/-/eslint-plugin-typescript-0.12.0.tgz#e23d58cb27fe28e89fc641a1f20e8d862cb99aef"
dependencies:
requireindex "~1.1.0"
@ -5674,9 +5668,9 @@ prepend-http@^1.0.0, prepend-http@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
prettier@1.11.1:
version "1.11.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.1.tgz#61e43fc4cd44e68f2b0dfc2c38cd4bb0fccdcc75"
prettier@1.13.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.0.tgz#054de8d5fb1a4405c845d16183f58a2c301f6f16"
pretty-bytes@^1.0.2:
version "1.0.4"
@ -7251,9 +7245,9 @@ typescript-eslint-parser@^15.0.0:
lodash.unescape "4.0.1"
semver "5.5.0"
typescript@^2.8.3:
version "2.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170"
typescript@^2.9.1:
version "2.9.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.1.tgz#fdb19d2c67a15d11995fd15640e373e09ab09961"
ua-parser-js@^0.7.9:
version "0.7.17"