Merge branch 'development' into visual-improvements-on-checkall

This commit is contained in:
tidy-dev 2024-02-27 12:42:05 -05:00
commit 2a008bc70d
18 changed files with 173 additions and 2 deletions

View file

@ -340,6 +340,8 @@ export interface IAppState {
* rulesets to check their bypass status. * rulesets to check their bypass status.
*/ */
readonly cachedRepoRulesets: ReadonlyMap<number, IAPIRepoRuleset> readonly cachedRepoRulesets: ReadonlyMap<number, IAPIRepoRuleset>
readonly underlineLinks: boolean
} }
export enum FoldoutType { export enum FoldoutType {

View file

@ -106,3 +106,5 @@ export const enableDiffCheckMarksAndLinkUnderlines = enableBetaFeatures
export const enableDiffCheckMarks = enableDiffCheckMarksAndLinkUnderlines export const enableDiffCheckMarks = enableDiffCheckMarksAndLinkUnderlines
export const enableGroupDiffCheckmarks = enableDevelopmentFeatures export const enableGroupDiffCheckmarks = enableDevelopmentFeatures
export const enableLinkUnderlines = enableDiffCheckMarksAndLinkUnderlines

View file

@ -238,7 +238,7 @@ import {
} from './updates/changes-state' } from './updates/changes-state'
import { ManualConflictResolution } from '../../models/manual-conflict-resolution' import { ManualConflictResolution } from '../../models/manual-conflict-resolution'
import { BranchPruner } from './helpers/branch-pruner' import { BranchPruner } from './helpers/branch-pruner'
import { enableMoveStash } from '../feature-flag' import { enableLinkUnderlines, enableMoveStash } from '../feature-flag'
import { Banner, BannerType } from '../../models/banner' import { Banner, BannerType } from '../../models/banner'
import { ComputedAction } from '../../models/computed-action' import { ComputedAction } from '../../models/computed-action'
import { import {
@ -407,6 +407,9 @@ const lastThankYouKey = 'version-and-users-of-last-thank-you'
const pullRequestSuggestedNextActionKey = const pullRequestSuggestedNextActionKey =
'pull-request-suggested-next-action-key' 'pull-request-suggested-next-action-key'
const underlineLinksKey = 'underline-links'
const underlineLinksDefault = true
const showDiffCheckMarksDefault = true const showDiffCheckMarksDefault = true
const showDiffCheckMarksKey = 'diff-check-marks-visible' const showDiffCheckMarksKey = 'diff-check-marks-visible'
@ -544,6 +547,8 @@ export class AppStore extends TypedBaseStore<IAppState> {
private cachedRepoRulesets = new Map<number, IAPIRepoRuleset>() private cachedRepoRulesets = new Map<number, IAPIRepoRuleset>()
private underlineLinks: boolean = underlineLinksDefault
public constructor( public constructor(
private readonly gitHubUserStore: GitHubUserStore, private readonly gitHubUserStore: GitHubUserStore,
private readonly cloningRepositoriesStore: CloningRepositoriesStore, private readonly cloningRepositoriesStore: CloningRepositoriesStore,
@ -1023,6 +1028,7 @@ export class AppStore extends TypedBaseStore<IAppState> {
pullRequestSuggestedNextAction: this.pullRequestSuggestedNextAction, pullRequestSuggestedNextAction: this.pullRequestSuggestedNextAction,
resizablePaneActive: this.resizablePaneActive, resizablePaneActive: this.resizablePaneActive,
cachedRepoRulesets: this.cachedRepoRulesets, cachedRepoRulesets: this.cachedRepoRulesets,
underlineLinks: this.underlineLinks,
showDiffCheckMarks: this.showDiffCheckMarks, showDiffCheckMarks: this.showDiffCheckMarks,
} }
} }
@ -2212,6 +2218,11 @@ export class AppStore extends TypedBaseStore<IAppState> {
PullRequestSuggestedNextAction PullRequestSuggestedNextAction
) ?? defaultPullRequestSuggestedNextAction ) ?? defaultPullRequestSuggestedNextAction
// Always false if the feature flag is disabled.
this.underlineLinks = enableLinkUnderlines()
? getBoolean(underlineLinksKey, underlineLinksDefault)
: false
this.showDiffCheckMarks = getBoolean( this.showDiffCheckMarks = getBoolean(
showDiffCheckMarksKey, showDiffCheckMarksKey,
showDiffCheckMarksDefault showDiffCheckMarksDefault
@ -7929,6 +7940,14 @@ export class AppStore extends TypedBaseStore<IAppState> {
this.emitUpdate() this.emitUpdate()
} }
} }
public _updateUnderlineLinks(underlineLinks: boolean) {
if (underlineLinks !== this.underlineLinks) {
this.underlineLinks = underlineLinks
setBoolean(underlineLinksKey, underlineLinks)
this.emitUpdate()
}
}
} }
/** /**

View file

@ -6,4 +6,5 @@ export enum PreferencesTab {
Notifications, Notifications,
Prompts, Prompts,
Advanced, Advanced,
Accessibility,
} }

View file

@ -1660,6 +1660,7 @@ export class App extends React.Component<IAppProps, IAppState> {
selectedTheme={this.state.selectedTheme} selectedTheme={this.state.selectedTheme}
repositoryIndicatorsEnabled={this.state.repositoryIndicatorsEnabled} repositoryIndicatorsEnabled={this.state.repositoryIndicatorsEnabled}
onOpenFileInExternalEditor={this.openFileInExternalEditor} onOpenFileInExternalEditor={this.openFileInExternalEditor}
underlineLinks={this.state.underlineLinks}
/> />
) )
case PopupType.RepositorySettings: { case PopupType.RepositorySettings: {
@ -1917,6 +1918,7 @@ export class App extends React.Component<IAppProps, IAppState> {
emoji={this.state.emoji} emoji={this.state.emoji}
newReleases={popup.newReleases} newReleases={popup.newReleases}
onDismissed={onPopupDismissedFn} onDismissed={onPopupDismissedFn}
underlineLinks={this.state.underlineLinks}
/> />
) )
case PopupType.DeletePullRequest: case PopupType.DeletePullRequest:
@ -2405,6 +2407,7 @@ export class App extends React.Component<IAppProps, IAppState> {
emoji={this.state.emoji} emoji={this.state.emoji}
onSubmit={onPopupDismissedFn} onSubmit={onPopupDismissedFn}
onDismissed={onPopupDismissedFn} onDismissed={onPopupDismissedFn}
underlineLinks={this.state.underlineLinks}
accounts={this.state.accounts} accounts={this.state.accounts}
/> />
) )
@ -2532,6 +2535,7 @@ export class App extends React.Component<IAppProps, IAppState> {
emoji={this.state.emoji} emoji={this.state.emoji}
onSubmit={onPopupDismissedFn} onSubmit={onPopupDismissedFn}
onDismissed={onPopupDismissedFn} onDismissed={onPopupDismissedFn}
underlineLinks={this.state.underlineLinks}
accounts={this.state.accounts} accounts={this.state.accounts}
/> />
) )
@ -3156,6 +3160,7 @@ export class App extends React.Component<IAppProps, IAppState> {
showCIStatusPopover={this.state.showCIStatusPopover} showCIStatusPopover={this.state.showCIStatusPopover}
emoji={this.state.emoji} emoji={this.state.emoji}
enableFocusTrap={enableFocusTrap} enableFocusTrap={enableFocusTrap}
underlineLinks={this.state.underlineLinks}
/> />
) )
} }
@ -3350,7 +3355,12 @@ export class App extends React.Component<IAppProps, IAppState> {
return null return null
} }
const className = this.state.appIsFocused ? 'focused' : 'blurred' const className = classNames(
this.state.appIsFocused ? 'focused' : 'blurred',
{
'underline-links': this.state.underlineLinks,
}
)
const currentTheme = this.state.showWelcomeFlow const currentTheme = this.state.showWelcomeFlow
? ApplicationTheme.Light ? ApplicationTheme.Light

View file

@ -54,6 +54,8 @@ interface IBranchesContainerProps {
/** Map from the emoji shortcut (e.g., :+1:) to the image's local path. */ /** Map from the emoji shortcut (e.g., :+1:) to the image's local path. */
readonly emoji: Map<string, string> readonly emoji: Map<string, string>
readonly underlineLinks: boolean
} }
interface IBranchesContainerState { interface IBranchesContainerState {
@ -138,6 +140,7 @@ export class BranchesContainer extends React.Component<
pullRequestItemTop={prListItemTop} pullRequestItemTop={prListItemTop}
onMouseEnter={this.onMouseEnterPullRequestQuickView} onMouseEnter={this.onMouseEnterPullRequestQuickView}
onMouseLeave={this.onMouseLeavePullRequestQuickView} onMouseLeave={this.onMouseLeavePullRequestQuickView}
underlineLinks={this.props.underlineLinks}
/> />
) )
} }

