1
0
mirror of https://github.com/desktop/desktop synced 2024-07-07 19:29:36 +00:00

Prettier the Markdown and SCSS 💄

This commit is contained in:
Jed Fox 2017-12-12 06:19:11 -05:00
parent adbffea777
commit 15e8fcf623
78 changed files with 1568 additions and 1088 deletions

View File

@ -5,9 +5,9 @@
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
size, disability, ethnicity, gender identity and expression, level of
experience, nationality, personal appearance, race, religion, or sexual identity
and orientation.
## Our Standards
@ -23,7 +23,7 @@ include:
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
@ -37,11 +37,11 @@ Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
Project maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, or to ban temporarily or permanently any
contributor for other behaviors that they deem inappropriate, threatening,
offensive, or harmful.
## Scope
@ -55,11 +55,11 @@ further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at opensource@github.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
reported by contacting the project team at opensource@github.com. All complaints
will be reviewed and investigated and will result in a response that is deemed
necessary and appropriate to the circumstances. The project team is obligated to
maintain confidentiality with regard to the reporter of an incident. Further
details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
@ -67,8 +67,8 @@ members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@ -1,11 +1,13 @@
# Contributing to GitHub Desktop
:+1: :tada: :sparkling_heart: Thanks for your interest! :sparkling_heart: :tada: :+1:
:+1: :tada: :sparkling_heart: Thanks for your interest! :sparkling_heart: :tada:
:+1:
The following is a set of guidelines for contributing to GitHub Desktop and its
related projects, which are hosted in the [Desktop organization](https://github.com/desktop)
on GitHub. These are just guidelines, not rules. Use your best judgment, and
feel free to propose changes to this document in a pull request.
related projects, which are hosted in the
[Desktop organization](https://github.com/desktop) on GitHub. These are just
guidelines, not rules. Use your best judgment, and feel free to propose changes
to this document in a pull request.
Note that GitHub Desktop is an evolving project, so expect things to change over
time as the team learns, listens and refines how we work with the community.
@ -13,24 +15,28 @@ time as the team learns, listens and refines how we work with the community.
#### Table Of Contents
[What should I know before I get started?](#what-should-i-know-before-i-get-started)
* [Code of Conduct](#code-of-conduct)
* [The Roadmap](#the-roadmap)
* [Code of Conduct](#code-of-conduct)
* [The Roadmap](#the-roadmap)
[How Can I Contribute?](#how-can-i-contribute)
* [Reporting Bugs](#reporting-bugs)
* [Suggesting Enhancements](#suggesting-enhancements)
* [Help Wanted](#help-wanted)
* [Reporting Bugs](#reporting-bugs)
* [Suggesting Enhancements](#suggesting-enhancements)
* [Help Wanted](#help-wanted)
[Additional Notes](#additional-notes)
* [Issue and Pull Request Labels](#issue-and-pull-request-labels)
* [Issue and Pull Request Labels](#issue-and-pull-request-labels)
## What should I know before I get started?
### Code of Conduct
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code.
Please report unacceptable behavior to [opensource+desktop@github.com](mailto:opensource+desktop@github.com).
This project adheres to the Contributor Covenant
[code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to
uphold this code. Please report unacceptable behavior to
[opensource+desktop@github.com](mailto:opensource+desktop@github.com).
### The Roadmap
@ -38,7 +44,8 @@ GitHub Desktop recently announced its
[1.0 release](https://github.com/blog/2437-announcing-github-desktop-1-0) and
are working towards deprecating the classic Mac and Windows applications.
Beyond that, we are working on a roadmap you can read [here](https://github.com/desktop/desktop/blob/master/docs/process/roadmap.md).
Beyond that, we are working on a roadmap you can read
[here](https://github.com/desktop/desktop/blob/master/docs/process/roadmap.md).
The immediate milestones are more detailed, and the latter milestones are more
fuzzy and subject to change.
@ -55,65 +62,71 @@ Following these guidelines helps maintainers and the community understand your
report :pencil:, reproduce the behavior :computer: :computer:, and find related
reports :mag_right:.
Before creating bug reports, please check [this list](#before-submitting-a-bug-report)
as you might find out that you don't need to create one. When you are creating
a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report).
Fill out [the required template](./.github/ISSUE_TEMPLATE.md), the information
it asks for helps us resolve issues faster.
Before creating bug reports, please check
[this list](#before-submitting-a-bug-report) as you might find out that you
don't need to create one. When you are creating a bug report, please
[include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill
out [the required template](./.github/ISSUE_TEMPLATE.md), the information it
asks for helps us resolve issues faster.
#### Before Submitting A Bug Report
**Perform a [cursory search](https://github.com/desktop/desktop/labels/bug)**
to see if the problem has already been reported. If it does exist, add a
:thumbsup: to the issue to indicate this is also an issue for you, and add a
comment to the existing issue if there is extra information you can contribute.
**Perform a [cursory search](https://github.com/desktop/desktop/labels/bug)** to
see if the problem has already been reported. If it does exist, add a :thumbsup:
to the issue to indicate this is also an issue for you, and add a comment to the
existing issue if there is extra information you can contribute.
#### How Do I Submit A (Good) Bug Report?
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/).
Simply create an issue on the [GitHub Desktop issue tracker](https://github.com/desktop/desktop/issues)
and fill out the provided [issue template](./.github/ISSUE_TEMPLATE.md).
Simply create an issue on the
[GitHub Desktop issue tracker](https://github.com/desktop/desktop/issues) and
fill out the provided [issue template](./.github/ISSUE_TEMPLATE.md).
The information we are interested in includes:
- details about your environment - which build, which operating system
- details about reproducing the issue - what steps to take, what happens, how
often it happens
- other relevant information - log files, screenshots, etc.
* details about your environment - which build, which operating system
* details about reproducing the issue - what steps to take, what happens, how
often it happens
* other relevant information - log files, screenshots, etc.
### Suggesting Enhancements
This section guides you through submitting an enhancement suggestion for
GitHub Desktop, including completely new features and minor improvements to
existing functionality. Following these guidelines helps maintainers and the
community understand your suggestion :pencil: and find related suggestions
:mag_right:.
This section guides you through submitting an enhancement suggestion for GitHub
Desktop, including completely new features and minor improvements to existing
functionality. Following these guidelines helps maintainers and the community
understand your suggestion :pencil: and find related suggestions :mag_right:.
Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion)
as you might find out that you don't need to create one. When you are creating
an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion).
Fill in [the template](./.github/ISSUE_TEMPLATE.md), including the steps
that you imagine you would take if the feature you're requesting existed.
Before creating enhancement suggestions, please check
[this list](#before-submitting-an-enhancement-suggestion) as you might find out
that you don't need to create one. When you are creating an enhancement
suggestion, please
[include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion).
Fill in [the template](./.github/ISSUE_TEMPLATE.md), including the steps that
you imagine you would take if the feature you're requesting existed.
#### Before Submitting An Enhancement Suggestion
**Perform a [cursory search](https://github.com/desktop/desktop/labels/enhancement)**
to see if the enhancement has already been suggested. If it has, add a
:thumbsup: to indicate your interest in it, or comment if there is additional
information you would like to add.
**Perform a
[cursory search](https://github.com/desktop/desktop/labels/enhancement)** to see
if the enhancement has already been suggested. If it has, add a :thumbsup: to
indicate your interest in it, or comment if there is additional information you
would like to add.
#### How Do I Submit A (Good) Enhancement Suggestion?
Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/).
Enhancement suggestions are tracked as
[GitHub issues](https://guides.github.com/features/issues/).
Simply create an issue on the [GitHub Desktop issue tracker](https://github.com/desktop/desktop/issues)
and provide the following information:
Simply create an issue on the
[GitHub Desktop issue tracker](https://github.com/desktop/desktop/issues) and
provide the following information:
* **Use a clear and descriptive title** for the issue to identify the
suggestion.
* **Provide a step-by-step description of the suggested enhancement** in as
much detail as possible. This additional context helps the maintainers to
* **Provide a step-by-step description of the suggested enhancement** in as much
detail as possible. This additional context helps the maintainers to
understand the enhancement from your perspective
* **Explain why this enhancement would be useful** to GitHub Desktop users.
* **Include screenshots and animated GIFs** if relevant to help you demonstrate
@ -127,47 +140,48 @@ and provide the following information:
As part of building GitHub Desktop, we'll identify tasks that are good for
external contributors to pick up. These tasks:
- have low impact, or have a known workaround
- should be addressed
- have a narrow scope and/or easy reproduction steps
- can be worked on independent of other tasks
* have low impact, or have a known workaround
* should be addressed
* have a narrow scope and/or easy reproduction steps
* can be worked on independent of other tasks
These issues will be labelled as [`help wanted`](https://github.com/desktop/desktop/labels/help%20wanted)
in the repository. If you are interested in contributing to the project, please
comment on the issue to let the core team (and the community) know you are
interested in the issue.
These issues will be labelled as
[`help wanted`](https://github.com/desktop/desktop/labels/help%20wanted) in the
repository. If you are interested in contributing to the project, please comment
on the issue to let the core team (and the community) know you are interested in
the issue.
## Additional Notes
### Issue and Pull Request Labels
This section lists the labels we use to help us track and manage issues and
pull requests.
This section lists the labels we use to help us track and manage issues and pull
requests.
#### Type of Issue and Issue State
| Label name | :mag_right: | Description |
| --- | --- | --- |
| `enhancement` | [search](https://github.com/desktop/desktop/labels/enhancement) | Feature requests. |
| `bug` | [search](https://github.com/desktop/desktop/labels/bug) | Confirmed bugs or reports that are very likely to be bugs. |
| Label name | :mag_right: | Description |
| ------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `enhancement` | [search](https://github.com/desktop/desktop/labels/enhancement) | Feature requests. |
| `bug` | [search](https://github.com/desktop/desktop/labels/bug) | Confirmed bugs or reports that are very likely to be bugs. |
| `more-information-needed` | [search](https://github.com/desktop/desktop/labels/more-information-needed) | More information needs to be collected about these problems or feature requests (e.g. steps to reproduce). |
| `needs-reproduction` | [search](https://github.com/desktop/desktop/labels/needs-reproduction) | Likely bugs, but haven't been reliably reproduced. |
| `stale` | [search](https://github.com/desktop/desktop/labels/stale) | Issues that are inactive and marked to be closed. |
| `macOS` | [search](https://github.com/desktop/desktop/labels/macOS) | Issues specific to macOS users. |
| `Windows` | [search](https://github.com/desktop/desktop/labels/Windows) | Issues specific to Windows users. |
| `codemirror` | [search](https://github.com/desktop/desktop/labels/codemirror) | Issues related to our use of [CodeMirror](https://codemirror.net/) that may require upstream fixes. |
| `electron` | [search](https://github.com/desktop/desktop/labels/electron) | Issues related to our use of [Electron](https://electron.atom.io) that may require upstream fixes. |
| `needs-reproduction` | [search](https://github.com/desktop/desktop/labels/needs-reproduction) | Likely bugs, but haven't been reliably reproduced. |
| `stale` | [search](https://github.com/desktop/desktop/labels/stale) | Issues that are inactive and marked to be closed. |
| `macOS` | [search](https://github.com/desktop/desktop/labels/macOS) | Issues specific to macOS users. |
| `Windows` | [search](https://github.com/desktop/desktop/labels/Windows) | Issues specific to Windows users. |
| `codemirror` | [search](https://github.com/desktop/desktop/labels/codemirror) | Issues related to our use of [CodeMirror](https://codemirror.net/) that may require upstream fixes. |
| `electron` | [search](https://github.com/desktop/desktop/labels/electron) | Issues related to our use of [Electron](https://electron.atom.io) that may require upstream fixes. |
#### Topics
| Label name | :mag_right: | Description |
| --- | --- | --- |
| `help wanted` | [search](https://github.com/desktop/desktop/labels/help%20wanted) | Issues marked as ideal for external contributors. |
| `tech-debt` | [search](https://github.com/desktop/desktop/labels/tech-debt) | Issues related to code or architecture decisions. |
| `needs-design-input` | [search](https://github.com/desktop/desktop/labels/needs-design-input) | Issues that require design input from the core team before the work can be started. |
| Label name | :mag_right: | Description |
| -------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `help wanted` | [search](https://github.com/desktop/desktop/labels/help%20wanted) | Issues marked as ideal for external contributors. |
| `tech-debt` | [search](https://github.com/desktop/desktop/labels/tech-debt) | Issues related to code or architecture decisions. |
| `needs-design-input` | [search](https://github.com/desktop/desktop/labels/needs-design-input) | Issues that require design input from the core team before the work can be started. |
#### Workflow
| Label name | :mag_right: | Description |
| --- | --- | --- |
| `ready-for-review` | [search](https://github.com/desktop/desktop/labels/ready-for-review) | Pull Requests that are ready to be reviewed by the maintainers. |
| Label name | :mag_right: | Description |
| ------------------ | -------------------------------------------------------------------- | --------------------------------------------------------------- |
| `ready-for-review` | [search](https://github.com/desktop/desktop/labels/ready-for-review) | Pull Requests that are ready to be reviewed by the maintainers. |

View File

@ -16,16 +16,19 @@ uses [React](https://facebook.github.io/react/).
Download the official installer for your operating system:
- [macOS](https://central.github.com/deployments/desktop/desktop/latest/darwin)
- [Windows](https://central.github.com/deployments/desktop/desktop/latest/win32)
- [Windows machine-wide install](https://central.github.com/deployments/desktop/desktop/latest/win32?format=msi)
* [macOS](https://central.github.com/deployments/desktop/desktop/latest/darwin)
* [Windows](https://central.github.com/deployments/desktop/desktop/latest/win32)
* [Windows machine-wide install](https://central.github.com/deployments/desktop/desktop/latest/win32?format=msi)
There are several community-supported package managers that can be used to install Github Desktop.
- Windows users can install using [Chocolatey](https://chocolatey.org/) package manager:
`c:\> choco install github-desktop`
- macOS users can install using [Homebrew](https://brew.sh/) package manager:
`$ brew cask install github`
- Arch Linux users can install the latest version from the [AUR](https://aur.archlinux.org/packages/github-desktop/).
There are several community-supported package managers that can be used to
install Github Desktop.
* Windows users can install using [Chocolatey](https://chocolatey.org/) package
manager: `c:\> choco install github-desktop`
* macOS users can install using [Homebrew](https://brew.sh/) package manager:
`$ brew cask install github`
* Arch Linux users can install the latest version from the
[AUR](https://aur.archlinux.org/packages/github-desktop/).
You can install this alongside your existing GitHub Desktop for Mac or GitHub
Desktop for Windows application.
@ -39,18 +42,19 @@ from disk onto the application to get started.
Want to test out new features and get fixes before everyone else? Install the
beta channel to get access to early builds of Desktop:
- [macOS](https://central.github.com/deployments/desktop/desktop/latest/darwin?env=beta)
- [Windows](https://central.github.com/deployments/desktop/desktop/latest/win32?env=beta)
* [macOS](https://central.github.com/deployments/desktop/desktop/latest/darwin?env=beta)
* [Windows](https://central.github.com/deployments/desktop/desktop/latest/win32?env=beta)
## I have a problem with GitHub Desktop
First, please search the [open issues](https://github.com/desktop/desktop/issues?q=is%3Aopen)
and [closed issues](https://github.com/desktop/desktop/issues?q=is%3Aclosed)
to see if your issue hasn't already been reported (it may also be fixed).
First, please search the
[open issues](https://github.com/desktop/desktop/issues?q=is%3Aopen) and
[closed issues](https://github.com/desktop/desktop/issues?q=is%3Aclosed) to see
if your issue hasn't already been reported (it may also be fixed).
If you can't find an issue that matches what you're seeing, open a [new issue](https://github.com/desktop/desktop/issues/new)
and fill out the template to provide us with enough information to investigate
further.
If you can't find an issue that matches what you're seeing, open a
[new issue](https://github.com/desktop/desktop/issues/new) and fill out the
template to provide us with enough information to investigate further.
## How can I contribute to GitHub Desktop?
@ -58,7 +62,9 @@ The [CONTRIBUTING.md](./CONTRIBUTING.md) document will help you get setup and
familiar with the source. The [documentation](docs/) folder also contains more
resources relevant to the project.
If you're looking for something to work on, check out the [help wanted](https://github.com/desktop/desktop/issues?q=is%3Aissue+is%3Aopen+label%3A%22help%20wanted%22) label.
If you're looking for something to work on, check out the
[help wanted](https://github.com/desktop/desktop/issues?q=is%3Aissue+is%3Aopen+label%3A%22help%20wanted%22)
label.
## More Resources
@ -70,10 +76,10 @@ information about GitHub Desktop.
**[MIT](LICENSE)**
The MIT license grant is not for GitHub's trademarks, which include the logo
designs. GitHub reserves all trademark and copyright rights in and to all
GitHub trademarks. GitHub's logos include, for instance, the stylized
Invertocat designs that include "logo" in the file title in the following
folder: [logos](app/static/logos).
designs. GitHub reserves all trademark and copyright rights in and to all GitHub
trademarks. GitHub's logos include, for instance, the stylized Invertocat
designs that include "logo" in the file title in the following folder:
[logos](app/static/logos).
GitHub® and its stylized versions and the Invertocat mark are GitHub's
Trademarks or registered Trademarks. When using GitHub's logos, be sure to

View File

@ -0,0 +1 @@
singleQuote: false

View File

@ -29,7 +29,8 @@ html {
// We never want the window to be scrollable, everything has to fit
// or be placed into a scrollable container.
html, body {
html,
body {
height: 100%;
width: 100%;
margin: 0;
@ -58,7 +59,9 @@ body {
}
:not(input):not(textarea) {
&, &::after, &::before {
&,
&::after,
&::before {
-webkit-user-select: none;
user-select: none;
cursor: default;
@ -81,9 +84,14 @@ img {
// margin for easier control within type scales as it avoids margin collapsing.
//
// From: https://github.com/twbs/bootstrap/blob/a0f10e6dcb9aef2d8e36e57f3c8b1b06034a8877/scss/_reboot.scss
h1, h2, h3, h4, h5, h6 {
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 0;
margin-bottom: .5rem;
margin-bottom: 0.5rem;
}
// Regardless of platform behavior we never want buttons to be

View File

@ -56,7 +56,7 @@
@import "ui/terms-and-conditions";
@import "ui/ref";
@import "ui/monospaced";
@import 'ui/initialize-lfs';
@import 'ui/ci-status';
@import 'ui/pull-request-badge';
@import 'ui/no-branches';
@import "ui/initialize-lfs";
@import "ui/ci-status";
@import "ui/pull-request-badge";
@import "ui/no-branches";

View File

@ -3,7 +3,7 @@
// This files contains CSS variables accessible to all selectors
// Primer colors, see https://github.com/primer/primer-css/blob/master/modules/primer-support/lib/variables/color-system.scss
@import '~primer-support/lib/variables/color-system.scss';
@import "~primer-support/lib/variables/color-system.scss";
:root {
--color-new: $green;
@ -36,8 +36,11 @@
// Typography
//
// Font, line-height, and color for body text, headings, and more.
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, sans-serif;
--font-family-monospace: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI",
"Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
"Helvetica Neue", Arial, sans-serif;
--font-family-monospace: Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
/**
* Font weight to use for semibold text

View File

@ -1,4 +1,4 @@
@import "~react-virtualized/styles.css";
@import "~codemirror/lib/codemirror.css";
@import "~codemirror/theme/solarized.css";
@import "~codemirror/addon/scroll/simplescrollbars.css"
@import "~codemirror/addon/scroll/simplescrollbars.css";

View File

@ -6,4 +6,4 @@
@import "globals";
@import "type";
@import "ui"
@import "ui";

View File

@ -1,12 +1,26 @@
@mixin octicon-status {
.status {
&-new { fill: var(--color-new); }
&-copied { fill: var(--color-new); }
&-modified { fill: var(--color-modified); }
&-renamed { fill: var(--color-renamed); }
&-deleted { fill: var(--color-deleted); }
&-conflicted { fill: var(--color-conflicted); }
&-new {
fill: var(--color-new);
}
&-copied {
fill: var(--color-new);
}
&-modified {
fill: var(--color-modified);
}
&-renamed {
fill: var(--color-renamed);
}
&-deleted {
fill: var(--color-deleted);
}
&-conflicted {
fill: var(--color-conflicted);
}
}
.line-endings { fill: var(--color-conflicted); }
.line-endings {
fill: var(--color-conflicted);
}
}

View File

@ -1,11 +1,11 @@
dialog#about {
.dialog-content {
.row-component {
justify-content: center;
}
p, h2 {
p,
h2 {
text-align: center;
}
@ -40,7 +40,6 @@ dialog#about {
}
.update-status {
.octicon.spin {
// Make sure the spinner is aligned with the text.
align-self: center;

View File

@ -46,8 +46,8 @@
padding: 0;
.row-component:not(:last-child) {
margin: 0;
}
margin: 0;
}
}
&.clone-generic-repository-content {

View File

@ -37,7 +37,6 @@
}
&:not(:last-child) {
// We want list items in previous menus to behave as if they have focus
// even though they don't, ie we want the selected+focus state
// to be in effect for all parent selected menu items as well as
@ -68,7 +67,9 @@
width: 100%;
min-width: 0;
&.disabled { opacity: 0.3; }
&.disabled {
opacity: 0.3;
}
.label {
flex-grow: 1;

View File

@ -1,7 +1,6 @@
@import "../mixins";
#desktop-app {
// This is just a dummy wrapper needed because react doesn't like
// being installed into <body>, see https://github.com/facebook/react/issues/3207
&-container {
@ -23,6 +22,6 @@
&-contents {
display: flex;
flex-direction: column;
flex-grow: 1
flex-grow: 1;
}
}

View File

@ -15,16 +15,21 @@
border-radius: var(--border-radius);
overflow: hidden; // To get those sweet rounded corners
&.emoji { width: 200px; }
&.user { width: 220px; }
&.issue { width: 300px; }
&.emoji {
width: 200px;
}
&.user {
width: 220px;
}
&.issue {
width: 300px;
}
background-color: var(--background-color);
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
.list-item
{
.list-item {
border-bottom: none;
&:not(:first-child) {
@ -40,14 +45,13 @@
border-top-color: var(--box-selected-active-background-color);
& + .list-item {
border-top-color: var(--box-selected-active-background-color);
border-top-color: var(--box-selected-active-background-color);
}
}
}
}
.autocompletion-item {
flex-grow: 1;
height: 100%;
min-width: 0;
@ -61,7 +65,6 @@
}
.emoji {
display: flex;
flex-grow: 1;

View File

@ -1,4 +1,4 @@
@import '../mixins';
@import "../mixins";
.branches-container {
height: 100%;
@ -168,7 +168,7 @@
rgba(255, 255, 255, 0.5) 50%,
rgba(255, 255, 255, 0) 100%
);
content: '';
content: "";
display: block;
height: 100%;
width: 100%;

View File

@ -26,14 +26,16 @@
box-shadow: 0 0 0 1px var(--secondary-button-focus-shadow-color);
}
&:disabled { opacity: 0.6; }
&:disabled {
opacity: 0.6;
}
.octicon {
vertical-align: middle;
}
}
.button-component[type='submit'] {
.button-component[type="submit"] {
background-color: var(--button-background);
color: var(--button-text-color);
border: 1px solid var(--button-background);

View File

@ -4,7 +4,6 @@
align-items: center;
input {
margin: 0;
// Only add a right margin if there's a label attached to it

View File

@ -1,7 +1,6 @@
@import "../mixins";
#cloning-repository-view {
/* The view's position in relation to its parent, ie full
* width, vertically centered... */
justify-content: center;

View File

@ -8,7 +8,6 @@
// allow easy layout using generalized components and elements such as <Row>
// and <p>.
dialog {
// These are custom version of the alert and stop octicons that have been
// scaled and adjusted to render crisply at 24px.
//
@ -38,7 +37,6 @@ dialog {
// The modal class here is the transition name for the react css transition
// group which allows us to apply an animation when the popup appears.
&.modal {
&-enter {
opacity: 1;
transform: scale(0.75);
@ -74,7 +72,7 @@ dialog {
opacity: 0.01;
transform: scale(0.25);
transition: opacity 100ms ease-in,
transform 100ms var(--easing-ease-in-back);
transform 100ms var(--easing-ease-in-back);
&::backdrop {
opacity: 0.01;
@ -143,7 +141,9 @@ dialog {
// Let the button deal with all mouse events.
// Without this the octicon resets the cursor when
// hovering over the <path>.
.octicon { pointer-events: none; }
.octicon {
pointer-events: none;
}
&:hover {
color: var(--text-color);
@ -155,7 +155,8 @@ dialog {
}
}
&.warning, &.error {
&.warning,
&.error {
.dialog-content {
position: relative;
margin-left: var(--spacing-double);
@ -167,7 +168,10 @@ dialog {
// Ensure that the dialog contents always have room for the icon,
// account for two double spacers at top and bottom plus the 5px
// icon offset (margin-top) and the size of the icon itself.
min-height: calc(var(--spacing-double) * 2 + var(--spacing-half) + var(--dialog-icon-size));
min-height: calc(
var(--spacing-double) * 2 + var(--spacing-half) +
var(--dialog-icon-size)
);
// We're creating an opaque 24 by 24px div with the background color
// that we want the icon to appear in and then apply the icon path
@ -176,7 +180,7 @@ dialog {
//
// https://codepen.io/noahblon/post/coloring-svgs-in-css-background-images
&::before {
content: '';
content: "";
display: block;
position: absolute;
left: 0;
@ -220,7 +224,8 @@ dialog {
}
}
h2, h3 {
h2,
h3 {
font-weight: var(--font-weight-semibold);
margin-top: 0;
margin-bottom: var(--spacing);
@ -230,15 +235,22 @@ dialog {
}
}
h2 { font-size: var(--font-size-md); }
h3 { font-size: var(--font-size); }
h2 {
font-size: var(--font-size-md);
}
h3 {
font-size: var(--font-size);
}
ul, ol {
ul,
ol {
margin-top: 0;
padding-left: var(--spacing-double);
list-style-position: outside;
&:last-child { margin-bottom: 0; }
&:last-child {
margin-bottom: 0;
}
li {
margin-bottom: var(--spacing);
@ -248,7 +260,6 @@ dialog {
}
.dialog-footer {
display: flex;
flex-direction: column;
@ -316,12 +327,24 @@ dialog {
}
}
&#preferences { width: 450px; }
&#about { width: 450px; }
&#create-repository { width: 400px; }
&#create-branch { width: 400px; }
&#push-branch-commits { width: 450px; }
&#publish-branch { width: 450px; }
&#preferences {
width: 450px;
}
&#about {
width: 450px;
}
&#create-repository {
width: 400px;
}
&#create-branch {
width: 400px;
}
&#push-branch-commits {
width: 450px;
}
&#publish-branch {
width: 450px;
}
&#generic-git-auth {
width: 450px;
}
@ -343,13 +366,16 @@ dialog {
text-align: center;
}
.forgot-password-row, .what-is-this-row {
.forgot-password-row,
.what-is-this-row {
font-size: var(--font-size-sm);
justify-content: flex-end;
}
}
&#add-existing-repository { width: 400px; }
&#add-existing-repository {
width: 400px;
}
&#initialize-lfs {
width: 400px;

View File

@ -1,4 +1,4 @@
@import '../mixins';
@import "../mixins";
/** The container for the CodeMirror element. */
.diff-code-mirror {

View File

@ -1,7 +1,6 @@
@import "../mixins";
.file-list {
// this value affects virtualized lists, and without it
// you'll see react-virtualized just skip rendering
// as the available vertical space is computed as zero
@ -33,7 +32,10 @@
width: 20px;
}
input, .status { flex-shrink: 0; }
input,
.status {
flex-shrink: 0;
}
.path {
display: flex;
@ -48,6 +50,8 @@
flex-shrink: 0;
}
.octicon { vertical-align: text-bottom; }
.octicon {
vertical-align: text-bottom;
}
}
}

View File

@ -1,4 +1,4 @@
@import '../mixins';
@import "../mixins";
.filter-list {
display: flex;

View File

@ -2,7 +2,6 @@
z-index: var(--foldout-z-index);
.overlay {
// No focus styles whatsovever for the overlay.
// The overlay has a tab index of -1 so that clicking on it
// won't immediately trigger the lost focus event on the app

View File

@ -6,7 +6,7 @@
&:after {
border-bottom: var(--base-border);
content: '';
content: "";
position: absolute;
left: 0;
right: 0;

View File

@ -33,10 +33,14 @@
// with the height of the content in the main container.
// Hide the actual scroll bar
.ReactVirtualized__Grid::-webkit-scrollbar { display: none; }
.ReactVirtualized__Grid::-webkit-scrollbar {
display: none;
}
// Hide the scroll bar by default
.fake-scroll { display: none; }
.fake-scroll {
display: none;
}
&:hover {
.fake-scroll {
@ -59,7 +63,6 @@
}
.list-item {
display: flex;
flex-direction: row;
align-items: center;
@ -83,5 +86,7 @@
}
}
&:focus { outline: none; }
&:focus {
outline: none;
}
}

View File

@ -1,7 +1,6 @@
@import "../mixins";
#missing-repository-view {
/* The view's position in relation to its parent, ie full
* width, vertically centered... */
justify-content: center;

View File

@ -1,7 +1,9 @@
@import '../mixins';
@import "../mixins";
.path-text-component {
@include ellipsis;
.dirname { color: var(--text-secondary-color); }
.dirname {
color: var(--text-secondary-color);
}
}

View File

@ -1,6 +1,5 @@
#preferences {
.accounts-tab {
.account-info {
.avatar {
// 32px for the image + 2 on each side for the base border.

View File

@ -12,9 +12,13 @@ progress {
}
&:indeterminate {
background-image:
-webkit-linear-gradient(-45deg, transparent 33%, var(--text-color) 33%,
var(--text-color) 66%, transparent 66%);
background-image: -webkit-linear-gradient(
-45deg,
transparent 33%,
var(--text-color) 33%,
var(--text-color) 66%,
transparent 66%
);
background-size: 25px 10px, 100% 100%, 100% 100%;
-webkit-animation: progress-indeterminate-animation 5s linear infinite;
@ -22,5 +26,7 @@ progress {
}
@-webkit-keyframes progress-indeterminate-animation {
100% { background-position: 100px 0px; }
100% {
background-position: 100px 0px;
}
}

View File

@ -2,7 +2,6 @@
/** A React component holding the currently selected repository */
#repository {
display: flex;
flex-direction: row;
flex: 1;

View File

@ -1,5 +1,4 @@
.resizable-component {
display: flex;
flex-direction: column;
flex-shrink: 0;

View File

@ -50,7 +50,8 @@
}
// When someone hovers over, or presses the bar we'll expand it to 8px
&:hover, &:active {
&:hover,
&:active {
border-width: 1px;
background-color: var(--scroll-bar-thumb-background-color-active);
cursor: pointer;

View File

@ -27,7 +27,7 @@
// adapted to be 8 by 5px. The gif is in 2x and the background-size
// scales it back down so that we can have crisp arrows on high-dpi
// displays. The path is M 0,0 4,5 8,0 Z and the color is #6a737d.
background-image: url('data:image/gif;base64,R0lGODlhEAAKAMQAAGpzff///8PHy6arsXqCi46UnN7g4vHy8/v7+253gYuSmm12gO/w8dve4Pz8/KassniAicfLzwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAQAAoAAAUw4ACMZFk+TmGugIIEB8GSEBPcRjIvze1HM4FvKDI9hsNUyYUcxka1JjLHkzYFwmYIADs=');
background-image: url("data:image/gif;base64,R0lGODlhEAAKAMQAAGpzff///8PHy6arsXqCi46UnN7g4vHy8/v7+253gYuSmm12gO/w8dve4Pz8/KassniAicfLzwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAQAAoAAAUw4ACMZFk+TmGugIIEB8GSEBPcRjIvze1HM4FvKDI9hsNUyYUcxka1JjLHkzYFwmYIADs=");
background-size: 8px 5px;
background-repeat: no-repeat;
background-position: right var(--spacing-half) center;

View File

@ -53,7 +53,7 @@
}
}
&.switch &-item {
&.switch &-item {
// Reset styles from global buttons
cursor: pointer;
border: none;

View File

@ -5,7 +5,12 @@
height: 250px;
overflow: scroll;
p, ol, ul, li, h2, h3 {
p,
ol,
ul,
li,
h2,
h3 {
cursor: text;
user-select: text;
}

View File

@ -23,23 +23,23 @@
}
.close {
position: absolute;
right: var(--spacing);
border: 0;
height: 16px;
width: 16px;
margin: 0;
padding: 0;
background: transparent;
position: absolute;
right: var(--spacing);
border: 0;
height: 16px;
width: 16px;
margin: 0;
padding: 0;
background: transparent;
color: var(--text-secondary-color);
color: var(--text-secondary-color);
&:hover {
color: var(--text-color);
}
&:hover {
color: var(--text-color);
}
&:focus {
outline: 0;
}
&:focus {
outline: 0;
}
}
}

View File

@ -1,7 +1,6 @@
@import "../mixins";
fieldset.vertical-segmented-control {
// Reset styles for fieldset
border: none;
margin: 0;

View File

@ -53,7 +53,8 @@
}
}
input, button {
input,
button {
font-size: var(--font-size-md);
height: auto;
}

View File

@ -35,10 +35,10 @@
@include ellipsis;
}
input[type=checkbox] {
input[type="checkbox"] {
flex-grow: 0;
flex-shrink: 0;
}
}
}
}
}

View File

@ -2,7 +2,6 @@
/** A React component holding the commit message entry */
#commit-message {
border-top: 1px solid var(--box-border-color);
flex-direction: column;
flex-shrink: 0;
@ -20,13 +19,15 @@
flex: 1;
margin-bottom: var(--spacing);
input { width: 100%; }
input {
width: 100%;
}
}
.avatar {
flex-shrink: 0;
width: var(--text-field-height);
height:var(--text-field-height);
height: var(--text-field-height);
border: var(--base-border);
margin-right: var(--spacing-half);
}
@ -52,6 +53,8 @@
* the contents of the button in a block element and put
* ellipsis on that instead. See commit 67fad24ed
*/
> span { @include ellipsis }
> span {
@include ellipsis;
}
}
}

View File

@ -1,4 +1,4 @@
@import '../../mixins';
@import "../../mixins";
dialog#merge {
width: 450px;
@ -15,7 +15,6 @@ dialog#merge {
}
.dialog-content {
padding: 0;
.filter-field-row {
@ -31,14 +30,15 @@ dialog#merge {
.list-item {
padding: 0 var(--spacing-double);
.filter-list-group-header, .branches-list-item {
.filter-list-group-header,
.branches-list-item {
padding: 0;
}
}
}
.dialog-footer {
button[type=submit] {
button[type="submit"] {
height: auto;
width: 100%;
padding: var(--spacing-half);

View File

@ -2,7 +2,6 @@
/** A React component holding history's commit list */
#commit-list {
display: flex;
flex-direction: column;
flex: 1;
@ -30,7 +29,10 @@
overflow: hidden;
margin-left: var(--spacing-half);
.summary, .byline { @include ellipsis }
.summary,
.byline {
@include ellipsis;
}
}
}
}

View File

@ -2,7 +2,6 @@
/** A React component holding the selected commit's detailed information */
#commit-summary {
display: flex;
flex-direction: column;
@ -24,7 +23,6 @@
}
&.expanded {
.commit-summary-description-container {
border-bottom: none;
}
@ -81,7 +79,13 @@
&:before {
content: "";
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0px, rgba(255, 255, 255, 0) 40px, rgba(255, 255, 255, 0.5) 40px, white 60px);
background: linear-gradient(
180deg,
rgba(255, 255, 255, 0) 0px,
rgba(255, 255, 255, 0) 40px,
rgba(255, 255, 255, 0.5) 40px,
white 60px
);
position: absolute;
height: 100%;
width: 100%;
@ -91,11 +95,14 @@
// Enable text selection inside the title and description elements.
&-title,
&-description {
span, a {
span,
a {
-webkit-user-select: text;
user-select: text;
}
span { cursor: text; }
span {
cursor: text;
}
}
&-description {

View File

@ -1,5 +1,4 @@
.toolbar-button {
// Make sure the contents shrink beyond their intrinsic width
// See https://css-tricks.com/flexbox-truncated-text/
min-width: 0;
@ -17,7 +16,7 @@
// explicitly use > here to only target the direct descendant button since
// there might be buttons in foldouts which would otherwise be affected
// as well.
&>button {
& > button {
// Reset styles from global buttons
-webkit-appearance: none;
border: none;
@ -28,7 +27,9 @@
margin: 0;
padding: 0;
&:active { box-shadow: none; }
&:active {
box-shadow: none;
}
&:focus {
background-color: var(--toolbar-button-focus-background-color);
@ -74,8 +75,7 @@
width: 100%;
}
&>button {
& > button {
position: relative;
display: flex;
@ -124,7 +124,10 @@
position: relative;
}
.title, .description { @include ellipsis }
.title,
.description {
@include ellipsis;
}
.progress {
position: absolute;
@ -135,7 +138,7 @@
background: var(--toolbar-button-progress-color);
transform-origin: left;
pointer-events: none;
transition: transform .3s var(--easing-ease-out-quint);
transition: transform 0.3s var(--easing-ease-out-quint);
}
}
@ -144,6 +147,8 @@
// progress we want the text to be slightly legible so we'll make it
// opaque. Since a toolbar button with progress also shows a spinner
// there's plenty of indication that it can't be used.
&:disabled { opacity: 1; }
&:disabled {
opacity: 1;
}
}
}

View File

@ -1,16 +1,15 @@
.toolbar-dropdown {
// Make sure the contents shrink beyond their intrinsic width
// See https://css-tricks.com/flexbox-truncated-text/
min-width: 0;
&>.toolbar-button {
& > .toolbar-button {
width: 100%;
height: 100%;
}
&.open {
&>.toolbar-button > button {
& > .toolbar-button > button {
color: var(--toolbar-button-active-color);
background-color: var(--toolbar-button-active-background-color);

View File

@ -25,17 +25,21 @@
flex-direction: row;
flex-shrink: 0;
&>:last-child {
& > :last-child {
flex-grow: 1;
}
}
.toolbar-button {
&.push-pull-button { width: 230px; }
&.push-pull-button {
width: 230px;
}
}
.toolbar-dropdown {
&.branch-button { width: 230px; }
&.branch-button {
width: 230px;
}
}
.toolbar-button {
@ -45,10 +49,15 @@
}
}
@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
@keyframes spin {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.spin {
animation:spin 1s linear infinite;
animation: spin 1s linear infinite;
}
.ahead-behind {
@ -78,7 +87,9 @@
// Only add left margin if both ahead and behind are
// showing at the same time.
&:nth-child(2) { margin-left: var(--spacing-half); }
&:nth-child(2) {
margin-left: var(--spacing-half);
}
// We're using arrowSmallUp and arrowSmallDown which are
// both exactly 6px wide. Let's use that so that spacing

View File

@ -2,7 +2,7 @@
display: flex;
.toolbar-button > button {
padding: 0 var(--spacing);
padding: 0 var(--spacing);
border: 0;
.access-key.highlight {
@ -13,7 +13,8 @@
.toolbar-dropdown:not(.open) > .toolbar-button > button {
color: var(--toolbar-button-secondary-color);
&:hover,&:focus {
&:hover,
&:focus {
color: var(--toolbar-button-color);
}
}

View File

@ -11,7 +11,7 @@
@include darwin {
height: var(--darwin-title-bar-height);
background: linear-gradient(to bottom, #3b3f46 0%,#2b2e33 100%);
background: linear-gradient(to bottom, #3b3f46 0%, #2b2e33 100%);
border-bottom: 1px solid #000;
}
@ -28,7 +28,6 @@
}
.resize-handle {
position: absolute;
top: 0px;
left: 0px;
@ -50,7 +49,6 @@
// automatically even for borderless window so we only render
// controls on Windows.
.window-controls {
flex-grow: 0;
flex-shrink: 0;
margin-left: auto;
@ -77,7 +75,9 @@
background-color: transparent;
transition: background-color 0.25s ease;
&:focus { outline: none; }
&:focus {
outline: none;
}
&:hover {
background-color: #888;
@ -110,7 +110,9 @@
}
/* https://css-tricks.com/cascading-svg-fill-color/ */
svg { fill: currentColor; }
svg {
fill: currentColor;
}
}
}
}

View File

@ -37,12 +37,18 @@
}
.toast-animation {
&-appear { transform: scale(0.25); opacity: 0.1; }
&-appear {
transform: scale(0.25);
opacity: 0.1;
}
&-appear-active {
transform: scale(1);
opacity: 1;
transition: all 100ms ease-out;
}
&-leave-active { opacity: 0; transition: all 250ms ease-out; }
&-leave-active {
opacity: 0;
transition: all 250ms ease-out;
}
}

View File

@ -11,7 +11,7 @@
top: 0;
left: 0;
&>div {
& > div {
padding: var(--spacing);
min-width: 100px;
background: rgba($gray-900, 0.6);
@ -27,15 +27,25 @@
}
.zoom-in {
&-appear { transform: scale(0.25); opacity: 0; }
&-appear {
transform: scale(0.25);
opacity: 0;
}
}
.zoom-out {
&-appear { transform: scale(1.75); opacity: 0; }
&-appear {
transform: scale(1.75);
opacity: 0;
}
}
.zoom-in, .zoom-out {
&-leave-active { opacity: 0; transition: opacity 100ms ease-out; }
.zoom-in,
.zoom-out {
&-leave-active {
opacity: 0;
transition: opacity 100ms ease-out;
}
&-appear-active {
transform: scale(1);
opacity: 1;

View File

@ -8,38 +8,39 @@ documentation.
If you are interested in contributing to the project, you should read these
resources to get familiar with how things work:
- **[How Can I Contribute?](../CONTRIBUTING.md#how-can-i-contribute)** -
details about how you can participate
- **[Development Environment Setup](contributing/setup.md)** - everything
you need to know to get Desktop up and running
- **[Engineering Values](contributing/engineering-values.md)** - our high-level engineering values
- **[Style Guide](contributing/styleguide.md)** - notes on the coding style
- **[Tooling](contributing/tooling.md)** - if you have a preferred IDE,
there's some enhancements to make your life easier
- **[Troubleshooting](contributing/troubleshooting.md)** - some additional
known issues if you're having environment issues
* **[How Can I Contribute?](../CONTRIBUTING.md#how-can-i-contribute)** - details
about how you can participate
* **[Development Environment Setup](contributing/setup.md)** - everything you
need to know to get Desktop up and running
* **[Engineering Values](contributing/engineering-values.md)** - our high-level
engineering values
* **[Style Guide](contributing/styleguide.md)** - notes on the coding style
* **[Tooling](contributing/tooling.md)** - if you have a preferred IDE, there's
some enhancements to make your life easier
* **[Troubleshooting](contributing/troubleshooting.md)** - some additional known
issues if you're having environment issues
## Process
Details about how the team is organizing and shipping GitHub Desktop:
- **[Roadmap](process/roadmap.md)** - the future as planned so far
- **[Release Planning](process/release-planning.md)** - how we plan and execute
releases
- **[Issue Triage](process/issue-triage.md)** - how we address issues reported
by users
- **[Review Process](process/reviews.md)** - how we review contributions
- **[Releasing Updates](process/releasing-updates.md)** - how we deploy things
* **[Roadmap](process/roadmap.md)** - the future as planned so far
* **[Release Planning](process/release-planning.md)** - how we plan and execute
releases
* **[Issue Triage](process/issue-triage.md)** - how we address issues reported
by users
* **[Review Process](process/reviews.md)** - how we review contributions
* **[Releasing Updates](process/releasing-updates.md)** - how we deploy things
## Technical
These documents contain more details about the internals of GitHub Desktop
and how things work:
These documents contain more details about the internals of GitHub Desktop and
how things work:
- **[Dialogs](technical/dialogs.md)** - details about the dialog component API
- **[Windows menu bar](technical/windows-menu-bar.md)** - Electron doesn't
provide inbuilt support for styling the menu for Windows, so we've created
our own custom components to achieve this.
- **[Developer OAuth App](technical/oauth.md)** - GitHub Desktop ships with
the ability to OAuth on behalf of a user. A developer OAuth app is bundled
to reduce the friction of getting started.
* **[Dialogs](technical/dialogs.md)** - details about the dialog component API
* **[Windows menu bar](technical/windows-menu-bar.md)** - Electron doesn't
provide inbuilt support for styling the menu for Windows, so we've created our
own custom components to achieve this.
* **[Developer OAuth App](technical/oauth.md)** - GitHub Desktop ships with the
ability to OAuth on behalf of a user. A developer OAuth app is bundled to
reduce the friction of getting started.

View File

@ -1,12 +1,19 @@
# GitHub Desktop Engineering Values
There's value in defining what we as shepherds of this project believe are important traits and practices. As we grow and welcome new members into our team it's beneficial to have a sense of what guided us towards the product being implemented the way it has been.
There's value in defining what we as shepherds of this project believe are
important traits and practices. As we grow and welcome new members into our team
it's beneficial to have a sense of what guided us towards the product being
implemented the way it has been.
## What this is and what this isn't
These values are not unbendable rules. They're an attempt to share knowledge about how the application came to be and how we currently think it should be developed. It's a non-exhaustive, living document of intentions, and beliefs.
These values are not unbendable rules. They're an attempt to share knowledge
about how the application came to be and how we currently think it should be
developed. It's a non-exhaustive, living document of intentions, and beliefs.
We've chosen to focus exclusively on the engineering (i.e. how we write code) part in this document. There are other values surrounding visual design, product and project management, community etc that we're not going to consider here.
We've chosen to focus exclusively on the engineering (i.e. how we write code)
part in this document. There are other values surrounding visual design, product
and project management, community etc that we're not going to consider here.
## Our values
@ -16,23 +23,47 @@ We've chosen to focus exclusively on the engineering (i.e. how we write code) pa
### Types are good
We believe in strongly typed programming languages that help us avoid mistakes that are all too easy to make. When the compiler can't help us we believe in augmenting with other kinds of static analysis. Type systems and static analysis helps us not only in the moment we're writing code but also extends further out. By codifying our intentions we help prevent the next person from making a mistake.
We believe in strongly typed programming languages that help us avoid mistakes
that are all too easy to make. When the compiler can't help us we believe in
augmenting with other kinds of static analysis. Type systems and static analysis
helps us not only in the moment we're writing code but also extends further out.
By codifying our intentions we help prevent the next person from making a
mistake.
#### Examples
Our [assertNever](https://github.com/desktop/desktop/blob/d26fd1ee670dfa7f16ded74b7a4108d2bfe68c79/app/src/lib/fatal-error.ts#L6-L21) helper lets us leverage the type system to verify exhaustiveness and get [compile-time errors](https://github.com/desktop/desktop/blob/8fc8e6f5d1a8153cc92bb0e324b9c26602211646/app/src/ui/branches/ci-status.tsx#L36-L47) when that assertion fails.
Our
[assertNever](https://github.com/desktop/desktop/blob/d26fd1ee670dfa7f16ded74b7a4108d2bfe68c79/app/src/lib/fatal-error.ts#L6-L21)
helper lets us leverage the type system to verify exhaustiveness and get
[compile-time errors](https://github.com/desktop/desktop/blob/8fc8e6f5d1a8153cc92bb0e324b9c26602211646/app/src/ui/branches/ci-status.tsx#L36-L47)
when that assertion fails.
Our [react-readonly-props-and-state](https://github.com/desktop/desktop/blob/d26fd1ee670dfa7f16ded74b7a4108d2bfe68c79/tslint-rules/reactReadonlyPropsAndStateRule.ts) static analysis ensures that we don't accidentally mutate state which React prohibits being mutated but isn't able to enforce due to the dynamic runtime.
Our
[react-readonly-props-and-state](https://github.com/desktop/desktop/blob/d26fd1ee670dfa7f16ded74b7a4108d2bfe68c79/tslint-rules/reactReadonlyPropsAndStateRule.ts)
static analysis ensures that we don't accidentally mutate state which React
prohibits being mutated but isn't able to enforce due to the dynamic runtime.
We [write our own type definitions](https://github.com/desktop/desktop/blob/eee92a96943afbc39057b1aae66c642e23dbf136/app/src/lib/globals.d.ts#L94-L112) when none exist.
We
[write our own type definitions](https://github.com/desktop/desktop/blob/eee92a96943afbc39057b1aae66c642e23dbf136/app/src/lib/globals.d.ts#L94-L112)
when none exist.
### Immutability is good
By choosing to keep as much of our state as possible in immutable data structures we can be explicit about when and where we update it and have confidence that it's not going to change from underneath us. The last part is especially important in an application such as GitHub Desktop which has lots of state. The best way we've found so far to maintain our sanity is to be explicit about how that state flows through the app and when it's updated and immutability is one tool to help us stay on the right track.
By choosing to keep as much of our state as possible in immutable data
structures we can be explicit about when and where we update it and have
confidence that it's not going to change from underneath us. The last part is
especially important in an application such as GitHub Desktop which has lots of
state. The best way we've found so far to maintain our sanity is to be explicit
about how that state flows through the app and when it's updated and
immutability is one tool to help us stay on the right track.
#### Examples
We use [read-only versions of arrays](https://github.com/desktop/desktop/blob/a61a5bdc94ee8237dfff328957cdaee99a9b61e1/app/src/models/commit.ts#L21) in interfaces and object as well as [in function parameters](https://github.com/desktop/desktop/blob/355f9671860e4777827912ddc6aac44399f5732f/app/src/lib/email.ts#L17). (
We use
[read-only versions of arrays](https://github.com/desktop/desktop/blob/a61a5bdc94ee8237dfff328957cdaee99a9b61e1/app/src/models/commit.ts#L21)
in interfaces and object as well as
[in function parameters](https://github.com/desktop/desktop/blob/355f9671860e4777827912ddc6aac44399f5732f/app/src/lib/email.ts#L17).
(
We prefer
@ -45,29 +76,54 @@ over
```ts
let a = someDefaultValue
if (someCondition) {
a = someOtherValue
a = someOtherValue
}
```
We prefer the first example to the second because it states to ourselves and future readers that you can trust `a` to not change. Not only does it make that intention clear, it enforces it. In the case of `let` we'd have to scan the method to verify that it doesn't get mutated and even then we can't be sure that some developer in the future adds logic which changes it. Again, we're stating our intentions and letting the type system help us keep our promises.
We prefer the first example to the second because it states to ourselves and
future readers that you can trust `a` to not change. Not only does it make that
intention clear, it enforces it. In the case of `let` we'd have to scan the
method to verify that it doesn't get mutated and even then we can't be sure that
some developer in the future adds logic which changes it. Again, we're stating
our intentions and letting the type system help us keep our promises.
If the checks required to determine the result are too complicated it might be time to create another function which does the heavy lifting and returns a value that you can assign to a `const`.
If the checks required to determine the result are too complicated it might be
time to create another function which does the heavy lifting and returns a value
that you can assign to a `const`.
### Passing values to functions is good
We believe that small, consistent, and composable methods are easier to understand, and less prone to errors than larger methods operating on data from sources other than those passed to it via arguments. You might recognize this sentiment from the concept of pure functions in functional programming. While we aren't using a language which lets us express such conditions we believe in striving towards writing methods which act on values that is provided to it via arguments and returns a consistent result based solely on those values.
We believe that small, consistent, and composable methods are easier to
understand, and less prone to errors than larger methods operating on data from
sources other than those passed to it via arguments. You might recognize this
sentiment from the concept of pure functions in functional programming. While we
aren't using a language which lets us express such conditions we believe in
striving towards writing methods which act on values that is provided to it via
arguments and returns a consistent result based solely on those values.
If a method has to acquire data from multiple sources to then do some processing on it we prefer that the gathering of data and the processing of it is separated into two methods such that the computational part doesn't get entangled with acquisition of state.
If a method has to acquire data from multiple sources to then do some processing
on it we prefer that the gathering of data and the processing of it is separated
into two methods such that the computational part doesn't get entangled with
acquisition of state.
At times we move methods out of classes or even out into their own file to reinforce that it's a function only acting on its given parameters (as opposed to instance fields or shared variables the function has closed over).
At times we move methods out of classes or even out into their own file to
reinforce that it's a function only acting on its given parameters (as opposed
to instance fields or shared variables the function has closed over).
#### Examples
In app-menu-bar we've extracted a method called [createState](https://github.com/desktop/desktop/blob/d26fd1ee670dfa7f16ded74b7a4108d2bfe68c79/app/src/ui/app-menu/app-menu-bar.tsx#L50-L75) from the component to live outside of the class such that we can be sure that the only thing that matters to the outcome of that function is the props object that's passed to it. By doing this we can avoid a very common example of using `this.props` inside of the method when, in fact, we might want to create a state object from `nextProps` or even `prevProps` that was given to us from one of the [React lifecycle methods](https://reactjs.org/docs/react-component.html#the-component-lifecycle).
In app-menu-bar we've extracted a method called
[createState](https://github.com/desktop/desktop/blob/d26fd1ee670dfa7f16ded74b7a4108d2bfe68c79/app/src/ui/app-menu/app-menu-bar.tsx#L50-L75)
from the component to live outside of the class such that we can be sure that
the only thing that matters to the outcome of that function is the props object
that's passed to it. By doing this we can avoid a very common example of using
`this.props` inside of the method when, in fact, we might want to create a state
object from `nextProps` or even `prevProps` that was given to us from one of the
[React lifecycle methods](https://reactjs.org/docs/react-component.html#the-component-lifecycle).
## Recommended resources
- [Lifting state up](https://reactjs.org/docs/lifting-state-up.html)
- [The Value of Values](https://www.infoq.com/presentations/Value-Values)
- [Simple Made Easy](https://www.infoq.com/presentations/Simple-Made-Easy)
- [Boundaries aka Functional Core, Imperative Shell](https://www.destroyallsoftware.com/talks/boundaries)
* [Lifting state up](https://reactjs.org/docs/lifting-state-up.html)
* [The Value of Values](https://www.infoq.com/presentations/Value-Values)
* [Simple Made Easy](https://www.infoq.com/presentations/Simple-Made-Easy)
* [Boundaries aka Functional Core, Imperative Shell](https://www.destroyallsoftware.com/talks/boundaries)

View File

@ -1,9 +1,9 @@
# Preview Features
If you're running GitHub Desktop you can enable **"preview features"**, which
we consider something we want to eventually ship to everyone, but needs some
sort of refinement before we can do that, and in the meantime we would like
feedback from users on these features.
If you're running GitHub Desktop you can enable **"preview features"**, which we
consider something we want to eventually ship to everyone, but needs some sort
of refinement before we can do that, and in the meantime we would like feedback
from users on these features.
To opt-in for testing preview features, set the
`GITHUB_DESKTOP_PREVIEW_FEATURES` environment variable to any value and launch

View File

@ -1,4 +1,4 @@
# Development Environment Setup
# Development Environment Setup
## Setup
@ -6,29 +6,33 @@ You will need to install these tools on your machine:
### macOS
- [Node.js v8.9.0](https://nodejs.org/dist/v8.9.0/)
- [Python 2.7](https://www.python.org/downloads/mac-osx/)
- Xcode and Xcode Command Line Tools (Xcode -> Preferences -> Downloads)
* [Node.js v8.9.0](https://nodejs.org/dist/v8.9.0/)
* [Python 2.7](https://www.python.org/downloads/mac-osx/)
* Xcode and Xcode Command Line Tools (Xcode -> Preferences -> Downloads)
### Windows
- [Node.js v8.9.0](https://nodejs.org/dist/v8.9.0/)
- *Make sure you allow the Node.js installer to add node to the PATH.*
- [Python 2.7](https://www.python.org/downloads/windows/)
- *Let Python install into the default suggested path (`c:\Python27`), otherwise you'll have
to configure node-gyp manually with the path which is annoying.*
- *Ensure the **Add python.exe to Path** option is selected.*
- One of Visual Studio 2015, Visual C++ Build Tools or Visual Studio 2017
- [Visual C++ Build Tools](http://go.microsoft.com/fwlink/?LinkId=691126)
- *Run `npm config set msvs_version 2015` to tell node to use this toolchain.*
- Visual Studio 2015
- *Ensure you select the **Common Tools for Visual C++ 2015** feature as that is required by Node.js
for installing native modules.*
- *Run `npm config set msvs_version 2015` to tell node to use this toolchain.*
- [Visual Studio 2017](https://www.visualstudio.com/vs/community/)
- *Ensure you select the **Desktop development with C++** feature as that is required by Node.js for
installing native modules.*
- *Run `npm config set msvs_version 2017` to tell node to use this toolchain.*
* [Node.js v8.9.0](https://nodejs.org/dist/v8.9.0/)
* _Make sure you allow the Node.js installer to add node to the PATH._
* [Python 2.7](https://www.python.org/downloads/windows/)
* _Let Python install into the default suggested path (`c:\Python27`),
otherwise you'll have to configure node-gyp manually with the path which is
annoying._
* _Ensure the **Add python.exe to Path** option is selected._
* One of Visual Studio 2015, Visual C++ Build Tools or Visual Studio 2017
* [Visual C++ Build Tools](http://go.microsoft.com/fwlink/?LinkId=691126)
* _Run `npm config set msvs_version 2015` to tell node to use this
toolchain._
* Visual Studio 2015
* _Ensure you select the **Common Tools for Visual C++ 2015** feature as
that is required by Node.js for installing native modules._
* _Run `npm config set msvs_version 2015` to tell node to use this
toolchain._
* [Visual Studio 2017](https://www.visualstudio.com/vs/community/)
* _Ensure you select the **Desktop development with C++** feature as that is
required by Node.js for installing native modules._
* _Run `npm config set msvs_version 2017` to tell node to use this
toolchain._
### Fedora 26
@ -44,15 +48,18 @@ After that, install the dependencies to build and test the app:
$ sudo dnf install -y nodejs gcc-c++ make libsecret-devel libXScrnSaver
```
If you want to package Desktop for distribution, you will need these additional dependencies:
If you want to package Desktop for distribution, you will need these additional
dependencies:
```shellsession
$ sudo dnf install fakeroot dpkg rpm rpm-build xz xorriso appstream bzip2-devel
```
If you have problems packaging for AppImage, you may need to force the linker to use the right
version of specific dependencies. More information [here](https://michaelheap.com/error-while-loading-shared-libraries-libbz2-so-1-0-cannot-open-shared-object-file-on-centos-7)
and [here](https://github.com/electron-userland/electron-builder/issues/993#issuecomment-291021974)
If you have problems packaging for AppImage, you may need to force the linker to
use the right version of specific dependencies. More information
[here](https://michaelheap.com/error-while-loading-shared-libraries-libbz2-so-1-0-cannot-open-shared-object-file-on-centos-7)
and
[here](https://github.com/electron-userland/electron-builder/issues/993#issuecomment-291021974)
```shellsession
$ sudo ln -s `find /usr/lib64/ -type f -name "libbz2.so.1*"` /usr/lib64/libbz2.so.1.0
@ -87,17 +94,19 @@ $ sudo apt install -y fakeroot dpkg rpm xz-utils xorriso zsync
## Verification
With these things installed, open a shell and install `yarn` (you might need
to `sudo` here depending on how Node was installed):
With these things installed, open a shell and install `yarn` (you might need to
`sudo` here depending on how Node was installed):
```shellsession
$ npm install -g yarn@1.3.2
```
This is important because yarn uses lock files to pin dependencies. If you find
yourself changing packages, this will prevent mismatches in versions between machines.
yourself changing packages, this will prevent mismatches in versions between
machines.
Then validate you have these commands available and that the versions look similar:
Then validate you have these commands available and that the versions look
similar:
```shellsession
$ node -v
@ -110,21 +119,21 @@ $ python --version
Python 2.7.13
```
There are also [additional resources](tooling.md) to
configure your favorite editor to work nicely with the GitHub Desktop
repository.
There are also [additional resources](tooling.md) to configure your favorite
editor to work nicely with the GitHub Desktop repository.
## Building Desktop
After cloning the repository, the typical workflow to get up running
is as follows:
After cloning the repository, the typical workflow to get up running is as
follows:
* Run `yarn` to get all required dependencies on your machine.
* Run `yarn build:dev` to create a development build of the app.
* Run `yarn start` to launch the application. Changes will be compiled in the
background. The app can then be reloaded to see the changes (Ctrl/Command+R).
**Optional Tip**: On macOS and Linux, you can use `screen` to avoid filling your terminal with logging output:
**Optional Tip**: On macOS and Linux, you can use `screen` to avoid filling your
terminal with logging output:
```shellsession
$ screen -S "desktop" yarn start # -S sets the name of the session; you can pick anything
@ -134,19 +143,18 @@ $ screen -R "desktop" # to reopen the session, read the logs, and exit (Ctrl+C)
[screen is terminating]
```
If you've made changes in the `main-process` folder you need to run `yarn
build:dev` to rebuild the package, and then `yarn start` for these changes to be
reflected in the running app.
If you've made changes in the `main-process` folder you need to run
`yarn build:dev` to rebuild the package, and then `yarn start` for these changes
to be reflected in the running app.
If you're still encountering issues with building, refer to our
[troubleshooting](troubleshooting.md) guide for more common
problems.
[troubleshooting](troubleshooting.md) guide for more common problems.
## Running tests
- `yarn test` - Runs all unit and integration tests
- `yarn test:unit` - Runs all unit tests
- `yarn test:integration` - Runs all integration tests
* `yarn test` - Runs all unit and integration tests
* `yarn test:unit` - Runs all unit 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
@ -171,8 +179,8 @@ When running the app in development mode,
should automatically install itself on first start when in development mode.
An additional extension, [Devtron](http://electron.atom.io/devtron/), is also
included but is disabled by default. To enable Devtron, select the Console
tab in Chrome Developer Tools and run this command:
included but is disabled by default. To enable Devtron, select the Console tab
in Chrome Developer Tools and run this command:
```js
require('devtron').install()
@ -182,7 +190,7 @@ require('devtron').install()
You're almost there! Here's a couple of things we recommend you read next:
- [Help Wanted](../../CONTRIBUTING.md#help-wanted) - we've marked some tasks in
the backlog that are ideal for external contributors
- [Code Reviews](../process/reviews.md) - some notes on how the team does
code reviews
* [Help Wanted](../../CONTRIBUTING.md#help-wanted) - we've marked some tasks in
the backlog that are ideal for external contributors
* [Code Reviews](../process/reviews.md) - some notes on how the team does code
reviews

View File

@ -1,33 +1,42 @@
# TypeScript Style Guide
Most of our preferred style when writing typescript is configured in our [`tslint.json`](../../tslint.json) and [`.eslintrc.yml`](../../.eslintrc.yml) files.
Most of our preferred style when writing typescript is configured in our
[`tslint.json`](../../tslint.json) and [`.eslintrc.yml`](../../.eslintrc.yml)
files.
## Do
- Use camelCase for methods
- Use PascalCase for class names
- Enable [TSLint](https://palantir.github.io/tslint/usage/third-party-tools/) and [ESLint](https://eslint.org/docs/user-guide/integrations) in your editor
* Use camelCase for methods
* Use PascalCase for class names
* Enable [TSLint](https://palantir.github.io/tslint/usage/third-party-tools/)
and [ESLint](https://eslint.org/docs/user-guide/integrations) in your editor
# Documenting your code
We currently use [JSDoc](http://usejsdoc.org/) even though we don't currently generate any documentation or
verify the format. We're using JSDoc over other formats because the typescript compiler has built-in support
for parsing jsdoc and presenting it in IDEs.
We currently use [JSDoc](http://usejsdoc.org/) even though we don't currently
generate any documentation or verify the format. We're using JSDoc over other
formats because the typescript compiler has built-in support for parsing jsdoc
and presenting it in IDEs.
While there doesn't appear to be any well-used typescript documentation export utilities out there at the
moment we hope that it's only a matter of time. JSDoc uses a lot of metadata that is already self-documented
in the typescript type system such as visibility, inheritance, membership.
While there doesn't appear to be any well-used typescript documentation export
utilities out there at the moment we hope that it's only a matter of time. JSDoc
uses a lot of metadata that is already self-documented in the typescript type
system such as visibility, inheritance, membership.
For now all you need to know is that you can document classes, methods, properties and fields by using the
following formatted comment on the line above whatever you're trying to document.
For now all you need to know is that you can document classes, methods,
properties and fields by using the following formatted comment on the line above
whatever you're trying to document.
```ts
/** This is a documentation string */
```
The double start `/**` opener is the key. It has to be exactly two stars for it to be a valid JSDoc open token.
The double start `/**` opener is the key. It has to be exactly two stars for it
to be a valid JSDoc open token.
If you need multiple lines to describe the subject try to sum up the thing you're describing in a short title
and leave a blank line before you go into detail, similar to a git commit message.
If you need multiple lines to describe the subject try to sum up the thing
you're describing in a short title and leave a blank line before you go into
detail, similar to a git commit message.
```ts
/**
@ -39,16 +48,18 @@ and leave a blank line before you go into detail, similar to a git commit messag
## Visibility of AppStore Methods
The [`Dispatcher`](https://github.com/desktop/desktop/blob/master/app/src/lib/dispatcher/dispatcher.ts)
is the entry point for most interactions with the application which update state,
and for most usages this work is then delegated to the [`AppStore`](https://github.com/desktop/desktop/blob/master/app/src/lib/dispatcher/app-store.ts).
The
[`Dispatcher`](https://github.com/desktop/desktop/blob/master/app/src/lib/dispatcher/dispatcher.ts)
is the entry point for most interactions with the application which update
state, and for most usages this work is then delegated to the
[`AppStore`](https://github.com/desktop/desktop/blob/master/app/src/lib/dispatcher/app-store.ts).
Due to this coupling, we need to discourage callers directly manipulating
specific methods in the `AppStore` unless there's a compelling reason.
We do this by making the methods look unappealing:
- underscore prefix on method name
- comment indicating that you should be looking elsewhere
* underscore prefix on method name
* comment indicating that you should be looking elsewhere
```ts
/** This shouldn't be called directly. See `Dispatcher`. */
@ -66,10 +77,10 @@ there's a compelling reason and no asynchronous alternative. In those cases the
method should be suffixed with `Sync` to make it clear to the caller what's
happening. We also fall back to `Sync` methods for readability in tests.
We use [an ESLint rule](https://eslint.org/docs/rules/no-sync) to enforce
this standard.
We use [an ESLint rule](https://eslint.org/docs/rules/no-sync) to enforce this
standard.
### Scripts
For scripts we should favor synchronous APIs as the asynchronous benefits are
not so important there, and it makes the code easier to read.
not so important there, and it makes the code easier to read.

View File

@ -1,43 +1,43 @@
# Profiling Desktop using the Chrome Developer Tools
Sometimes performance issues are hard to identify and recreate. If you notice
a regression and can reproduce it, you can use the Timeline tools in Chrome Dev
Sometimes performance issues are hard to identify and recreate. If you notice a
regression and can reproduce it, you can use the Timeline tools in Chrome Dev
Tools to take a snapshot of the application performance and attach it to an
issue.
## Steps
- Launch Desktop and select **View** | **Toggle Developer Tools**.
* Launch Desktop and select **View** | **Toggle Developer Tools**.
<img width="558" src="https://user-images.githubusercontent.com/359239/26888284-f80ed244-4b80-11e7-86cf-933c59b8f370.png">
- Get the Desktop application ready to perform the problem action.
- Select the **Timeline** tab.
* Get the Desktop application ready to perform the problem action.
* Select the **Timeline** tab.
<img width="1123" src="https://user-images.githubusercontent.com/359239/26887089-7c82f0cc-4b7d-11e7-9cf4-fcbd5a994e1f.png">
- Ensure you have **JS Profile** checked - other items might be helpful, but
will add to the size of the generated timeline data.
* Ensure you have **JS Profile** checked - other items might be helpful, but
will add to the size of the generated timeline data.
<img width="1123" src="https://user-images.githubusercontent.com/359239/26888385-3fc9157c-4b81-11e7-9083-379a37d20641.png">
- Press the **Record** button on the left to start recording.
* Press the **Record** button on the left to start recording.
<img width="1123" src="https://user-images.githubusercontent.com/359239/26887091-7c8acc3e-4b7d-11e7-9d32-961ac353f1b9.png">
- Perform the problem action in Desktop. Try and keep the test focused on the
issue you're seeing.
- Switch back to the Developer tools and press **Stop** to complete recording.
* Perform the problem action in Desktop. Try and keep the test focused on the
issue you're seeing.
* Switch back to the Developer tools and press **Stop** to complete recording.
<img width="1011" src="https://user-images.githubusercontent.com/359239/26887304-0700a514-4b7e-11e7-9a1d-74fac88cecee.png">
- In the graph section, right-click and select **Save timeline data**. Save the
JSON file somewhere you can access later.
* In the graph section, right-click and select **Save timeline data**. Save the
JSON file somewhere you can access later.
<img width="1014" alt="screen shot 2017-06-07 at 12 38 18 pm" src="https://user-images.githubusercontent.com/359239/26887386-472e9c7c-4b7e-11e7-9d39-a9b71ea3d70a.png">
- Compress the JSON file to reduce the file size (it could be 10MB or more
depending on how long you ran the test for).
* Compress the JSON file to reduce the file size (it could be 10MB or more
depending on how long you ran the test for).
- Attach the file to your GitHub issue so the contributors can load this into
their environment and spelunk the diagnostic information.
* Attach the file to your GitHub issue so the contributors can load this into
their environment and spelunk the diagnostic information.

View File

@ -6,17 +6,19 @@ Recommended packages:
* [atom-typescript](https://atom.io/packages/atom-typescript) - syntax
highlighting and intellisense for TypeScript
* [atom-build-npm-apm](https://atom.io/packages/build-npm-apm) - invoke
all npm scripts straight from the editor by pressing F7 (requires
* [atom-build-npm-apm](https://atom.io/packages/build-npm-apm) - invoke all npm
scripts straight from the editor by pressing F7 (requires
[atom-build](https://atom.io/packages/build))
* [linter](https://atom.io/packages/linter) and
[linter-tslint](https://atom.io/packages/linter-tslint) - shows linter errors and warning in the editor
[linter-tslint](https://atom.io/packages/linter-tslint) - shows linter errors
and warning in the editor
### [Visual Studio Code](https://code.visualstudio.com/)
The Desktop repository includes a list of recommended extensions:
1. Select the _Extension_ view, select *Show Workspace Recommended Extensions* from the dropdown menu
1. Select the _Extension_ view, select _Show Workspace Recommended Extensions_
from the dropdown menu
2. Install all the extensions
## Debugging
@ -26,5 +28,7 @@ The Desktop repository includes a list of recommended extensions:
1. Run the command `npm start`
2. Open _Chrome Dev Tools_
[React Dev Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en) should automatically install itself on first start. If you would also like to use [Devtron](http://electron.atom.io/devtron/), run the command `require('devtron').install()` inside of the console in _Chrome Dev Tools_.
[React Dev Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en)
should automatically install itself on first start. If you would also like to
use [Devtron](http://electron.atom.io/devtron/), run the command
`require('devtron').install()` inside of the console in _Chrome Dev Tools_.

View File

@ -5,7 +5,8 @@ while working on GitHub Desktop:
### Issues compiling node-keytar on Windows
If keytar fails to build on Windows with the following error during `npm install`:
If keytar fails to build on Windows with the following error during
`npm install`:
```
npm ERR! keytar@3.0.2 install: `node-gyp rebuild`

View File

@ -50,4 +50,4 @@ To remove any packages that are no longer needed:
```sh
> yarn remove [package-name]
```
```

View File

@ -1,30 +1,48 @@
# Installing GitHub Desktop
GitHub Desktop currently supports Windows 7 (or higher) and macOS 10.9 (or higher).
GitHub Desktop currently supports Windows 7 (or higher) and macOS 10.9 (or
higher).
### macOS
Download the `GitHub Desktop.zip`, unpack the application and put it wherever you want.
Download the `GitHub Desktop.zip`, unpack the application and put it wherever
you want.
### Windows
On Windows you have two options:
- Download the `GitHubDesktopSetup.exe` and run it to install it for the current user.
- Download the `GitHubDesktopSetup.msi` and run it to install a machine-wide version of GitHub Desktop - each logged-in user will then be able to run GitHub Desktop from the program at `%PROGRAMFILES(x86)\GitHub Desktop Installer\desktop.exe`
* Download the `GitHubDesktopSetup.exe` and run it to install it for the current
user.
* Download the `GitHubDesktopSetup.msi` and run it to install a machine-wide
version of GitHub Desktop - each logged-in user will then be able to run
GitHub Desktop from the program at
`%PROGRAMFILES(x86)\GitHub Desktop Installer\desktop.exe`
## Data Directories
GitHub Desktop will create directories to manage the files and data it needs to function. If you manage a network of computers and want to install GitHub Desktop, here is more information about how things work.
GitHub Desktop will create directories to manage the files and data it needs to
function. If you manage a network of computers and want to install GitHub
Desktop, here is more information about how things work.
### macOS
- `~/Library/Application Support/GitHub Desktop/` - this directory contains user-specific data which the application requires to run, and is created on launch if it doesn't exist. Log files are also stored in this location.
* `~/Library/Application Support/GitHub Desktop/` - this directory contains
user-specific data which the application requires to run, and is created on
launch if it doesn't exist. Log files are also stored in this location.
### Windows
- `%LOCALAPPDATA%\GitHubDesktop\` - contains the latest versions of the app, and some older versions if the user has updated from a previous version.
- `%APPDATA%\GitHub Desktop\` - this directory contains user-specific data which the application requires to run, and is created on launch if it doesn't exist. Log files are also stored in this location.
* `%LOCALAPPDATA%\GitHubDesktop\` - contains the latest versions of the app, and
some older versions if the user has updated from a previous version.
* `%APPDATA%\GitHub Desktop\` - this directory contains user-specific data which
the application requires to run, and is created on launch if it doesn't exist.
Log files are also stored in this location.
## Log Files
GitHub Desktop will generate log files if an unhandled exception is raised, to assist with troubleshooting. They are located in the data directory that GitHub Desktop uses (see above) under a `logs` subdirectory, organized by date using the format `YYYY-MM-DD.desktop.production.log`, where `YYYY-MM-DD` is the day the log was created.
GitHub Desktop will generate log files if an unhandled exception is raised, to
assist with troubleshooting. They are located in the data directory that GitHub
Desktop uses (see above) under a `logs` subdirectory, organized by date using
the format `YYYY-MM-DD.desktop.production.log`, where `YYYY-MM-DD` is the day
the log was created.

View File

@ -2,20 +2,23 @@
## Authentication
To authenticate against Visual Studio Team Services repositories, you need to enable the alternate authentication credentials.
To authenticate against Visual Studio Team Services repositories, you need to
enable the alternate authentication credentials.
- Select **Security** in the user profile's dropdown:
* Select **Security** in the user profile's dropdown:
![](https://user-images.githubusercontent.com/4404199/29400833-79755fe0-8337-11e7-8cfb-1d346a6801b4.png)
- Select **Alternate authentication credentials**:
* Select **Alternate authentication credentials**:
![](https://user-images.githubusercontent.com/4404199/29400853-8cc5918c-8337-11e7-92ad-60563d4d49e2.png)
- Check the **Enable alternate authentication credentials** checkbox, and then choose a suitable username/password:
* Check the **Enable alternate authentication credentials** checkbox, and then
choose a suitable username/password:
![](https://user-images.githubusercontent.com/4404199/29400917-bed11cc8-8337-11e7-9d3e-1bda2e99d519.png)
- Enter your chosen credentials in Desktop when prompted. You can either use your email or the chosen username to authenticate:
* Enter your chosen credentials in Desktop when prompted. You can either use
your email or the chosen username to authenticate:
![](https://user-images.githubusercontent.com/4404199/29401109-8bf03536-8338-11e7-8abb-b467378b6115.png)

View File

@ -10,15 +10,31 @@ We have a first responder rotation. The goals of the rotation are:
Each rotation is a week long. While first responder your primary duties are:
1. Triage issues.
* Troubleshoot or follow up on troubleshooting started by the previous first responder. The current first responder should always bear responsibility for pushing troubleshooting forward, unless another team member has explicitly taken ownership.
* Ensure issues are labeled accurately.
* Review the [`more-information-needed`](https://github.com/desktop/desktop/issues?q=is%3Aopen+is%3Aissue+label%3Amore-information-needed+sort%3Aupdated-asc) and [`needs-reproduction`](https://github.com/desktop/desktop/issues?q=is%3Aopen+is%3Aissue+sort%3Aupdated-asc+label%3Aneeds-reproduction) issues and close any that have gone 2 weeks with no new activity.
* See [issue-triage.md](issue-triage.md) for more information on our issue triage process.
* Troubleshoot or follow up on troubleshooting started by the previous first
responder. The current first responder should always bear responsibility
for pushing troubleshooting forward, unless another team member has
explicitly taken ownership.
* Ensure issues are labeled accurately.
* Review the
[`more-information-needed`](https://github.com/desktop/desktop/issues?q=is%3Aopen+is%3Aissue+label%3Amore-information-needed+sort%3Aupdated-asc)
and
[`needs-reproduction`](https://github.com/desktop/desktop/issues?q=is%3Aopen+is%3Aissue+sort%3Aupdated-asc+label%3Aneeds-reproduction)
issues and close any that have gone 2 weeks with no new activity.
* See [issue-triage.md](issue-triage.md) for more information on our issue
triage process.
1. Check community pull requests and label ones that are `ready-for-review`.
1. Review community pull requests.
Once those things are done, you should feel free to spend your time scratching your own itches on the project. Really wanna refactor that one monstrous component? Go for it! Wanna fix that one bug that drives you nuts? Do it! Wanna upgrade all of our dependencies? You're an awesome masochist!
Once those things are done, you should feel free to spend your time scratching
your own itches on the project. Really wanna refactor that one monstrous
component? Go for it! Wanna fix that one bug that drives you nuts? Do it! Wanna
upgrade all of our dependencies? You're an awesome masochist!
That said, tasks which need design work generally *aren't* well-suited to this. It would pull our fantastic designers away from milestone work and it would be hard to get done in a week's time.
That said, tasks which need design work generally _aren't_ well-suited to this.
It would pull our fantastic designers away from milestone work and it would be
hard to get done in a week's time.
If you're at a loss for ideas or wonder if something is an appropriate first responder task, ask the rest of the team! Or poke through the [`tech-debt`](https://github.com/desktop/desktop/labels/tech-debt) label for some inspiration.
If you're at a loss for ideas or wonder if something is an appropriate first
responder task, ask the rest of the team! Or poke through the
[`tech-debt`](https://github.com/desktop/desktop/labels/tech-debt) label for
some inspiration.

View File

@ -1,11 +1,11 @@
# Issue Triage
> Triage (/ˈtriːɑːʒ/ or /triːˈɑːʒ/) is the process of determining the priority
> of patients' treatments based on the severity of their condition. This
> rations patient treatment efficiently when resources are insufficient for all
> to be treated immediately.
> of patients' treatments based on the severity of their condition. This rations
> patient treatment efficiently when resources are insufficient for all to be
> treated immediately.
>
> *From Wikipedia*
> _From Wikipedia_
The above describes medical triage but it is clear that it also applies to our
situation. Triage is a process of sifting through all the things that we could
@ -19,18 +19,18 @@ participation. In order to do this, we will have to be clear about what we need
from people so that we can deliver what they need. This also means that we will
have to be very clear and decisive when we are not getting the information or
cooperation we need so that we can move on. Just like in an emergency room, if
it is a choice between spending several hours to have a 10% chance of saving
one person or spending several hours definitely saving multiple people, the
choice is clear.
it is a choice between spending several hours to have a 10% chance of saving one
person or spending several hours definitely saving multiple people, the choice
is clear.
## Goals
* Communicate clearly and effectively
* What the maintainers will work on
* What pull requests will be reviewed for acceptance
* What pull requests *will not* be reviewed for acceptance
* Outline exactly what is expected for an issue to meet the "triage bar" so
that issues that don't meet the bar can be closed
* What the maintainers will work on
* What pull requests will be reviewed for acceptance
* What pull requests _will not_ be reviewed for acceptance
* Outline exactly what is expected for an issue to meet the "triage bar" so that
issues that don't meet the bar can be closed
* Reduce the amount of time and back-and-forth needed to take an issue from
being first-opened to `triaged` or closed
* Accept input from the community that helps us deliver meaningful results back
@ -39,9 +39,9 @@ choice is clear.
## The Issues List Is Our Backlog
The GitHub Desktop issues list is what the maintainers team uses to guide our
work. In order for our work to be focused and efficient, our issues list must
be clean and well-organized. Accepting input from the community is a
significant benefit *when it does not distract us from making things better*.
work. In order for our work to be focused and efficient, our issues list must be
clean and well-organized. Accepting input from the community is a significant
benefit _when it does not distract us from making things better_.
* Untriaged issues are tasks that are being evaluated to determine if they meet
the triage bar
@ -57,19 +57,19 @@ contain in the body of the issue:
* The build number associated with the given issue
* The operating system and OS version number that the problem was reproduced on
* Specific steps to reproduce the problem or desired behavior
* If the steps to reproduce the problem do not reproduce it 100% of the time,
an estimate of how often it reproduces with the given steps and configuration
* If the steps to reproduce the problem do not reproduce it 100% of the time, an
estimate of how often it reproduces with the given steps and configuration
* **One** and only one issue
* Any other information that is required to reproduce the problem (sample Git
repository, specific OS configuration, etc)
### The Body of the Issue
You'll notice above that the body of the issue gets special mention. The body
of the issue is the description of the task to be done. A maintainer should
only have to read the body of the issue to understand what needs to happen.
They should not have to read the pages of comments to understand what they need
to do in order to address the issue at hand.
You'll notice above that the body of the issue gets special mention. The body of
the issue is the description of the task to be done. A maintainer should only
have to read the body of the issue to understand what needs to happen. They
should not have to read the pages of comments to understand what they need to do
in order to address the issue at hand.
## Process
@ -81,7 +81,8 @@ issues from time to time that isn't and won't be covered here.
1. Person files a new issue
1. Maintainer checks to ensure they adequately filled out the template. If not,
close with the [request to fill out the template](canned-messages/needs-template.md).
close with the
[request to fill out the template](canned-messages/needs-template.md).
1. Label the issue as a `bug` if the issue is a regression or behaviour that
needs to be fixed.
1. If the issue has already been fixed, add a comment linking to the original
@ -89,25 +90,26 @@ issues from time to time that isn't and won't be covered here.
1. If anything is unclear but the template is adequately filled out, post what
questions you have and label with `more-information-needed`
1. Maintainer attempts to reproduce the problem
1. If the problem is not reproducible, label with `needs-reproduction` and
ask the author of the issue for [clarification on the repro steps](canned-messages/repro-steps.md)
1. Label the issue as an `enhancement` if the issue mentions new behaviour
or functionality that the app should have.
1. If the problem is not reproducible, label with `needs-reproduction` and
ask the author of the issue for
[clarification on the repro steps](canned-messages/repro-steps.md)
1. Label the issue as an `enhancement` if the issue mentions new behaviour or
functionality that the app should have.
# Labels
## More Information Needed
Periodically we should be doing a sweep of issues that are open and labeled
`more-information-needed`. If the original poster has not responded within
two weeks after the last question by an official maintainer, close the issue
with [the no response message](canned-messages/no-response.md).
`more-information-needed`. If the original poster has not responded within two
weeks after the last question by an official maintainer, close the issue with
[the no response message](canned-messages/no-response.md).
## Needs Reproduction
If a problem is consistently not reproducible, we **need** more information
from the person reporting the problem. If it isn't a simple misunderstanding
about the steps to reproduce the problem, then we should label it
If a problem is consistently not reproducible, we **need** more information from
the person reporting the problem. If it isn't a simple misunderstanding about
the steps to reproduce the problem, then we should label it
`more-information-needed` as well and follow that process.
## Bugs
@ -115,9 +117,9 @@ about the steps to reproduce the problem, then we should label it
These are problems with the current app that are identified by users. These
should be reviewed to ensure they:
- specify the build associated with the issue
- have instructions sufficient to reproduce the issue
- have details about the impact and severity of the issue
* specify the build associated with the issue
* have instructions sufficient to reproduce the issue
* have details about the impact and severity of the issue
We will use the `more-information-needed` and `reproduction-required` labels to
indicate when issues are incomplete.
@ -139,9 +141,9 @@ To ensure the quality of the application remains high over time, the core team
may need to work with the user proposing the change to clarify details before
work should proceed:
- user interface - appropriate use of styles, layout
- user experience - ensure things are consistent, discoverable
- quality - ensure the change does not adversely affect other features
* user interface - appropriate use of styles, layout
* user experience - ensure things are consistent, discoverable
* quality - ensure the change does not adversely affect other features
e.g. GitHub Desktop should support worktrees as a first class feature.
@ -153,11 +155,12 @@ by the community will be for things that are interesting but are also well
beyond the current plans of the team.
We will apply the `future-proposal` label to these issues, so that they can be
searched for when it comes time to plan for the future. However, to keep
our issue tracker focused on tasks currently on the roadmap we will close these
searched for when it comes time to plan for the future. However, to keep our
issue tracker focused on tasks currently on the roadmap we will close these
future proposals to avoid information overload.
You can view [the list](https://github.com/desktop/desktop/issues?q=is%3Aissue+label%3Afuture-proposal)
You can view
[the list](https://github.com/desktop/desktop/issues?q=is%3Aissue+label%3Afuture-proposal)
of these `future-proposal` tasks, and continue to add your thoughts and feedback
there.

View File

@ -1,7 +1,12 @@
# Release Planning
We plan work at two levels of granularity: first at the marketing release level (1.1, 1.2, etc.) and then at the milestone level. Marketing releases are made up of multiple milestones. Milestones should contain roughly a months worth of work.
We plan work at two levels of granularity: first at the marketing release level
(1.1, 1.2, etc.) and then at the milestone level. Marketing releases are made up
of multiple milestones. Milestones should contain roughly a months worth of
work.
Well release updates as needed or when a milestone is completed.
Large features and user-visible changes are feature-flagged, to be unflagged in the next marketing release. Beta and dev builds will have all feature flags enabled.
Large features and user-visible changes are feature-flagged, to be unflagged in
the next marketing release. Beta and dev builds will have all feature flags
enabled.

View File

@ -2,23 +2,34 @@
## Channels
We have three channels to which we can release: `production`, `beta`, and `test`.
We have three channels to which we can release: `production`, `beta`, and
`test`.
- `production` is the channel from which the general public downloads and receives updates. It should be stable and polished.
* `production` is the channel from which the general public downloads and
receives updates. It should be stable and polished.
- `beta` is released more often than `production`. It may be buggy and unpolished.
* `beta` is released more often than `production`. It may be buggy and
unpolished.
- `test` is unlike the other two. It does not receive updates. Each test release is locked in time. It's used entirely for providing test releases.
* `test` is unlike the other two. It does not receive updates. Each test release
is locked in time. It's used entirely for providing test releases.
## The Process
1. Ensure the release notes for `$version` in [`changelog.json`](../../changelog.json) are up-to-date.
1. Ensure the release notes for `$version` in
[`changelog.json`](../../changelog.json) are up-to-date.
1. Bump `version` in [`app/package.json`](../../app/package.json) to `$version`.
1. Commit & push the changes.
1. Run `.release! desktop/YOUR_BRANCH to {production|beta|test}`.
* We're using `.release` with a bang so that we don't have to wait for any current CI on the branch to finish. This might feel a little wrong, but it's OK since making the release itself will also run CI.
1. If you're releasing a production update, release a beta update for the next version too, so that beta users are on the latest release.
* We're using `.release` with a bang so that we don't have to wait for any
current CI on the branch to finish. This might feel a little wrong, but it's
OK since making the release itself will also run CI.
1. If you're releasing a production update, release a beta update for the next
version too, so that beta users are on the latest release.
## Error Reporting
If an error occurs during the release process, a needle will be reported to Central's [haystack](https://haystack.githubapp.com/central).
If an error occurs during the release process, a needle will be reported to
Central's [haystack](https://haystack.githubapp.com/central).

View File

@ -4,8 +4,8 @@ This is the typical flow:
1. **Contributor** opens pull request.
1. When it's ready for review, they comment on it saying so.
1. A member of the maintainer team will give it a quick look over and
add the `ready-for-review` label.
1. A member of the maintainer team will give it a quick look over and add the
`ready-for-review` label.
1. Suddenly a wild **reviewer** appears!
1. **Reviewer** assigns the PR to themselves.
1. **Reviewer** leaves line comments with suggestions or questions.
@ -16,7 +16,7 @@ This is the typical flow:
comment on the PR with an emoji, meme, pokémon or words to that effect.
1. Goto 6 until both parties are happy with the PR.
1. The **reviewer** hits the big green merge button and deletes the branch (if
applicable).
applicable).
The rest of this document goes into more details around this flow.
@ -40,17 +40,18 @@ understand quickly what's changed.
### Keep The Commit History Tidy
We're not that fussy about the history, but to make reviewing easier here's
some general tips:
We're not that fussy about the history, but to make reviewing easier here's some
general tips:
- make small, meaningful and logical commits - these make the review process easier
- [write good commit messages](https://chris.beams.io/posts/git-commit/) -
these help the reviewer to understand the changes
- keep up to date with `master` - not only does this address potential merge
conflicts, it ensures you're integrating with the latest code
* make small, meaningful and logical commits - these make the review process
easier
* [write good commit messages](https://chris.beams.io/posts/git-commit/) - these
help the reviewer to understand the changes
* keep up to date with `master` - not only does this address potential merge
conflicts, it ensures you're integrating with the latest code
When merging, we prefer you merge `master` into your branch, but for small
PRs a rebase is fine.
When merging, we prefer you merge `master` into your branch, but for small PRs a
rebase is fine.
### At Least One Assignee
@ -64,11 +65,11 @@ reviewer.
We're using GitHub's review tools to co-ordinate feedback, and we like to be
methodical with our reviews, so you'll probably end up with one of two results:
- **Approved**: nothing else to do; the reviewer merges
- **Request Changes**: there are things to address; reviewer provides details
* **Approved**: nothing else to do; the reviewer merges
* **Request Changes**: there are things to address; reviewer provides details
Reviews can take a few iterations, especially for large contributions. Don't
be disheartened if you feel it takes time - we just want to ensure each
Reviews can take a few iterations, especially for large contributions. Don't be
disheartened if you feel it takes time - we just want to ensure each
contribution is high-quality and that any outstanding questions are resolved,
captured or documented for posterity.
@ -90,4 +91,3 @@ requests.
While everyone has their own domain expertise around the codebase, we encourage
people to share the load of reviews and reviewing areas of the codebase that
aren't as familiar. This spreads knowledge across the team

View File

@ -1,63 +1,75 @@
# Roadmap
The following are our marketing releases as planned to date. They contain the broad features we're considering. The further away a release is, the less defined it is. Releases are subject to change at any time.
The following are our marketing releases as planned to date. They contain the
broad features we're considering. The further away a release is, the less
defined it is. Releases are subject to change at any time.
## 1.1
- Relationship to _X_
- Show how the current branch relates to the target branch
- The target is the default branch or the upstream's default branch
- _Probably_ let the user switch the target branch
* Relationship to _X_
- Conflict resolution lite
- Differentiate conflicted files from other changed files
- Let me choose my mergetool
- Let me open my mergetool
* Show how the current branch relates to the target branch
* The target is the default branch or the upstream's default branch
* _Probably_ let the user switch the target branch
- Pull request list
- _Probably_ a tab in the Branches foldout
- Group my pull requests vs. others
* Conflict resolution lite
- Pull request CI status
- Show PRs CI status in the above pull request list
* Differentiate conflicted files from other changed files
* Let me choose my mergetool
* Let me open my mergetool
- Auto-config upstreams on fork
- Create an `upstream` remote for forks
- Fetch periodically
* Pull request list
* _Probably_ a tab in the Branches foldout
* Group my pull requests vs. others
* Pull request CI status
* Show PRs CI status in the above pull request list
* Auto-config upstreams on fork
* Create an `upstream` remote for forks
* Fetch periodically
## 1.2
- Full conflict resolution
- Lots TBD
- Pick ours/theirs/both
- Edit inline
- Abort merge
- How did I get here?
* Full conflict resolution
- Fork if needed
- Offer to fork on clone, or push, or ?
* Lots TBD
* Pick ours/theirs/both
* Edit inline
* Abort merge
* How did I get here?
- Protected branches and default branch protection
- Don't let me commit to branches I shouldn't commit to
- Guide me to creating my own branches
* Fork if needed
- CI status notifications lite
- Only on my PRs
- Use OS notifications
- Notifications link to the PR on dotcom
* Offer to fork on clone, or push, or ?
* Protected branches and default branch protection
* Don't let me commit to branches I shouldn't commit to
* Guide me to creating my own branches
* CI status notifications lite
* Only on my PRs
* Use OS notifications
* Notifications link to the PR on dotcom
## 1.3
- Keep environment up-to-date
- Do I need to run `npm install`? `bundle install`?
- Is it pluggable?
* Keep environment up-to-date
- Linting
- TBD
* Do I need to run `npm install`? `bundle install`?
* Is it pluggable?
- Save face
- Keep me from making embarrassing mistakes
- Don't let me commit a file with conflict markers
* Linting
- Repository list info
- Does a repository need my attention?
* TBD
* Save face
* Keep me from making embarrassing mistakes
* Don't let me commit a file with conflict markers
* Repository list info
* Does a repository need my attention?

View File

@ -1,366 +1,491 @@
### Download Desktop
- [ ] User can download latest (Mac & Windows) Desktop from https://desktop.github.com/
- [ ] Mac: https://central.github.com/deployments/desktop/desktop/latest/darwin
- [ ] Homebrew package manager: $ brew cask install github-desktop
- [ ] Windows: https://central.github.com/deployments/desktop/desktop/latest/win32
- [ ] Chocolatey package manager: c:\> choco install github-desktop
- [ ] 64-bit and up
- [ ] Data is retained if you download and open a fresh copy
- [ ] Release notes page is up-to-date
- [ ] Help page is accessible
- [ ] 'Please update' notifcation shown in Classic apps
* [ ] User can download latest (Mac & Windows) Desktop from
https://desktop.github.com/
* [ ] Mac:
https://central.github.com/deployments/desktop/desktop/latest/darwin
* [ ] Homebrew package manager: $ brew cask install github-desktop
* [ ] Windows:
https://central.github.com/deployments/desktop/desktop/latest/win32
* [ ] Chocolatey package manager: c:\> choco install github-desktop
* [ ] 64-bit and up
* [ ] Data is retained if you download and open a fresh copy
* [ ] Release notes page is up-to-date
* [ ] Help page is accessible
* [ ] 'Please update' notifcation shown in Classic apps
### Welcome Flow
- [ ] Create your account (/join?source=github-desktop)
- [ ] User is not automatically logged into Desktop post account creation
- [ ] `Sign in to Github.com` link
- [ ] `Sign in` successful if valid username/email and password
- [ ] If 2FA activated, user sent auth code to enter (test SMS and authenticator app)
- [ ] User can reissue auth code with `Resend SMS` link
- [ ] Sign in successful with active 2FA code, user goes to Configure Git
- [ ] User sees Repository landing page if sign in successful
- [ ] Error message if code is wrong or inactive
- [ ] Error message if incorrect username/email or password
- [ ] Forgot link (/password_reset)
- [ ] `Cancel` returns to initial Welcome Flow
- [ ] `Sign in using your browser` opens default browser
- [ ] Browser login, "authorize" GitHub Desktop, “accept” link
- [ ] If successful, Desktop shown in `/settings/applications` in user profile
- [ ] `Sign in to Enterprise` link (works with v2.8 and up)
- [ ] `Continue` successful if server address is valid, else error message
- [ ] `Sign in using your browser` opens default browser
- [ ] Browser login, [insert custom security measure], Authorize GitHub Desktop, “accept” link
- [ ] User goes to Configure Git if successful
- [ ] `Cancel` returns to initial Welcome Flow
- [ ] User served generic message if not authorized to access Enterprise server
- [ ] Skip "username+password" step
- [ ] Configure Git
- [ ] Name and email pulled from global `.gitconfig` file, if configured
- [ ] If recognized, your avatar is present in example commit; gravatars not recognized
- [ ] `Continue` okay if fields populated or blank
- [ ] Valid login credentials from dotcom or Enterprise carried through
- [ ] User sees Repository landing page if sign in successful
- [ ] Usage Data
- [ ] Checked by default; user can uncheck. (Should not be checked if user on free plan only.)
- [ ] Clicking `Finish`, and user is signed in successfully to Desktop
- [ ] `Cancel` returns to initial Configure Git page
### Repositories landing page; default no repositories
- [ ] Create New Repository (Mac: ⌘N; Windows: Ctrl+N)
- [ ] Modal opens with name, path (choose option), readme (unchecked), git ignore, license. Name and path mandatory.
- [ ] If `Add this repository` warning message appears, clicking it adds to Repo list
- [ ] If repository name is over 100 characterers, warning message is surfaced in modal
- [ ] If repository contains URL-hostile characters, show error message
- [ ] `Create Repository` button adds new repo, which is added to Repo list
- [ ] `Cancel` button does not save any changes made; modal closed
- [ ] User cannot create a new repo inside a locked local directory
- [ ] Clone a Repository (Mac: ⇧⌘O; Windows: Ctrl+Shift+O)
- [ ] Enter valid URL or username/repo/gist, else error message
- [ ] If authentication error for Github.com, modal with username/password surfaced; `Cancel` or `Save and Retry` buttons
- [ ] If successful, repo is cloned
- [ ] Modal surfaces again if unsuccessful
- [ ] If authentication error for Enterprise, user redirected to Preferences
- [ ] Valid path can be entered or selected
- [ ] Local path is prepopulated; if not unique then error surfaced
- [ ] All repos from both GitHub.com and Enterprise are populated -- your repos are listed first, followed by org(s)
- [ ] User must be logged in to view list; else `Sign In` button present
- [ ] Results are filterable, and can be selected for cloning
- [ ] `Clone` creates repo at selected path
- [ ] Repo added to Repo list
- [ ] `Cancel` closes modal, no repo cloned
- [ ] Add a Local Repository (Mac: ⌘O; Windows: Ctrl+O)
- [ ] Valid path can be entered or selected
- [ ] `Add repository` activated if repo path exists
- [ ] Repo added to Repo list
- [ ] If directory path not valid, 'Create a new repo' error message is present
- [ ] `Cancel` closes modal, no repo added
- [ ] Large repos (> 100MB) trigger Initialize Git LFS modal
- [ ] Link takes user to (https://git-lfs.github.com/)
- [ ] Local path to repo is displayed
- [ ] User can click `Cancel` or `Initialize Git LFS`
- [ ] Drag and drop repository
- [ ] User can drag existing local repository into Desktop
- [ ] Successful attempt adds repo to Repo list; else error message
* [ ] Create your account (/join?source=github-desktop)
* [ ] User is not automatically logged into Desktop post account creation
* [ ] `Sign in to Github.com` link
* [ ] `Sign in` successful if valid username/email and password
* [ ] If 2FA activated, user sent auth code to enter (test SMS and
authenticator app)
* [ ] User can reissue auth code with `Resend SMS` link
* [ ] Sign in successful with active 2FA code, user goes to Configure Git
* [ ] User sees Repository landing page if sign in successful
* [ ] Error message if code is wrong or inactive
* [ ] Error message if incorrect username/email or password
* [ ] Forgot link (/password_reset)
* [ ] `Cancel` returns to initial Welcome Flow
* [ ] `Sign in using your browser` opens default browser
* [ ] Browser login, "authorize" GitHub Desktop, “accept” link
* [ ] If successful, Desktop shown in `/settings/applications` in user
profile
* [ ] `Sign in to Enterprise` link (works with v2.8 and up)
* [ ] `Continue` successful if server address is valid, else error message
* [ ] `Sign in using your browser` opens default browser
* [ ] Browser login, [insert custom security measure], Authorize GitHub
Desktop, “accept” link
* [ ] User goes to Configure Git if successful
* [ ] `Cancel` returns to initial Welcome Flow
* [ ] User served generic message if not authorized to access Enterprise
server
* [ ] Skip "username+password" step
* [ ] Configure Git
* [ ] Name and email pulled from global `.gitconfig` file, if configured
* [ ] If recognized, your avatar is present in example commit; gravatars not
recognized
* [ ] `Continue` okay if fields populated or blank
* [ ] Valid login credentials from dotcom or Enterprise carried through
* [ ] User sees Repository landing page if sign in successful
* [ ] Usage Data
* [ ] Checked by default; user can uncheck. (Should not be checked if user on
free plan only.)
* [ ] Clicking `Finish`, and user is signed in successfully to Desktop
* [ ] `Cancel` returns to initial Configure Git page
### Repositories landing page; default no repositories
* [ ] Create New Repository (Mac: ⌘N; Windows: Ctrl+N)
* [ ] Modal opens with name, path (choose option), readme (unchecked), git
ignore, license. Name and path mandatory.
* [ ] If `Add this repository` warning message appears, clicking it adds to
Repo list
* [ ] If repository name is over 100 characterers, warning message is
surfaced in modal
* [ ] If repository contains URL-hostile characters, show error message
* [ ] `Create Repository` button adds new repo, which is added to Repo list
* [ ] `Cancel` button does not save any changes made; modal closed
* [ ] User cannot create a new repo inside a locked local directory
* [ ] Clone a Repository (Mac: ⇧⌘O; Windows: Ctrl+Shift+O)
* [ ] Enter valid URL or username/repo/gist, else error message
* [ ] If authentication error for Github.com, modal with username/password
surfaced; `Cancel` or `Save and Retry` buttons
* [ ] If successful, repo is cloned
* [ ] Modal surfaces again if unsuccessful
* [ ] If authentication error for Enterprise, user redirected to Preferences
* [ ] Valid path can be entered or selected
* [ ] Local path is prepopulated; if not unique then error surfaced
* [ ] All repos from both GitHub.com and Enterprise are populated -- your
repos are listed first, followed by org(s)
* [ ] User must be logged in to view list; else `Sign In` button present
* [ ] Results are filterable, and can be selected for cloning
* [ ] `Clone` creates repo at selected path
* [ ] Repo added to Repo list
* [ ] `Cancel` closes modal, no repo cloned
* [ ] Add a Local Repository (Mac: ⌘O; Windows: Ctrl+O)
* [ ] Valid path can be entered or selected
* [ ] `Add repository` activated if repo path exists
* [ ] Repo added to Repo list
* [ ] If directory path not valid, 'Create a new repo' error message is
present
* [ ] `Cancel` closes modal, no repo added
* [ ] Large repos (> 100MB) trigger Initialize Git LFS modal
* [ ] Link takes user to (https://git-lfs.github.com/)
* [ ] Local path to repo is displayed
* [ ] User can click `Cancel` or `Initialize Git LFS`
* [ ] Drag and drop repository
* [ ] User can drag existing local repository into Desktop
* [ ] Successful attempt adds repo to Repo list; else error message
### Publishing a repository
- [ ] Publish Repository modal present if repo is unpublished and user clicks `Publish repository` button
- [ ] GitHub tab is default; Enterprise tab is also present
- [ ] User must be signed in to publish, else `Sign In` button present on tab
- [ ] Modal fields are Name, Description (optional), `Keep this code private` checkbox, Organization list (alpha order, tab-specific), `Cancel` button, `Publish Repository` button
- [ ] Clicking `Publish Repository` button pushes repo to GitHub.com or Enterprise; `Cancel` button closes modal
- [ ] Repository is present on GitHub.com or Enterprise if published
- [ ] 'Visibility can't be private error' shown, if user's plan is not sufficient
- [ ] A `.gitattributes` file is added to the repository as part of the initial commit
* [ ] Publish Repository modal present if repo is unpublished and user clicks
`Publish repository` button
* [ ] GitHub tab is default; Enterprise tab is also present
* [ ] User must be signed in to publish, else `Sign In` button present on
tab
* [ ] Modal fields are Name, Description (optional), `Keep this code private`
checkbox, Organization list (alpha order, tab-specific), `Cancel`
button, `Publish Repository` button
* [ ] Clicking `Publish Repository` button pushes repo to GitHub.com or
Enterprise; `Cancel` button closes modal
* [ ] Repository is present on GitHub.com or Enterprise if published
* [ ] 'Visibility can't be private error' shown, if user's plan is not
sufficient
* [ ] A `.gitattributes` file is added to the repository as part of the
initial commit
### Application
- [ ] Minimize, Maximize, Close buttons work in top nav
- [ ] If user zooms in and quits app, settings should be retained when reopened
- [ ] Double-clicking local desktop icon opens the application (Mac only)
- [ ] Double clicking top nav bar toggles full-screen / last used screen-size (Mac only); Exit by (Mac: ^⌘f11; Windows: Alt)
- [ ] Clicking Desktop icon in dock/taskbar opens the application
- [ ] Changing desktop icon name while app is open results in package error; closed app name change is successful
* [ ] Minimize, Maximize, Close buttons work in top nav
* [ ] If user zooms in and quits app, settings should be retained when
reopened
* [ ] Double-clicking local desktop icon opens the application (Mac only)
* [ ] Double clicking top nav bar toggles full-screen / last used screen-size
(Mac only); Exit by (Mac: ^⌘f11; Windows: Alt)
* [ ] Clicking Desktop icon in dock/taskbar opens the application
* [ ] Changing desktop icon name while app is open results in package error;
closed app name change is successful
### GitHub Desktop menu top-level
- [ ] About GitHub Desktop
- [ ] Current version shown
- [ ] Links to release notes (dotcom), terms (modal), licenses (modal)
- [ ] Update banner shows `whats new` link and `retart now` link
- [ ] Update modal shows enhancements / bug fixes in latest build with `Install button`; user can X the banner
- [ ] Clicking the version number copies to clipboard
- [ ] Edge case: If build is "old", error message displays warning user to "... manually check for updates".
- [ ] Clicking `Check for updates` button produces "read-only volume" error message, with link for help
- [ ] Clicking `Check for updates` button timestamps last attempt
- [ ] If update available, `Install Update` button will quit app and install update
- [ ] If update available, download banner is present in main window with `restart` and `whats new` links
- [ ] If checking for update or download latest update, the `Check for updates` button is disabled
- [ ] Restarting the app automatically checks for updates
- [ ] `Close` button closes modal
- [ ] Preferences/Options (Mac/Windows: ⌘,)
- [ ] Accounts
- [ ] GitHub.com name, handle, avatar, `sign out` button, if user signed in
- [ ] Enterprise handle, avatar, `sign out` button, if user signed in
- [ ] User can sign out of either account
- [ ] User can sign-in to both Enterprise and GitHub.com at same time
- [ ] Git
- [ ] Username and email are displayed if `.gitconfig` configured for Welcome flow
- [ ] `Save` button saves any changes made
- [ ] `Cancel` button does not save any changes made; modal closed
- [ ] Advanced
- [ ] External Editor options shown in dropdown; else show "Install Atom?" link
- [ ] Shell options shown in dropdown
- [ ] Shared usage data option; selection carried through from Welcome flow
- [ ] `anonymous usage data` link opens https://desktop.github.com/usage-data/
- [ ] Check `stats-opt-out` value in Dev Tools > Application > Local storage > file://
- [ ] Confirmation dialogue for removing repositories is checked by default; user can toggle
- [ ] Check `ConfirmDiscardChanges` value in Dev Tools > Application > Local storage > file://
- [ ] Confirmation dialogue for disgarding files is checked by default; user can toggle
- [ ] Check `ConfirmRepoRemoval` value in Dev Tools > Application > Local storage > file://
- [ ] `Save` button saves any changes made
- [ ] `Cancel` button does not save any changes made; modal closed
- [ ] Install command line tool installs tool at `/usr/local/bin/github` (Mac only as Windows done automagically, Helper may require password, else error message)
- [ ] If already installed, user sees: "The command line tool has been installed at /usr/local/bin/github"
- [ ] Clicking `OK` closes modal
- [ ] Quit/Exit Desktop (Mac: ⌘Q)
- [ ] Quitting/Exiting and reopening Desktop returns you to last visited repo
* [ ] About GitHub Desktop
* [ ] Current version shown
* [ ] Links to release notes (dotcom), terms (modal), licenses (modal)
* [ ] Update banner shows `whats new` link and `retart now` link
* [ ] Update modal shows enhancements / bug fixes in latest build with
`Install button`; user can X the banner
* [ ] Clicking the version number copies to clipboard
* [ ] Edge case: If build is "old", error message displays warning user to
"... manually check for updates".
* [ ] Clicking `Check for updates` button produces "read-only volume" error
message, with link for help
* [ ] Clicking `Check for updates` button timestamps last attempt
* [ ] If update available, `Install Update` button will quit app and install
update
* [ ] If update available, download banner is present in main window with
`restart` and `whats new` links
* [ ] If checking for update or download latest update, the
`Check for updates` button is disabled
* [ ] Restarting the app automatically checks for updates
* [ ] `Close` button closes modal
* [ ] Preferences/Options (Mac/Windows: ⌘,)
* [ ] Accounts
* [ ] GitHub.com name, handle, avatar, `sign out` button, if user signed in
* [ ] Enterprise handle, avatar, `sign out` button, if user signed in
* [ ] User can sign out of either account
* [ ] User can sign-in to both Enterprise and GitHub.com at same time
* [ ] Git
* [ ] Username and email are displayed if `.gitconfig` configured for
Welcome flow
* [ ] `Save` button saves any changes made
* [ ] `Cancel` button does not save any changes made; modal closed
* [ ] Advanced
* [ ] External Editor options shown in dropdown; else show "Install Atom?"
link
* [ ] Shell options shown in dropdown
* [ ] Shared usage data option; selection carried through from Welcome flow
* [ ] `anonymous usage data` link opens
https://desktop.github.com/usage-data/
* [ ] Check `stats-opt-out` value in Dev Tools > Application > Local
storage > file://
* [ ] Confirmation dialogue for removing repositories is checked by default;
user can toggle
* [ ] Check `ConfirmDiscardChanges` value in Dev Tools > Application >
Local storage > file://
* [ ] Confirmation dialogue for disgarding files is checked by default; user
can toggle
* [ ] Check `ConfirmRepoRemoval` value in Dev Tools > Application > Local
storage > file://
* [ ] `Save` button saves any changes made
* [ ] `Cancel` button does not save any changes made; modal closed
* [ ] Install command line tool installs tool at `/usr/local/bin/github` (Mac
only as Windows done automagically, Helper may require password, else
error message)
* [ ] If already installed, user sees: "The command line tool has been
installed at /usr/local/bin/github"
* [ ] Clicking `OK` closes modal
* [ ] Quit/Exit Desktop (Mac: ⌘Q)
* [ ] Quitting/Exiting and reopening Desktop returns you to last visited repo
### File top-level menu
- [ ] Create New Repository (Mac: ⌘N; Windows: Ctrl+N)
- [ ] Clone a Repository (Mac: ⇧⌘O; Windows: Ctrl+Shift+O)
- [ ] Add a Local Repository (Mac: ⌘O; Windows: Ctrl+O)
- [ ] Options... (Windows only: Ctrl+,)
- [ ] Exit (Windows only; quits the app)
* [ ] Create New Repository (Mac: ⌘N; Windows: Ctrl+N)
* [ ] Clone a Repository (Mac: ⇧⌘O; Windows: Ctrl+Shift+O)
* [ ] Add a Local Repository (Mac: ⌘O; Windows: Ctrl+O)
* [ ] Options... (Windows only: Ctrl+,)
* [ ] Exit (Windows only; quits the app)
### Edit top-level menu
- [ ] Undo (Mac: ⌘Z; Windows: Ctrl+Z)
- [ ] Redo (Mac: ⇧⌘Z; Windows: Ctrl+Y)
- [ ] Cut (Mac: ⌘X; Windows: Ctrl+X)
- [ ] Copy (Mac: ⌘C; Windows: Ctrl+C)
- [ ] Paste (Mac: ⌘V; Windows: Ctrl+V)
- [ ] Select all (Mac: ⌘A; Windows: Ctrl+A)
* [ ] Undo (Mac: ⌘Z; Windows: Ctrl+Z)
* [ ] Redo (Mac: ⇧⌘Z; Windows: Ctrl+Y)
* [ ] Cut (Mac: ⌘X; Windows: Ctrl+X)
* [ ] Copy (Mac: ⌘C; Windows: Ctrl+C)
* [ ] Paste (Mac: ⌘V; Windows: Ctrl+V)
* [ ] Select all (Mac: ⌘A; Windows: Ctrl+A)
### View top-level menu
- [ ] Show Changes (Mac: ⌘1; Windows: Ctrl+1)
- [ ] Show History (Mac: ⌘2; Windows: Ctrl+2)
- [ ] Show Repositories List (Mac: ⌘T; Windows: Ctrl+T)
- [ ] Show Branches List (Mac: ⌘B; Windows: Ctrl+B)
- [ ] Enter Full Zoom (Mac: ^⌘F; Windows: F11)
- [ ] Reset Zoom (Mac: ⌘0; Windows: Ctrl+0)
- [ ] Zoom In (Mac: ⌘=; Windows: Ctrl+=)
- [ ] Zoom Out (Mac: ⌘-; Windows: Ctrl+-)
- [ ] Toggle Developer Tools (Mac: ⌥⌘I; Windows: Ctrl+Shift+I)
* [ ] Show Changes (Mac: ⌘1; Windows: Ctrl+1)
* [ ] Show History (Mac: ⌘2; Windows: Ctrl+2)
* [ ] Show Repositories List (Mac: ⌘T; Windows: Ctrl+T)
* [ ] Show Branches List (Mac: ⌘B; Windows: Ctrl+B)
* [ ] Enter Full Zoom (Mac: ^⌘F; Windows: F11)
* [ ] Reset Zoom (Mac: ⌘0; Windows: Ctrl+0)
* [ ] Zoom In (Mac: ⌘=; Windows: Ctrl+=)
* [ ] Zoom Out (Mac: ⌘-; Windows: Ctrl+-)
* [ ] Toggle Developer Tools (Mac: ⌥⌘I; Windows: Ctrl+Shift+I)
### Repository top-level menu. (Only enabled if one repo present)
- [ ] Push (Mac: ⌘P; Windows: Ctrl+P)
- [ ] Commits from repo pushed to .com; error message shown if conflicts
- [ ] Pull (Mac: ⇧⌘P; Windows: Ctrl+Shirt+P)
- [ ] Commits from repo pulled from .com; error message shown if conflicts
- [ ] Remove
- [ ] Repo is removed from Repo List; confirmation dialgue shown if Preferences option enabled
- [ ] View on GitHub (Mac: ⌥⌘G; Windows: Ctrl+Alt+G)
- [ ] Repo on .com is opened; must be logged in if private repo or Enterprise
- [ ] Open in Terminal/Command prompt
- [ ] Local repo is opened
- [ ] If git not installed, modal asks to Open with Git or Install Git
- [ ] Show in Finder/Explorer (Mac: ⇧⌘F; Windows: Ctrl+Shift+F)
- [ ] Local repo is opened
- [ ] Open in External Editor (Mac: ⇧⌘A; Windows: Ctrl+Shift+A); see External Editor option in prefs
- [ ] Secondary modal appears if no Editors set; option to Download Atom
- [ ] Repository settings
- [ ] Remote path can be edited; origin already set. Cannot be empty string, else error message.
- [ ] `Saved` button saves last entry
- [ ] `Cancel` button closes modal
- [ ] Ignored Files
- [ ] `.gitignore` file contents are shown and can be edited
- [ ] `Saved` button saves last entry; changes create a new commit
- [ ] `Cancel` button closes modal
* [ ] Push (Mac: ⌘P; Windows: Ctrl+P)
* [ ] Commits from repo pushed to .com; error message shown if conflicts
* [ ] Pull (Mac: ⇧⌘P; Windows: Ctrl+Shirt+P)
* [ ] Commits from repo pulled from .com; error message shown if conflicts
* [ ] Remove
* [ ] Repo is removed from Repo List; confirmation dialgue shown if
Preferences option enabled
* [ ] View on GitHub (Mac: ⌥⌘G; Windows: Ctrl+Alt+G)
* [ ] Repo on .com is opened; must be logged in if private repo or Enterprise
* [ ] Open in Terminal/Command prompt
* [ ] Local repo is opened
* [ ] If git not installed, modal asks to Open with Git or Install Git
* [ ] Show in Finder/Explorer (Mac: ⇧⌘F; Windows: Ctrl+Shift+F)
* [ ] Local repo is opened
* [ ] Open in External Editor (Mac: ⇧⌘A; Windows: Ctrl+Shift+A); see External
Editor option in prefs
* [ ] Secondary modal appears if no Editors set; option to Download Atom
* [ ] Repository settings
* [ ] Remote path can be edited; origin already set. Cannot be empty string,
else error message.
* [ ] `Saved` button saves last entry
* [ ] `Cancel` button closes modal
* [ ] Ignored Files
* [ ] `.gitignore` file contents are shown and can be edited
* [ ] `Saved` button saves last entry; changes create a new commit
* [ ] `Cancel` button closes modal
### Branch top-level menu
- [ ] New Branch (Mac: ⇧⌘N; Windows: Ctrl+Shift+N)
- [ ] Clicking `Create Branch` makes new branch based on the entered name, if not a duplicate
- [ ] Master branch is mentioned in the list; current branch shown first
- [ ] `Cancel` button closes modal
- [ ] Rename (cannot be master)
- [ ] `Rename` button changes branch name if field updated
- [ ] Same branch on GitHub.com is not renamed
- [ ] `Cancel` button closes modal
- [ ] Protected branches cannot be renamed
- [ ] Delete (cannot be master)
- [ ] Option to delete branch on the remote; default is unchecked
- [ ] `Delete` button deletes branch name (and remote too if option checked)
- [ ] `Cancel` button closes modal
- [ ] Protected branches cannot be deleted
- [ ] Update from Default Branch (cannot be master)
- [ ] Merge into Current Branch
- [ ] Use can filter existing branches
- [ ] User can select branch, other than current
- [ ] `Merge` button only activated if something to merge
- [ ] `Cancel` button closes modal
- [ ] Compare on GitHub (Mac: ⇧⌘C; Windows: Ctrl+Shift+C) (if repo already published on `github.com`)
- [ ] Create Pull request (Mac: ⌘R; Windows: Ctrl+R) opens Pull Request on `github.com`
- [ ] If branch unpublished, dialogue asks to publish the branch
- [ ] `Push Local Changes` modal surfaces with option to `Create Without Pushing` and `Push Commits`;(trigger: `Create Pull Request` after commit on branch before pushing)
* [ ] New Branch (Mac: ⇧⌘N; Windows: Ctrl+Shift+N)
* [ ] Clicking `Create Branch` makes new branch based on the entered name, if
not a duplicate
* [ ] Master branch is mentioned in the list; current branch shown first
* [ ] `Cancel` button closes modal
* [ ] Rename (cannot be master)
* [ ] `Rename` button changes branch name if field updated
* [ ] Same branch on GitHub.com is not renamed
* [ ] `Cancel` button closes modal
* [ ] Protected branches cannot be renamed
* [ ] Delete (cannot be master)
* [ ] Option to delete branch on the remote; default is unchecked
* [ ] `Delete` button deletes branch name (and remote too if option checked)
* [ ] `Cancel` button closes modal
* [ ] Protected branches cannot be deleted
* [ ] Update from Default Branch (cannot be master)
* [ ] Merge into Current Branch
* [ ] Use can filter existing branches
* [ ] User can select branch, other than current
* [ ] `Merge` button only activated if something to merge
* [ ] `Cancel` button closes modal
* [ ] Compare on GitHub (Mac: ⇧⌘C; Windows: Ctrl+Shift+C) (if repo already
published on `github.com`)
* [ ] Create Pull request (Mac: ⌘R; Windows: Ctrl+R) opens Pull Request on
`github.com`
* [ ] If branch unpublished, dialogue asks to publish the branch
* [ ] `Push Local Changes` modal surfaces with option to
`Create Without Pushing` and `Push Commits`;(trigger:
`Create Pull Request` after commit on branch before pushing)
### Window top-level menu (Mac only)
- [ ] Minimize, Zoom (maximize app size), Close, Bring All to Front, GitHub Desktop
* [ ] Minimize, Zoom (maximize app size), Close, Bring All to Front, GitHub
Desktop
### Help top-level menu
- [ ] `Report Issue` opens issue template in Desktop repo on `github.com`
- [ ] `Contact GitHub Support` opens `https://github.com/contact` page with user and build prepopulated
- [ ] `Show User Guides` opens Desktop help page on `github.com`
- [ ] `Show Logs in Finder/Explorer` opens Finder/Explorer logs in local directory
- [ ] Mac: `ls ~/Library/Application\ Support/GitHub\ Desktop/Logs/*.log`
- [ ] Windows: `%LOCALAPPDATA%\\Desktop\\*.desktop.production.log`
- [ ] About GitHub Desktop (Windows only)
* [ ] `Report Issue` opens issue template in Desktop repo on `github.com`
* [ ] `Contact GitHub Support` opens `https://github.com/contact` page with user
and build prepopulated
* [ ] `Show User Guides` opens Desktop help page on `github.com`
* [ ] `Show Logs in Finder/Explorer` opens Finder/Explorer logs in local
directory
* [ ] Mac: `ls ~/Library/Application\ Support/GitHub\ Desktop/Logs/*.log`
* [ ] Windows: `%LOCALAPPDATA%\\Desktop\\*.desktop.production.log`
* [ ] About GitHub Desktop (Windows only)
### Repositories list
- [ ] Current repo is always shown in top slot with respective icon; if repo exists
- [ ] Opening list shows all repos in categorized format with a working filter
- [ ] `ESC` clears the filter
- [ ] All repos (private, enterprise, local, public, forked, other) have proper icon and found in the proper category (GitHub.com/Enterprise/Other)
- [ ] Hover shows username/repo, url, and/or local path in tooltip
- [ ] User must have paid account for private repos
- [ ] Repo icon is updated if admin changes status (public vs private)
- [ ] Repositories cloned from non-github servers should always be in the Other group, and have the 'computer' icon.
- [ ] Selecting a repo updates Changes/History/Diff areas
- [ ] If no Changes, Diff area shows `Open this repository` link to Finder/Explorer on local
- [ ] `Right-click` on any repo shows `Open in Terminal`, `Open in Finder/Explorer`, `Open in External Editor`, and `Remove` options
- [ ] Repos which have been removed locally (and trash emptied) have 'cannot find repository' warning
- [ ] Relaunching the app when it displays a missing repository preserves the repo's name and last seen path
- [ ] Remove a repo which can not be found (deleted locally & trash emptied)
- [ ] Repos which are cloning display a progress bar
* [ ] Current repo is always shown in top slot with respective icon; if repo
exists
* [ ] Opening list shows all repos in categorized format with a working filter
* [ ] `ESC` clears the filter
* [ ] All repos (private, enterprise, local, public, forked, other) have
proper icon and found in the proper category
(GitHub.com/Enterprise/Other)
* [ ] Hover shows username/repo, url, and/or local path in tooltip
* [ ] User must have paid account for private repos
* [ ] Repo icon is updated if admin changes status (public vs private)
* [ ] Repositories cloned from non-github servers should always be in the Other
group, and have the 'computer' icon.
* [ ] Selecting a repo updates Changes/History/Diff areas
* [ ] If no Changes, Diff area shows `Open this repository` link to
Finder/Explorer on local
* [ ] `Right-click` on any repo shows `Open in Terminal`,
`Open in Finder/Explorer`, `Open in External Editor`, and `Remove` options
* [ ] Repos which have been removed locally (and trash emptied) have 'cannot
find repository' warning
* [ ] Relaunching the app when it displays a missing repository preserves the
repo's name and last seen path
* [ ] Remove a repo which can not be found (deleted locally & trash emptied)
* [ ] Repos which are cloning display a progress bar
### Changes tab
- [ ] Changes tab shows `•` icon if files are waiting to be committed
- [ ] Number of changed files is always present; it can be 0
- [ ] Any changed files appear in the list, with respective +/•/- sign; with arrow keys enabled
- [ ] Merge-conflicted files showin with hazard icon; cannot be committed until fixed
- [ ] User can check none, or check one or more files to commit; list is scrollable
- [ ] User can select one or more lines to commit; diff is scrollable
- [ ] Right-clicking any file shows menu with options
- [ ] User can discard the file; pending confirmation dialogue
- [ ] `Do not show this message again`overrides the preference setting if true
- [ ] User can ignore single/all files, show in Finder/Explorer, reveal in external editor, or open in default program
- [ ] A specific files can only be ignored once
- [ ] All ignored files found in Repository Settings > Ignored Files tab
- [ ] Panes can be resized horizontally, and contents resize to take the full width
- [ ] Quitting Desktop and relaunching remembers sizes
* [ ] Changes tab shows `•` icon if files are waiting to be committed
* [ ] Number of changed files is always present; it can be 0
* [ ] Any changed files appear in the list, with respective +/•/- sign; with
arrow keys enabled
* [ ] Merge-conflicted files showin with hazard icon; cannot be committed
until fixed
* [ ] User can check none, or check one or more files to commit; list is
scrollable
* [ ] User can select one or more lines to commit; diff is scrollable
* [ ] Right-clicking any file shows menu with options
* [ ] User can discard the file; pending confirmation dialogue
* [ ] `Do not show this message again`overrides the preference setting if
true
* [ ] User can ignore single/all files, show in Finder/Explorer, reveal in
external editor, or open in default program
* [ ] A specific files can only be ignored once
* [ ] All ignored files found in Repository Settings > Ignored Files tab
* [ ] Panes can be resized horizontally, and contents resize to take the full
width
* [ ] Quitting Desktop and relaunching remembers sizes
### History tab
- [ ] All commits listed in chronological order, with avatar, date and name; list is scrollable with arrow keys enabled
- [ ] Right clicking any commit shows options: Revert, Copy SHA, View on GitHub
- [ ] Hover shows file name in tooltip
### Diffs tab
- [ ] All commits have avatar, selectable SHA, # of files changed, commit message, commit description (optional)
- [ ] Long commit descriptions can be toggled with expand/collapse icon
- [ ] Reverting commit repopulates commit area
- [ ] Error message if no changes to commit
- [ ] All files within a commit listed, with respective +/•/-/-> sign; list is scrollable
- [ ] Diffs are viewable; list is scrollable with arrow keys enabled
- [ ] Green is for additions, red for deletions
- [ ] Different file types are rendered properly
- [ ] Single pic file with the `->` sign has multiple view options: 2-up (default); Swipe; Onion Skin; and Difference
- [ ] Panes can be resized horizontally, and contents resize to take the full width
- [ ] Diffs cannot be over 3MB
- [ ] Diffs cannot be longer than 500,000 characters
* [ ] All commits listed in chronological order, with avatar, date and name;
list is scrollable with arrow keys enabled
* [ ] Right clicking any commit shows options: Revert, Copy SHA, View on
GitHub
* [ ] Hover shows file name in tooltip
### Diffs tab
* [ ] All commits have avatar, selectable SHA, # of files changed, commit
message, commit description (optional)
* [ ] Long commit descriptions can be toggled with expand/collapse icon
* [ ] Reverting commit repopulates commit area
* [ ] Error message if no changes to commit
* [ ] All files within a commit listed, with respective +/•/-/-> sign; list is
scrollable
* [ ] Diffs are viewable; list is scrollable with arrow keys enabled
* [ ] Green is for additions, red for deletions
* [ ] Different file types are rendered properly
* [ ] Single pic file with the `->` sign has multiple view options: 2-up
(default); Swipe; Onion Skin; and Difference
* [ ] Panes can be resized horizontally, and contents resize to take the full
width
* [ ] Diffs cannot be over 3MB
* [ ] Diffs cannot be longer than 500,000 characters
### Commit section
- [ ] Commit created if user clicks `Commit to [branch]` button with commit message and at least one checked file
- [ ] `Fetch origin` changes to `Push` with number of commits badge
- [ ] Avatar of user is shown
- [ ] User can 'at-mention' those associated with the respective repo; either subject or description field is ok (published repositories only)
- [ ] User can 'pound-mention' an issue in the either subject or description field; issue number should populate (published repositories only)
- [ ] Description field is optional
- [ ] User can undo last commit
- [ ] `Push` with number of commits badge is decremented or reverts to `Fetch origin`
- [ ] `Undo` button disabled if user is pushing commit
- [ ] User can publish a new repo with no commits (aka unborn repo/branch)
* [ ] Commit created if user clicks `Commit to [branch]` button with commit
message and at least one checked file
* [ ] `Fetch origin` changes to `Push` with number of commits badge
* [ ] Avatar of user is shown
* [ ] User can 'at-mention' those associated with the respective repo; either
subject or description field is ok (published repositories only)
* [ ] User can 'pound-mention' an issue in the either subject or description
field; issue number should populate (published repositories only)
* [ ] Description field is optional
* [ ] User can undo last commit
* [ ] `Push` with number of commits badge is decremented or reverts to
`Fetch origin`
* [ ] `Undo` button disabled if user is pushing commit
* [ ] User can publish a new repo with no commits (aka unborn repo/branch)
### Branches list
- [ ] Current branch always shows if repository present
- [ ] Hover shows full branch name in tooltip
- [ ] Opening list shows all branches in categorized format with a working filter
- [ ] `New` button opens 'New Branch' modal
- [ ] If filters results are nil, then prefill branch name in modal if user clicks `Create New Branch`
- [ ] Active branch is highlighted and marked with a check
- [ ] `ESC` clears the filter
- [ ] Hover shows full branch name in tooltip
- [ ] Default branch labeled and listed first, with timestamp
- [ ] Selecting a branch switches branches
- [ ] Creating a new branch shows `Publish branch` button
- [ ] Publishing successful if logged in only; else error message
- [ ] `Create Pull Request` menu option shows warning if branch not published yet
- [ ] Renamed branches updated on .com and vice-versa if logged in; else error message
- [ ] Opens modal with ability to enter new name
- [ ] Deleted branches updated on .com and vice-versa if logged in; else error message
- [ ] Deleting branch show warning message
* [ ] Current branch always shows if repository present
* [ ] Hover shows full branch name in tooltip
* [ ] Opening list shows all branches in categorized format with a working
filter
* [ ] `New` button opens 'New Branch' modal
* [ ] If filters results are nil, then prefill branch name in modal if user
clicks `Create New Branch`
* [ ] Active branch is highlighted and marked with a check
* [ ] `ESC` clears the filter
* [ ] Hover shows full branch name in tooltip
* [ ] Default branch labeled and listed first, with timestamp
* [ ] Selecting a branch switches branches
* [ ] Creating a new branch shows `Publish branch` button
* [ ] Publishing successful if logged in only; else error message
* [ ] `Create Pull Request` menu option shows warning if branch not
published yet
* [ ] Renamed branches updated on .com and vice-versa if logged in; else error
message
* [ ] Opens modal with ability to enter new name
* [ ] Deleted branches updated on .com and vice-versa if logged in; else error
message
* [ ] Deleting branch show warning message
### Fetching origin/Pull
- [ ] Code is constantly being fetched from .com with timestamp
- [ ] Hover shows timestamp in tooltip
- [ ] If Pull Requests on .com, they are reflected with down arrow and quantity
- [ ] Pull Requests and Commits can co-exist; error surfaces if merge commit
- [ ] User cannot Push/Pull without being signed in; error message surfaced
- [ ] Push/Pull works with public/private/Enterprise repos
- [ ] Tooltip shows status upon hover, if progress to display
- [ ] When a branch is local-only make sure that the `Fetch` button changes to `Publish` and it publishes
* [ ] Code is constantly being fetched from .com with timestamp
* [ ] Hover shows timestamp in tooltip
* [ ] If Pull Requests on .com, they are reflected with down arrow and
quantity
* [ ] Pull Requests and Commits can co-exist; error surfaces if merge commit
* [ ] User cannot Push/Pull without being signed in; error message surfaced
* [ ] Push/Pull works with public/private/Enterprise repos
* [ ] Tooltip shows status upon hover, if progress to display
* [ ] When a branch is local-only make sure that the `Fetch` button changes to
`Publish` and it publishes
### Publishing only
- [ ] Unpublished repository, unborn HEAD - `Publish button` enabled (user can publish repository)
- [ ] Unpublished repository, valid branch - `Publish button` enabled (user can publish repository and branch)
- [ ] Published repository, unborn HEAD - `Publish button` disabled (no branch to push)
- [ ] Published repository, branch without tracking - `Publish button` enabled (user can publish branch)
- [ ] Published repository, network action - `Publish button` disabled (don't interfere with existing action)
* [ ] Unpublished repository, unborn HEAD - `Publish button` enabled (user can
publish repository)
* [ ] Unpublished repository, valid branch - `Publish button` enabled (user can
publish repository and branch)
* [ ] Published repository, unborn HEAD - `Publish button` disabled (no branch
to push)
* [ ] Published repository, branch without tracking - `Publish button` enabled
(user can publish branch)
* [ ] Published repository, network action - `Publish button` disabled (don't
interfere with existing action)
### Dotcom
- [ ] If Desktop linked to .com (/settings/applications), the Desktop icon should show on File Revisions tab for all Pull Requests.
- [ ] Clicking the "computer icon" opens from a Pull Request page opens the branch on Desktop
- [ ] If private email is enabled (http://github.com/settings/emails), user is blocked from pushing to all associated repositories on Desktop?
- [ ] If user updates name in Settings, change should reflect in Preferences
* [ ] If Desktop linked to .com (/settings/applications), the Desktop icon
should show on File Revisions tab for all Pull Requests.
* [ ] Clicking the "computer icon" opens from a Pull Request page opens the
branch on Desktop
* [ ] If private email is enabled (http://github.com/settings/emails), user is
blocked from pushing to all associated repositories on Desktop?
* [ ] If user updates name in Settings, change should reflect in Preferences
### Pull Request list + CI status (v1.1)
- [ ] Pull request list shown as subsection of Branch list
- [ ] Only open Pull Requests are reflected; closed Pull Requests not shown in the list
- [ ] Pull Request toolbar status is surfaced with yellow, green or red icon, or no icon if no status
- [ ] If no pull requests, then no badge shown, and Pull Request tab shows `0`
- [ ] User shown current branch in text area, and given option to create a new branch or create new pull request
- [ ] Pull request for the current branch selected by default, with pull-request-number badge in header
- [ ] Pull request list can be filtered; `esc` key clears filter; arrow keys can scroll list
- [ ] Results in chronological order, with name, id number, date, username, and CI status
- [ ] Status checks run frequently in background, especially if yellow
- [ ] PR status can be updated independently of respective PR
* [ ] Pull request list shown as subsection of Branch list
* [ ] Only open Pull Requests are reflected; closed Pull Requests not shown in
the list
* [ ] Pull Request toolbar status is surfaced with yellow, green or red icon, or
no icon if no status
* [ ] If no pull requests, then no badge shown, and Pull Request tab shows `0`
* [ ] User shown current branch in text area, and given option to create a new
branch or create new pull request
* [ ] Pull request for the current branch selected by default, with
pull-request-number badge in header
* [ ] Pull request list can be filtered; `esc` key clears filter; arrow keys
can scroll list
* [ ] Results in chronological order, with name, id number, date, username,
and CI status
* [ ] Status checks run frequently in background, especially if yellow
* [ ] PR status can be updated independently of respective PR
### TBD placeholder (WIP)
- Merge tool for conflicted files
- Conflicted files vs changed files
- Relationship between branches
- Commit/Compare tabs now occupy left pane
- Compare tab shows branch dropdown
- Choose a branch from the list (same order as branch list? current branch present?) or user filter; `esc` clears filter
- Once branch selected, quantity of commits behind surfaced; matches commits shown
- `Merge X commits` button is activated
- Merge conflict count surfaced below button if relevant
- Clicking `Merge` button merges all shown commits
- Commit history present, chronological order, descending
- Show Git LFS (Cloning, Committing, Checking out, Reverting, Switching branches)
- Report Git LFS (Cloning, Pushing, Pulling, Switching branches, Reverting)
* Merge tool for conflicted files
* Conflicted files vs changed files
* Relationship between branches
* Commit/Compare tabs now occupy left pane
* Compare tab shows branch dropdown
* Choose a branch from the list (same order as branch list? current branch
present?) or user filter; `esc` clears filter
* Once branch selected, quantity of commits behind surfaced; matches
commits shown
* `Merge X commits` button is activated
* Merge conflict count surfaced below button if relevant
* Clicking `Merge` button merges all shown commits
* Commit history present, chronological order, descending
* Show Git LFS (Cloning, Committing, Checking out, Reverting, Switching
branches)
* Report Git LFS (Cloning, Pushing, Pulling, Switching branches, Reverting)

View File

@ -25,10 +25,10 @@ are constrained to within the dialog itself.
## Errors
Dialogs should, when practical, render errors caused by its actions inline as
opposed to opening an error dialog. An example of this is the Preferences dialog.
If the dialog fails to write to the .gitignore or git config files as part of
persisting changes it renders a short error message inline in the dialog using
the `DialogError` component.
opposed to opening an error dialog. An example of this is the Preferences
dialog. If the dialog fails to write to the .gitignore or git config files as
part of persisting changes it renders a short error message inline in the dialog
using the `DialogError` component.
The `DialogError` component, if used, must be the first child element of the
Dialog itself.
@ -49,22 +49,21 @@ Dialog itself.
</Dialog>
```
The content inside of the DialogError should be primarily text based. Avoid using
the term 'Error' inside the text as that should be evident already based on the
styling of the `DialogError` component.
The content inside of the DialogError should be primarily text based. Avoid
using the term 'Error' inside the text as that should be evident already based
on the styling of the `DialogError` component.
## Best practices
### DO: Let children render the DialogContent component
If you're using a one-child-per-tab approach you should render the DialogContent
as the top-level element in those children instead of wrapping children inside the
DialogContent element. This avoid needless nesting and lets us leverage generic
dialog/form/row styles in a more straightforward way.
as the top-level element in those children instead of wrapping children inside
the DialogContent element. This avoid needless nesting and lets us leverage
generic dialog/form/row styles in a more straightforward way.
#### Example (good)
```html
<!-- SomeComponent.tsx -->
<Dialog title='Title'>
@ -85,7 +84,6 @@ dialog/form/row styles in a more straightforward way.
#### Example (bad)
```html
<!-- SomeComponent.tsx -->
<Dialog title='Title'>
@ -108,8 +106,8 @@ dialog/form/row styles in a more straightforward way.
### DO: Use Row components to lay out content
The `Row` component receives a bottom margin, when used as an immediate
child of `DialogContent`, making it an excellent tool for structuring content.
The `Row` component receives a bottom margin, when used as an immediate child of
`DialogContent`, making it an excellent tool for structuring content.
If the content is primary text, as opposed to form component the `<p>` element
should be used instead of the `Row` component.

View File

@ -8,10 +8,10 @@ on a repository in the sidebar.
This is the checklist of things that it needs to support:
- the editor supports opening a directory, not just a file
- the editor is installed by the user, so there is a reliable way to find it
on the user's machine
- it comes with a command-line interface that can be launched by Desktop
* the editor supports opening a directory, not just a file
* the editor is installed by the user, so there is a reliable way to find it on
the user's machine
* it comes with a command-line interface that can be launched by Desktop
If you think your editor satisfies all these please read on to understand how
Desktop integrates with each OS, and if you're still keen to integrate this
@ -24,9 +24,9 @@ The source for the editor integration on Windows is found in
These editors are currently supported:
- [Atom](https://atom.io/)
- [Visual Studio Code](https://code.visualstudio.com/)
- [Sublime Text](https://www.sublimetext.com/)
* [Atom](https://atom.io/)
* [Visual Studio Code](https://code.visualstudio.com/)
* [Sublime Text](https://www.sublimetext.com/)
These are defined in an enum at the top of the file:
@ -38,8 +38,8 @@ export enum ExternalEditor {
}
```
If you want to add another editor, add a new key to the `ExternalEditor`
enum with a friendly name for the value. This will trigger a number of compiler
If you want to add another editor, add a new key to the `ExternalEditor` enum
with a friendly name for the value. This will trigger a number of compiler
errors, which are places in the module you need to add code.
The steps for resolving each editor can be found in `findApplication()` and in
@ -60,10 +60,9 @@ entries to the registry to help the OS with cleaning up later, if the user
wishes to uninstall. These entries are used by GitHub Desktop to identify
relevant programs and where they can be located.
The registry locations for each editor are listed in `getRegistryKeys()`.
Some editors support multiple install locations, but are structurally the
same (for example 64-bit or 32-bit application, or stable and developer
channels).
The registry locations for each editor are listed in `getRegistryKeys()`. Some
editors support multiple install locations, but are structurally the same (for
example 64-bit or 32-bit application, or stable and developer channels).
```ts
function getRegistryKeys(editor: ExternalEditor): ReadonlyArray<string> {
@ -83,26 +82,25 @@ function getRegistryKeys(editor: ExternalEditor): ReadonlyArray<string> {
If you're not sure how your editor is installed, check one of these locations:
- `HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall` -
uninstall information about 64-bit Windows software is found here
* `HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall` -
uninstall information about 64-bit Windows software is found here
- `HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall` -
uninstall information about 32-bit Windows software is found here
* `HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall` -
uninstall information about 32-bit Windows software is found here
- `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall` -
uninstall information for software that doesn't require administrator
permissions is found here
* `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall` -
uninstall information for software that doesn't require administrator
permissions is found here
Your editor is probably hiding behind a GUID in one of these locations - this
is the the key that Desktop needs to read the registry and find the installation for your editor.
Your editor is probably hiding behind a GUID in one of these locations - this is
the the key that Desktop needs to read the registry and find the installation
for your editor.
### Step 2: Validate The Installation
As part of installing to the registry, a program will insert a
number of key-value pairs - Desktop will enumerate these to ensure it's the
application it expects, and identify where the install location of the
application.
As part of installing to the registry, a program will insert a number of
key-value pairs - Desktop will enumerate these to ensure it's the application it
expects, and identify where the install location of the application.
There's two steps to this process. The first step is reading the registry, and
you can see this code in `extractApplicationInformation()`:
@ -171,11 +169,11 @@ function isExpectedInstallation(
### Step 3: Launch the program
Now that Desktop knows the program is the one it expects, it can use the
install location to then find the executable to launch. Many editors provide a
shim or standalone tool to manage this, rather than launching the
executable directly. Whatever options there are, this should be a known
location with an interface that doesn't change between updates.
Now that Desktop knows the program is the one it expects, it can use the install
location to then find the executable to launch. Many editors provide a shim or
standalone tool to manage this, rather than launching the executable directly.
Whatever options there are, this should be a known location with an interface
that doesn't change between updates.
```ts
function getExecutableShim(
@ -191,8 +189,8 @@ function getExecutableShim(
}
```
Desktop will confirm this file exists on disk before launching - if it's
missing or lost it won't let you launch the external editor.
Desktop will confirm this file exists on disk before launching - if it's missing
or lost it won't let you launch the external editor.
## macOS
@ -201,10 +199,10 @@ The source for the editor integration on macOS is found in
These editors are currently supported:
- [Atom](https://atom.io/)
- [Visual Studio Code](https://code.visualstudio.com/)
- [Sublime Text](https://www.sublimetext.com/)
- [BBEdit](http://www.barebones.com/products/bbedit/)
* [Atom](https://atom.io/)
* [Visual Studio Code](https://code.visualstudio.com/)
* [Sublime Text](https://www.sublimetext.com/)
* [BBEdit](http://www.barebones.com/products/bbedit/)
These are defined in an enum at the top of the file:
@ -216,8 +214,8 @@ export enum ExternalEditor {
}
```
If you want to add another editor, add a new key to the `ExternalEditor`
enum with a friendly name for the value. This will trigger a number of compiler
If you want to add another editor, add a new key to the `ExternalEditor` enum
with a friendly name for the value. This will trigger a number of compiler
errors, which are places in the module you need to add code.
The steps for resolving each editor can be found in `findApplication()` and in
@ -232,12 +230,12 @@ async function findApplication(editor: ExternalEditor): Promise<string | null> {
### Step 1: Find installation path
macOS programs are packaged as application bundles, and applications can
read information from the OS to see if they are present.
macOS programs are packaged as application bundles, and applications can read
information from the OS to see if they are present.
The `CFBundleIdentifier` value in the plist is what applications use to
uniquely identify themselves, for example `com.github.GitHubClient` is the
identifier for GitHub Desktop.
The `CFBundleIdentifier` value in the plist is what applications use to uniquely
identify themselves, for example `com.github.GitHubClient` is the identifier for
GitHub Desktop.
The `getBundleIdentifier()` method is the lookup method for this value:
@ -252,9 +250,10 @@ function getBundleIdentifier(editor: ExternalEditor): string {
}
```
AppKit provides an [`API`](https://developer.apple.com/documentation/appkit/nsworkspace/1533086-absolutepathforappbundlewithiden?language=objc)
for searching for an application bundle. If it finds an application bundle,
it will return the path to the application on disk. Otherwise it will raise an
AppKit provides an
[`API`](https://developer.apple.com/documentation/appkit/nsworkspace/1533086-absolutepathforappbundlewithiden?language=objc)
for searching for an application bundle. If it finds an application bundle, it
will return the path to the application on disk. Otherwise it will raise an
exception.
### Step 2: Find executable to launch
@ -287,15 +286,14 @@ function getExecutableShim(
## Linux
The source for the editor integration on Linux is found in
[`app/src/lib/editors/linux.ts`](https://github.com/desktop/desktop/blob/master/app/src/lib/editors/linux.ts).
These editors are currently supported:
- [Atom](https://atom.io/)
- [Visual Studio Code](https://code.visualstudio.com/)
- [Sublime Text](https://www.sublimetext.com/)
* [Atom](https://atom.io/)
* [Visual Studio Code](https://code.visualstudio.com/)
* [Sublime Text](https://www.sublimetext.com/)
These are defined in an enum at the top of the file:
@ -307,24 +305,24 @@ export enum ExternalEditor {
}
```
If you want to add another editor, add a new key to the `ExternalEditor`
enum with a friendly name for the value. This will trigger a compiler
error, and you need to add code to `getEditorPath()` to get the source
building again.
If you want to add another editor, add a new key to the `ExternalEditor` enum
with a friendly name for the value. This will trigger a compiler error, and you
need to add code to `getEditorPath()` to get the source building again.
### Step 1: Find executable path
The `getEditorPath()` maps the editor enum to an expected path to the
editor executable. Add a new `case` statement for your editor.
The `getEditorPath()` maps the editor enum to an expected path to the editor
executable. Add a new `case` statement for your editor.
```ts
case ExternalEditor.VisualStudioCode:
return getPathIfAvailable('/usr/bin/code')
```
### Step 2: Lookup executable
Once you've done that, add code to `getAvailableEditors()` so that it checks
for your new editor, following the existing patterns.
Once you've done that, add code to `getAvailableEditors()` so that it checks for
your new editor, following the existing patterns.
```ts
export async function getAvailableEditors(): Promise<

View File

@ -13,7 +13,8 @@ old friend `undefined is not a function`. This is a problem with the code itself
which cannot be resolved at runtime. Our only option is to quit the app and
relaunch.
We handle uncaught exceptions by registering a [global listener](https://github.com/desktop/desktop/blob/fb4e73560127f491ccf5f59984a310481911f2b6/app/src/ui/index.tsx#L75).
We handle uncaught exceptions by registering a
[global listener](https://github.com/desktop/desktop/blob/fb4e73560127f491ccf5f59984a310481911f2b6/app/src/ui/index.tsx#L75).
We report the exception to Central, tell the user that an unrecoverable error
happened, and then quit and relaunch. End of story.
@ -24,8 +25,10 @@ standard usage of the app. For example, if the internet's down or a git
repository is in a funny state, we're gonna get some errors.
Our error reporting flows through the `Dispatcher` like most everything in the
app. [`postError`](https://github.com/desktop/desktop/blob/fb4e73560127f491ccf5f59984a310481911f2b6/app/src/lib/dispatcher/dispatcher.ts#L308)
calls the [registered](https://github.com/desktop/desktop/blob/fb4e73560127f491ccf5f59984a310481911f2b6/app/src/lib/dispatcher/dispatcher.ts#L711)
app.
[`postError`](https://github.com/desktop/desktop/blob/fb4e73560127f491ccf5f59984a310481911f2b6/app/src/lib/dispatcher/dispatcher.ts#L308)
calls the
[registered](https://github.com/desktop/desktop/blob/fb4e73560127f491ccf5f59984a310481911f2b6/app/src/lib/dispatcher/dispatcher.ts#L711)
[error handlers](https://github.com/desktop/desktop/blob/fb4e73560127f491ccf5f59984a310481911f2b6/app/src/lib/dispatcher/error-handlers.ts),
starting with the most recently registered. The error handlers have the chance
to pass the error through untouched, return a different or more specific error,
@ -43,7 +46,8 @@ export async function myCoolErrorHandler(
```
If an error passes through all the registered error handlers, the final error
handler will call [`Dispatcher#presentError`](https://github.com/desktop/desktop/blob/75445ea61177347b2df08e846aae30e637d5f1de/app/src/lib/dispatcher/dispatcher.ts#L334).
handler will call
[`Dispatcher#presentError`](https://github.com/desktop/desktop/blob/75445ea61177347b2df08e846aae30e637d5f1de/app/src/lib/dispatcher/dispatcher.ts#L334).
That will present the generic error dialog to the user.
```
@ -74,9 +78,11 @@ We have a couple `Error` subclasses which we use to provide more context to
error handlers:
* [`GitError`](https://github.com/desktop/desktop/blob/75445ea61177347b2df08e846aae30e637d5f1de/app/src/lib/git/core.ts#L62) -
All errors coming from git should be `GitError`s.
All errors coming from git should be `GitError`s.
* [`ErrorWithMetadata`](https://github.com/desktop/desktop/blob/75445ea61177347b2df08e846aae30e637d5f1de/app/src/lib/error-with-metadata.ts) -
Wraps an existing `Error` with additional metadata.
Wraps an existing `Error` with additional metadata.
`ErrorWithMetadata` instances can provide a [`RetryAction`](https://github.com/desktop/desktop/blob/75445ea61177347b2df08e846aae30e637d5f1de/app/src/lib/retry-actions.ts)
which gives error handlers the ability to retry whatever action caused the error.
`ErrorWithMetadata` instances can provide a
[`RetryAction`](https://github.com/desktop/desktop/blob/75445ea61177347b2df08e846aae30e637d5f1de/app/src/lib/retry-actions.ts)
which gives error handlers the ability to retry whatever action caused the
error.

View File

@ -2,27 +2,27 @@
To ensure Desktop along without being blocked on design feedback, we need a way
to be able to ship features that are stable but not necessarily ready for
general usage. This document outlines what we should flag and how to flag
these features.
general usage. This document outlines what we should flag and how to flag these
features.
## What Should Be Feature Flagged?
A **preview feature** can be considered as:
- something that has a well-defined scope
- a consensus exists that the team is happy to proceed, but
- some details need to be thought through or clarified
* something that has a well-defined scope
* a consensus exists that the team is happy to proceed, but
* some details need to be thought through or clarified
We're currently focused on user interface changes - new views, significant
changes to existing views, and so on. We can revisit this list when we
identify other cases where this sort of feature flagging needs to occur.
changes to existing views, and so on. We can revisit this list when we identify
other cases where this sort of feature flagging needs to occur.
A **beta feature** should be:
- a feature that is slated for an upcoming release, and
- is usably complete, but
- needs more testing, or
- needs to be used to see how it feels
* a feature that is slated for an upcoming release, and
* is usably complete, but
* needs more testing, or
* needs to be used to see how it feels
Beta features are a superset of preview features.
@ -30,19 +30,24 @@ Beta features are a superset of preview features.
A few reasons:
- some solutions just need time to appear, and this lets us get working code
out quicker.
- we want to get feedback easily - users can opt-in to these preview features.
- we want to be conservative with evolving the UI - most users aren't fans of
frequent, unnecessary churn.
- if we don't like something we can pull it before people get too attached to
it.
* some solutions just need time to appear, and this lets us get working code out
quicker.
* we want to get feedback easily - users can opt-in to these preview features.
* we want to be conservative with evolving the UI - most users aren't fans of
frequent, unnecessary churn.
* if we don't like something we can pull it before people get too attached to
it.
## How to Feature Flag?
First add a new function to [feature-flag.ts](https://github.com/desktop/desktop/blob/3ee29eb1bd083a53f69fdbec2e2b10ec93404e44/app/src/lib/feature-flag.ts#L30). The function should usually check `enableDevelopmentFeatures()` or `enableBetaFeatures()`. Then, at runtime, your code should check either your feature flag function and either display the new feature or the existing one.
First add a new function to
[feature-flag.ts](https://github.com/desktop/desktop/blob/3ee29eb1bd083a53f69fdbec2e2b10ec93404e44/app/src/lib/feature-flag.ts#L30).
The function should usually check `enableDevelopmentFeatures()` or
`enableBetaFeatures()`. Then, at runtime, your code should check either your
feature flag function and either display the new feature or the existing one.
See pull request integration in [#3339](https://github.com/desktop/desktop/pull/3339) for an example.
See pull request integration in
[#3339](https://github.com/desktop/desktop/pull/3339) for an example.
This separation and naming scheme makes it easier to clean up the new or old
feature once things are stabilized.

View File

@ -1,20 +1,22 @@
# Developer OAuth App
Because GitHub Desktop uses [OAuth web application flow](https://developer.github.com/v3/oauth/#web-application-flow)
Because GitHub Desktop uses
[OAuth web application flow](https://developer.github.com/v3/oauth/#web-application-flow)
to interact with the GitHub API and perform actions on behalf of a user, it
needs to be bundled with a Client ID and Secret.
For external contributors, we have bundled a developer OAuth application
with the Desktop application so that you can complete the sign in flow locally
For external contributors, we have bundled a developer OAuth application with
the Desktop application so that you can complete the sign in flow locally
without needing to configure your own application.
These are listed in [app/webpack.common.js](https://github.com/desktop/desktop/blob/c286d0d513d82b97e1a9c60d44c23020f2ba34d7/app/webpack.common.js#L9-L10).
These are listed in
[app/webpack.common.js](https://github.com/desktop/desktop/blob/c286d0d513d82b97e1a9c60d44c23020f2ba34d7/app/webpack.common.js#L9-L10).
**DO NOT TRUST THIS CLIENT ID AND SECRET! THIS IS ONLY FOR TESTING PURPOSES!!**
The limitation with this developer application is that **this will not work
with GitHub Enterprise**. You will see sign-in will fail on the OAuth callback
due to the credentials not being present there.
The limitation with this developer application is that **this will not work with
GitHub Enterprise**. You will see sign-in will fail on the OAuth callback due to
the credentials not being present there.
## Provide your own Client ID and Secret
@ -22,5 +24,5 @@ The OAuth client ID and Client Secret are bundled into the application with
webpack. If you want to provide your own Client ID and Client Secret, set these
environment variables:
- `DESKTOP_OAUTH_CLIENT_ID`
- `DESKTOP_OAUTH_CLIENT_SECRET`
* `DESKTOP_OAUTH_CLIENT_ID`
* `DESKTOP_OAUTH_CLIENT_SECRET`

View File

@ -1,10 +1,11 @@
## Placeholders and Replacements in Source Code
As GitHub Desktop uses Webpack to transpile, minify and merge our code
into unified scripts for each configuration we define, we use some tricks
to manage complexity and enable some optimizations.
As GitHub Desktop uses Webpack to transpile, minify and merge our code into
unified scripts for each configuration we define, we use some tricks to manage
complexity and enable some optimizations.
For example, you might come across this code in [`app-window.ts`](https://github.com/desktop/desktop/blob/master/app/src/main-process/app-window.ts):
For example, you might come across this code in
[`app-window.ts`](https://github.com/desktop/desktop/blob/master/app/src/main-process/app-window.ts):
```ts
if (__DARWIN__) {
@ -29,7 +30,8 @@ we get significant benefits from doing it the first way.
### Replacements
The replacements defined for Desktop are found in [`app/app-info.js`](https://github.com/desktop/desktop/blob/master/app/app-info.js)
The replacements defined for Desktop are found in
[`app/app-info.js`](https://github.com/desktop/desktop/blob/master/app/app-info.js)
as a hash of key-value pairs.
```ts
@ -54,8 +56,8 @@ function getReplacements() {
}
```
This means we can embed values at build time based on the current platform.
Note the values we are embeddeding for `__DARWIN__` and `__WIN32__`:
This means we can embed values at build time based on the current platform. Note
the values we are embeddeding for `__DARWIN__` and `__WIN32__`:
```ts
__DARWIN__: process.platform === 'darwin',
@ -96,13 +98,14 @@ And this code for Windows:
windowOptions.frame = false
```
This means less code is emitted as part of the packaged app, and less
JavaScript is interpreted and executed at runtime.
This means less code is emitted as part of the packaged app, and less JavaScript
is interpreted and executed at runtime.
### Placeholders
As we are working in TypeScript, we need to define these placeholders as
globals under [`app/src/lib/globals.ts`](https://github.com/desktop/desktop/blob/master/app/src/lib/globals.d.ts)
As we are working in TypeScript, we need to define these placeholders as globals
under
[`app/src/lib/globals.ts`](https://github.com/desktop/desktop/blob/master/app/src/lib/globals.d.ts)
to provide the appropriate type information to the source code.
For example, the values for `__DARWIN__` and `__WIN32__` are declared as

View File

@ -7,26 +7,26 @@ machine, to work with Git repositories outside of Desktop.
This is the checklist of things that it needs to support:
- Desktop can check it exists on the user's machine
- Desktop is able to launch it using the operating system's APIs
- It has a stable interface (command line arguments) that doesn't change
between updates
* Desktop can check it exists on the user's machine
* Desktop is able to launch it using the operating system's APIs
* It has a stable interface (command line arguments) that doesn't change between
updates
If you think your shell satifies all these requirements please read on to
understand how Desktop integrates with each OS, and if you're still keen to
integrate this please fork and contribute a pull request for the team to
review.
integrate this please fork and contribute a pull request for the team to review.
## Windows
The source for the Windows shell integration is found in [`app/src/lib/shells/win32.ts`](https://github.com/desktop/desktop/blob/master/app/src/lib/shell/win32.ts).
The source for the Windows shell integration is found in
[`app/src/lib/shells/win32.ts`](https://github.com/desktop/desktop/blob/master/app/src/lib/shell/win32.ts).
These shells are currently supported:
- Command Prompt (cmd)
- PowerShell
- [Hyper](https://hyper.sh/)
- Git Bash (from [Git for Windows](https://git-for-windows.github.io/))
* Command Prompt (cmd)
* PowerShell
* [Hyper](https://hyper.sh/)
* Git Bash (from [Git for Windows](https://git-for-windows.github.io/))
These are defined in an enum at the top of the file:
@ -39,14 +39,14 @@ export enum Shell {
}
```
To add another shell, add a new key to the `Shell` enum with a friendly name
for the value. You will need to add code in this module to find your shell, and I'll
To add another shell, add a new key to the `Shell` enum with a friendly name for
the value. You will need to add code in this module to find your shell, and I'll
use **Git Bash** as a reference for the rest of the process.
### Step 1: Find the shell executable
The `getAvailableShells()` method is used to find each shell, as some may not
be present on the user's machine. You will need to add some code in here.
The `getAvailableShells()` method is used to find each shell, as some may not be
present on the user's machine. You will need to add some code in here.
For Git Bash we perform a couple of checks:
@ -67,9 +67,9 @@ if (gitBash.length > 0) {
This approximately reads as:
- check if Git for Windows has been installed, using the registry
- if it is, check the installation path exists
- return the path to `git-bash.exe` within that directory
* check if Git for Windows has been installed, using the registry
* if it is, check the installation path exists
* return the path to `git-bash.exe` within that directory
### Step 2: Launch the shell
@ -87,13 +87,14 @@ changes here.
## 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/shell/darwin.ts).
These shells are currently supported:
- Terminal
- [Hyper](https://hyper.sh/)
- [iTerm2](https://www.iterm2.com/)
* Terminal
* [Hyper](https://hyper.sh/)
* [iTerm2](https://www.iterm2.com/)
These are defined in an enum at the top of the file:
@ -108,22 +109,21 @@ export enum Shell {
If you want to add another shell, add a new key to the `Shell` enum with a
friendly name for the value.
There's a couple of places you need to add code to find your shell, and I'll
use Hyper as a reference to explain the rest of the process.
There's a couple of places you need to add code to find your shell, and I'll use
Hyper as a reference to explain the rest of the process.
### Step 1: Find the shell application
The `getBundleID()` function is used to map a shell enum to it's bundle ID
that is defined in it's manifest. You should add a new entry here for your
shell.
The `getBundleID()` function is used to map a shell enum to it's bundle ID that
is defined in it's manifest. You should add a new entry here for your shell.
```ts
case Shell.Hyper:
return 'co.zeit.hyper'
```
After that, follow the existing patterns in `getAvailableShells()` and add a
new entry to lookup the install path for your shell.
After that, follow the existing patterns in `getAvailableShells()` and add a new
entry to lookup the install path for your shell.
```ts
export async function getAvailableShells(): Promise<
@ -147,9 +147,9 @@ export async function getAvailableShells(): Promise<
### Step 2: Launch the shell
The launch step will use the `open` command in macOS to launch a given bundle
at the path requested by the user. You may not need to make changes here,
unless your shell behaviour differs significanlty from this.
The launch step will use the `open` command in macOS to launch a given bundle at
the path requested by the user. You may not need to make changes here, unless
your shell behaviour differs significanlty from this.
```ts
export async function launch(shell: Shell, path: string): Promise<void> {
@ -161,15 +161,16 @@ export async function launch(shell: Shell, path: string): Promise<void> {
## 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/shell/linux.ts).
These shells are currently supported:
- [GNOME Terminal](https://help.gnome.org/users/gnome-terminal/stable/)
- [Tilix](https://github.com/gnunn1/tilix)
- [Rxvt Unicode](http://software.schmorp.de/pkg/rxvt-unicode.html)
- [Konsole](https://konsole.kde.org/)
- [XTerm](http://invisible-island.net/xterm/)
* [GNOME Terminal](https://help.gnome.org/users/gnome-terminal/stable/)
* [Tilix](https://github.com/gnunn1/tilix)
* [Rxvt Unicode](http://software.schmorp.de/pkg/rxvt-unicode.html)
* [Konsole](https://konsole.kde.org/)
* [XTerm](http://invisible-island.net/xterm/)
These are defined in an enum at the top of the file:
@ -183,9 +184,9 @@ export enum Shell {
}
```
To add another shell, add a new key to the `Shell` enum with a friendly name
for the value. You will need to add code in this module to find your shell, and
I'll use Tilix as a reference for the rest of the process.
To add another shell, add a new key to the `Shell` enum with a friendly name for
the value. You will need to add code in this module to find your shell, and I'll
use Tilix as a reference for the rest of the process.
### Step 1: Find the shell application
@ -198,8 +199,8 @@ case Shell.Tilix:
return getPathIfAvailable('/usr/bin/tilix')
```
After that, follow the existing patterns in `getAvailableShells()` and add a
new entry to lookup the install path for your shell.
After that, follow the existing patterns in `getAvailableShells()` and add a new
entry to lookup the install path for your shell.
```ts
export async function getAvailableShells(): Promise<
@ -224,8 +225,8 @@ export async function getAvailableShells(): Promise<
### Step 2: Launch the shell
The `launch()` method will use the received `shell.shell` executable path and
the path requested by the user. You may need to make changes here, if your
shell has a different command line interface.
the path requested by the user. You may need to make changes here, if your shell
has a different command line interface.
```ts
export async function launch(
@ -251,5 +252,4 @@ export async function launch(
const commandArgs = ['--working-directory', path]
await spawn(shell.path, commandArgs)
}
```

View File

@ -1,6 +1,7 @@
# Syntax Highlighted Diffs
We introduced syntax highlighted diffs in [#3101](https://github.com/desktop/desktop/pull/3101).
We introduced syntax highlighted diffs in
[#3101](https://github.com/desktop/desktop/pull/3101).
<img width="578" alt="A screenshot of GitHub Desktop showing a diff with syntax highlighting" src="https://user-images.githubusercontent.com/634063/31934229-d2ffdac8-b8ab-11e7-84e7-1bb2c0e1a0ec.png">
@ -8,41 +9,86 @@ We introduced syntax highlighted diffs in [#3101](https://github.com/desktop/des
We currently support syntax highlighting for the following languages.
JavaScript, JSON, TypeScript, Coffeescript, HTML, CSS, SCSS, LESS, VUE, Markdown, Yaml, XML, Objective-C, Scala, C#, Java, C, C++, Kotlin, Ocaml, F#, sh/bash, Swift, SQL, CYPHER, Go, Perl, PHP, Python, Ruby, Clojure
JavaScript, JSON, TypeScript, Coffeescript, HTML, CSS, SCSS, LESS, VUE,
Markdown, Yaml, XML, Objective-C, Scala, C#, Java, C, C++, Kotlin, Ocaml, F#,
sh/bash, Swift, SQL, CYPHER, Go, Perl, PHP, Python, Ruby, Clojure
This list was never meant to be exhaustive, we expect to add more languages going forward but this seemed like a good first step.
This list was never meant to be exhaustive, we expect to add more languages
going forward but this seemed like a good first step.
Note, however that this list is likely to grow stale so I'd recommend checking [the code](https://github.com/desktop/desktop/blob/master/app/src/highlighter/index.ts) directly.
Note, however that this list is likely to grow stale so I'd recommend checking
[the code](https://github.com/desktop/desktop/blob/master/app/src/highlighter/index.ts)
directly.
### I want to add my favorite language
Cool! As long as it's a language that [CodeMirror supports out of the box](https://codemirror.net/mode/index.html) we should be able to make it work. Open an issue and we'll take it from there.
Cool! As long as it's a language that
[CodeMirror supports out of the box](https://codemirror.net/mode/index.html) we
should be able to make it work. Open an issue and we'll take it from there.
If you want to create a PR and add highlighter support for your favourite programming langauge don't forget to:
1. Submit a PR with a sample file for the language to [desktop/highlighter-tests](https://github.com/desktop/highlighter-tests).
2. Add the language that the highlighter going to support to the `Supported Languages` list above.
If you want to create a PR and add highlighter support for your favourite
programming langauge don't forget to:
1. Submit a PR with a sample file for the language to
[desktop/highlighter-tests](https://github.com/desktop/highlighter-tests).
2. Add the language that the highlighter going to support to the
`Supported Languages` list above.
## Why do the diffs on GitHub.com and Desktop look different
GitHub.com uses TextMate/Atom grammars whereas GitHub Desktop currently uses the [built-in](https://codemirror.net/mode/index.html) modes in CodeMirror. There's some significant differences both in granularity and in tokenization between these two. CodeMirror was a good way for us to get started but depending on how it plays out we might consider looking into other grammars.
GitHub.com uses TextMate/Atom grammars whereas GitHub Desktop currently uses the
[built-in](https://codemirror.net/mode/index.html) modes in CodeMirror. There's
some significant differences both in granularity and in tokenization between
these two. CodeMirror was a good way for us to get started but depending on how
it plays out we might consider looking into other grammars.
## The Problem
Syntax highlighting is a well-understood problem with tons of options. Atom uses TextMate grammars to do theirs but since we're already using CodeMirror I took a stab at implementing ours using that.
Syntax highlighting is a well-understood problem with tons of options. Atom uses
TextMate grammars to do theirs but since we're already using CodeMirror I took a
stab at implementing ours using that.
Syntax highlighted diffs have been a much appreciated feature of GitHub.com for a long time now and one that I have missed in GitHub Desktop for a long time. Highlighting in diffs presents some added complexity over that of highlighting in a normal source file though. Pretty much all languages are contextual, in that what happened on some line "higher up" affects what's going on further down. As such you can't just pull out a line from a diff and expect it to be highlighted properly. Here's a good example
Syntax highlighted diffs have been a much appreciated feature of GitHub.com for
a long time now and one that I have missed in GitHub Desktop for a long time.
Highlighting in diffs presents some added complexity over that of highlighting
in a normal source file though. Pretty much all languages are contextual, in
that what happened on some line "higher up" affects what's going on further
down. As such you can't just pull out a line from a diff and expect it to be
highlighted properly. Here's a good example
<img width="658" alt="A screenshot of GitHub Desktop showing a diff with a multi-line comment which is missing the opening statement" src="https://user-images.githubusercontent.com/634063/31782735-34dfe412-b4fc-11e7-8d79-46a949417ed2.png">
Had we just tried to highlight individual lines here we wouldn't have been able to infer that the first line was part of a multi-line comment.
Instead, we have to take the contents of the file before the change, and the contents of it after and run highlighting on both versions. Once that's done we can stitch these together to form one syntax highlighted diff.
Had we just tried to highlight individual lines here we wouldn't have been able
to infer that the first line was part of a multi-line comment.
Instead, we have to take the contents of the file before the change, and the
contents of it after and run highlighting on both versions. Once that's done we
can stitch these together to form one syntax highlighted diff.
## The Approach
When we are about to perform highlighting on a diff we start out by scanning through the diff to figure out which lines we need from which file. Context lines can be pulled from either version while added/removed lines obviously need to come from a particular version. If we find that a file consists entirely of additions or entirely of deletions we can optimize further by adding a preference for one of the versions and thus getting away with loading just one file.
When we are about to perform highlighting on a diff we start out by scanning
through the diff to figure out which lines we need from which file. Context
lines can be pulled from either version while added/removed lines obviously need
to come from a particular version. If we find that a file consists entirely of
additions or entirely of deletions we can optimize further by adding a
preference for one of the versions and thus getting away with loading just one
file.
Once we've got that settled we load the first 256kb from both versions (256kb picked arbitrarily because I figured it should cover the majority of source files while adding a very manageable memory overhead for the feature). We then pass this content, along with which lines we want to get tokens for to one or two web workers which then run the modes. CodeMirror modes are synchronous but running them in a web worker means we can get on with other things while we're tokenizing up to half a megabyte of content in up to two different threads (threads in javascript, what have we come to). It also means that we have a real nice containment of the highlighting process and that we can terminate it should it for some reason end up taking a very long time to complete.
Once we've got that settled we load the first 256kb from both versions (256kb
picked arbitrarily because I figured it should cover the majority of source
files while adding a very manageable memory overhead for the feature). We then
pass this content, along with which lines we want to get tokens for to one or
two web workers which then run the modes. CodeMirror modes are synchronous but
running them in a web worker means we can get on with other things while we're
tokenizing up to half a megabyte of content in up to two different threads
(threads in javascript, what have we come to). It also means that we have a real
nice containment of the highlighting process and that we can terminate it should
it for some reason end up taking a very long time to complete.
When we get the results from the workers we apply our own custom CodeMirror mode which takes the tokens from the language modes and applies them inside of our diff. That means that there's a small window in between when users see the diff and when highlighting gets applied. In my testing it's barely noticeable and it means we can deliver what really matters (the diff) as quickly as we've done before.
When we get the results from the workers we apply our own custom CodeMirror mode
which takes the tokens from the language modes and applies them inside of our
diff. That means that there's a small window in between when users see the diff
and when highlighting gets applied. In my testing it's barely noticeable and it
means we can deliver what really matters (the diff) as quickly as we've done
before.

View File

@ -6,54 +6,62 @@ the application (visually) and anchored at the top of the screen. On Windows
things aren't quite as simple.
Since we wanted a "frameless" design on Windows we explored putting the
application menu behind a hamburger icon in [#689](https://github.com/desktop/desktop/pull/689)
which worked decently until the advent of the separate title bar in [#775](https://github.com/desktop/desktop/pull/775) which was introduced so that
there would be draggable areas of the window even when running on small resolutions.
application menu behind a hamburger icon in
[#689](https://github.com/desktop/desktop/pull/689) which worked decently until
the advent of the separate title bar in
[#775](https://github.com/desktop/desktop/pull/775) which was introduced so that
there would be draggable areas of the window even when running on small
resolutions.
Ultimately we decided that the familiar UX of a menu bar was superior to anything
we had tried up until that point.
Ultimately we decided that the familiar UX of a menu bar was superior to
anything we had tried up until that point.
The first iteration of this menu bar was implemented in [#991](https://github.com/desktop/desktop/pull/991) and this document serves to
The first iteration of this menu bar was implemented in
[#991](https://github.com/desktop/desktop/pull/991) and this document serves to
document what a Windows menu bar is supposed to do such that we can detect
regressions going forward.
## The basics
The menu bar should display the top-level menu items and each menu item
should be clickable. When clicking on a menu item the associated sub menu
should expand (or collapse if already open).
The menu bar should display the top-level menu items and each menu item should
be clickable. When clicking on a menu item the associated sub menu should expand
(or collapse if already open).
## Keyboard navigation
When a user is holding down the <kbd>Alt</kbd> key the access-keys (which is separate from
accelerator or "shortcut" keys) in the top-level menu items should be underlined.
When a user is holding down the <kbd>Alt</kbd> key the access-keys (which is
separate from accelerator or "shortcut" keys) in the top-level menu items should
be underlined.
![underlined access keys](https://cloud.githubusercontent.com/assets/634063/24377826/02f7cb34-1341-11e7-9514-4b229372f985.png)
Pressing, and holding down, <kbd>Alt</kbd> followed by one of the access keys in the top
level menu should expand that menu. The menu should now be put in such as state
that menu items in sub menus have their access keys highlighted as well.
Pressing, and holding down, <kbd>Alt</kbd> followed by one of the access keys in
the top level menu should expand that menu. The menu should now be put in such
as state that menu items in sub menus have their access keys highlighted as
well.
If a menu is opened using <kbd>ALT</kbd>+<kbd>X</kbd> (where x is an access key for a top level menu
item) a user should be able to activate (execute) its sub menu items should by
pressing the corresponding access key. Note, however, that this key should *not*
be used in conjunction with the <kbd>Alt</kbd> key. In other words, to execute the
File -> New Branch item a user should be able to press <kbd>ALT</kbd>+<kbd>F</kbd>
followed by <kbd>B</kbd>.
If a menu is opened using <kbd>ALT</kbd>+<kbd>X</kbd> (where x is an access key
for a top level menu item) a user should be able to activate (execute) its sub
menu items should by pressing the corresponding access key. Note, however, that
this key should _not_ be used in conjunction with the <kbd>Alt</kbd> key. In
other words, to execute the File -> New Branch item a user should be able to
press <kbd>ALT</kbd>+<kbd>F</kbd> followed by <kbd>B</kbd>.
Pressing the <kbd>Alt</kbd> key and releasing it without pressing an access key should
put focus on the first top level menu item if no menu is currently expanded. If
any menus are expanded pressing <kbd>Alt</kbd> should immediately close any open menus.
Pressing the <kbd>Alt</kbd> key and releasing it without pressing an access key
should put focus on the first top level menu item if no menu is currently
expanded. If any menus are expanded pressing <kbd>Alt</kbd> should immediately
close any open menus.
![focused menu item](https://cloud.githubusercontent.com/assets/634063/24378079/f6bff85e-1341-11e7-8d79-dbc8681fa9f0.png)
Pressing and releasing the <kbd>Alt</kbd> key while a top level menu item is focused should
remove keyboard focus from the item.
Pressing and releasing the <kbd>Alt</kbd> key while a top level menu item is
focused should remove keyboard focus from the item.
### Focused top-level menu items
When a top-level menu item has keyboard focused (and its menu is collapsed) a
user should be able to expand the menu by pressing <kbd>Enter</kbd> or <kbd></kbd>.
user should be able to expand the menu by pressing <kbd>Enter</kbd> or
<kbd></kbd>.
Using the <kbd></kbd> and <kbd></kbd> keys should move focus to the next
adjacent menu item in that direction, looping around if necessary.
@ -63,18 +71,20 @@ adjacent menu item in that direction, looping around if necessary.
An expanded menu respond to <kbd></kbd> and <kbd></kbd>, moving the selection
to the next adjacent menu item in that direction, looping around if necessary.
Hitting <kbd>Enter</kbd> or <kbd>Space</kbd> should execute the currently selected menu item.
Hitting <kbd>Enter</kbd> or <kbd>Space</kbd> should execute the currently
selected menu item.
<kbd></kbd> should open a submenu if the currently selected item has one and
move selection (and focus) to the first item in that submenu. If the current
item does not have a submenu <kbd></kbd> should have no effect.
Similarly <kbd></kbd> should close the currently open submenu and move focus
back to the sub-menu's parent item.
item does not have a submenu <kbd></kbd> should have no effect. Similarly
<kbd></kbd> should close the currently open submenu and move focus back to the
sub-menu's parent item.
#### Pointer device interactions
Menu item selection should follow the pointer device so that pointing on a menu
item automatically selects it. Moving outside of a menu should not close the menu.
item automatically selects it. Moving outside of a menu should not close the
menu.
If a user points at a menu item which has a submenu of its own the selection
should immediately switch to that menu item but the sub menu should not expand