mirror of
https://github.com/desktop/desktop
synced 2024-07-17 11:08:04 +00:00
Merge branch 'development' into releases/3.1.6
This commit is contained in:
commit
d1a16d80e8
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
@ -15,7 +15,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node: [16.13.0]
|
||||
node: [16.17.1]
|
||||
os: [macos-11, windows-2019]
|
||||
arch: [x64, arm64]
|
||||
include:
|
||||
|
@ -57,6 +57,8 @@ jobs:
|
|||
env:
|
||||
npm_config_arch: ${{ matrix.arch }}
|
||||
TARGET_ARCH: ${{ matrix.arch }}
|
||||
- name: Validate Electron version
|
||||
run: yarn run validate-electron-version
|
||||
- name: Lint
|
||||
run: yarn lint
|
||||
- name: Validate changelog
|
||||
|
|
|
@ -1 +1 @@
|
|||
16.13.0
|
||||
16.17.1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
python 3.9.5
|
||||
nodejs 16.13.0
|
||||
nodejs 16.17.1
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
runtime = electron
|
||||
disturl = https://electronjs.org/headers
|
||||
target = 19.0.0
|
||||
target = 22.0.0
|
||||
|
|
|
@ -327,6 +327,7 @@ export enum FoldoutType {
|
|||
Branch,
|
||||
AppMenu,
|
||||
AddMenu,
|
||||
PushPull,
|
||||
}
|
||||
|
||||
export type AppMenuFoldout = {
|
||||
|
@ -358,6 +359,7 @@ export type Foldout =
|
|||
| { type: FoldoutType.AddMenu }
|
||||
| BranchFoldout
|
||||
| AppMenuFoldout
|
||||
| { type: FoldoutType.PushPull }
|
||||
|
||||
export enum RepositorySectionTab {
|
||||
Changes,
|
||||
|
|
|
@ -91,6 +91,10 @@ const editors: IDarwinExternalEditor[] = [
|
|||
name: 'WebStorm',
|
||||
bundleIdentifiers: ['com.jetbrains.WebStorm'],
|
||||
},
|
||||
{
|
||||
name: 'CLion',
|
||||
bundleIdentifiers: ['com.jetbrains.CLion'],
|
||||
},
|
||||
{
|
||||
name: 'Typora',
|
||||
bundleIdentifiers: ['abnerworks.Typora'],
|
||||
|
|
|
@ -23,9 +23,26 @@ const editors: ILinuxExternalEditor[] = [
|
|||
name: 'Neovim',
|
||||
paths: ['/usr/bin/nvim'],
|
||||
},
|
||||
{
|
||||
name: 'Neovim-Qt',
|
||||
paths: ['/usr/bin/nvim-qt'],
|
||||
},
|
||||
{
|
||||
name: 'Neovide',
|
||||
paths: ['/usr/bin/neovide'],
|
||||
},
|
||||
{
|
||||
name: 'gVim',
|
||||
paths: ['/usr/bin/gvim'],
|
||||
},
|
||||
{
|
||||
name: 'Visual Studio Code',
|
||||
paths: ['/usr/share/code/bin/code', '/snap/bin/code', '/usr/bin/code'],
|
||||
paths: [
|
||||
'/usr/share/code/bin/code',
|
||||
'/snap/bin/code',
|
||||
'/usr/bin/code',
|
||||
'/mnt/c/Program Files/Microsoft VS Code/bin/code',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Visual Studio Code (Insiders)',
|
||||
|
@ -33,7 +50,11 @@ const editors: ILinuxExternalEditor[] = [
|
|||
},
|
||||
{
|
||||
name: 'VSCodium',
|
||||
paths: ['/usr/bin/codium', '/var/lib/flatpak/app/com.vscodium.codium'],
|
||||
paths: [
|
||||
'/usr/bin/codium',
|
||||
'/var/lib/flatpak/app/com.vscodium.codium',
|
||||
'/usr/share/vscodium-bin/bin/codium',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Sublime Text',
|
||||
|
@ -74,6 +95,34 @@ const editors: ILinuxExternalEditor[] = [
|
|||
name: 'Emacs',
|
||||
paths: ['/snap/bin/emacs', '/usr/local/bin/emacs', '/usr/bin/emacs'],
|
||||
},
|
||||
{
|
||||
name: 'Kate',
|
||||
paths: ['/usr/bin/kate'],
|
||||
},
|
||||
{
|
||||
name: 'GEdit',
|
||||
paths: ['/usr/bin/gedit'],
|
||||
},
|
||||
{
|
||||
name: 'GNOME Text Editor',
|
||||
paths: ['/usr/bin/gnome-text-editor'],
|
||||
},
|
||||
{
|
||||
name: 'GNOME Builder',
|
||||
paths: ['/usr/bin/gnome-builder'],
|
||||
},
|
||||
{
|
||||
name: 'Notepadqq',
|
||||
paths: ['/usr/bin/notepadqq'],
|
||||
},
|
||||
{
|
||||
name: 'Geany',
|
||||
paths: ['/usr/bin/geany'],
|
||||
},
|
||||
{
|
||||
name: 'Mousepad',
|
||||
paths: ['/usr/bin/mousepad'],
|
||||
},
|
||||
]
|
||||
|
||||
async function getAvailablePath(paths: string[]): Promise<string | null> {
|
||||
|
|
|
@ -59,7 +59,7 @@ type WindowsExternalEditor = {
|
|||
readonly displayNamePrefix: string
|
||||
|
||||
/** Value of the Publisher registry key that belongs to this editor. */
|
||||
readonly publisher: string
|
||||
readonly publishers: string[]
|
||||
|
||||
/**
|
||||
* Default shell script name for JetBrains Product
|
||||
|
@ -150,21 +150,21 @@ const editors: WindowsExternalEditor[] = [
|
|||
registryKeys: [CurrentUserUninstallKey('atom')],
|
||||
executableShimPaths: [['bin', 'atom.cmd']],
|
||||
displayNamePrefix: 'Atom',
|
||||
publisher: 'GitHub Inc.',
|
||||
publishers: ['GitHub Inc.'],
|
||||
},
|
||||
{
|
||||
name: 'Atom Beta',
|
||||
registryKeys: [CurrentUserUninstallKey('atom-beta')],
|
||||
executableShimPaths: [['bin', 'atom-beta.cmd']],
|
||||
displayNamePrefix: 'Atom Beta',
|
||||
publisher: 'GitHub Inc.',
|
||||
publishers: ['GitHub Inc.'],
|
||||
},
|
||||
{
|
||||
name: 'Atom Nightly',
|
||||
registryKeys: [CurrentUserUninstallKey('atom-nightly')],
|
||||
executableShimPaths: [['bin', 'atom-nightly.cmd']],
|
||||
displayNamePrefix: 'Atom Nightly',
|
||||
publisher: 'GitHub Inc.',
|
||||
publishers: ['GitHub Inc.'],
|
||||
},
|
||||
{
|
||||
name: 'Visual Studio Code',
|
||||
|
@ -186,7 +186,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
],
|
||||
executableShimPaths: [['bin', 'code.cmd']],
|
||||
displayNamePrefix: 'Microsoft Visual Studio Code',
|
||||
publisher: 'Microsoft Corporation',
|
||||
publishers: ['Microsoft Corporation'],
|
||||
},
|
||||
{
|
||||
name: 'Visual Studio Code (Insiders)',
|
||||
|
@ -208,29 +208,63 @@ const editors: WindowsExternalEditor[] = [
|
|||
],
|
||||
executableShimPaths: [['bin', 'code-insiders.cmd']],
|
||||
displayNamePrefix: 'Microsoft Visual Studio Code Insiders',
|
||||
publisher: 'Microsoft Corporation',
|
||||
publishers: ['Microsoft Corporation'],
|
||||
},
|
||||
{
|
||||
name: 'Visual Studio Codium',
|
||||
registryKeys: [
|
||||
// 64-bit version of VSCodium (user)
|
||||
CurrentUserUninstallKey('{2E1F05D1-C245-4562-81EE-28188DB6FD17}_is1'),
|
||||
// 32-bit version of VSCodium (user)
|
||||
// 32-bit version of VSCodium (user) - new key
|
||||
CurrentUserUninstallKey('{0FD05EB4-651E-4E78-A062-515204B47A3A}_is1'),
|
||||
// ARM64 version of VSCodium (user) - new key
|
||||
CurrentUserUninstallKey('{57FD70A5-1B8D-4875-9F40-C5553F094828}_is1'),
|
||||
// 64-bit version of VSCodium (system) - new key
|
||||
LocalMachineUninstallKey('{88DA3577-054F-4CA1-8122-7D820494CFFB}_is1'),
|
||||
// 32-bit version of VSCodium (system) - new key
|
||||
Wow64LocalMachineUninstallKey(
|
||||
'{763CBF88-25C6-4B10-952F-326AE657F16B}_is1'
|
||||
),
|
||||
// ARM64 version of VSCodium (system) - new key
|
||||
LocalMachineUninstallKey('{67DEE444-3D04-4258-B92A-BC1F0FF2CAE4}_is1'),
|
||||
// 32-bit version of VSCodium (user) - old key
|
||||
CurrentUserUninstallKey('{C6065F05-9603-4FC4-8101-B9781A25D88E}}_is1'),
|
||||
// ARM64 version of VSCodium (user)
|
||||
// ARM64 version of VSCodium (user) - old key
|
||||
CurrentUserUninstallKey('{3AEBF0C8-F733-4AD4-BADE-FDB816D53D7B}_is1'),
|
||||
// 64-bit version of VSCodium (system)
|
||||
// 64-bit version of VSCodium (system) - old key
|
||||
LocalMachineUninstallKey('{D77B7E06-80BA-4137-BCF4-654B95CCEBC5}_is1'),
|
||||
// 32-bit version of VSCodium (system)
|
||||
// 32-bit version of VSCodium (system) - old key
|
||||
Wow64LocalMachineUninstallKey(
|
||||
'{E34003BB-9E10-4501-8C11-BE3FAA83F23F}_is1'
|
||||
),
|
||||
// ARM64 version of VSCodium (system)
|
||||
// ARM64 version of VSCodium (system) - old key
|
||||
LocalMachineUninstallKey('{D1ACE434-89C5-48D1-88D3-E2991DF85475}_is1'),
|
||||
],
|
||||
executableShimPaths: [['bin', 'codium.cmd']],
|
||||
displayNamePrefix: 'VSCodium',
|
||||
publisher: 'Microsoft Corporation',
|
||||
publishers: ['VSCodium', 'Microsoft Corporation'],
|
||||
},
|
||||
{
|
||||
name: 'Visual Studio Codium (Insiders)',
|
||||
registryKeys: [
|
||||
// 64-bit version of VSCodium - Insiders (user)
|
||||
CurrentUserUninstallKey('{20F79D0D-A9AC-4220-9A81-CE675FFB6B41}_is1'),
|
||||
// 32-bit version of VSCodium - Insiders (user)
|
||||
CurrentUserUninstallKey('{ED2E5618-3E7E-4888-BF3C-A6CCC84F586F}_is1'),
|
||||
// ARM64 version of VSCodium - Insiders (user)
|
||||
CurrentUserUninstallKey('{2E362F92-14EA-455A-9ABD-3E656BBBFE71}_is1'),
|
||||
// 64-bit version of VSCodium - Insiders (system)
|
||||
LocalMachineUninstallKey('{B2E0DDB2-120E-4D34-9F7E-8C688FF839A2}_is1'),
|
||||
// 32-bit version of VSCodium - Insiders (system)
|
||||
Wow64LocalMachineUninstallKey(
|
||||
'{EF35BB36-FA7E-4BB9-B7DA-D1E09F2DA9C9}_is1'
|
||||
),
|
||||
// ARM64 version of VSCodium - Insiders (system)
|
||||
LocalMachineUninstallKey('{44721278-64C6-4513-BC45-D48E07830599}_is1'),
|
||||
],
|
||||
executableShimPaths: [['bin', 'codium-insiders.cmd']],
|
||||
displayNamePrefix: 'VSCodium (Insiders)',
|
||||
publishers: ['VSCodium'],
|
||||
},
|
||||
{
|
||||
name: 'Sublime Text',
|
||||
|
@ -242,7 +276,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
],
|
||||
executableShimPaths: [['subl.exe']],
|
||||
displayNamePrefix: 'Sublime Text',
|
||||
publisher: 'Sublime HQ Pty Ltd',
|
||||
publishers: ['Sublime HQ Pty Ltd'],
|
||||
},
|
||||
{
|
||||
name: 'Brackets',
|
||||
|
@ -251,7 +285,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
],
|
||||
executableShimPaths: [['Brackets.exe']],
|
||||
displayNamePrefix: 'Brackets',
|
||||
publisher: 'brackets.io',
|
||||
publishers: ['brackets.io'],
|
||||
},
|
||||
{
|
||||
name: 'ColdFusion Builder',
|
||||
|
@ -263,7 +297,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
],
|
||||
executableShimPaths: [['CFBuilder.exe']],
|
||||
displayNamePrefix: 'Adobe ColdFusion Builder',
|
||||
publisher: 'Adobe Systems Incorporated',
|
||||
publishers: ['Adobe Systems Incorporated'],
|
||||
},
|
||||
{
|
||||
name: 'Typora',
|
||||
|
@ -277,7 +311,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
],
|
||||
executableShimPaths: [['typora.exe']],
|
||||
displayNamePrefix: 'Typora',
|
||||
publisher: 'typora.io',
|
||||
publishers: ['typora.io'],
|
||||
},
|
||||
{
|
||||
name: 'SlickEdit',
|
||||
|
@ -307,7 +341,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
],
|
||||
executableShimPaths: [['win', 'vs.exe']],
|
||||
displayNamePrefix: 'SlickEdit',
|
||||
publisher: 'SlickEdit Inc.',
|
||||
publishers: ['SlickEdit Inc.'],
|
||||
},
|
||||
{
|
||||
name: 'Aptana Studio 3',
|
||||
|
@ -316,7 +350,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
],
|
||||
executableShimPaths: [['AptanaStudio3.exe']],
|
||||
displayNamePrefix: 'Aptana Studio',
|
||||
publisher: 'Appcelerator',
|
||||
publishers: ['Appcelerator'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains Webstorm',
|
||||
|
@ -324,7 +358,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
executableShimPaths: executableShimPathsForJetBrainsIDE('webstorm'),
|
||||
jetBrainsToolboxScriptName: 'webstorm',
|
||||
displayNamePrefix: 'WebStorm',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains Phpstorm',
|
||||
|
@ -332,7 +366,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
executableShimPaths: executableShimPathsForJetBrainsIDE('phpstorm'),
|
||||
jetBrainsToolboxScriptName: 'phpstorm',
|
||||
displayNamePrefix: 'PhpStorm',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
{
|
||||
name: 'Android Studio',
|
||||
|
@ -344,7 +378,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
['..', 'bin', `studio.exe`],
|
||||
],
|
||||
displayNamePrefix: 'Android Studio',
|
||||
publisher: 'Google LLC',
|
||||
publishers: ['Google LLC'],
|
||||
},
|
||||
{
|
||||
name: 'Notepad++',
|
||||
|
@ -356,7 +390,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
],
|
||||
installLocationRegistryKey: 'DisplayIcon',
|
||||
displayNamePrefix: 'Notepad++',
|
||||
publisher: 'Notepad++ Team',
|
||||
publishers: ['Notepad++ Team'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains Rider',
|
||||
|
@ -364,14 +398,14 @@ const editors: WindowsExternalEditor[] = [
|
|||
executableShimPaths: executableShimPathsForJetBrainsIDE('rider'),
|
||||
jetBrainsToolboxScriptName: 'rider',
|
||||
displayNamePrefix: 'JetBrains Rider',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
{
|
||||
name: 'RStudio',
|
||||
registryKeys: [Wow64LocalMachineUninstallKey('RStudio')],
|
||||
installLocationRegistryKey: 'DisplayIcon',
|
||||
displayNamePrefix: 'RStudio',
|
||||
publisher: 'RStudio',
|
||||
publishers: ['RStudio', 'Posit Software'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains IntelliJ Idea',
|
||||
|
@ -379,7 +413,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
executableShimPaths: executableShimPathsForJetBrainsIDE('idea'),
|
||||
jetBrainsToolboxScriptName: 'idea',
|
||||
displayNamePrefix: 'IntelliJ IDEA ',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains IntelliJ Idea Community Edition',
|
||||
|
@ -388,7 +422,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
),
|
||||
executableShimPaths: executableShimPathsForJetBrainsIDE('idea'),
|
||||
displayNamePrefix: 'IntelliJ IDEA Community Edition ',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains PyCharm',
|
||||
|
@ -396,14 +430,14 @@ const editors: WindowsExternalEditor[] = [
|
|||
executableShimPaths: executableShimPathsForJetBrainsIDE('pycharm'),
|
||||
jetBrainsToolboxScriptName: 'pycharm',
|
||||
displayNamePrefix: 'PyCharm ',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains PyCharm Community Edition',
|
||||
registryKeys: registryKeysForJetBrainsIDE('PyCharm Community Edition'),
|
||||
executableShimPaths: executableShimPathsForJetBrainsIDE('pycharm'),
|
||||
displayNamePrefix: 'PyCharm Community Edition',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains CLion',
|
||||
|
@ -411,7 +445,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
executableShimPaths: executableShimPathsForJetBrainsIDE('clion'),
|
||||
jetBrainsToolboxScriptName: 'clion',
|
||||
displayNamePrefix: 'CLion ',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains RubyMine',
|
||||
|
@ -419,7 +453,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
executableShimPaths: executableShimPathsForJetBrainsIDE('rubymine'),
|
||||
jetBrainsToolboxScriptName: 'rubymine',
|
||||
displayNamePrefix: 'RubyMine ',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains GoLand',
|
||||
|
@ -427,7 +461,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
executableShimPaths: executableShimPathsForJetBrainsIDE('goland'),
|
||||
jetBrainsToolboxScriptName: 'goland',
|
||||
displayNamePrefix: 'GoLand ',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
{
|
||||
name: 'JetBrains Fleet',
|
||||
|
@ -435,7 +469,7 @@ const editors: WindowsExternalEditor[] = [
|
|||
jetBrainsToolboxScriptName: 'fleet',
|
||||
installLocationRegistryKey: 'DisplayIcon',
|
||||
displayNamePrefix: 'Fleet ',
|
||||
publisher: 'JetBrains s.r.o.',
|
||||
publishers: ['JetBrains s.r.o.'],
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -471,7 +505,7 @@ async function findApplication(editor: WindowsExternalEditor) {
|
|||
|
||||
if (
|
||||
!displayName.startsWith(editor.displayNamePrefix) ||
|
||||
publisher !== editor.publisher
|
||||
!editor.publishers.includes(publisher)
|
||||
) {
|
||||
log.debug(`Unexpected registry entries for ${editor.name}`)
|
||||
continue
|
||||
|
|
|
@ -122,3 +122,8 @@ export function enableStackedPopups(): boolean {
|
|||
export function enablePreventClosingWhileUpdating(): boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
/** Should we enable the new push-pull-fetch dropdown? */
|
||||
export function enablePushPullFetchDropdown(): boolean {
|
||||
return enableBetaFeatures()
|
||||
}
|
||||
|
|
|
@ -689,11 +689,11 @@ app.on('activate', () => {
|
|||
})
|
||||
|
||||
app.on('web-contents-created', (event, contents) => {
|
||||
contents.on('new-window', (event, url) => {
|
||||
// Prevent links or window.open from opening new windows
|
||||
event.preventDefault()
|
||||
contents.setWindowOpenHandler(({ url }) => {
|
||||
log.warn(`Prevented new window to: ${url}`)
|
||||
return { action: 'deny' }
|
||||
})
|
||||
|
||||
// prevent link navigation within our windows
|
||||
// see https://www.electronjs.org/docs/tutorial/security#12-disable-or-limit-navigation
|
||||
contents.on('will-navigate', (event, url) => {
|
||||
|
@ -729,7 +729,13 @@ function createWindow() {
|
|||
electron: '>=1.2.1',
|
||||
}
|
||||
|
||||
const extensions = [REACT_DEVELOPER_TOOLS, ChromeLens]
|
||||
const axeDevTools = {
|
||||
id: 'lhdoppojpmngadmnindnejefpokejbdd',
|
||||
electron: '>=1.2.1',
|
||||
Permissions: ['tabs', 'debugger'],
|
||||
}
|
||||
|
||||
const extensions = [REACT_DEVELOPER_TOOLS, ChromeLens, axeDevTools]
|
||||
|
||||
for (const extension of extensions) {
|
||||
try {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {
|
||||
WebRequest,
|
||||
OnBeforeRequestListenerDetails,
|
||||
Response,
|
||||
CallbackResponse,
|
||||
OnBeforeSendHeadersListenerDetails,
|
||||
BeforeSendResponse,
|
||||
OnCompletedListenerDetails,
|
||||
|
@ -112,7 +112,7 @@ export class OrderedWebRequest {
|
|||
|
||||
public readonly onBeforeRequest: AsyncListenerSet<
|
||||
OnBeforeRequestListenerDetails,
|
||||
Response
|
||||
CallbackResponse
|
||||
>
|
||||
|
||||
public readonly onBeforeSendHeaders: AsyncListenerSet<
|
||||
|
@ -140,7 +140,7 @@ export class OrderedWebRequest {
|
|||
this.onBeforeRequest = new AsyncListenerSet(
|
||||
webRequest.onBeforeRequest.bind(webRequest),
|
||||
async (listeners, details) => {
|
||||
let response: Response = {}
|
||||
let response: CallbackResponse = {}
|
||||
|
||||
for (const listener of listeners) {
|
||||
response = await listener(details)
|
||||
|
|
|
@ -93,10 +93,7 @@ import { RepositoryStateCache } from '../lib/stores/repository-state-cache'
|
|||
import { PopupType, Popup } from '../models/popup'
|
||||
import { OversizedFiles } from './changes/oversized-files-warning'
|
||||
import { PushNeedsPullWarning } from './push-needs-pull'
|
||||
import {
|
||||
ForcePushBranchState,
|
||||
getCurrentBranchForcePushState,
|
||||
} from '../lib/rebase'
|
||||
import { getCurrentBranchForcePushState } from '../lib/rebase'
|
||||
import { Banner, BannerType } from '../models/banner'
|
||||
import { StashAndSwitchBranch } from './stash-changes/stash-and-switch-branch-dialog'
|
||||
import { OverwriteStash } from './stash-changes/overwrite-stashed-changes-dialog'
|
||||
|
@ -2800,9 +2797,15 @@ export class App extends React.Component<IAppProps, IAppState> {
|
|||
remoteName = tip.branch.upstreamRemoteName
|
||||
}
|
||||
|
||||
const isForcePush =
|
||||
getCurrentBranchForcePushState(branchesState, aheadBehind) ===
|
||||
ForcePushBranchState.Recommended
|
||||
const currentFoldout = this.state.currentFoldout
|
||||
|
||||
const isDropdownOpen =
|
||||
currentFoldout !== null && currentFoldout.type === FoldoutType.PushPull
|
||||
|
||||
const forcePushBranchState = getCurrentBranchForcePushState(
|
||||
branchesState,
|
||||
aheadBehind
|
||||
)
|
||||
|
||||
return (
|
||||
<PushPullButton
|
||||
|
@ -2817,10 +2820,13 @@ export class App extends React.Component<IAppProps, IAppState> {
|
|||
tipState={tip.kind}
|
||||
pullWithRebase={pullWithRebase}
|
||||
rebaseInProgress={rebaseInProgress}
|
||||
isForcePush={isForcePush}
|
||||
forcePushBranchState={forcePushBranchState}
|
||||
shouldNudge={
|
||||
this.state.currentOnboardingTutorialStep === TutorialStep.PushBranch
|
||||
}
|
||||
isDropdownOpen={isDropdownOpen}
|
||||
askForConfirmationOnForcePush={this.state.askForConfirmationOnForcePush}
|
||||
onDropdownStateChanged={this.onPushPullDropdownStateChanged}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -2884,6 +2890,14 @@ export class App extends React.Component<IAppProps, IAppState> {
|
|||
this.props.dispatcher.openCreatePullRequestInBrowser(repository, branch)
|
||||
}
|
||||
|
||||
private onPushPullDropdownStateChanged = (newState: DropdownState) => {
|
||||
if (newState === 'open') {
|
||||
this.props.dispatcher.showFoldout({ type: FoldoutType.PushPull })
|
||||
} else {
|
||||
this.props.dispatcher.closeFoldout(FoldoutType.PushPull)
|
||||
}
|
||||
}
|
||||
|
||||
private onBranchDropdownStateChanged = (newState: DropdownState) => {
|
||||
if (newState === 'open') {
|
||||
this.props.dispatcher.showFoldout({ type: FoldoutType.Branch })
|
||||
|
|
|
@ -536,6 +536,7 @@ export class CommitSummary extends React.Component<
|
|||
let filesAdded = 0
|
||||
let filesModified = 0
|
||||
let filesRemoved = 0
|
||||
let filesRenamed = 0
|
||||
for (const file of this.props.changesetData.files) {
|
||||
switch (file.status.kind) {
|
||||
case AppFileStatusKind.New:
|
||||
|
@ -547,9 +548,14 @@ export class CommitSummary extends React.Component<
|
|||
case AppFileStatusKind.Deleted:
|
||||
filesRemoved += 1
|
||||
break
|
||||
case AppFileStatusKind.Renamed:
|
||||
filesRenamed += 1
|
||||
}
|
||||
}
|
||||
|
||||
const hasFileDescription =
|
||||
filesAdded + filesModified + filesRemoved + filesRenamed > 0
|
||||
|
||||
const filesLongDescription = (
|
||||
<>
|
||||
{filesAdded > 0 ? (
|
||||
|
@ -579,6 +585,15 @@ export class CommitSummary extends React.Component<
|
|||
{filesRemoved} deleted
|
||||
</span>
|
||||
) : null}
|
||||
{filesRenamed > 0 ? (
|
||||
<span>
|
||||
<Octicon
|
||||
className="files-renamed-icon"
|
||||
symbol={OcticonSymbol.diffRenamed}
|
||||
/>
|
||||
{filesRenamed} renamed
|
||||
</span>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
|
||||
|
@ -586,7 +601,9 @@ export class CommitSummary extends React.Component<
|
|||
<TooltippedContent
|
||||
className="commit-summary-meta-item without-truncation"
|
||||
tooltipClassName="changed-files-description-tooltip"
|
||||
tooltip={fileCount > 0 ? filesLongDescription : undefined}
|
||||
tooltip={
|
||||
fileCount > 0 && hasFileDescription ? filesLongDescription : undefined
|
||||
}
|
||||
>
|
||||
<Octicon symbol={OcticonSymbol.diff} />
|
||||
{filesShortDescription}
|
||||
|
|
|
@ -8,7 +8,6 @@ export type PathType =
|
|||
| 'home'
|
||||
| 'appData'
|
||||
| 'userData'
|
||||
| 'cache'
|
||||
| 'temp'
|
||||
| 'exe'
|
||||
| 'module'
|
||||
|
@ -21,6 +20,7 @@ export type PathType =
|
|||
| 'recent'
|
||||
| 'logs'
|
||||
| 'crashDumps'
|
||||
| 'sessionData'
|
||||
|
||||
/**
|
||||
* Get the version of the app.
|
||||
|
|
|
@ -288,12 +288,14 @@ export class RepositorySettings extends React.Component<
|
|||
const errors = new Array<JSX.Element | string>()
|
||||
|
||||
if (this.state.remote && this.props.remote) {
|
||||
if (this.state.remote.url !== this.props.remote.url) {
|
||||
const trimmedUrl = this.state.remote.url.trim()
|
||||
|
||||
if (trimmedUrl !== this.props.remote.url) {
|
||||
try {
|
||||
await this.props.dispatcher.setRemoteURL(
|
||||
this.props.repository,
|
||||
this.props.remote.name,
|
||||
this.state.remote.url
|
||||
trimmedUrl
|
||||
)
|
||||
} catch (e) {
|
||||
log.error(
|
||||
|
|
|
@ -183,7 +183,7 @@ export class BranchDropdown extends React.Component<
|
|||
|
||||
const isOpen = this.props.isOpen
|
||||
const currentState: DropdownState = isOpen && canOpen ? 'open' : 'closed'
|
||||
const buttonClassName = classNames('nudge-arrow', {
|
||||
const buttonClassName = classNames('branch-toolbar-button', 'nudge-arrow', {
|
||||
'nudge-arrow-up': this.props.shouldNudge,
|
||||
})
|
||||
|
||||
|
|
|
@ -13,7 +13,26 @@ import { TooltipTarget } from '../lib/tooltip'
|
|||
|
||||
export type DropdownState = 'open' | 'closed'
|
||||
|
||||
/** Represents the style of the dropdown */
|
||||
export enum ToolbarDropdownStyle {
|
||||
/**
|
||||
* The dropdown is rendered as a single button and, when expanded, takes the
|
||||
* full height of the window.
|
||||
*/
|
||||
Foldout,
|
||||
|
||||
/**
|
||||
* The dropdown is rendered as two buttons: one is the toolbar button itself,
|
||||
* and the other one is the expand/collapse button.
|
||||
* When expanded, it only takes the height of the content.
|
||||
*/
|
||||
MultiOption,
|
||||
}
|
||||
|
||||
export interface IToolbarDropdownProps {
|
||||
/** The style of the dropdown. Default: Foldout */
|
||||
readonly dropdownStyle?: ToolbarDropdownStyle
|
||||
|
||||
/** The primary button text, describing its function */
|
||||
readonly title?: string
|
||||
|
||||
|
@ -74,6 +93,8 @@ export interface IToolbarDropdownProps {
|
|||
*/
|
||||
readonly onContextMenu?: (event: React.MouseEvent<HTMLButtonElement>) => void
|
||||
|
||||
readonly onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void
|
||||
|
||||
/**
|
||||
* A function that's called whenever something is dragged over the
|
||||
* dropdown.
|
||||
|
@ -185,7 +206,8 @@ export class ToolbarDropdown extends React.Component<
|
|||
IToolbarDropdownProps,
|
||||
IToolbarDropdownState
|
||||
> {
|
||||
private innerButton: ToolbarButton | null = null
|
||||
private innerButton = React.createRef<ToolbarButton>()
|
||||
private rootDiv = React.createRef<HTMLDivElement>()
|
||||
private focusTrapOptions: FocusTrapOptions
|
||||
|
||||
public constructor(props: IToolbarDropdownProps) {
|
||||
|
@ -224,13 +246,25 @@ export class ToolbarDropdown extends React.Component<
|
|||
}
|
||||
|
||||
const state = this.props.dropdownState
|
||||
|
||||
return (
|
||||
const dropdownIcon = (
|
||||
<Octicon symbol={this.dropdownIcon(state)} className="dropdownArrow" />
|
||||
)
|
||||
|
||||
return this.props.dropdownStyle === ToolbarDropdownStyle.MultiOption ? (
|
||||
<ToolbarButton
|
||||
className="toolbar-dropdown-arrow-button"
|
||||
onClick={this.onToggleDropdownClick}
|
||||
>
|
||||
{dropdownIcon}
|
||||
</ToolbarButton>
|
||||
) : (
|
||||
dropdownIcon
|
||||
)
|
||||
}
|
||||
|
||||
private onClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
private onToggleDropdownClick = (
|
||||
event: React.MouseEvent<HTMLButtonElement>
|
||||
) => {
|
||||
const newState: DropdownState =
|
||||
this.props.dropdownState === 'open' ? 'closed' : 'open'
|
||||
|
||||
|
@ -247,13 +281,22 @@ export class ToolbarDropdown extends React.Component<
|
|||
this.props.onDropdownStateChanged(newState, source)
|
||||
}
|
||||
|
||||
private onMainButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
if (this.props.dropdownStyle === ToolbarDropdownStyle.MultiOption) {
|
||||
this.props.onClick?.(event)
|
||||
return
|
||||
}
|
||||
|
||||
this.onToggleDropdownClick(event)
|
||||
}
|
||||
|
||||
private onContextMenu = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
this.props.onContextMenu?.(event)
|
||||
}
|
||||
|
||||
private updateClientRectIfNecessary() {
|
||||
if (this.props.dropdownState === 'open' && this.innerButton) {
|
||||
const newRect = this.innerButton.getButtonBoundingClientRect()
|
||||
if (this.props.dropdownState === 'open' && this.rootDiv.current) {
|
||||
const newRect = this.rootDiv.current.getBoundingClientRect()
|
||||
if (newRect) {
|
||||
const currentRect = this.state.clientRect
|
||||
|
||||
|
@ -268,10 +311,6 @@ export class ToolbarDropdown extends React.Component<
|
|||
this.updateClientRectIfNecessary()
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.innerButton = null
|
||||
}
|
||||
|
||||
public componentDidUpdate() {
|
||||
this.updateClientRectIfNecessary()
|
||||
}
|
||||
|
@ -305,12 +344,16 @@ export class ToolbarDropdown extends React.Component<
|
|||
return undefined
|
||||
}
|
||||
|
||||
const heightStyle: React.CSSProperties =
|
||||
this.props.dropdownStyle === ToolbarDropdownStyle.MultiOption
|
||||
? { maxHeight: '100%', width: rect.width }
|
||||
: { height: '100%', minWidth: rect.width }
|
||||
|
||||
return {
|
||||
position: 'absolute',
|
||||
marginLeft: rect.left,
|
||||
minWidth: rect.width,
|
||||
height: '100%',
|
||||
top: 0,
|
||||
...heightStyle,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,22 +397,21 @@ export class ToolbarDropdown extends React.Component<
|
|||
)
|
||||
}
|
||||
|
||||
private onRef = (ref: ToolbarButton | null) => {
|
||||
this.innerButton = ref
|
||||
}
|
||||
|
||||
/**
|
||||
* Programmatically move keyboard focus to the button element.
|
||||
*/
|
||||
public focusButton = () => {
|
||||
if (this.innerButton) {
|
||||
this.innerButton.focusButton()
|
||||
if (this.innerButton.current) {
|
||||
this.innerButton.current.focusButton()
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const className = classNames(
|
||||
'toolbar-dropdown',
|
||||
this.props.dropdownStyle === ToolbarDropdownStyle.MultiOption
|
||||
? 'multi-option-style'
|
||||
: 'foldout-style',
|
||||
this.props.dropdownState,
|
||||
this.props.className
|
||||
)
|
||||
|
@ -383,16 +425,17 @@ export class ToolbarDropdown extends React.Component<
|
|||
role={this.props.role}
|
||||
aria-expanded={ariaExpanded}
|
||||
onDragOver={this.props.onDragOver}
|
||||
ref={this.rootDiv}
|
||||
>
|
||||
{this.renderDropdownContents()}
|
||||
<ToolbarButton
|
||||
className={this.props.buttonClassName}
|
||||
ref={this.onRef}
|
||||
ref={this.innerButton}
|
||||
icon={this.props.icon}
|
||||
title={this.props.title}
|
||||
description={this.props.description}
|
||||
tooltip={this.props.tooltip}
|
||||
onClick={this.onClick}
|
||||
onClick={this.onMainButtonClick}
|
||||
onContextMenu={this.onContextMenu}
|
||||
onMouseEnter={this.props.onMouseEnter}
|
||||
style={this.props.style}
|
||||
|
@ -407,8 +450,11 @@ export class ToolbarDropdown extends React.Component<
|
|||
isOverflowed={this.props.isOverflowed}
|
||||
>
|
||||
{this.props.children}
|
||||
{this.renderDropdownArrow()}
|
||||
{this.props.dropdownStyle !== ToolbarDropdownStyle.MultiOption &&
|
||||
this.renderDropdownArrow()}
|
||||
</ToolbarButton>
|
||||
{this.props.dropdownStyle === ToolbarDropdownStyle.MultiOption &&
|
||||
this.renderDropdownArrow()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
133
app/src/ui/toolbar/push-pull-button-dropdown.tsx
Normal file
133
app/src/ui/toolbar/push-pull-button-dropdown.tsx
Normal file
|
@ -0,0 +1,133 @@
|
|||
import React from 'react'
|
||||
import { Button } from '../lib/button'
|
||||
import { Octicon, syncClockwise } from '../octicons'
|
||||
import {
|
||||
DropdownItem,
|
||||
DropdownItemClassName,
|
||||
DropdownItemType,
|
||||
forcePushIcon,
|
||||
} from './push-pull-button'
|
||||
|
||||
interface IPushPullButtonDropDownProps {
|
||||
readonly itemTypes: ReadonlyArray<DropdownItemType>
|
||||
/** The name of the remote. */
|
||||
readonly remoteName: string | null
|
||||
|
||||
/** Will the app prompt the user to confirm a force push? */
|
||||
readonly askForConfirmationOnForcePush: boolean
|
||||
|
||||
readonly fetch: () => void
|
||||
readonly forcePushWithLease: () => void
|
||||
}
|
||||
|
||||
export class PushPullButtonDropDown extends React.Component<IPushPullButtonDropDownProps> {
|
||||
private buttonsContainerRef: HTMLDivElement | null = null
|
||||
|
||||
public componentDidMount() {
|
||||
window.addEventListener('keydown', this.onDropdownKeyDown)
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
window.removeEventListener('keydown', this.onDropdownKeyDown)
|
||||
}
|
||||
|
||||
private onButtonsContainerRef = (ref: HTMLDivElement | null) => {
|
||||
this.buttonsContainerRef = ref
|
||||
}
|
||||
|
||||
private onDropdownKeyDown = (event: KeyboardEvent) => {
|
||||
// Allow using Up and Down arrow keys to navigate the dropdown items
|
||||
// (equivalent to Tab and Shift+Tab)
|
||||
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
|
||||
return
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
const items = this.buttonsContainerRef?.querySelectorAll<HTMLElement>(
|
||||
`.${DropdownItemClassName}`
|
||||
)
|
||||
|
||||
if (items === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const focusedItem =
|
||||
this.buttonsContainerRef?.querySelector<HTMLElement>(':focus')
|
||||
if (!focusedItem) {
|
||||
return
|
||||
}
|
||||
|
||||
const focusedIndex = Array.from(items).indexOf(focusedItem)
|
||||
const nextIndex =
|
||||
event.key === 'ArrowDown' ? focusedIndex + 1 : focusedIndex - 1
|
||||
// http://javascript.about.com/od/problemsolving/a/modulobug.htm
|
||||
const nextItem = items[(nextIndex + items.length) % items.length]
|
||||
nextItem?.focus()
|
||||
}
|
||||
|
||||
private getDropdownItemWithType(type: DropdownItemType): DropdownItem {
|
||||
const { remoteName } = this.props
|
||||
|
||||
switch (type) {
|
||||
case DropdownItemType.Fetch:
|
||||
return {
|
||||
title: `Fetch ${remoteName}`,
|
||||
description: `Fetch the latest changes from ${remoteName}`,
|
||||
action: this.props.fetch,
|
||||
icon: syncClockwise,
|
||||
}
|
||||
case DropdownItemType.ForcePush: {
|
||||
const forcePushWarning = this.props
|
||||
.askForConfirmationOnForcePush ? null : (
|
||||
<>
|
||||
<br />
|
||||
<br />
|
||||
<div className="warning">
|
||||
<span className="warning-title">Warning:</span> A force push will
|
||||
rewrite history on the remote. Any collaborators working on this
|
||||
branch will need to reset their own local branch to match the
|
||||
history of the remote.
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
return {
|
||||
title: `Force push ${remoteName}`,
|
||||
description: (
|
||||
<>
|
||||
Overwrite any changes on {remoteName} with your local changes
|
||||
{forcePushWarning}
|
||||
</>
|
||||
),
|
||||
action: this.props.forcePushWithLease,
|
||||
icon: forcePushIcon,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public renderDropdownItem = (type: DropdownItemType) => {
|
||||
const item = this.getDropdownItemWithType(type)
|
||||
return (
|
||||
<Button
|
||||
className={DropdownItemClassName}
|
||||
key={type}
|
||||
onClick={item.action}
|
||||
>
|
||||
<Octicon symbol={item.icon} />
|
||||
<div className="text-container">
|
||||
<div className="title">{item.title}</div>
|
||||
<div className="detail">{item.description}</div>
|
||||
</div>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { itemTypes } = this.props
|
||||
return (
|
||||
<div className="push-pull-dropdown" ref={this.onButtonsContainerRef}>
|
||||
{itemTypes.map(this.renderDropdownItem)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -13,6 +13,18 @@ import { RelativeTime } from '../relative-time'
|
|||
|
||||
import { ToolbarButton, ToolbarButtonStyle } from './button'
|
||||
import classNames from 'classnames'
|
||||
import {
|
||||
DropdownState,
|
||||
IToolbarDropdownProps,
|
||||
ToolbarDropdown,
|
||||
ToolbarDropdownStyle,
|
||||
} from './dropdown'
|
||||
import { FoldoutType } from '../../lib/app-state'
|
||||
import { ForcePushBranchState } from '../../lib/rebase'
|
||||
import { PushPullButtonDropDown } from './push-pull-button-dropdown'
|
||||
import { enablePushPullFetchDropdown } from '../../lib/feature-flag'
|
||||
|
||||
export const DropdownItemClassName = 'push-pull-dropdown-item'
|
||||
|
||||
interface IPushPullButtonProps {
|
||||
/**
|
||||
|
@ -52,8 +64,8 @@ interface IPushPullButtonProps {
|
|||
/** Is the detached HEAD state related to a rebase or not? */
|
||||
readonly rebaseInProgress: boolean
|
||||
|
||||
/** If the current branch has been rebased, the user is permitted to force-push */
|
||||
readonly isForcePush: boolean
|
||||
/** Force push state of the current branch */
|
||||
readonly forcePushBranchState: ForcePushBranchState
|
||||
|
||||
/** Whether this component should show its onboarding tutorial nudge arrow */
|
||||
readonly shouldNudge: boolean
|
||||
|
@ -62,6 +74,32 @@ interface IPushPullButtonProps {
|
|||
* The number of tags that would get pushed if the user performed a push.
|
||||
*/
|
||||
readonly numTagsToPush: number
|
||||
|
||||
/** Whether or not the push-pull dropdown is currently open */
|
||||
readonly isDropdownOpen: boolean
|
||||
|
||||
/** Will the app prompt the user to confirm a force push? */
|
||||
readonly askForConfirmationOnForcePush: boolean
|
||||
|
||||
/**
|
||||
* An event handler for when the drop down is opened, or closed, by a pointer
|
||||
* event or by pressing the space or enter key while focused.
|
||||
*
|
||||
* @param state - The new state of the drop down
|
||||
*/
|
||||
readonly onDropdownStateChanged: (state: DropdownState) => void
|
||||
}
|
||||
|
||||
export enum DropdownItemType {
|
||||
Fetch = 'fetch',
|
||||
ForcePush = 'force-push',
|
||||
}
|
||||
|
||||
export type DropdownItem = {
|
||||
readonly title: string
|
||||
readonly description: string | JSX.Element
|
||||
readonly action: () => void
|
||||
readonly icon: OcticonSymbol.OcticonSymbolType
|
||||
}
|
||||
|
||||
function renderAheadBehind(aheadBehind: IAheadBehind, numTagsToPush: number) {
|
||||
|
@ -104,165 +142,11 @@ function renderLastFetched(lastFetched: Date | null): JSX.Element | string {
|
|||
}
|
||||
}
|
||||
|
||||
/** The common props for all button states */
|
||||
const defaultProps = {
|
||||
className: 'push-pull-button',
|
||||
style: ToolbarButtonStyle.Subtitle,
|
||||
}
|
||||
|
||||
function progressButton(progress: Progress, networkActionInProgress: boolean) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...defaultProps}
|
||||
title={progress.title}
|
||||
description={progress.description || 'Hang on…'}
|
||||
progressValue={progress.value}
|
||||
icon={syncClockwise}
|
||||
iconClassName={networkActionInProgress ? 'spin' : ''}
|
||||
tooltip={progress.description}
|
||||
disabled={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function publishRepositoryButton(onClick: () => void) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...defaultProps}
|
||||
title="Publish repository"
|
||||
description="Publish this repository to GitHub"
|
||||
className="push-pull-button"
|
||||
icon={OcticonSymbol.upload}
|
||||
style={ToolbarButtonStyle.Subtitle}
|
||||
onClick={onClick}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function unbornRepositoryButton() {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...defaultProps}
|
||||
title="Publish branch"
|
||||
description="Cannot publish unborn HEAD"
|
||||
icon={OcticonSymbol.upload}
|
||||
disabled={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function detachedHeadButton(rebaseInProgress: boolean) {
|
||||
const description = rebaseInProgress
|
||||
? 'Rebase in progress'
|
||||
: 'Cannot publish detached HEAD'
|
||||
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...defaultProps}
|
||||
title="Publish branch"
|
||||
description={description}
|
||||
icon={OcticonSymbol.upload}
|
||||
disabled={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function publishBranchButton(
|
||||
isGitHub: boolean,
|
||||
onClick: () => void,
|
||||
shouldNudge: boolean
|
||||
) {
|
||||
const description = isGitHub
|
||||
? 'Publish this branch to GitHub'
|
||||
: 'Publish this branch to the remote'
|
||||
|
||||
const className = classNames(defaultProps.className, 'nudge-arrow', {
|
||||
'nudge-arrow-up': shouldNudge,
|
||||
})
|
||||
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...defaultProps}
|
||||
title="Publish branch"
|
||||
description={description}
|
||||
icon={OcticonSymbol.upload}
|
||||
onClick={onClick}
|
||||
className={className}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function fetchButton(
|
||||
remoteName: string,
|
||||
aheadBehind: IAheadBehind,
|
||||
numTagsToPush: number,
|
||||
lastFetched: Date | null,
|
||||
onClick: () => void
|
||||
) {
|
||||
const title = `Fetch ${remoteName}`
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...defaultProps}
|
||||
title={title}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={syncClockwise}
|
||||
onClick={onClick}
|
||||
>
|
||||
{renderAheadBehind(aheadBehind, numTagsToPush)}
|
||||
</ToolbarButton>
|
||||
)
|
||||
}
|
||||
|
||||
function pullButton(
|
||||
remoteName: string,
|
||||
aheadBehind: IAheadBehind,
|
||||
numTagsToPush: number,
|
||||
lastFetched: Date | null,
|
||||
pullWithRebase: boolean,
|
||||
onClick: () => void
|
||||
) {
|
||||
const title = pullWithRebase
|
||||
? `Pull ${remoteName} with rebase`
|
||||
: `Pull ${remoteName}`
|
||||
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...defaultProps}
|
||||
title={title}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={OcticonSymbol.arrowDown}
|
||||
onClick={onClick}
|
||||
>
|
||||
{renderAheadBehind(aheadBehind, numTagsToPush)}
|
||||
</ToolbarButton>
|
||||
)
|
||||
}
|
||||
|
||||
function pushButton(
|
||||
remoteName: string,
|
||||
aheadBehind: IAheadBehind,
|
||||
numTagsToPush: number,
|
||||
lastFetched: Date | null,
|
||||
onClick: () => void
|
||||
) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...defaultProps}
|
||||
title={`Push ${remoteName}`}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={OcticonSymbol.arrowUp}
|
||||
onClick={onClick}
|
||||
>
|
||||
{renderAheadBehind(aheadBehind, numTagsToPush)}
|
||||
</ToolbarButton>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This represents the "double arrow" icon used to show a force-push, and is a
|
||||
* less complicated icon than the generated Octicon from the `octicons` package.
|
||||
*/
|
||||
const forcePushIcon: OcticonSymbol.OcticonSymbolType = {
|
||||
export const forcePushIcon: OcticonSymbol.OcticonSymbolType = {
|
||||
w: 10,
|
||||
h: 16,
|
||||
d:
|
||||
|
@ -273,51 +157,83 @@ const forcePushIcon: OcticonSymbol.OcticonSymbolType = {
|
|||
fr: 'evenodd',
|
||||
}
|
||||
|
||||
function forcePushButton(
|
||||
remoteName: string,
|
||||
aheadBehind: IAheadBehind,
|
||||
numTagsToPush: number,
|
||||
lastFetched: Date | null,
|
||||
onClick: () => void
|
||||
) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...defaultProps}
|
||||
title={`Force push ${remoteName}`}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={forcePushIcon}
|
||||
onClick={onClick}
|
||||
>
|
||||
{renderAheadBehind(aheadBehind, numTagsToPush)}
|
||||
</ToolbarButton>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A button which pushes, pulls, or updates depending on the state of the
|
||||
* repository.
|
||||
*/
|
||||
export class PushPullButton extends React.Component<IPushPullButtonProps, {}> {
|
||||
export class PushPullButton extends React.Component<IPushPullButtonProps> {
|
||||
/** The common props for all button states */
|
||||
private defaultButtonProps() {
|
||||
return {
|
||||
className: 'push-pull-button',
|
||||
style: ToolbarButtonStyle.Subtitle,
|
||||
}
|
||||
}
|
||||
|
||||
/** The common props for all dropdown states */
|
||||
private defaultDropdownProps(): Omit<
|
||||
IToolbarDropdownProps,
|
||||
'dropdownContentRenderer'
|
||||
> {
|
||||
return {
|
||||
buttonClassName: 'push-pull-button',
|
||||
style: ToolbarButtonStyle.Subtitle,
|
||||
dropdownStyle: ToolbarDropdownStyle.MultiOption,
|
||||
dropdownState: this.props.isDropdownOpen ? 'open' : 'closed',
|
||||
onDropdownStateChanged: this.props.onDropdownStateChanged,
|
||||
}
|
||||
}
|
||||
|
||||
private closeDropdown() {
|
||||
this.props.dispatcher.closeFoldout(FoldoutType.PushPull)
|
||||
}
|
||||
|
||||
private push = () => {
|
||||
this.closeDropdown()
|
||||
this.props.dispatcher.push(this.props.repository)
|
||||
}
|
||||
|
||||
private forcePushWithLease = () => {
|
||||
this.closeDropdown()
|
||||
this.props.dispatcher.confirmOrForcePush(this.props.repository)
|
||||
}
|
||||
|
||||
private pull = () => {
|
||||
this.closeDropdown()
|
||||
this.props.dispatcher.pull(this.props.repository)
|
||||
}
|
||||
|
||||
private fetch = () => {
|
||||
this.closeDropdown()
|
||||
this.props.dispatcher.fetch(
|
||||
this.props.repository,
|
||||
FetchType.UserInitiatedTask
|
||||
)
|
||||
}
|
||||
|
||||
private getDropdownContentRenderer(
|
||||
itemTypes: ReadonlyArray<DropdownItemType>
|
||||
) {
|
||||
return () => {
|
||||
return (
|
||||
<PushPullButtonDropDown
|
||||
itemTypes={itemTypes}
|
||||
remoteName={this.props.remoteName}
|
||||
fetch={this.fetch}
|
||||
forcePushWithLease={this.forcePushWithLease}
|
||||
askForConfirmationOnForcePush={
|
||||
this.props.askForConfirmationOnForcePush
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
return this.renderButton()
|
||||
}
|
||||
|
||||
private renderButton() {
|
||||
const {
|
||||
progress,
|
||||
networkActionInProgress,
|
||||
|
@ -329,28 +245,28 @@ export class PushPullButton extends React.Component<IPushPullButtonProps, {}> {
|
|||
rebaseInProgress,
|
||||
lastFetched,
|
||||
pullWithRebase,
|
||||
isForcePush,
|
||||
forcePushBranchState,
|
||||
} = this.props
|
||||
|
||||
if (progress !== null) {
|
||||
return progressButton(progress, networkActionInProgress)
|
||||
return this.progressButton(progress, networkActionInProgress)
|
||||
}
|
||||
|
||||
if (remoteName === null) {
|
||||
return publishRepositoryButton(this.push)
|
||||
return this.publishRepositoryButton(this.push)
|
||||
}
|
||||
|
||||
if (tipState === TipState.Unborn) {
|
||||
return unbornRepositoryButton()
|
||||
return this.unbornRepositoryButton()
|
||||
}
|
||||
|
||||
if (tipState === TipState.Detached) {
|
||||
return detachedHeadButton(rebaseInProgress)
|
||||
return this.detachedHeadButton(rebaseInProgress)
|
||||
}
|
||||
|
||||
if (aheadBehind === null) {
|
||||
const isGitHubRepository = repository.gitHubRepository !== null
|
||||
return publishBranchButton(
|
||||
return this.publishBranchButton(
|
||||
isGitHubRepository,
|
||||
this.push,
|
||||
this.props.shouldNudge
|
||||
|
@ -360,17 +276,11 @@ export class PushPullButton extends React.Component<IPushPullButtonProps, {}> {
|
|||
const { ahead, behind } = aheadBehind
|
||||
|
||||
if (ahead === 0 && behind === 0 && numTagsToPush === 0) {
|
||||
return fetchButton(
|
||||
remoteName,
|
||||
aheadBehind,
|
||||
numTagsToPush,
|
||||
lastFetched,
|
||||
this.fetch
|
||||
)
|
||||
return this.fetchButton(remoteName, lastFetched, this.fetch)
|
||||
}
|
||||
|
||||
if (isForcePush) {
|
||||
return forcePushButton(
|
||||
if (forcePushBranchState === ForcePushBranchState.Recommended) {
|
||||
return this.forcePushButton(
|
||||
remoteName,
|
||||
aheadBehind,
|
||||
numTagsToPush,
|
||||
|
@ -380,17 +290,18 @@ export class PushPullButton extends React.Component<IPushPullButtonProps, {}> {
|
|||
}
|
||||
|
||||
if (behind > 0) {
|
||||
return pullButton(
|
||||
return this.pullButton(
|
||||
remoteName,
|
||||
aheadBehind,
|
||||
numTagsToPush,
|
||||
lastFetched,
|
||||
pullWithRebase || false,
|
||||
forcePushBranchState,
|
||||
this.pull
|
||||
)
|
||||
}
|
||||
|
||||
return pushButton(
|
||||
return this.pushButton(
|
||||
remoteName,
|
||||
aheadBehind,
|
||||
numTagsToPush,
|
||||
|
@ -398,4 +309,254 @@ export class PushPullButton extends React.Component<IPushPullButtonProps, {}> {
|
|||
this.push
|
||||
)
|
||||
}
|
||||
|
||||
private progressButton(progress: Progress, networkActionInProgress: boolean) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...this.defaultButtonProps()}
|
||||
title={progress.title}
|
||||
description={progress.description || 'Hang on…'}
|
||||
progressValue={progress.value}
|
||||
icon={syncClockwise}
|
||||
iconClassName={networkActionInProgress ? 'spin' : ''}
|
||||
tooltip={progress.description}
|
||||
disabled={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private publishRepositoryButton(onClick: () => void) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...this.defaultButtonProps()}
|
||||
title="Publish repository"
|
||||
description="Publish this repository to GitHub"
|
||||
className="push-pull-button"
|
||||
icon={OcticonSymbol.upload}
|
||||
style={ToolbarButtonStyle.Subtitle}
|
||||
onClick={onClick}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private unbornRepositoryButton() {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...this.defaultButtonProps()}
|
||||
title="Publish branch"
|
||||
description="Cannot publish unborn HEAD"
|
||||
icon={OcticonSymbol.upload}
|
||||
disabled={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private detachedHeadButton(rebaseInProgress: boolean) {
|
||||
const description = rebaseInProgress
|
||||
? 'Rebase in progress'
|
||||
: 'Cannot publish detached HEAD'
|
||||
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...this.defaultButtonProps()}
|
||||
title="Publish branch"
|
||||
description={description}
|
||||
icon={OcticonSymbol.upload}
|
||||
disabled={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private publishBranchButton(
|
||||
isGitHub: boolean,
|
||||
onClick: () => void,
|
||||
shouldNudge: boolean
|
||||
) {
|
||||
const description = isGitHub
|
||||
? 'Publish this branch to GitHub'
|
||||
: 'Publish this branch to the remote'
|
||||
|
||||
if (!enablePushPullFetchDropdown()) {
|
||||
const className = classNames(
|
||||
this.defaultButtonProps().className,
|
||||
'nudge-arrow',
|
||||
{
|
||||
'nudge-arrow-up': shouldNudge,
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...this.defaultButtonProps()}
|
||||
title="Publish branch"
|
||||
description={description}
|
||||
icon={OcticonSymbol.upload}
|
||||
onClick={onClick}
|
||||
className={className}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const className = classNames(
|
||||
this.defaultDropdownProps().className,
|
||||
'nudge-arrow',
|
||||
{
|
||||
'nudge-arrow-up': shouldNudge,
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<ToolbarDropdown
|
||||
{...this.defaultDropdownProps()}
|
||||
title="Publish branch"
|
||||
description={description}
|
||||
icon={OcticonSymbol.upload}
|
||||
onClick={onClick}
|
||||
className={className}
|
||||
dropdownContentRenderer={this.getDropdownContentRenderer([
|
||||
DropdownItemType.Fetch,
|
||||
])}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private fetchButton(
|
||||
remoteName: string,
|
||||
lastFetched: Date | null,
|
||||
onClick: () => void
|
||||
) {
|
||||
const title = `Fetch ${remoteName}`
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...this.defaultButtonProps()}
|
||||
title={title}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={syncClockwise}
|
||||
onClick={onClick}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private pullButton(
|
||||
remoteName: string,
|
||||
aheadBehind: IAheadBehind,
|
||||
numTagsToPush: number,
|
||||
lastFetched: Date | null,
|
||||
pullWithRebase: boolean,
|
||||
forcePushBranchState: ForcePushBranchState,
|
||||
onClick: () => void
|
||||
) {
|
||||
const title = pullWithRebase
|
||||
? `Pull ${remoteName} with rebase`
|
||||
: `Pull ${remoteName}`
|
||||
|
||||
const dropdownItemTypes = [DropdownItemType.Fetch]
|
||||
|
||||
if (forcePushBranchState !== ForcePushBranchState.NotAvailable) {
|
||||
dropdownItemTypes.push(DropdownItemType.ForcePush)
|
||||
}
|
||||
|
||||
if (!enablePushPullFetchDropdown()) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...this.defaultButtonProps()}
|
||||
title={title}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={OcticonSymbol.arrowDown}
|
||||
onClick={onClick}
|
||||
>
|
||||
{renderAheadBehind(aheadBehind, numTagsToPush)}
|
||||
</ToolbarButton>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ToolbarDropdown
|
||||
{...this.defaultDropdownProps()}
|
||||
title={title}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={OcticonSymbol.arrowDown}
|
||||
onClick={onClick}
|
||||
dropdownContentRenderer={this.getDropdownContentRenderer(
|
||||
dropdownItemTypes
|
||||
)}
|
||||
>
|
||||
{renderAheadBehind(aheadBehind, numTagsToPush)}
|
||||
</ToolbarDropdown>
|
||||
)
|
||||
}
|
||||
|
||||
private pushButton(
|
||||
remoteName: string,
|
||||
aheadBehind: IAheadBehind,
|
||||
numTagsToPush: number,
|
||||
lastFetched: Date | null,
|
||||
onClick: () => void
|
||||
) {
|
||||
if (!enablePushPullFetchDropdown()) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...this.defaultButtonProps()}
|
||||
title={`Push ${remoteName}`}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={OcticonSymbol.arrowUp}
|
||||
onClick={onClick}
|
||||
>
|
||||
{renderAheadBehind(aheadBehind, numTagsToPush)}
|
||||
</ToolbarButton>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ToolbarDropdown
|
||||
{...this.defaultDropdownProps()}
|
||||
title={`Push ${remoteName}`}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={OcticonSymbol.arrowUp}
|
||||
onClick={onClick}
|
||||
dropdownContentRenderer={this.getDropdownContentRenderer([
|
||||
DropdownItemType.Fetch,
|
||||
])}
|
||||
>
|
||||
{renderAheadBehind(aheadBehind, numTagsToPush)}
|
||||
</ToolbarDropdown>
|
||||
)
|
||||
}
|
||||
|
||||
private forcePushButton(
|
||||
remoteName: string,
|
||||
aheadBehind: IAheadBehind,
|
||||
numTagsToPush: number,
|
||||
lastFetched: Date | null,
|
||||
onClick: () => void
|
||||
) {
|
||||
if (!enablePushPullFetchDropdown()) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
{...this.defaultButtonProps()}
|
||||
title={`Force push ${remoteName}`}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={forcePushIcon}
|
||||
onClick={onClick}
|
||||
>
|
||||
{renderAheadBehind(aheadBehind, numTagsToPush)}
|
||||
</ToolbarButton>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ToolbarDropdown
|
||||
{...this.defaultDropdownProps()}
|
||||
title={`Force push ${remoteName}`}
|
||||
description={renderLastFetched(lastFetched)}
|
||||
icon={forcePushIcon}
|
||||
onClick={onClick}
|
||||
dropdownContentRenderer={this.getDropdownContentRenderer([
|
||||
DropdownItemType.Fetch,
|
||||
])}
|
||||
>
|
||||
{renderAheadBehind(aheadBehind, numTagsToPush)}
|
||||
</ToolbarDropdown>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
@import 'ui/toolbar/toolbar';
|
||||
@import 'ui/toolbar/button';
|
||||
@import 'ui/toolbar/dropdown';
|
||||
@import 'ui/toolbar/push-pull-button';
|
||||
@import 'ui/tab-bar';
|
||||
@import 'ui/panel';
|
||||
@import 'ui/popup';
|
||||
|
|
|
@ -248,6 +248,8 @@ $overlay-background-color: rgba(0, 0, 0, 0.4);
|
|||
--toolbar-button-focus-progress-color: #{$gray-700};
|
||||
--toolbar-button-hover-progress-color: #{$gray-700};
|
||||
--toolbar-dropdown-open-progress-color: #{$gray-200};
|
||||
--toolbar-dropdown-text-warning-color: #{$yellow-800};
|
||||
--toolbar-dropdown-text-hover-color: var(--box-hover-text-color);
|
||||
|
||||
/**
|
||||
* App menu bar colors (Windows/Linux only)
|
||||
|
|
|
@ -174,6 +174,8 @@ body.theme-dark {
|
|||
--toolbar-button-focus-progress-color: #{$gray-700};
|
||||
--toolbar-button-hover-progress-color: #{$gray-700};
|
||||
--toolbar-dropdown-open-progress-color: #{$gray-200};
|
||||
--toolbar-dropdown-text-warning-color: #{$yellow-700};
|
||||
--toolbar-dropdown-text-hover-color: #{$white};
|
||||
|
||||
/**
|
||||
* App menu bar colors (Windows/Linux only)
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
.toolbar-button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
|
||||
// Make sure the contents shrink beyond their intrinsic width
|
||||
// See https://css-tricks.com/flexbox-truncated-text/
|
||||
min-width: 0;
|
||||
|
@ -11,6 +15,11 @@
|
|||
// above all the other content.
|
||||
position: relative;
|
||||
|
||||
.toolbar-dropdown-button {
|
||||
width: 40px;
|
||||
height: 49px;
|
||||
}
|
||||
|
||||
// General button behavior, mostly resets.
|
||||
// For the button content styling see second button style. Note that we
|
||||
// explicitly use > here to only target the direct descendant button since
|
||||
|
|
|
@ -3,13 +3,21 @@
|
|||
// See https://css-tricks.com/flexbox-truncated-text/
|
||||
min-width: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
& > .toolbar-button {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
& .toolbar-dropdown-arrow-button {
|
||||
width: 39px;
|
||||
}
|
||||
|
||||
&.open {
|
||||
& > .toolbar-button > button {
|
||||
&.foldout-style > .toolbar-button > button,
|
||||
&.multi-option-style > .toolbar-dropdown-arrow-button > button {
|
||||
color: var(--toolbar-button-active-color);
|
||||
background-color: var(--toolbar-button-active-background-color);
|
||||
|
||||
|
|
66
app/styles/ui/toolbar/_push-pull-button.scss
Normal file
66
app/styles/ui/toolbar/_push-pull-button.scss
Normal file
|
@ -0,0 +1,66 @@
|
|||
.push-pull-dropdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 1px;
|
||||
z-index: 0;
|
||||
max-width: 100%;
|
||||
|
||||
.push-pull-dropdown-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: fit-content;
|
||||
padding: 10px;
|
||||
gap: 10px;
|
||||
color: var(--text-color);
|
||||
background-color: var(--box-background-color);
|
||||
white-space: normal;
|
||||
|
||||
// Unset styles from Button component
|
||||
text-align: unset;
|
||||
border: unset;
|
||||
border-radius: unset;
|
||||
box-shadow: unset !important;
|
||||
|
||||
.octicon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
// Override background on focus to keep the default color
|
||||
&:focus {
|
||||
background-color: var(--box-background-color);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--box-hover-background-color) !important;
|
||||
color: var(--toolbar-dropdown-text-hover-color) !important;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
// Enforce this bottom border style even in focused state
|
||||
border-bottom: 1px solid var(--box-border-color) !important;
|
||||
}
|
||||
|
||||
.text-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 3px;
|
||||
|
||||
.title {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.detail {
|
||||
color: var(--text-secondary-color);
|
||||
|
||||
.warning {
|
||||
color: var(--toolbar-dropdown-text-warning-color);
|
||||
|
||||
.warning-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,16 +37,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
.toolbar-dropdown {
|
||||
&.branch-button {
|
||||
.toolbar-button {
|
||||
&.branch-toolbar-button {
|
||||
width: 230px;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar-button {
|
||||
&.revert-progress {
|
||||
width: 230px;
|
||||
}
|
||||
&.toolbar-dropdown-arrow-button {
|
||||
width: 39px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -193,6 +193,10 @@ body > .tooltip,
|
|||
color: var(--color-deleted);
|
||||
}
|
||||
|
||||
.files-renamed-icon {
|
||||
color: var(--color-renamed);
|
||||
}
|
||||
|
||||
.octicon {
|
||||
margin-right: var(--spacing-third);
|
||||
vertical-align: bottom; // For some reason, `bottom` places the text in the middle
|
||||
|
|
|
@ -3,6 +3,18 @@
|
|||
"3.1.6": [
|
||||
"[Improved] Upgrade embedded Git to 2.39.1 and Git LFS to 3.3.0 - #15915"
|
||||
],
|
||||
"3.1.6-beta2": [
|
||||
"[Fixed] Fix crash launching the app on Apple silicon devices - #16011",
|
||||
"[Fixed] Trim leading and trailing whitespaces in URLs of repository remotes - #15821. Thanks @Shivareddy-Aluri!",
|
||||
"[Fixed] Fix support for the latest versions of RStudio on Windows - #15810"
|
||||
],
|
||||
"3.1.6-beta1": [
|
||||
"[Added] Add fetch and force-push actions in a dropdown as an alternative to the main Pull/Push/Publish action button - #15907",
|
||||
"[Added] Add JetBrains CLion support on macOS - #15881. Thanks @tsvetilian-ty!",
|
||||
"[Fixed] Fix support for latest versions of VSCodium on Windows - #15585. Thanks @voidei!",
|
||||
"[Improved] Upgrade to Electron v22.0.3 - #15831",
|
||||
"[Improved] Upgrade embedded Git to 2.39.1 and Git LFS to 3.3.0 - #15915"
|
||||
],
|
||||
"3.1.5": [
|
||||
"[Added] Enable menu option to Force-push branches that have diverged - #15211",
|
||||
"[Added] Add menu option to Fetch the current repository at any time - #7805",
|
||||
|
@ -28,6 +40,7 @@
|
|||
"[Improved] Close repository list after creating or adding repositories - #15508. Thanks @angusdev!",
|
||||
"[Improved] Always show an error message when an update fails - #15530"
|
||||
],
|
||||
"3.1.4": ["[Improved] Upgrade embedded Git to 2.35.6"],
|
||||
"3.1.4-beta1": [
|
||||
"[Added] Add support for JetBrains Toolbox and JetBrains Fleet editor for Windows - #12912. Thanks @tsvetilian-ty!",
|
||||
"[Added] Add support for Emacs editor for Linux - #15857. Thanks @zipperer!",
|
||||
|
|
|
@ -252,6 +252,7 @@ These editors are currently supported:
|
|||
- [JetBrains PhpStorm](https://www.jetbrains.com/phpstorm/)
|
||||
- [JetBrains PyCharm](https://www.jetbrains.com/pycharm/)
|
||||
- [JetBrains RubyMine](https://www.jetbrains.com/rubymine/)
|
||||
- [JetBrains CLion](https://www.jetbrains.com/clion/)
|
||||
- [RStudio](https://rstudio.com/)
|
||||
- [TextMate](https://macromates.com)
|
||||
- [Brackets](http://brackets.io/)
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
"eslint": "eslint --cache --rulesdir ./eslint-rules \"./eslint-rules/**/*.js\" \"./script/**/*.ts{,x}\" \"./app/{src,typings,test}/**/*.{j,t}s{,x}\" \"./changelog.json\"",
|
||||
"eslint-check": "eslint --print-config .eslintrc.* | eslint-config-prettier-check",
|
||||
"publish": "ts-node -P script/tsconfig.json script/publish.ts",
|
||||
"validate-electron-version": "ts-node -P script/tsconfig.json script/validate-electron-version.ts",
|
||||
"clean-slate": "rimraf out node_modules app/node_modules && yarn",
|
||||
"rebuild-hard:dev": "yarn clean-slate && yarn build:dev",
|
||||
"rebuild-hard:prod": "yarn clean-slate && yarn build:prod",
|
||||
|
@ -84,7 +85,7 @@
|
|||
"jest-diff": "^25.0.0",
|
||||
"jest-extended": "^0.11.2",
|
||||
"jest-localstorage-mock": "^2.3.0",
|
||||
"jszip": "^3.7.1",
|
||||
"jszip": "^3.8.0",
|
||||
"klaw-sync": "^3.0.0",
|
||||
"legal-eagle": "0.16.0",
|
||||
"mini-css-extract-plugin": "^2.5.3",
|
||||
|
@ -155,7 +156,7 @@
|
|||
"@types/webpack-hot-middleware": "^2.25.6",
|
||||
"@types/webpack-merge": "^5.0.0",
|
||||
"@types/xml2js": "^0.4.0",
|
||||
"electron": "19.0.0",
|
||||
"electron": "22.0.3",
|
||||
"electron-builder": "^22.7.0",
|
||||
"electron-packager": "^15.1.0",
|
||||
"electron-winstaller": "^5.0.0",
|
||||
|
|
|
@ -199,7 +199,7 @@ function packageApp() {
|
|||
new RegExp('/\\.git($|/)'),
|
||||
new RegExp('/node_modules/\\.bin($|/)'),
|
||||
],
|
||||
appCopyright: 'Copyright © 2017 GitHub, Inc.',
|
||||
appCopyright: 'Copyright © 2023 GitHub, Inc.',
|
||||
|
||||
// macOS
|
||||
appBundleId: getBundleID(),
|
||||
|
|
|
@ -8,5 +8,7 @@
|
|||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -6,5 +6,7 @@
|
|||
<true/>
|
||||
<key>com.apple.security.automation.apple-events</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
53
script/validate-electron-version.ts
Normal file
53
script/validate-electron-version.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* eslint-disable no-sync */
|
||||
/// <reference path="./globals.d.ts" />
|
||||
|
||||
import * as distInfo from './dist-info'
|
||||
|
||||
type ChannelToValidate = 'production' | 'beta'
|
||||
|
||||
/**
|
||||
* This object states the valid/expected Electron versions for each publishable
|
||||
* channel of GitHub Desktop.
|
||||
*
|
||||
* The purpose of this is to ensure that we don't accidentally publish a
|
||||
* production/beta/test build with the wrong version of Electron, which could
|
||||
* cause really bad regressions to our users, and also the inability to go back
|
||||
* to a previous version of GitHub Desktop without losing all settings.
|
||||
*/
|
||||
const ValidElectronVersions: Record<ChannelToValidate, string> = {
|
||||
production: '19.0.0',
|
||||
beta: '22.0.3',
|
||||
}
|
||||
|
||||
const channel = getChannelToValidate()
|
||||
|
||||
if (channel === null) {
|
||||
console.log(
|
||||
`No need to validate the Electron version of a ${distInfo.getChannel()} build.`
|
||||
)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const expectedVersion = ValidElectronVersions[channel]
|
||||
const pkg: Package = require('../package.json')
|
||||
const actualVersion = pkg.devDependencies?.electron
|
||||
|
||||
if (actualVersion !== expectedVersion) {
|
||||
console.error(
|
||||
`The Electron version for the ${channel} channel is incorrect. Expected ${expectedVersion} but found ${actualVersion}.`
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(
|
||||
`The Electron version for the ${channel} channel is correct: ${actualVersion}.`
|
||||
)
|
||||
|
||||
function getChannelToValidate(): ChannelToValidate | null {
|
||||
const channel = distInfo.getChannel()
|
||||
return isChannelToValidate(channel) ? channel : null
|
||||
}
|
||||
|
||||
function isChannelToValidate(channel: string): channel is ChannelToValidate {
|
||||
return Object.keys(ValidElectronVersions).includes(channel)
|
||||
}
|
257
yarn.lock
257
yarn.lock
|
@ -521,22 +521,6 @@
|
|||
ajv "^6.12.0"
|
||||
ajv-keywords "^3.4.1"
|
||||
|
||||
"@electron/get@^1.14.1":
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.14.1.tgz#16ba75f02dffb74c23965e72d617adc721d27f40"
|
||||
integrity sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
env-paths "^2.2.0"
|
||||
fs-extra "^8.1.0"
|
||||
got "^9.6.0"
|
||||
progress "^2.0.3"
|
||||
semver "^6.2.0"
|
||||
sumchecker "^3.0.1"
|
||||
optionalDependencies:
|
||||
global-agent "^3.0.0"
|
||||
global-tunnel-ng "^2.7.1"
|
||||
|
||||
"@electron/get@^1.6.0":
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.7.1.tgz#41aa60871b9d7e225bbe68135012f88a9ef87012"
|
||||
|
@ -552,6 +536,21 @@
|
|||
global-agent "^2.0.2"
|
||||
global-tunnel-ng "^2.7.1"
|
||||
|
||||
"@electron/get@^2.0.0":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.2.tgz#ae2a967b22075e9c25aaf00d5941cd79c21efd7e"
|
||||
integrity sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
env-paths "^2.2.0"
|
||||
fs-extra "^8.1.0"
|
||||
got "^11.8.5"
|
||||
progress "^2.0.3"
|
||||
semver "^6.2.0"
|
||||
sumchecker "^3.0.1"
|
||||
optionalDependencies:
|
||||
global-agent "^3.0.0"
|
||||
|
||||
"@es-joy/jsdoccomment@~0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.18.0.tgz#2532b2ecb8576d694011b157c447ed6b12534c70"
|
||||
|
@ -879,6 +878,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
|
||||
integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
|
||||
|
||||
"@sindresorhus/is@^4.0.0":
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f"
|
||||
integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==
|
||||
|
||||
"@sinonjs/commons@^1.7.0":
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217"
|
||||
|
@ -900,6 +904,13 @@
|
|||
dependencies:
|
||||
defer-to-connect "^1.0.1"
|
||||
|
||||
"@szmarczak/http-timer@^4.0.5":
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807"
|
||||
integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==
|
||||
dependencies:
|
||||
defer-to-connect "^2.0.0"
|
||||
|
||||
"@tootallnate/once@1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||
|
@ -953,6 +964,16 @@
|
|||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/cacheable-request@^6.0.1":
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183"
|
||||
integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==
|
||||
dependencies:
|
||||
"@types/http-cache-semantics" "*"
|
||||
"@types/keyv" "^3.1.4"
|
||||
"@types/node" "*"
|
||||
"@types/responselike" "^1.0.0"
|
||||
|
||||
"@types/classnames@^2.2.2":
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.3.tgz#3f0ff6873da793870e20a260cada55982f38a9e5"
|
||||
|
@ -1108,6 +1129,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"
|
||||
integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==
|
||||
|
||||
"@types/http-cache-semantics@*":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812"
|
||||
integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==
|
||||
|
||||
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
|
||||
|
@ -1173,6 +1199,13 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||
|
||||
"@types/keyv@^3.1.4":
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6"
|
||||
integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/klaw-sync@^6.0.0":
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/klaw-sync/-/klaw-sync-6.0.0.tgz#ff0b36601efaaa109d513c4ced109311fd06ba36"
|
||||
|
@ -1339,6 +1372,13 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/reserved-words/-/reserved-words-0.1.0.tgz#a9d5318bb4ac4466862b93fc702542b75d2cd3ac"
|
||||
integrity sha512-ls6lSkkhEFm8XSVQjHj47pJoCL9sVK91mwIONw0Iwjqkmy98ForMFYa5+/vb6sytTaK0HSwkzKKYzREPTUhhhg==
|
||||
|
||||
"@types/responselike@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29"
|
||||
integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/semver@^5.5.0":
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
|
||||
|
@ -2663,6 +2703,11 @@ cache-base@^1.0.1:
|
|||
union-value "^1.0.0"
|
||||
unset-value "^1.0.0"
|
||||
|
||||
cacheable-lookup@^5.0.3:
|
||||
version "5.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005"
|
||||
integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==
|
||||
|
||||
cacheable-request@^6.0.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912"
|
||||
|
@ -2676,6 +2721,19 @@ cacheable-request@^6.0.0:
|
|||
normalize-url "^4.1.0"
|
||||
responselike "^1.0.2"
|
||||
|
||||
cacheable-request@^7.0.2:
|
||||
version "7.0.2"
|
||||
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27"
|
||||
integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==
|
||||
dependencies:
|
||||
clone-response "^1.0.2"
|
||||
get-stream "^5.1.0"
|
||||
http-cache-semantics "^4.0.0"
|
||||
keyv "^4.0.0"
|
||||
lowercase-keys "^2.0.0"
|
||||
normalize-url "^6.0.1"
|
||||
responselike "^2.0.0"
|
||||
|
||||
call-bind@^1.0.0, call-bind@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||
|
@ -2979,16 +3037,6 @@ concat-map@0.0.1:
|
|||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
concat-stream@^1.6.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
|
||||
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^2.2.2"
|
||||
typedarray "^0.0.6"
|
||||
|
||||
config-chain@^1.1.11:
|
||||
version "1.1.12"
|
||||
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
|
||||
|
@ -3246,6 +3294,13 @@ decompress-response@^3.3.0:
|
|||
dependencies:
|
||||
mimic-response "^1.0.0"
|
||||
|
||||
decompress-response@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
|
||||
integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
|
||||
dependencies:
|
||||
mimic-response "^3.1.0"
|
||||
|
||||
deep-extend@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
|
||||
|
@ -3271,6 +3326,11 @@ defer-to-connect@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
|
||||
integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
|
||||
|
||||
defer-to-connect@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587"
|
||||
integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==
|
||||
|
||||
define-properties@^1.1.2, define-properties@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||
|
@ -3603,14 +3663,14 @@ electron-winstaller@*, electron-winstaller@^5.0.0:
|
|||
lodash.template "^4.2.2"
|
||||
temp "^0.9.0"
|
||||
|
||||
electron@19.0.0:
|
||||
version "19.0.0"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-19.0.0.tgz#f6b742b708ec118676ba3b38d0f3712d8f0311cf"
|
||||
integrity sha512-VXwqLQxuIUr0SI8vOYDj5OLPwtKa/trn5DVKd/BFGT/U/IerfVoSZuydGLOjSL5yJlckfmKQpiq+8PW4gI8hXA==
|
||||
electron@22.0.3:
|
||||
version "22.0.3"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-22.0.3.tgz#44806cd053ea2ed35bffefd92143d3fc69d7337d"
|
||||
integrity sha512-eETrJTINTzlXgQrnJSrKiF2Xdt5EHpxZ6Kk+WUjFCE0zUztdVm+hrngUecqhj8TPFlYScTANzPwRwUIjOChl+g==
|
||||
dependencies:
|
||||
"@electron/get" "^1.14.1"
|
||||
"@electron/get" "^2.0.0"
|
||||
"@types/node" "^16.11.26"
|
||||
extract-zip "^1.0.3"
|
||||
extract-zip "^2.0.1"
|
||||
|
||||
element-closest@^2.0.2:
|
||||
version "2.0.2"
|
||||
|
@ -4371,17 +4431,7 @@ extglob@^2.0.4:
|
|||
snapdragon "^0.8.1"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
extract-zip@^1.0.3:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927"
|
||||
integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==
|
||||
dependencies:
|
||||
concat-stream "^1.6.2"
|
||||
debug "^2.6.9"
|
||||
mkdirp "^0.5.4"
|
||||
yauzl "^2.10.0"
|
||||
|
||||
extract-zip@^2.0.0:
|
||||
extract-zip@^2.0.0, extract-zip@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
|
||||
integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
|
||||
|
@ -4923,6 +4973,23 @@ globby@^11.0.4, globby@^11.1.0:
|
|||
merge2 "^1.4.1"
|
||||
slash "^3.0.0"
|
||||
|
||||
got@^11.8.5:
|
||||
version "11.8.6"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a"
|
||||
integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==
|
||||
dependencies:
|
||||
"@sindresorhus/is" "^4.0.0"
|
||||
"@szmarczak/http-timer" "^4.0.5"
|
||||
"@types/cacheable-request" "^6.0.1"
|
||||
"@types/responselike" "^1.0.0"
|
||||
cacheable-lookup "^5.0.3"
|
||||
cacheable-request "^7.0.2"
|
||||
decompress-response "^6.0.0"
|
||||
http2-wrapper "^1.0.0-beta.5.2"
|
||||
lowercase-keys "^2.0.0"
|
||||
p-cancelable "^2.0.0"
|
||||
responselike "^2.0.0"
|
||||
|
||||
got@^9.6.0:
|
||||
version "9.6.0"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
|
||||
|
@ -5178,9 +5245,9 @@ htmlparser2@^6.1.0:
|
|||
entities "^2.0.0"
|
||||
|
||||
http-cache-semantics@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
|
||||
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
|
||||
integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
|
||||
|
||||
http-errors@1.8.1:
|
||||
version "1.8.1"
|
||||
|
@ -5211,6 +5278,14 @@ http-signature@~1.2.0:
|
|||
jsprim "^1.2.2"
|
||||
sshpk "^1.7.0"
|
||||
|
||||
http2-wrapper@^1.0.0-beta.5.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d"
|
||||
integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==
|
||||
dependencies:
|
||||
quick-lru "^5.1.1"
|
||||
resolve-alpn "^1.0.0"
|
||||
|
||||
https-proxy-agent@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
|
||||
|
@ -6353,6 +6428,11 @@ json-buffer@3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
|
||||
integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=
|
||||
|
||||
json-buffer@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
||||
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
|
||||
|
||||
json-edm-parser@0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/json-edm-parser/-/json-edm-parser-0.1.2.tgz#1e60b0fef1bc0af67bc0d146dfdde5486cd615b4"
|
||||
|
@ -6478,10 +6558,10 @@ jsx-ast-utils@^3.3.2:
|
|||
array-includes "^3.1.5"
|
||||
object.assign "^4.1.3"
|
||||
|
||||
jszip@^3.7.1:
|
||||
version "3.7.1"
|
||||
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.7.1.tgz#bd63401221c15625a1228c556ca8a68da6fda3d9"
|
||||
integrity sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==
|
||||
jszip@^3.8.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.8.0.tgz#a2ac3c33fe96a76489765168213655850254d51b"
|
||||
integrity sha512-cnpQrXvFSLdsR9KR5/x7zdf6c3m8IhZfZzSblFEHSqBaVwD2nvJ4CuCKLyvKvwBgZm08CgfSoiTBQLm5WW9hGw==
|
||||
dependencies:
|
||||
lie "~3.3.0"
|
||||
pako "~1.0.2"
|
||||
|
@ -6500,6 +6580,13 @@ keyv@^3.0.0:
|
|||
dependencies:
|
||||
json-buffer "3.0.0"
|
||||
|
||||
keyv@^4.0.0:
|
||||
version "4.5.2"
|
||||
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56"
|
||||
integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==
|
||||
dependencies:
|
||||
json-buffer "3.0.1"
|
||||
|
||||
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
|
||||
|
@ -7024,6 +7111,11 @@ mimic-response@^1.0.0, mimic-response@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
||||
integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
|
||||
|
||||
mimic-response@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
|
||||
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
|
||||
|
||||
mini-css-extract-plugin@^2.5.3:
|
||||
version "2.5.3"
|
||||
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz#c5c79f9b22ce9b4f164e9492267358dbe35376d9"
|
||||
|
@ -7082,13 +7174,6 @@ mkdirp@^0.5.1:
|
|||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mkdirp@^0.5.4:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
||||
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
mrmime@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b"
|
||||
|
@ -7238,6 +7323,11 @@ normalize-url@^4.1.0:
|
|||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
|
||||
integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
|
||||
|
||||
normalize-url@^6.0.1:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
|
||||
integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
|
||||
|
||||
npm-conf@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9"
|
||||
|
@ -7483,6 +7573,11 @@ p-cancelable@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
|
||||
integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
|
||||
|
||||
p-cancelable@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
|
||||
integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==
|
||||
|
||||
p-each-series@^2.1.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a"
|
||||
|
@ -7980,6 +8075,11 @@ queue-microtask@^1.2.2:
|
|||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
||||
|
||||
quick-lru@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
|
||||
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
|
||||
|
||||
raf@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575"
|
||||
|
@ -8112,19 +8212,6 @@ read-pkg@^5.2.0:
|
|||
parse-json "^5.0.0"
|
||||
type-fest "^0.6.0"
|
||||
|
||||
readable-stream@^2.2.2, readable-stream@~2.3.6:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@^3.0.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||
|
@ -8146,6 +8233,19 @@ readable-stream@~2.0.0:
|
|||
string_decoder "~0.10.x"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@~2.3.6:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readdir-scoped-modules@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747"
|
||||
|
@ -8323,6 +8423,11 @@ reserved-words@^0.1.2:
|
|||
resolved "https://registry.yarnpkg.com/reserved-words/-/reserved-words-0.1.2.tgz#00a0940f98cd501aeaaac316411d9adc52b31ab1"
|
||||
integrity sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=
|
||||
|
||||
resolve-alpn@^1.0.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
|
||||
integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==
|
||||
|
||||
resolve-cwd@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
|
||||
|
@ -8391,6 +8496,13 @@ responselike@^1.0.2:
|
|||
dependencies:
|
||||
lowercase-keys "^1.0.0"
|
||||
|
||||
responselike@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc"
|
||||
integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==
|
||||
dependencies:
|
||||
lowercase-keys "^2.0.0"
|
||||
|
||||
ret@~0.1.10:
|
||||
version "0.1.15"
|
||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||
|
@ -9621,11 +9733,6 @@ typedarray-to-buffer@^3.1.5:
|
|||
dependencies:
|
||||
is-typedarray "^1.0.0"
|
||||
|
||||
typedarray@^0.0.6:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@^4.6.4:
|
||||
version "4.6.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9"
|
||||
|
|
Loading…
Reference in a new issue