View file

@ -3913,4 +3913,8 @@ export class Dispatcher {
) { ) {
this.appStore.onChecksFailedNotification(repository, pullRequest, checks) this.appStore.onChecksFailedNotification(repository, pullRequest, checks)
} }
public setUnderlineLinksSetting(underlineLinks: boolean) {
return this.appStore._updateUnderlineLinks(underlineLinks)
}
} }

View file

@ -40,6 +40,8 @@ interface ISandboxedMarkdownProps {
/** The context of which markdown resides - such as PullRequest, PullRequestComment, Commit */ /** The context of which markdown resides - such as PullRequest, PullRequestComment, Commit */
readonly markdownContext?: MarkdownContext readonly markdownContext?: MarkdownContext
readonly underlineLinks: boolean
} }
interface ISandboxedMarkdownState { interface ISandboxedMarkdownState {
@ -202,7 +204,12 @@ export class SandboxedMarkdown extends React.PureComponent<
${scrapeVariable('--text-color')} ${scrapeVariable('--text-color')}
${scrapeVariable('--background-color')} ${scrapeVariable('--background-color')}
} }
${css} ${css}
.markdown-body a {
text-decoration: ${this.props.underlineLinks ? 'underline' : 'inherit'};
}
</style>` </style>`
} }

View file

@ -32,6 +32,8 @@ interface IPullRequestCommentLikeProps {
readonly switchingToPullRequest: boolean readonly switchingToPullRequest: boolean
readonly underlineLinks: boolean
readonly renderFooterContent: () => JSX.Element readonly renderFooterContent: () => JSX.Element
readonly onSubmit: () => void readonly onSubmit: () => void
@ -173,6 +175,7 @@ export abstract class PullRequestCommentLike extends React.Component<IPullReques
repository={base.gitHubRepository} repository={base.gitHubRepository}
onMarkdownLinkClicked={this.onMarkdownLinkClicked} onMarkdownLinkClicked={this.onMarkdownLinkClicked}
markdownContext={'PullRequestComment'} markdownContext={'PullRequestComment'}
underlineLinks={this.props.underlineLinks}
/> />
) )
} }

View file

@ -19,6 +19,8 @@ interface IPullRequestCommentProps {
/** Map from the emoji shortcut (e.g., :+1:) to the image's local path. */ /** Map from the emoji shortcut (e.g., :+1:) to the image's local path. */
readonly emoji: Map<string, string> readonly emoji: Map<string, string>
readonly underlineLinks: boolean
/** /**
* Whether or not the dialog should offer to switch to the PR's repository or * Whether or not the dialog should offer to switch to the PR's repository or
* to checkout the PR branch when applicable (e.g. non-approved reviews). * to checkout the PR branch when applicable (e.g. non-approved reviews).
@ -83,6 +85,7 @@ export class PullRequestComment extends React.Component<
renderFooterContent={this.renderFooterContent} renderFooterContent={this.renderFooterContent}
onSubmit={onSubmit} onSubmit={onSubmit}
onDismissed={onDismissed} onDismissed={onDismissed}
underlineLinks={this.props.underlineLinks}
accounts={accounts} accounts={accounts}
/> />
) )

View file

@ -22,6 +22,8 @@ interface IPullRequestReviewProps {
/** Map from the emoji shortcut (e.g., :+1:) to the image's local path. */ /** Map from the emoji shortcut (e.g., :+1:) to the image's local path. */
readonly emoji: Map<string, string> readonly emoji: Map<string, string>
readonly underlineLinks: boolean
/** /**
* Whether or not the dialog should offer to switch to the PR's repository or * Whether or not the dialog should offer to switch to the PR's repository or
* to checkout the PR branch when applicable (e.g. non-approved reviews). * to checkout the PR branch when applicable (e.g. non-approved reviews).
@ -85,6 +87,7 @@ export class PullRequestReview extends React.Component<
renderFooterContent={this.renderFooterContent} renderFooterContent={this.renderFooterContent}
onSubmit={onSubmit} onSubmit={onSubmit}
onDismissed={onDismissed} onDismissed={onDismissed}
underlineLinks={this.props.underlineLinks}
accounts={this.props.accounts} accounts={this.props.accounts}
/> />
) )

View file

@ -0,0 +1,13 @@
import { OcticonSymbolVariant } from '.'
/**
* An check mark produced by Gavin that is scaled for 12x12 as opposed to the
* regular 16x16 and is thicker for better visibility.
*/
export const diffCheck: OcticonSymbolVariant = {
w: 12,
h: 12,
p: [
'M10.5303 2.96967C10.8232 3.26256 10.8232 3.73744 10.5303 4.03033L5.03033 9.53033C4.73744 9.82322 4.26256 9.82322 3.96967 9.53033L1.46967 7.03033C1.17678 6.73744 1.17678 6.26256 1.46967 5.96967C1.76256 5.67678 2.23744 5.67678 2.53033 5.96967L4.5 7.93934L9.46967 2.96967C9.76256 2.67678 10.2374 2.67678 10.5303 2.96967Z',
],
}

View file

@ -0,0 +1,62 @@
import * as React from 'react'
import { DialogContent } from '../dialog'
import { Checkbox, CheckboxValue } from '../lib/checkbox'
interface IAccessibilityPreferencesProps {
readonly underlineLinks: boolean
readonly onUnderlineLinksChanged: (value: boolean) => void
}
export class Accessibility extends React.Component<
IAccessibilityPreferencesProps,
{}
> {
public constructor(props: IAccessibilityPreferencesProps) {
super(props)
}
public render() {
return (
<DialogContent>
<div className="advanced-section">
<h2>Accessibility</h2>
<Checkbox
label="Underline links"
value={
this.props.underlineLinks ? CheckboxValue.On : CheckboxValue.Off
}
onChange={this.onUnderlineLinksChanged}
ariaDescribedBy="underline-setting-description"
/>
<p
id="underline-setting-description"
className="git-settings-description"
>
When enabled, GitHub Desktop will underline links in commit
messages, comments, and other text fields. This can help make links
easier to distinguish. {this.renderExampleLink()}
</p>
</div>
</DialogContent>
)
}
private renderExampleLink() {
// The example link is rendered with inline style to override the global setting.
const style = {
textDecoration: this.props.underlineLinks ? 'underline' : 'none',
}
return (
<span className="link-button-component" style={style}>
This is an example link
</span>
)
}
private onUnderlineLinksChanged = (
event: React.FormEvent<HTMLInputElement>
) => {
this.props.onUnderlineLinksChanged(event.currentTarget.checked)
}
}

View file

@ -42,6 +42,8 @@ import {
import { Prompts } from './prompts' import { Prompts } from './prompts'
import { Repository } from '../../models/repository' import { Repository } from '../../models/repository'
import { Notifications } from './notifications' import { Notifications } from './notifications'
import { Accessibility } from './accessibility'
import { enableLinkUnderlines } from '../../lib/feature-flag'
interface IPreferencesProps { interface IPreferencesProps {
readonly dispatcher: Dispatcher readonly dispatcher: Dispatcher
@ -67,6 +69,7 @@ interface IPreferencesProps {
readonly selectedTheme: ApplicationTheme readonly selectedTheme: ApplicationTheme
readonly repositoryIndicatorsEnabled: boolean readonly repositoryIndicatorsEnabled: boolean
readonly onOpenFileInExternalEditor: (path: string) => void readonly onOpenFileInExternalEditor: (path: string) => void
readonly underlineLinks: boolean
} }
interface IPreferencesState { interface IPreferencesState {
@ -94,6 +97,7 @@ interface IPreferencesState {
readonly selectedExternalEditor: string | null readonly selectedExternalEditor: string | null
readonly availableShells: ReadonlyArray<Shell> readonly availableShells: ReadonlyArray<Shell>
readonly selectedShell: Shell readonly selectedShell: Shell
/** /**
* If unable to save Git configuration values (name, email) * If unable to save Git configuration values (name, email)
* due to an existing configuration lock file this property * due to an existing configuration lock file this property
@ -108,6 +112,8 @@ interface IPreferencesState {
readonly isLoadingGitConfig: boolean readonly isLoadingGitConfig: boolean
readonly globalGitConfigPath: string | null readonly globalGitConfigPath: string | null
readonly underlineLinks: boolean
} }
/** The app-level preferences component. */ /** The app-level preferences component. */
@ -147,6 +153,7 @@ export class Preferences extends React.Component<
initiallySelectedTheme: this.props.selectedTheme, initiallySelectedTheme: this.props.selectedTheme,
isLoadingGitConfig: true, isLoadingGitConfig: true,
globalGitConfigPath: null, globalGitConfigPath: null,
underlineLinks: this.props.underlineLinks,
} }
} }
@ -263,6 +270,12 @@ export class Preferences extends React.Component<
<Octicon className="icon" symbol={octicons.gear} /> <Octicon className="icon" symbol={octicons.gear} />
Advanced Advanced
</span> </span>
{enableLinkUnderlines() && (
<span>
<Octicon className="icon" symbol={octicons.accessibility} />
Accessibility
</span>
)}
</TabBar> </TabBar>
{this.renderActiveTab()} {this.renderActiveTab()}
@ -423,6 +436,14 @@ export class Preferences extends React.Component<
) )
break break
} }
case PreferencesTab.Accessibility:
View = (
<Accessibility
underlineLinks={this.state.underlineLinks}
onUnderlineLinksChanged={this.onUnderlineLinksChanged}
/>
)
break
default: default:
return assertNever(index, `Unknown tab index: ${index}`) return assertNever(index, `Unknown tab index: ${index}`)
} }
@ -525,6 +546,10 @@ export class Preferences extends React.Component<
this.props.dispatcher.setSelectedTheme(theme) this.props.dispatcher.setSelectedTheme(theme)
} }
private onUnderlineLinksChanged = (underlineLinks: boolean) => {
this.setState({ underlineLinks })
}
private renderFooter() { private renderFooter() {
const hasDisabledError = this.state.disallowedCharactersMessage != null const hasDisabledError = this.state.disallowedCharactersMessage != null
@ -645,6 +670,8 @@ export class Preferences extends React.Component<
this.state.uncommittedChangesStrategy this.state.uncommittedChangesStrategy
) )
this.props.dispatcher.setUnderlineLinksSetting(this.state.underlineLinks)
this.props.onDismissed() this.props.onDismissed()
} }

View file

@ -34,6 +34,8 @@ interface IPullRequestQuickViewProps {
/** Map from the emoji shortcut (e.g., :+1:) to the image's local path. */ /** Map from the emoji shortcut (e.g., :+1:) to the image's local path. */
readonly emoji: Map<string, string> readonly emoji: Map<string, string>
readonly underlineLinks: boolean
} }
interface IPullRequestQuickViewState { interface IPullRequestQuickViewState {
@ -209,6 +211,7 @@ export class PullRequestQuickView extends React.Component<
markdownContext={'PullRequest'} markdownContext={'PullRequest'}
onMarkdownLinkClicked={this.onMarkdownLinkClicked} onMarkdownLinkClicked={this.onMarkdownLinkClicked}
onMarkdownParsed={this.onMarkdownParsed} onMarkdownParsed={this.onMarkdownParsed}
underlineLinks={this.props.underlineLinks}
/> />
</div> </div>
) )

View file

@ -15,6 +15,7 @@ interface IReleaseNotesProps {
readonly onDismissed: () => void readonly onDismissed: () => void
readonly emoji: Map<string, string> readonly emoji: Map<string, string>
readonly newReleases: ReadonlyArray<ReleaseSummary> readonly newReleases: ReadonlyArray<ReleaseSummary>
readonly underlineLinks: boolean
} }
/** /**
@ -118,6 +119,7 @@ export class ReleaseNotes extends React.Component<IReleaseNotesProps, {}> {
markdown={pretext[0].message} markdown={pretext[0].message}
emoji={this.props.emoji} emoji={this.props.emoji}
onMarkdownLinkClicked={this.onMarkdownLinkClicked} onMarkdownLinkClicked={this.onMarkdownLinkClicked}
underlineLinks={this.props.underlineLinks}
/> />
) )
} }

View file

@ -72,6 +72,8 @@ interface IBranchDropdownProps {
* using the dialog focus management. * using the dialog focus management.
*/ */
readonly enableFocusTrap: boolean readonly enableFocusTrap: boolean
readonly underlineLinks: boolean
} }
/** /**
@ -101,6 +103,7 @@ export class BranchDropdown extends React.Component<IBranchDropdownProps> {
emoji={this.props.emoji} emoji={this.props.emoji}
onDeleteBranch={this.onDeleteBranch} onDeleteBranch={this.onDeleteBranch}
onRenameBranch={this.onRenameBranch} onRenameBranch={this.onRenameBranch}
underlineLinks={this.props.underlineLinks}
/> />
) )
} }

View file

@ -6,3 +6,7 @@
font-size: var(--font-size-sm); font-size: var(--font-size-sm);
color: var(--text-secondary-color); color: var(--text-secondary-color);
} }
.underline-links a {
text-decoration: underline;
}