diff --git a/client/browser/BUILD.bazel b/client/browser/BUILD.bazel index 544ef6f998c..8ea13cd68a0 100644 --- a/client/browser/BUILD.bazel +++ b/client/browser/BUILD.bazel @@ -171,9 +171,7 @@ ts_project( "src/shared/code-hosts/shared/errors.ts", "src/shared/code-hosts/shared/extensions.tsx", "src/shared/code-hosts/shared/getNotificationClassName.ts", - "src/shared/code-hosts/shared/hoverAlerts.tsx", "src/shared/code-hosts/shared/inject.ts", - "src/shared/code-hosts/shared/nativeTooltips.tsx", "src/shared/code-hosts/shared/testHelpers.ts", "src/shared/code-hosts/shared/util/fileInfo.ts", "src/shared/code-hosts/shared/util/selections.ts", diff --git a/client/browser/src/browser-extension/web-extension-api/types.ts b/client/browser/src/browser-extension/web-extension-api/types.ts index 32254230e66..2052c4f9b57 100644 --- a/client/browser/src/browser-extension/web-extension-api/types.ts +++ b/client/browser/src/browser-extension/web-extension-api/types.ts @@ -55,7 +55,6 @@ export interface SyncStorageItems extends SourcegraphURL { * Overrides settings from Sourcegraph. */ clientSettings: string - dismissedHoverAlerts: Record } export interface LocalStorageItems {} diff --git a/client/browser/src/shared.scss b/client/browser/src/shared.scss index 69ae55f1518..70f0aff0db4 100644 --- a/client/browser/src/shared.scss +++ b/client/browser/src/shared.scss @@ -14,22 +14,6 @@ $body-bg-color-light: #ffffff; --dropdown-border-color: var(--border-color); } -.command-palette-button { - align-self: center; - - > .command-list-popover-button { - user-select: none; - position: relative; - } -} - -.command-list-popover { - isolation: isolate; - z-index: 1100; // high enough to prevent most things from obscuring it - border: 1px solid var(--dropdown-border-color); - border-radius: 3px; -} - .sourcegraph-extensions-global { position: fixed; bottom: 0; diff --git a/client/browser/src/shared/code-hosts/bitbucket-cloud/codeHost.ts b/client/browser/src/shared/code-hosts/bitbucket-cloud/codeHost.ts index ef14f6e841e..1ce56a48ec1 100644 --- a/client/browser/src/shared/code-hosts/bitbucket-cloud/codeHost.ts +++ b/client/browser/src/shared/code-hosts/bitbucket-cloud/codeHost.ts @@ -194,7 +194,6 @@ export const bitbucketCloudCodeHost: CodeHost = { iconClassName: styles.icon, contentClassName: styles.content, }, - notificationClassNames: { 1: '', 2: '', 3: '', 4: '', 5: '' }, codeViewsRequireTokenization: true, observeLineSelection: fromEvent(window, 'hashchange').pipe( startWith(undefined), // capture intital value diff --git a/client/browser/src/shared/code-hosts/bitbucket/codeHost.module.scss b/client/browser/src/shared/code-hosts/bitbucket/codeHost.module.scss index 8004cbf2b3a..ebe1d1151a4 100644 --- a/client/browser/src/shared/code-hosts/bitbucket/codeHost.module.scss +++ b/client/browser/src/shared/code-hosts/bitbucket/codeHost.module.scss @@ -1,31 +1,3 @@ -/* Command palette */ -.command-palette-button { - z-index: 3000; - font-size: 13px; - - svg { - /* The icon we use is taller than the other items' font size, so make it a bit shorter. */ - height: 13px; - } -} - -.command-palette-popover { - display: block !important; - max-width: unset !important; - - header { - padding: 8px; - } - - input { - max-width: unset !important; - } -} - -.no-results { - padding: 10px; -} - /* Open on Sourcegraph button */ .open-on-sourcegraph { margin-left: 2px; /* same as other buttons in the row */ @@ -141,28 +113,3 @@ opacity: 0.7; } } - -/* Bitbucket's style is copied here because adding the aui-dropdown2-trigger class - * to the command palette causes exceptions in Atlassian's JS. */ -.command-list-popover-button { - padding-right: 24px !important; - - &::after { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - -webkit-text-stroke-width: 0; - font-family: 'Adgs Icons'; - font-weight: normal; - font-style: normal; - content: '\f15b'; - font-size: 16px; - height: 16px; - line-height: 1; - margin-top: -8px; - position: absolute; - right: 4px; - top: 50%; - text-indent: 0; - width: 16px; - } -} diff --git a/client/browser/src/shared/code-hosts/bitbucket/codeHost.test.ts b/client/browser/src/shared/code-hosts/bitbucket/codeHost.test.ts index 32884a84a18..465f85bdee8 100644 --- a/client/browser/src/shared/code-hosts/bitbucket/codeHost.test.ts +++ b/client/browser/src/shared/code-hosts/bitbucket/codeHost.test.ts @@ -6,7 +6,6 @@ import { bitbucketServerCodeHost, getToolbarMount, parseHash } from './codeHost' describe('bitbucketServerCodeHost', () => { testCodeHostMountGetters(bitbucketServerCodeHost, { - getCommandPaletteMount: `${__dirname}/__fixtures__/browse.html`, getViewContextOnSourcegraphMount: `${__dirname}/__fixtures__/browse.html`, }) describe('getToolbarMount()', () => { diff --git a/client/browser/src/shared/code-hosts/bitbucket/codeHost.tsx b/client/browser/src/shared/code-hosts/bitbucket/codeHost.tsx index 43b26d7a7c0..a5d48d868f9 100644 --- a/client/browser/src/shared/code-hosts/bitbucket/codeHost.tsx +++ b/client/browser/src/shared/code-hosts/bitbucket/codeHost.tsx @@ -5,13 +5,11 @@ import { Omit } from 'utility-types' import { AdjustmentDirection, PositionAdjuster } from '@sourcegraph/codeintellify' import { LineOrPositionOrRange } from '@sourcegraph/common' -import { NotificationType } from '@sourcegraph/shared/src/api/extension/extensionHostApi' import { FileSpec, RepoSpec, ResolvedRevisionSpec, RevisionSpec } from '@sourcegraph/shared/src/util/url' import { querySelectorOrSelf } from '../../util/dom' -import { CodeHost, MountGetter } from '../shared/codeHost' +import { CodeHost } from '../shared/codeHost' import { CodeView, DOMFunctions } from '../shared/codeViews' -import { createNotificationClassNameGetter } from '../shared/getNotificationClassName' import { ViewResolver } from '../shared/views' import { getContext } from './context' @@ -183,22 +181,6 @@ const newDiffCodeView: Omit = { dom: newDiffDOMFunctions, } -const getCommandPaletteMount: MountGetter = (container: HTMLElement): HTMLElement | null => { - const headerElement = querySelectorOrSelf(container, '.aui-header-primary .aui-nav') - if (!headerElement) { - return null - } - const classNames = ['command-palette-button', styles.commandPaletteButton] - const create = (): HTMLElement => { - const mount = document.createElement('li') - mount.className = classNames.join(' ') - headerElement.append(mount) - return mount - } - const preexisting = headerElement.querySelector(classNames.map(className => `.${className}`).join('')) - return preexisting || create() -} - function getViewContextOnSourcegraphMount(container: HTMLElement): HTMLElement | null { const branchSelectorButtons = querySelectorOrSelf(container, '.branch-selector-toolbar .aui-buttons') if (!branchSelectorButtons) { @@ -221,14 +203,6 @@ export const checkIsBitbucket = (): boolean => const iconClassName = 'aui-icon' -const notificationClassNames = { - [NotificationType.Log]: 'aui-message aui-message-info', - [NotificationType.Success]: 'aui-message aui-message-success', - [NotificationType.Info]: 'aui-message aui-message-info', - [NotificationType.Warning]: 'aui-message aui-message-warning', - [NotificationType.Error]: 'aui-message aui-message-error', -} - export const parseHash = (hash: string): LineOrPositionOrRange => { if (hash.startsWith('#')) { hash = hash.slice(1) @@ -254,29 +228,6 @@ export const bitbucketServerCodeHost: CodeHost = { name: 'Bitbucket Server', check: checkIsBitbucket, codeViewResolvers: [codeViewResolver, diffCodeViewResolver], - getCommandPaletteMount, - notificationClassNames, - commandPaletteClassProps: { - buttonClassName: classNames( - styles.commandListPopoverButton, - 'aui-alignment-target aui-alignment-abutted aui-alignment-abutted-left aui-alignment-element-attached-top aui-alignment-element-attached-left aui-alignment-target-attached-bottom aui-alignment-target-attached-left' - ), - buttonElement: 'a', - buttonOpenClassName: 'aui-dropdown2-active active aui-alignment-enabled', - showCaret: false, - popoverClassName: classNames( - styles.commandPalettePopover, - 'aui-dropdown2 aui-style-default aui-layer aui-dropdown2-in-header aui-alignment-element aui-alignment-side-bottom aui-alignment-snap-left aui-alignment-enabled aui-alignment-abutted aui-alignment-abutted-left aui-alignment-element-attached-top aui-alignment-element-attached-left aui-alignment-target-attached-bottom aui-alignment-target-attached-left' - ), - formClassName: 'aui', - inputClassName: 'text', - resultsContainerClassName: 'results', - listClassName: 'results-list', - listItemClassName: 'result', - selectedListItemClassName: 'focused', - noResultsClassName: styles.noResults, - iconClassName, - }, codeViewToolbarClassProps: { className: classNames(styles.codeViewToolbar, 'aui-buttons'), actionItemClass: 'aui-button', @@ -287,7 +238,6 @@ export const bitbucketServerCodeHost: CodeHost = { hoverOverlayClassProps: { className: 'aui-dialog', actionItemClassName: classNames('aui-button', styles.hoverActionItem), - getAlertClassName: createNotificationClassNameGetter(notificationClassNames), iconClassName, }, getViewContextOnSourcegraphMount, diff --git a/client/browser/src/shared/code-hosts/gerrit/codeHost.ts b/client/browser/src/shared/code-hosts/gerrit/codeHost.ts index a49812d9a71..4dbce59a5f1 100644 --- a/client/browser/src/shared/code-hosts/gerrit/codeHost.ts +++ b/client/browser/src/shared/code-hosts/gerrit/codeHost.ts @@ -365,7 +365,6 @@ export const gerritCodeHost: CodeHost = { type: 'gerrit', name: 'Gerrit', codeViewResolvers, - nativeTooltipResolvers: [], codeViewsRequireTokenization: true, // This overrides the default observeMutations because we need to handle shadow DOMS. observeMutations, @@ -378,7 +377,6 @@ export const gerritCodeHost: CodeHost = { }) }, check: checkIsGerrit, - notificationClassNames: { 1: '', 2: '', 3: '', 4: '', 5: '' }, hoverOverlayClassProps: { className: styles.hoverOverlay, }, diff --git a/client/browser/src/shared/code-hosts/github/codeHost.module.scss b/client/browser/src/shared/code-hosts/github/codeHost.module.scss index 39509eb97c6..b10a4f10365 100644 --- a/client/browser/src/shared/code-hosts/github/codeHost.module.scss +++ b/client/browser/src/shared/code-hosts/github/codeHost.module.scss @@ -18,21 +18,6 @@ } } -.command-palette-popover { - --dropdown-bg: var(--body-bg); - --dropdown-border-color: var(--border-color); - --popover-border-radius: 6px; -} - -.command-palette-action-item { - /* Reset GitHub's 44px min-height */ - min-height: initial; - - /* Reset default user agent button styles */ - border: none; - background-color: transparent; -} - .action-item { /* Match GitHub's button height even if button only contains icon * (no text that would push the height) */ diff --git a/client/browser/src/shared/code-hosts/github/codeHost.tsx b/client/browser/src/shared/code-hosts/github/codeHost.tsx index 44a93fae6a5..a9cb5c9e486 100644 --- a/client/browser/src/shared/code-hosts/github/codeHost.tsx +++ b/client/browser/src/shared/code-hosts/github/codeHost.tsx @@ -7,7 +7,6 @@ import { Omit } from 'utility-types' import { AdjustmentDirection, PositionAdjuster } from '@sourcegraph/codeintellify' import { LineOrPositionOrRange } from '@sourcegraph/common' -import { NotificationType } from '@sourcegraph/shared/src/api/extension/extensionHostApi' import { observeSystemIsLightTheme } from '@sourcegraph/shared/src/deprecated-theme-utils' import { PlatformContext } from '@sourcegraph/shared/src/platform/context' import { createURLWithUTM } from '@sourcegraph/shared/src/tracking/utm' @@ -27,13 +26,10 @@ import { getPlatformName } from '../../util/context' import { querySelectorAllOrSelf, querySelectorOrSelf } from '../../util/dom' import { CodeHost, MountGetter } from '../shared/codeHost' import { CodeView, toCodeViewResolver } from '../shared/codeViews' -import { createNotificationClassNameGetter } from '../shared/getNotificationClassName' -import { NativeTooltip } from '../shared/nativeTooltips' import { getSelectionsFromHash, observeSelectionsFromHash } from '../shared/util/selections' import { ViewResolver } from '../shared/views' import { diffDomFunctions, searchCodeSnippetDOMFunctions, singleFileDOMFunctions } from './domFunctions' -import { getCommandPaletteMount } from './extensions' import { resolveDiffFileInfo, resolveFileInfo, resolveSnippetFileInfo } from './fileInfo' import { getFileContainers, parseURL, getSelectorFor } from './util' @@ -320,21 +316,8 @@ export const createOpenOnSourcegraphIfNotExists: MountGetter = (container: HTMLE return mount } -const nativeTooltipResolver: ViewResolver = { - selector: '.js-tagsearch-popover', - resolveView: element => ({ element }), -} - const iconClassName = classNames(styles.icon, 'v-align-text-bottom') -const notificationClassNames = { - [NotificationType.Log]: 'flash', - [NotificationType.Success]: 'flash flash-success', - [NotificationType.Info]: 'flash', - [NotificationType.Warning]: 'flash flash-warn', - [NotificationType.Error]: 'flash flash-error', -} - const searchEnhancement: GithubCodeHost['searchEnhancement'] = { searchViewResolver: { selector: '.js-site-search-form input[type="text"][aria-controls="jump-to-results"]', @@ -682,7 +665,6 @@ export const githubCodeHost: GithubCodeHost = { searchEnhancement, enhanceSearchPage, codeViewResolvers: [genericCodeViewResolver, fileLineContainerResolver, searchResultCodeViewResolver], - nativeTooltipResolvers: [nativeTooltipResolver], routeChange: mutations => mutations.pipe( map(() => { @@ -728,24 +710,6 @@ export const githubCodeHost: GithubCodeHost = { iconClassName, }, check: checkIsGitHub, - getCommandPaletteMount, - notificationClassNames, - commandPaletteClassProps: { - buttonClassName: 'Header-link d-flex flex-items-baseline', - popoverClassName: classNames('Box', styles.commandPalettePopover), - formClassName: 'p-1', - inputClassName: 'form-control input-sm header-search-input jump-to-field-active', - listClassName: 'p-0 m-0 js-navigation-container jump-to-suggestions-results-container', - selectedListItemClassName: 'navigation-focus', - listItemClassName: - 'd-flex flex-justify-start flex-items-center p-0 f5 navigation-item js-navigation-item js-jump-to-scoped-search', - actionItemClassName: classNames( - styles.commandPaletteActionItem, - 'no-underline d-flex flex-auto flex-items-center jump-to-suggestions-path p-2' - ), - noResultsClassName: 'd-flex flex-auto flex-items-center jump-to-suggestions-path p-2', - iconClassName, - }, codeViewToolbarClassProps: { className: styles.codeViewToolbar, listItemClass: classNames(styles.codeViewToolbarItem, 'BtnGroup'), @@ -759,7 +723,6 @@ export const githubCodeHost: GithubCodeHost = { actionItemPressedClassName: 'active', closeButtonClassName: 'btn-octicon p-0 hover-overlay__close-button--github', badgeClassName: classNames('label', styles.hoverOverlayBadge), - getAlertClassName: createNotificationClassNameGetter(notificationClassNames, 'flash-full'), iconClassName, }, urlToFile: (sourcegraphURL, target, context) => { diff --git a/client/browser/src/shared/code-hosts/github/extensions.tsx b/client/browser/src/shared/code-hosts/github/extensions.tsx deleted file mode 100644 index 43a1251e974..00000000000 --- a/client/browser/src/shared/code-hosts/github/extensions.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { querySelectorOrSelf } from '../../util/dom' -import { MountGetter } from '../shared/codeHost' - -export const getCommandPaletteMount: MountGetter = (container: HTMLElement): HTMLElement | null => { - const className = 'command-palette-button' - // This selector matches both GitHub Enterprise and github.com - const existing = - container.querySelector(`.Header .${className}`) || - container.querySelector(`.Header-old .${className}`) // selector for not logged in user on github.com - if (existing) { - return existing - } - // Legacy header (GitHub Enterprise) - const gheHeaderElement = querySelectorOrSelf(container, '.HeaderMenu > :last-child') - if (gheHeaderElement) { - const mount = document.createElement('div') - mount.classList.add(className) - gheHeaderElement.prepend(mount) - return mount - } - // github.com doesn't use HeaderMenu to wrap the right-hand-side menu anymore, - // it has a flatter DOM structure - // Instead of finding the parent to insert into, find the sibling to insert next to - let rightNeighbor = querySelectorOrSelf(container, '.Header-item:nth-last-child(2)') - if (rightNeighbor) { - // Caveat: there is no noticiations icon if web notifications are disabled, - // but the empty header item is still there - if (rightNeighbor.previousElementSibling!.children.length !== 0) { - rightNeighbor = rightNeighbor.previousElementSibling! - } - const mount = document.createElement('div') - mount.classList.add('Header-item', 'mr-0', 'mr-lg-3', className) - rightNeighbor.before(mount) - return mount - } - return null -} diff --git a/client/browser/src/shared/code-hosts/gitlab/codeHost.module.scss b/client/browser/src/shared/code-hosts/gitlab/codeHost.module.scss index c3f41615952..a2bbd109360 100644 --- a/client/browser/src/shared/code-hosts/gitlab/codeHost.module.scss +++ b/client/browser/src/shared/code-hosts/gitlab/codeHost.module.scss @@ -2,25 +2,6 @@ --gray-10: #fafafa; // override value to avoid style conflics: https://github.com/sourcegraph/sourcegraph/pull/32548 } -.command-list-popover { - // The navbar has z-index 1000 - z-index: 1001 !important; - - --dropdown-bg: var(--gray-50, #ffffff); - --dropdown-shadow: 0 2px 4px rgba(0, 0, 0, 10%); - --dropdown-border-color: var(--border-color); - --popover-border-radius: 3px; -} - -:global(.show) > .command-list-popover { - display: block; -} - -.command-palette-button > span { - display: flex; - align-items: center; -} - .btn-icon { img { // Gitlab applies this to svgs, diff --git a/client/browser/src/shared/code-hosts/gitlab/codeHost.ts b/client/browser/src/shared/code-hosts/gitlab/codeHost.ts index 2c975dc0e48..d6443fbca31 100644 --- a/client/browser/src/shared/code-hosts/gitlab/codeHost.ts +++ b/client/browser/src/shared/code-hosts/gitlab/codeHost.ts @@ -6,7 +6,6 @@ import { Omit } from 'utility-types' import { fetchCache, LineOrPositionOrRange, subtypeOf } from '@sourcegraph/common' import { gql, dataOrThrowErrors } from '@sourcegraph/http-client' -import { NotificationType } from '@sourcegraph/shared/src/api/extension/extensionHostApi' import { toAbsoluteBlobURL } from '@sourcegraph/shared/src/util/url' import { background } from '../../../browser-extension/web-extension-api/runtime' @@ -14,12 +13,10 @@ import { ResolveRepoNameResult, ResolveRepoNameVariables } from '../../../graphq import { isInPage } from '../../context' import { CodeHost } from '../shared/codeHost' import { CodeView } from '../shared/codeViews' -import { createNotificationClassNameGetter } from '../shared/getNotificationClassName' import { getSelectionsFromHash, observeSelectionsFromHash } from '../shared/util/selections' import { queryWithSelector, ViewResolver } from '../shared/views' import { diffDOMFunctions, singleFileDOMFunctions } from './domFunctions' -import { getCommandPaletteMount } from './extensions' import { resolveCommitFileInfo, resolveDiffFileInfo, resolveFileInfo } from './fileInfo' import { getPageInfo, @@ -121,14 +118,6 @@ const codeViewResolver: ViewResolver = { resolveView, } -const notificationClassNames = { - [NotificationType.Log]: 'alert alert-secondary', - [NotificationType.Success]: 'alert alert-success', - [NotificationType.Info]: 'alert alert-info', - [NotificationType.Warning]: 'alert alert-warning', - [NotificationType.Error]: 'alert alert-danger', -} - /** * Checks whether repository is private or not using Gitlab API * @@ -202,7 +191,6 @@ export const gitlabCodeHost = subtypeOf()({ name: 'GitLab', check: checkIsGitlab, codeViewResolvers: [codeViewResolver], - getCommandPaletteMount, getContext: async () => { const { repoName, ...pageInfo } = getPageInfo() return { @@ -252,16 +240,6 @@ export const gitlabCodeHost = subtypeOf()({ } return url.href }, - notificationClassNames, - commandPaletteClassProps: { - popoverClassName: classNames('dropdown-menu', styles.commandListPopover), - formClassName: 'dropdown-input', - inputClassName: 'dropdown-input-field', - resultsContainerClassName: 'dropdown-content', - selectedActionItemClassName: 'is-focused', - noResultsClassName: 'px-3', - iconClassName: 's16 align-bottom', - }, codeViewToolbarClassProps: { className: 'pl-0', actionItemClass: 'btn btn-md gl-button btn-icon', @@ -274,7 +252,6 @@ export const gitlabCodeHost = subtypeOf()({ actionItemPressedClassName: 'active', closeButtonClassName: 'btn btn-transparent p-0 btn-icon--gitlab', iconClassName: 'square s16', - getAlertClassName: createNotificationClassNameGetter(notificationClassNames), }, codeViewsRequireTokenization: true, getHoverOverlayMountLocation: (): string | null => { diff --git a/client/browser/src/shared/code-hosts/gitlab/extensions.ts b/client/browser/src/shared/code-hosts/gitlab/extensions.ts deleted file mode 100644 index bad7a51e4eb..00000000000 --- a/client/browser/src/shared/code-hosts/gitlab/extensions.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { querySelectorOrSelf } from '../../util/dom' -import { MountGetter } from '../shared/codeHost' - -import styles from './codeHost.module.scss' - -export const getCommandPaletteMount: MountGetter = (container: HTMLElement): HTMLElement | null => { - const headerElement = querySelectorOrSelf(container, '.navbar-collapse') - if (!headerElement) { - return null - } - const commandListClass = 'command-palette-button' - const createCommandList = (): HTMLElement => { - const mount = document.createElement('div') - mount.classList.add(commandListClass, styles.commandPaletteButton) - headerElement.prepend(mount) - return mount - } - return headerElement.querySelector('.' + commandListClass) || createCommandList() -} diff --git a/client/browser/src/shared/code-hosts/phabricator/codeHost.ts b/client/browser/src/shared/code-hosts/phabricator/codeHost.ts index a6d61957802..88fdf9ba68a 100644 --- a/client/browser/src/shared/code-hosts/phabricator/codeHost.ts +++ b/client/browser/src/shared/code-hosts/phabricator/codeHost.ts @@ -3,14 +3,12 @@ import { map } from 'rxjs/operators' import { AdjustmentDirection, PositionAdjuster } from '@sourcegraph/codeintellify' import { Position } from '@sourcegraph/extension-api-types' -import { NotificationType } from '@sourcegraph/shared/src/api/extension/extensionHostApi' import { PlatformContext } from '@sourcegraph/shared/src/platform/context' import { FileSpec, RepoSpec, ResolvedRevisionSpec, RevisionSpec } from '@sourcegraph/shared/src/util/url' import { fetchBlobContentLines } from '../../repo/backend' import { CodeHost } from '../shared/codeHost' import { CodeView, toCodeViewResolver } from '../shared/codeViews' -import { createNotificationClassNameGetter } from '../shared/getNotificationClassName' import { ViewResolver } from '../shared/views' import { diffDomFunctions, diffusionDOMFns } from './domFunctions' @@ -175,14 +173,6 @@ const phabSourceCodeViewResolver = toCodeViewResolver('.phabricator-source-code- resolveFileInfo: resolveDiffusionFileInfo, }) -const notificationClassNames = { - [NotificationType.Log]: 'phui-info-view phui-info-severity-plain', - [NotificationType.Success]: 'phui-info-view phui-info-severity-success', - [NotificationType.Info]: 'phui-info-view phui-info-severity-notice', - [NotificationType.Warning]: 'phui-info-view phui-info-severity-warning', - [NotificationType.Error]: 'phui-info-view phui-info-severity-error', -} - export const checkIsPhabricator = (): boolean => !!document.querySelector('.phabricator-wordmark') export const phabricatorCodeHost: CodeHost = { @@ -201,13 +191,11 @@ export const phabricatorCodeHost: CodeHost = { actionItemClass: classNames('button grey', styles.actionItem), actionItemIconClass: styles.icon, }, - notificationClassNames, hoverOverlayClassProps: { className: classNames('aphront-dialog-view', styles.hoverOverlay), actionItemClassName: classNames('button grey', styles.hoverOverlayActionItem), closeButtonClassName: 'button grey btn-icon--phabricator', iconClassName: styles.hoverOverlayActionItemIcon, - getAlertClassName: createNotificationClassNameGetter(notificationClassNames), }, codeViewsRequireTokenization: true, } diff --git a/client/browser/src/shared/code-hosts/shared/codeHost.test.tsx b/client/browser/src/shared/code-hosts/shared/codeHost.test.tsx index be1c499afac..4dd6a8fba8b 100644 --- a/client/browser/src/shared/code-hosts/shared/codeHost.test.tsx +++ b/client/browser/src/shared/code-hosts/shared/codeHost.test.tsx @@ -15,7 +15,6 @@ import { SuccessGraphQLResult } from '@sourcegraph/http-client' import { wrapRemoteObservable } from '@sourcegraph/shared/src/api/client/api/common' import { FlatExtensionHostAPI } from '@sourcegraph/shared/src/api/contract' import { ExtensionCodeEditor } from '@sourcegraph/shared/src/api/extension/api/codeEditor' -import { NotificationType } from '@sourcegraph/shared/src/api/extension/extensionHostApi' import { Controller } from '@sourcegraph/shared/src/extensions/controller' import { NOOP_TELEMETRY_SERVICE } from '@sourcegraph/shared/src/telemetry/telemetryService' import { MockIntersectionObserver } from '@sourcegraph/shared/src/testing/MockIntersectionObserver' @@ -39,14 +38,6 @@ import { DEFAULT_GRAPHQL_RESPONSES, mockRequestGraphQL } from './testHelpers' const RENDER = sinon.spy() -const notificationClassNames = { - [NotificationType.Log]: 'log', - [NotificationType.Success]: 'success', - [NotificationType.Info]: 'info', - [NotificationType.Warning]: 'warning', - [NotificationType.Error]: 'error', -} - const elementRenderedAtMount = (mount: Element): RenderResult | undefined => { const call = RENDER.args.find(call => call[1] === mount) return call?.[0] @@ -68,7 +59,6 @@ jest.mock('uuid', () => ({ const createMockController = (extensionHostAPI: Remote): Controller => ({ executeCommand: () => Promise.resolve(), registerCommand: () => new Subscription(), - commandErrors: NEVER, unsubscribe: noop, extHostAPI: Promise.resolve(extensionHostAPI), }) @@ -149,7 +139,6 @@ describe('codeHost', () => { name: 'GitHub', check: () => true, codeViewResolvers: [], - notificationClassNames, }, extensionsController: createMockController(extensionHostAPI), }) @@ -161,27 +150,6 @@ describe('codeHost', () => { expect(renderedOverlay).not.toBeUndefined() }) - test('renders the command palette if codeHost.getCommandPaletteMount is defined', async () => { - const { extensionHostAPI } = await integrationTestContext() - const commandPaletteMount = createTestElement() - subscriptions.add( - await handleCodeHost({ - ...commonArguments(), - codeHost: { - type: 'github', - name: 'GitHub', - check: () => true, - getCommandPaletteMount: () => commandPaletteMount, - codeViewResolvers: [], - notificationClassNames, - }, - extensionsController: createMockController(extensionHostAPI), - }) - ) - const renderedCommandPalette = elementRenderedAtMount(commandPaletteMount) - expect(renderedCommandPalette).not.toBeUndefined() - }) - test('detects code views based on selectors', async () => { const { extensionHostAPI, extensionAPI } = await integrationTestContext(undefined, { roots: [], @@ -205,7 +173,6 @@ describe('codeHost', () => { type: 'github', name: 'GitHub', check: () => true, - notificationClassNames, codeViewResolvers: [ toCodeViewResolver('#code', { dom: { @@ -214,7 +181,7 @@ describe('codeHost', () => { getLineElementFromLineNumber: sinon.spy(), getLineNumberFromCodeElement: sinon.spy(), }, - resolveFileInfo: codeView => of(blobInfo), + resolveFileInfo: () => of(blobInfo), getToolbarMount: () => toolbarMount, }), ], @@ -284,7 +251,6 @@ describe('codeHost', () => { type: 'github', name: 'GitHub', check: () => true, - notificationClassNames, codeViewResolvers: [ toCodeViewResolver('.code', { dom: { @@ -349,7 +315,7 @@ describe('codeHost', () => { expect(getEditors(extensionAPI)).toEqual([]) }) - test('Hoverifies a view if the code host has no nativeTooltipResolvers', async () => { + test('Hoverifies a view', async () => { const { extensionHostAPI, extensionAPI } = await integrationTestContext(undefined, { roots: [], viewers: [], @@ -372,11 +338,10 @@ describe('codeHost', () => { type: 'github', name: 'GitHub', check: () => true, - notificationClassNames, codeViewResolvers: [ toCodeViewResolver('#code', { dom, - resolveFileInfo: codeView => + resolveFileInfo: () => of({ blob: { rawRepoName: 'foo', @@ -396,129 +361,6 @@ describe('codeHost', () => { codeView.dispatchEvent(new MouseEvent('mouseover')) sinon.assert.called(dom.getCodeElementFromTarget) }) - - test('Does not hoverify a view if the code host has nativeTooltipResolvers and they are enabled from settings', async () => { - const { extensionHostAPI, extensionAPI } = await integrationTestContext(undefined, { - roots: [], - viewers: [], - }) - const codeView = createTestElement() - codeView.id = 'code' - const codeElement = document.createElement('span') - codeElement.textContent = 'alert(1)' - codeView.append(codeElement) - const dom = { - getCodeElementFromTarget: sinon.spy(() => codeElement), - getCodeElementFromLineNumber: sinon.spy(() => codeElement), - getLineElementFromLineNumber: sinon.spy(() => codeElement), - getLineNumberFromCodeElement: sinon.spy(() => 1), - } - subscriptions.add( - await handleCodeHost({ - ...commonArguments(), - codeHost: { - type: 'github', - name: 'GitHub', - check: () => true, - notificationClassNames, - nativeTooltipResolvers: [{ selector: '.native', resolveView: element => ({ element }) }], - codeViewResolvers: [ - toCodeViewResolver('#code', { - dom, - resolveFileInfo: codeView => - of({ - blob: { - rawRepoName: 'foo', - filePath: '/bar.ts', - commitID: '1', - }, - }), - }), - ], - }, - extensionsController: createMockController(extensionHostAPI), - platformContext: { - ...createMockPlatformContext(), - settings: of({ - subjects: [], - final: { - extensions: {}, - 'codeHost.useNativeTooltips': true, - }, - }), - }, - }) - ) - await wrapRemoteObservable(extensionHostAPI.viewerUpdates()).pipe(first()).toPromise() - - expect(getEditors(extensionAPI).length).toEqual(1) - await tick() - - codeView.dispatchEvent(new MouseEvent('mouseover')) - sinon.assert.notCalled(dom.getCodeElementFromTarget) - }) - - test('Hides native tooltips if they are disabled from settings', async () => { - const { extensionHostAPI, extensionAPI } = await integrationTestContext(undefined, { - roots: [], - viewers: [], - }) - const codeView = createTestElement() - codeView.id = 'code' - const codeElement = document.createElement('span') - codeElement.textContent = 'alert(1)' - codeView.append(codeElement) - const nativeTooltip = createTestElement() - nativeTooltip.classList.add('native') - const dom = { - getCodeElementFromTarget: sinon.spy(() => codeElement), - getCodeElementFromLineNumber: sinon.spy(() => codeElement), - getLineElementFromLineNumber: sinon.spy(() => codeElement), - getLineNumberFromCodeElement: sinon.spy(() => 1), - } - subscriptions.add( - await handleCodeHost({ - ...commonArguments(), - codeHost: { - type: 'github', - name: 'GitHub', - check: () => true, - notificationClassNames, - nativeTooltipResolvers: [{ selector: '.native', resolveView: element => ({ element }) }], - codeViewResolvers: [ - toCodeViewResolver('#code', { - dom, - resolveFileInfo: codeView => - of({ - blob: { - rawRepoName: 'foo', - filePath: '/bar.ts', - commitID: '1', - }, - }), - }), - ], - }, - extensionsController: createMockController(extensionHostAPI), - platformContext: { - ...createMockPlatformContext(), - settings: of({ - subjects: [], - final: { - extensions: {}, - 'codeHost.useNativeTooltips': false, - }, - }), - }, - }) - ) - await wrapRemoteObservable(extensionHostAPI.viewerUpdates()).pipe(first()).toPromise() - expect(getEditors(extensionAPI).length).toEqual(1) - await tick() - codeView.dispatchEvent(new MouseEvent('mouseover')) - sinon.assert.called(dom.getCodeElementFromTarget) - expect(nativeTooltip).toHaveAttribute('data-native-tooltip-hidden', 'true') - }) }) describe('observeHoverOverlayMountLocation()', () => { diff --git a/client/browser/src/shared/code-hosts/shared/codeHost.tsx b/client/browser/src/shared/code-hosts/shared/codeHost.tsx index 0c7507ee8ca..c5990874c86 100644 --- a/client/browser/src/shared/code-hosts/shared/codeHost.tsx +++ b/client/browser/src/shared/code-hosts/shared/codeHost.tsx @@ -63,16 +63,10 @@ import { ActionItemAction } from '@sourcegraph/shared/src/actions/ActionItem' import { wrapRemoteObservable } from '@sourcegraph/shared/src/api/client/api/common' import { CodeEditorData, CodeEditorWithPartialModel } from '@sourcegraph/shared/src/api/viewerTypes' import { isRepoNotFoundErrorLike } from '@sourcegraph/shared/src/backend/errors' -import { HoverAlert } from '@sourcegraph/shared/src/codeintel/legacy-extensions/api' -import { - CommandListClassProps, - CommandListPopoverButtonClassProps, -} from '@sourcegraph/shared/src/commandPalette/CommandList' import { Controller } from '@sourcegraph/shared/src/extensions/controller' import { getHoverActions, registerHoverContributions } from '@sourcegraph/shared/src/hover/actions' import { HoverContext, HoverOverlay, HoverOverlayClassProps } from '@sourcegraph/shared/src/hover/HoverOverlay' import { getModeFromPath } from '@sourcegraph/shared/src/languages' -import { UnbrandedNotificationItemStyleProps } from '@sourcegraph/shared/src/notifications/NotificationItem' import { PlatformContext, URLToFileContext } from '@sourcegraph/shared/src/platform/context' import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService' import { createURLWithUTM } from '@sourcegraph/shared/src/tracking/utm' @@ -112,14 +106,7 @@ import { phabricatorCodeHost } from '../phabricator/codeHost' import { CodeView, trackCodeViews, fetchFileContentForDiffOrFileInfo } from './codeViews' import { NotAuthenticatedError, RepoURLParseError } from './errors' -import { initializeExtensions, renderCommandPalette } from './extensions' -import { createRepoNotFoundHoverAlert, getActiveHoverAlerts, onHoverAlertDismissed } from './hoverAlerts' -import { - handleNativeTooltips, - NativeTooltip, - nativeTooltipsEnabledFromSettings, - registerNativeTooltipContributions, -} from './nativeTooltips' +import { initializeExtensions } from './extensions' import { SignInButton } from './SignInButton' import { resolveRepoNamesForDiffOrFileInfo, defaultRevisionToCommitID } from './util/fileInfo' import { @@ -218,11 +205,6 @@ export interface CodeHost { */ codeViewResolvers: ViewResolver[] - /** - * Resolves {@link NativeTooltip}s from the DOM. - */ - nativeTooltipResolvers?: ViewResolver[] - /** * Override of `observeMutations`, used where a MutationObserve is not viable, such as in the shadow DOMs in Gerrit. */ @@ -230,13 +212,6 @@ export interface CodeHost { // Extensions related input - /** - * Mount getter for the command palette button for extensions. - * - * If undefined, the command palette button won't be rendered on the code host. - */ - getCommandPaletteMount?: MountGetter - /** * Returns a selector used to determine the mount location of the hover overlay in the DOM. * @@ -259,13 +234,6 @@ export interface CodeHost { observeLineSelection?: Observable - notificationClassNames: UnbrandedNotificationItemStyleProps['notificationItemClassNames'] - - /** - * CSS classes for the command palette to customize styling - */ - commandPaletteClassProps?: CommandListPopoverButtonClassProps & CommandListClassProps - /** * CSS classes for the code view toolbar to customize styling */ @@ -349,11 +317,9 @@ function initCodeIntelligence({ extensionsController, render, telemetryService, - hoverAlerts, repoSyncErrors, }: Pick & { render: Renderer - hoverAlerts: Observable[] mutations: Observable repoSyncErrors: Observable }): { @@ -394,8 +360,8 @@ function initCodeIntelligence({ getHover: ({ line, character, part, ...rest }) => concat( [{ isLoading: true, result: null }], - combineLatest([ - from(extensionsController.extHostAPI).pipe( + from(extensionsController.extHostAPI) + .pipe( withLatestFrom(repoSyncErrors), switchMap(([extensionHost, hasRepoSyncError]) => // Prevent GraphQL requests that we know will result in error/null when the repo is private (and not added to Cloud) @@ -407,23 +373,15 @@ function initCodeIntelligence({ ) ) ) - ), - getActiveHoverAlerts([ - ...hoverAlerts, - repoSyncErrors.pipe( - distinctUntilChanged(), - map(showAlert => (showAlert ? createRepoNotFoundHoverAlert(codeHost) : undefined)), - filter(isDefined) - ), - ]), - ]).pipe( - map( - ([{ isLoading, result: hoverMerged }, alerts]): MaybeLoadingResult => ({ - isLoading, - result: hoverMerged || alerts?.length ? { contents: [], ...hoverMerged, alerts } : null, - }) ) - ) + .pipe( + map( + ({ isLoading, result: hoverMerged }): MaybeLoadingResult => ({ + isLoading, + result: hoverMerged || null, + }) + ) + ) ), getDocumentHighlights: ({ line, character, part, ...rest }) => from(extensionsController.extHostAPI).pipe( @@ -512,7 +470,6 @@ function initCodeIntelligence({ extensionsController={extensionsController} platformContext={platformContext} location={H.createLocation(window.location)} - onAlertDismissed={onHoverAlertDismissed} useBrandedLogo={true} /> @@ -754,7 +711,6 @@ export async function handleCodeHost({ hideActions, background, }: HandleCodeHostOptions): Promise { - const history = H.createBrowserHistory() const subscriptions = new Subscription() const { requestGraphQL, sourcegraphURL } = platformContext @@ -771,11 +727,6 @@ export async function handleCodeHost({ document.body.classList.toggle('theme-dark', !isLightTheme) }) ) - const nativeTooltipsEnabled = codeHost.nativeTooltipResolvers - ? nativeTooltipsEnabledFromSettings(platformContext.settings) - : of(false) - - const hoverAlerts: Observable[] = [] /** * A stream that emits a boolean that signifies whether any request for @@ -817,49 +768,18 @@ export async function handleCodeHost({ return subscriptions } - if (codeHost.nativeTooltipResolvers) { - const { subscription, nativeTooltipsAlert } = handleNativeTooltips( - mutations, - nativeTooltipsEnabled, - codeHost, - repoSyncErrors - ) - subscriptions.add(subscription) - hoverAlerts.push(nativeTooltipsAlert) - subscriptions.add(registerNativeTooltipContributions(extensionsController)) - } - const { hoverifier, subscription } = initCodeIntelligence({ codeHost, extensionsController, platformContext, telemetryService, render, - hoverAlerts, mutations, repoSyncErrors, }) subscriptions.add(hoverifier) subscriptions.add(subscription) - // Inject UI components - // Render command palette - if (codeHost.getCommandPaletteMount && !minimalUI && extensionsController !== null) { - subscriptions.add( - addedElements.pipe(map(codeHost.getCommandPaletteMount), filter(isDefined)).subscribe( - renderCommandPalette({ - extensionsController, - history, - platformContext, - telemetryService, - render, - ...codeHost.commandPaletteClassProps, - notificationClassNames: codeHost.notificationClassNames, - }) - ) - ) - } - const signInCloses = new Subject() const nextSignInClose = signInCloses.next.bind(signInCloses) @@ -1268,32 +1188,25 @@ export async function handleCodeHost({ } const adjustPosition = getPositionAdjuster?.(platformContext.requestGraphQL) - let hoverSubscription = new Subscription() codeViewEvent.subscriptions.add( - nativeTooltipsEnabled.subscribe(useNativeTooltips => { - hoverSubscription.unsubscribe() - if (!useNativeTooltips) { - hoverSubscription = hoverifier.hoverify({ - dom: domFunctions, - positionEvents: of(element).pipe( - findPositionsFromEvents({ - domFunctions, - tokenize: !!(typeof overrideTokenize === 'boolean' - ? overrideTokenize - : codeHost.codeViewsRequireTokenization), - }) - ), - resolveContext, - adjustPosition, - scrollBoundaries: codeViewEvent.getScrollBoundaries - ? codeViewEvent.getScrollBoundaries(codeViewEvent.element) - : [], - overrideTokenize, + hoverifier.hoverify({ + dom: domFunctions, + positionEvents: of(element).pipe( + findPositionsFromEvents({ + domFunctions, + tokenize: !!(typeof overrideTokenize === 'boolean' + ? overrideTokenize + : codeHost.codeViewsRequireTokenization), }) - } + ), + resolveContext, + adjustPosition, + scrollBoundaries: codeViewEvent.getScrollBoundaries + ? codeViewEvent.getScrollBoundaries(codeViewEvent.element) + : [], + overrideTokenize, }) ) - codeViewEvent.subscriptions.add(hoverSubscription) element.classList.add('sg-mounted') // Render toolbar @@ -1458,7 +1371,7 @@ export function injectCodeIntelligenceToCodeHost( } subscriptions.add( - // eslint-disable-next-line rxjs/no-async-subscribe, @typescript-eslint/no-misused-promises + // eslint-disable-next-line rxjs/no-async-subscribe combineLatest([codeHostReady, extensionDisabled]).subscribe(async ([isCodeHostReady, disableExtension]) => { if (disableExtension) { // We don't need to unsubscribe if the extension starts with disabled state. diff --git a/client/browser/src/shared/code-hosts/shared/codeHostTestUtils.ts b/client/browser/src/shared/code-hosts/shared/codeHostTestUtils.ts index b2f862e49a1..5f4f97740b7 100644 --- a/client/browser/src/shared/code-hosts/shared/codeHostTestUtils.ts +++ b/client/browser/src/shared/code-hosts/shared/codeHostTestUtils.ts @@ -9,7 +9,7 @@ import { DiffPart } from '@sourcegraph/codeintellify' import { CodeHost, MountGetter } from './codeHost' import { CodeView, DOMFunctions } from './codeViews' -const mountGetterKeys = ['getCommandPaletteMount', 'getViewContextOnSourcegraphMount'] as const +const mountGetterKeys = ['getViewContextOnSourcegraphMount'] as const type MountGetterKey = typeof mountGetterKeys[number] /** diff --git a/client/browser/src/shared/code-hosts/shared/extensions.tsx b/client/browser/src/shared/code-hosts/shared/extensions.tsx index 3cd15da8d6f..d74c3fe97ca 100644 --- a/client/browser/src/shared/code-hosts/shared/extensions.tsx +++ b/client/browser/src/shared/code-hosts/shared/extensions.tsx @@ -1,23 +1,6 @@ -import classNames from 'classnames' -import * as H from 'history' -import { Renderer } from 'react-dom' - -import { ContributableMenu } from '@sourcegraph/client-api' -import { - CommandListPopoverButton, - CommandListPopoverButtonProps, -} from '@sourcegraph/shared/src/commandPalette/CommandList' -import { - ExtensionsControllerProps, - RequiredExtensionsControllerProps, -} from '@sourcegraph/shared/src/extensions/controller' +import { ExtensionsControllerProps } from '@sourcegraph/shared/src/extensions/controller' import { createController as createExtensionsController } from '@sourcegraph/shared/src/extensions/createSyncLoadedController' -import { UnbrandedNotificationItemStyleProps } from '@sourcegraph/shared/src/notifications/NotificationItem' -import { Notifications } from '@sourcegraph/shared/src/notifications/Notifications' -import { PlatformContextProps } from '@sourcegraph/shared/src/platform/context' -import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService' -import { ShortcutProvider } from '../../components/ShortcutProvider' import { createPlatformContext, SourcegraphIntegrationURLs, BrowserPlatformContext } from '../../platform/context' import { CodeHost } from './codeHost' @@ -35,38 +18,3 @@ export function initializeExtensions( const extensionsController = createExtensionsController(platformContext) return { platformContext, extensionsController } } - -interface InjectProps extends PlatformContextProps<'settings' | 'sourcegraphURL'>, RequiredExtensionsControllerProps { - history: H.History - render: Renderer -} - -interface RenderCommandPaletteProps - extends TelemetryProps, - InjectProps, - Pick { - notificationClassNames: UnbrandedNotificationItemStyleProps['notificationItemClassNames'] -} - -export const renderCommandPalette = - ({ extensionsController, history, render, ...props }: RenderCommandPaletteProps) => - (mount: HTMLElement): void => { - render( - - - - , - mount - ) - } diff --git a/client/browser/src/shared/code-hosts/shared/getNotificationClassName.ts b/client/browser/src/shared/code-hosts/shared/getNotificationClassName.ts deleted file mode 100644 index 68d5bd66096..00000000000 --- a/client/browser/src/shared/code-hosts/shared/getNotificationClassName.ts +++ /dev/null @@ -1,8 +0,0 @@ -import classNames from 'classnames' - -import type { NotificationType } from '@sourcegraph/shared/src/codeintel/legacy-extensions/api' - -export const createNotificationClassNameGetter = - (notificationClassNames: Record, extraClassName?: string) => - (notificationType: NotificationType): string => - classNames(notificationClassNames[notificationType], extraClassName) diff --git a/client/browser/src/shared/code-hosts/shared/hoverAlerts.tsx b/client/browser/src/shared/code-hosts/shared/hoverAlerts.tsx deleted file mode 100644 index 9935f48c278..00000000000 --- a/client/browser/src/shared/code-hosts/shared/hoverAlerts.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { Observable, of } from 'rxjs' -import { catchError, map, startWith, switchMap } from 'rxjs/operators' - -import { combineLatestOrDefault } from '@sourcegraph/common' -import { MarkupKind } from '@sourcegraph/extension-api-classes' -import type { HoverAlert } from '@sourcegraph/shared/src/codeintel/legacy-extensions/api' -import { ButtonLink } from '@sourcegraph/wildcard' - -import { observeStorageKey, storage } from '../../../browser-extension/web-extension-api/storage' -import { SyncStorageItems } from '../../../browser-extension/web-extension-api/types' -import { isInPage } from '../../context' - -import { CodeHost } from './codeHost' - -/** - * Returns an Observable of all hover alerts that have not yet - * been dismissed by the user. - */ -export function getActiveHoverAlerts(allAlerts: Observable[]): Observable { - if (isInPage) { - return of(undefined) - } - return observeStorageKey('sync', 'dismissedHoverAlerts').pipe( - switchMap(dismissedAlerts => - combineLatestOrDefault(allAlerts).pipe( - map(alerts => (dismissedAlerts ? alerts.filter(({ type }) => !type || !dismissedAlerts[type]) : alerts)) - ) - ), - catchError(error => { - console.error('Error getting hover alerts', error) - return [undefined] - }), - startWith([]) - ) -} -/** - * Marks a hover alert as dismissed in sync storage. - */ -export async function onHoverAlertDismissed(alertType: string): Promise { - try { - const partialStorageItems: Pick = { - dismissedHoverAlerts: {}, - ...(await storage.sync.get('dismissedHoverAlerts')), - } - partialStorageItems.dismissedHoverAlerts[alertType] = true - await storage.sync.set(partialStorageItems) - } catch (error) { - console.error('Error dismissing alert', error) - } -} - -/** - * Returns the alert to show when the user is on an unindexed repo and does not - * have sourcegraph.com as the URL. The alert informs the user to setup add a - * repo. - */ -export const createRepoNotFoundHoverAlert = (codeHost: Pick): HoverAlert => ({ - type: 'private-code', - buttons: [ - - Learn more - , - ], - summary: { - kind: MarkupKind.Markdown, - value: - '#### Repository not added\n\n' + - 'This repository is not indexed by your Sourcegraph instance. Add the repository to get Code Intelligence overlays.', - }, -}) diff --git a/client/browser/src/shared/code-hosts/shared/nativeTooltips.tsx b/client/browser/src/shared/code-hosts/shared/nativeTooltips.tsx deleted file mode 100644 index 47b248f23e6..00000000000 --- a/client/browser/src/shared/code-hosts/shared/nativeTooltips.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { isEqual } from 'lodash' -import { from, Observable, Unsubscribable } from 'rxjs' -import { - distinctUntilChanged, - filter, - first, - map, - mapTo, - publishReplay, - refCount, - switchMap, - withLatestFrom, -} from 'rxjs/operators' - -import { ErrorLike, isErrorLike, isDefined, isNot } from '@sourcegraph/common' -import { MarkupKind } from '@sourcegraph/extension-api-classes' -import { syncRemoteSubscription } from '@sourcegraph/shared/src/api/util' -import type { HoverAlert } from '@sourcegraph/shared/src/codeintel/legacy-extensions/api' -import { Controller as ExtensionsController } from '@sourcegraph/shared/src/extensions/controller' -import { PlatformContext } from '@sourcegraph/shared/src/platform/context' -import { Settings } from '@sourcegraph/shared/src/settings/settings' - -import { MutationRecordLike } from '../../util/dom' - -import { CodeHost } from './codeHost' -import { trackViews } from './views' - -import styles from './nativeTooltips.module.scss' - -const NATIVE_TOOLTIP_HIDDEN = styles.nativeTooltipHidden -const NATIVE_TOOLTIP_TYPE = 'nativeTooltips' - -/** - * Defines a native tooltip that is present on a page and exposes operations for manipulating it. - */ -export interface NativeTooltip { - /** The native tooltip HTML element. */ - element: HTMLElement -} - -export function handleNativeTooltips( - mutations: Observable, - nativeTooltipsEnabled: Observable, - { nativeTooltipResolvers, name }: Pick, - repoSyncErrors: Observable -): { nativeTooltipsAlert: Observable; subscription: Unsubscribable } { - const nativeTooltips = mutations.pipe(trackViews(nativeTooltipResolvers || [])) - const nativeTooltipsAlert = nativeTooltips.pipe( - first(), - switchMap(() => - repoSyncErrors.pipe( - filter(hasError => !hasError), - mapTo({ - type: NATIVE_TOOLTIP_TYPE, - summary: { - kind: MarkupKind.Markdown, - value: `Sourcegraph has hidden ${name}'s native hover tooltips. You can toggle this at any time: to enable the native tooltips run "Code host: prefer non-Sourcegraph hover tooltips" from the command palette or set {"codeHost.useNativeTooltips": true} in your user settings.`, - }, - }) - ) - ), - publishReplay(1), - refCount() - ) - return { - nativeTooltipsAlert, - subscription: nativeTooltips.subscribe(({ element, subscriptions }) => { - subscriptions.add( - nativeTooltipsEnabled - .pipe(withLatestFrom(repoSyncErrors)) - // This subscription is correctly handled through the view's `subscriptions` - // eslint-disable-next-line rxjs/no-nested-subscribe - .subscribe(([enabled, hasRepoSyncError]) => { - // If we can't provide the user hovers because it's private code, don't hide native tooltips. - // Otherwise we would have to show the user two alerts at the same time. - const isTooltipHidden = !enabled && !hasRepoSyncError - element.dataset.nativeTooltipHidden = String(isTooltipHidden) - element.classList.toggle(NATIVE_TOOLTIP_HIDDEN, isTooltipHidden) - }) - ) - }), - } -} - -export function nativeTooltipsEnabledFromSettings(settings: PlatformContext['settings']): Observable { - return from(settings).pipe( - map(({ final }) => final), - filter(isDefined), - filter(isNot(isErrorLike)), - map(settings => !!settings['codeHost.useNativeTooltips']), - distinctUntilChanged((a, b) => isEqual(a, b)), - publishReplay(1), - refCount() - ) -} - -export function registerNativeTooltipContributions( - extensionsController: Pick -): Unsubscribable { - return syncRemoteSubscription( - extensionsController.extHostAPI.then(extensionHostAPI => - extensionHostAPI.registerContributions({ - actions: [ - { - id: 'codeHost.toggleUseNativeTooltips', - command: 'updateConfiguration', - category: 'Code host', - commandArguments: [ - 'codeHost.useNativeTooltips', - /* eslint-disable-next-line no-template-curly-in-string */ - '${!config.codeHost.useNativeTooltips}', - null, - 'json', - ], - title: - /* eslint-disable-next-line no-template-curly-in-string */ - 'Prefer ${config.codeHost.useNativeTooltips && "Sourcegraph" || "non-Sourcegraph"} hover tooltips', - }, - ], - menus: { - commandPalette: [ - { - action: 'codeHost.toggleUseNativeTooltips', - }, - ], - }, - }) - ) - ) -} diff --git a/client/browser/src/shared/components/HoverOverlay.story.tsx b/client/browser/src/shared/components/HoverOverlay.story.tsx index 3eacabf5045..ad647ddac77 100644 --- a/client/browser/src/shared/components/HoverOverlay.story.tsx +++ b/client/browser/src/shared/components/HoverOverlay.story.tsx @@ -4,7 +4,6 @@ import classNames from 'classnames' import { BrowserRouter } from 'react-router-dom' import { registerHighlightContributions } from '@sourcegraph/common' -import { NotificationType } from '@sourcegraph/shared/src/api/extension/extensionHostApi' import { HoverOverlay, HoverOverlayClassProps } from '@sourcegraph/shared/src/hover/HoverOverlay' import { commonProps, @@ -45,14 +44,6 @@ const BITBUCKET_CLASS_PROPS: HoverOverlayClassProps = { className: 'aui-dialog', actionItemClassName: classNames('aui-button', bitbucketCodeHostStyles.hoverActionItem), iconClassName: 'aui-icon', - getAlertClassName: alertKind => { - switch (alertKind) { - case NotificationType.Error: - return 'aui-message aui-message-error' - default: - return 'aui-message aui-message-info' - } - }, } export const BitbucketStyles: Story = (props = {}) => ( diff --git a/client/browser/src/types/string-score/index.d.ts b/client/browser/src/types/string-score/index.d.ts deleted file mode 100644 index 515ca6fbe7b..00000000000 --- a/client/browser/src/types/string-score/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module 'string-score' { - function score(target: string, query: string, fuzzyFactor?: number): number - - export = score -} diff --git a/client/client-api/src/contribution.ts b/client/client-api/src/contribution.ts index b3c47fa49be..d2fad060a51 100644 --- a/client/client-api/src/contribution.ts +++ b/client/client-api/src/contribution.ts @@ -225,9 +225,6 @@ export interface ActionItem { } export enum ContributableMenu { - /** The global command palette. */ - CommandPalette = 'commandPalette', - /** The global navigation bar in the application. */ GlobalNav = 'global/nav', diff --git a/client/client-api/src/hover.test.ts b/client/client-api/src/hover.test.ts index acd9a2bbf2c..d1bcba91537 100644 --- a/client/client-api/src/hover.test.ts +++ b/client/client-api/src/hover.test.ts @@ -13,7 +13,6 @@ describe('HoverMerged', () => { test('1 MarkupContent', () => expect(fromHoverMerged([{ contents: { kind: MarkupKind.Markdown, value: 'x' } }])).toEqual({ contents: [{ kind: MarkupKind.Markdown, value: 'x' }], - alerts: [], aggregatedBadges: [], })) test('2 MarkupContents', () => @@ -28,39 +27,6 @@ describe('HoverMerged', () => { { kind: MarkupKind.Markdown, value: 'y' }, ], range: FIXTURE_RANGE, - alerts: [], - aggregatedBadges: [], - })) - test('1 Alert', () => - expect( - fromHoverMerged([ - { - contents: { kind: MarkupKind.Markdown, value: 'x' }, - alerts: [{ summary: { kind: MarkupKind.PlainText, value: 'x' } }], - }, - ]) - ).toEqual({ - contents: [{ kind: MarkupKind.Markdown, value: 'x' }], - alerts: [{ summary: { kind: MarkupKind.PlainText, value: 'x' } }], - aggregatedBadges: [], - })) - test('2 Alerts', () => - expect( - fromHoverMerged([ - { - contents: { kind: MarkupKind.Markdown, value: 'x' }, - alerts: [ - { summary: { kind: MarkupKind.PlainText, value: 'x' } }, - { summary: { kind: MarkupKind.PlainText, value: 'y' } }, - ], - }, - ]) - ).toEqual({ - contents: [{ kind: MarkupKind.Markdown, value: 'x' }], - alerts: [ - { summary: { kind: MarkupKind.PlainText, value: 'x' } }, - { summary: { kind: MarkupKind.PlainText, value: 'y' } }, - ], aggregatedBadges: [], })) @@ -69,12 +35,10 @@ describe('HoverMerged', () => { fromHoverMerged([ { contents: { kind: MarkupKind.Markdown, value: 'x' }, - alerts: [], aggregableBadges: [{ text: 't01' }, { text: 't03' }], }, { contents: { kind: MarkupKind.Markdown, value: 'y' }, - alerts: [], aggregableBadges: [{ text: 't02' }], }, ]) @@ -83,7 +47,6 @@ describe('HoverMerged', () => { { kind: MarkupKind.Markdown, value: 'x' }, { kind: MarkupKind.Markdown, value: 'y' }, ], - alerts: [], aggregatedBadges: [{ text: 't01' }, { text: 't02' }, { text: 't03' }], })) }) diff --git a/client/client-api/src/hover.ts b/client/client-api/src/hover.ts index db0b6f94e8c..d477bd7858b 100644 --- a/client/client-api/src/hover.ts +++ b/client/client-api/src/hover.ts @@ -1,4 +1,4 @@ -import { Badged, Hover, MarkupContent, HoverAlert, AggregableBadge } from 'sourcegraph' +import { Badged, Hover, MarkupContent, AggregableBadge } from 'sourcegraph' import { MarkupKind, Range } from '@sourcegraph/extension-api-classes' import { Hover as PlainHover, Range as PlainRange } from '@sourcegraph/extension-api-types' @@ -6,7 +6,6 @@ import { Hover as PlainHover, Range as PlainRange } from '@sourcegraph/extension /** A hover that is merged from multiple Hover results and normalized. */ export interface HoverMerged { contents: Badged[] - alerts?: HoverAlert[] range?: PlainRange /** Sorted and de-duplicated set of badges in all source hover values. */ @@ -14,11 +13,8 @@ export interface HoverMerged { } /** Create a merged hover from the given individual hovers. */ -export function fromHoverMerged( - values: (Badged | null | undefined)[] -): HoverMerged | null { +export function fromHoverMerged(values: (Badged | null | undefined)[]): HoverMerged | null { const contents: HoverMerged['contents'] = [] - const alerts: HoverMerged['alerts'] = [] const aggregatedBadges = new Map() let range: PlainRange | undefined for (const result of values) { @@ -29,9 +25,6 @@ export function fromHoverMerged( kind: result.contents.kind || MarkupKind.PlainText, }) } - if ('alerts' in result && result.alerts) { - alerts.push(...result.alerts) - } for (const badge of result.aggregableBadges || []) { aggregatedBadges.set(badge.text, badge) @@ -54,7 +47,6 @@ export function fromHoverMerged( return { contents, - alerts, ...(range ? { range } : {}), aggregatedBadges: [...aggregatedBadges.values()].sort((a, b) => a.text.localeCompare(b.text)), } diff --git a/client/extension-api-types/src/hover.d.ts b/client/extension-api-types/src/hover.d.ts index 6f2cb4e0ead..52755d9a910 100644 --- a/client/extension-api-types/src/hover.d.ts +++ b/client/extension-api-types/src/hover.d.ts @@ -7,7 +7,7 @@ import { Range } from './location' * * @see module:sourcegraph.Hover */ -export interface Hover extends Pick { +export interface Hover extends Pick { /** The range that the hover applies to. */ readonly range?: Range } diff --git a/client/extension-api/src/sourcegraph.d.ts b/client/extension-api/src/sourcegraph.d.ts index d7f91a05fb3..e9951d6196b 100644 --- a/client/extension-api/src/sourcegraph.d.ts +++ b/client/extension-api/src/sourcegraph.d.ts @@ -422,54 +422,6 @@ declare module 'sourcegraph' { */ export type DocumentSelector = (string | DocumentFilter)[] - /** - * Options for an input box displayed as a result of calling {@link Window#showInputBox}. - */ - export interface InputBoxOptions { - /** - * The text that describes what input the user should provide. - */ - prompt?: string - - /** - * The pre-filled input value for the input box. - */ - value?: string - } - - export interface ProgressOptions { - title?: string - } - - export interface Progress { - /** Optional message. If not set, the previous message is still shown. */ - message?: string - - /** Integer from 0 to 100. If not set, the previous percentage is still shown. */ - percentage?: number - } - - export interface ProgressReporter { - /** - * Updates the progress display with a new message and/or percentage. - */ - next(status: Progress): void - - /** - * Turns the progress display into an error display for the given error or message. - * Use if the operation failed. - * No further progress updates can be sent after this. - */ - error(error: any): void - - /** - * Completes the progress bar and hides the display. - * Sending a percentage of 100 has the same effect. - * No further progress updates can be sent after this. - */ - complete(): void - } - /** * A window in the client application that is running the extension. */ @@ -488,52 +440,6 @@ declare module 'sourcegraph' { * An event that is fired when the active view component changes. */ activeViewComponentChanges: Subscribable - - /** - * Show a notification message to the user that does not require interaction or steal focus. - * - * @param message The message to show. Markdown is supported. - * @param type a {@link NotificationType} affecting the display of the notification. - */ - showNotification(message: string, type: NotificationType): void - - /** - * Show progress in the window. Progress is shown while running the given callback - * and while the promise it returned isn't resolved nor rejected. - * - * @param task A callback returning a promise. Progress state can be reported with - * the provided [ProgressReporter](#ProgressReporter)-object. - * - * @returns The Promise the task-callback returned. - */ - withProgress(options: ProgressOptions, task: (reporter: ProgressReporter) => Promise): Promise - - /** - * Show progress in the window. The returned ProgressReporter can be used to update the - * progress bar, complete it or turn the notification into an error notification in case the operation failed. - * - * @returns A ProgressReporter that allows updating the progress display. - */ - showProgress(options: ProgressOptions): Promise - - /** - * Show a modal message to the user that the user must dismiss before continuing. - * - * @param message The message to show. - * @returns A promise that resolves when the user dismisses the message. - */ - showMessage(message: string): Promise - - /** - * Displays an input box to ask the user for input. - * - * The returned value will be `undefined` if the input box was canceled (e.g., because the user pressed the - * ESC key). Otherwise the returned value will be the string provided by the user. - * - * @param options Configures the behavior of the input box. - * @returns The string provided by the user, or `undefined` if the input box was canceled. - */ - showInputBox(options?: InputBoxOptions): Promise } /** @@ -1090,32 +996,6 @@ declare module 'sourcegraph' { kind?: MarkupKind } - /** - * The type of a notification shown through {@link Window.showNotification}. - */ - export enum NotificationType { - /** - * An error message. - */ - Error = 1, - /** - * A warning message. - */ - Warning = 2, - /** - * An info message. - */ - Info = 3, - /** - * A log message. - */ - Log = 4, - /** - * A success message. - */ - Success = 5, - } - /** A badge holds the extra fields that can be attached to a providable type T via Badged. */ export interface Badge { /** @@ -1164,41 +1044,6 @@ declare module 'sourcegraph' { * position or the current position itself. */ range?: Range - - /** - * Alerts that should be shown in this hover. - */ - alerts?: HoverAlert[] - } - - export interface HoverAlert { - /** - * Text content to be shown on hovers. Since the alert is displayed inline, - * multiparagraph content will be rendered on one line. It's recommended to - * provide a brief message here, and place futher details in the badge or - * provide a link. - */ - summary: MarkupContent - - /** - * When an alert has a dismissal type, dismissing it will prevent all alerts - * of that type from being shown. If no type is provided, the alert is not - * dismissible. - */ - type?: string - - /** Predefined icons to display next ot the summary. */ - iconKind?: 'info' | 'error' | 'warning' - - /** - * When set, this renders a row of button underneath the content. Note - * that this was added after the extension deprecation and will only - * work with newer clients. - * - * When buttons are rendered this way, an eventual dismiss button is - * appended to this list. - */ - buttons?: React.ReactNode[] } export interface HoverProvider { diff --git a/client/shared/BUILD.bazel b/client/shared/BUILD.bazel index 07c51332779..bfd78c2b02a 100644 --- a/client/shared/BUILD.bazel +++ b/client/shared/BUILD.bazel @@ -202,10 +202,6 @@ ts_project( "src/codeintel/legacy-extensions/util/uri.ts", "src/codeintel/scip.ts", "src/codeintel/searchContext.ts", - "src/commandPalette/CommandList.tsx", - "src/commandPalette/EmptyCommandList.tsx", - "src/commandPalette/EmptyCommandListContainer/EmptyCommandListContainer.tsx", - "src/commandPalette/EmptyCommandListContainer/index.ts", "src/commands/commands.ts", "src/components/CodeMirrorEditor.tsx", "src/components/HighlightedMatches.tsx", @@ -236,8 +232,6 @@ ts_project( "src/hover/HoverOverlay.fixtures.ts", "src/hover/HoverOverlay.tsx", "src/hover/HoverOverlay.types.ts", - "src/hover/HoverOverlayAlerts/HoverOverlayAlerts.tsx", - "src/hover/HoverOverlayAlerts/index.ts", "src/hover/HoverOverlayContents/HoverOverlayContent/HoverOverlayContent.tsx", "src/hover/HoverOverlayContents/HoverOverlayContent/index.ts", "src/hover/HoverOverlayContents/HoverOverlayContents.tsx", @@ -251,9 +245,6 @@ ts_project( "src/keyboardShortcuts/keyboardShortcuts.ts", "src/keyboardShortcuts/useKeyboardShortcut.ts", "src/languages.ts", - "src/notifications/NotificationItem.tsx", - "src/notifications/Notifications.tsx", - "src/notifications/notification.ts", "src/platform/context.ts", "src/polyfills/configure-core-js.ts", "src/polyfills/index.ts", diff --git a/client/shared/src/actions/ActionItem.story.tsx b/client/shared/src/actions/ActionItem.story.tsx index cac155f17f7..1c5a5e7c8b4 100644 --- a/client/shared/src/actions/ActionItem.story.tsx +++ b/client/shared/src/actions/ActionItem.story.tsx @@ -62,7 +62,6 @@ export const CommandAction: Story = () => ( telemetryService={NOOP_TELEMETRY_SERVICE} disabledDuringExecution={true} showLoadingSpinnerDuringExecution={true} - showInlineError={true} onDidExecute={onDidExecute} /> ) @@ -105,7 +104,6 @@ export const Executing: Story = () => { action={{ id: 'a', command: 'c', title: 'Hello', iconURL: ICON_URL }} disabledDuringExecution={true} showLoadingSpinnerDuringExecution={true} - showInlineError={true} /> ) } @@ -124,7 +122,6 @@ export const _Error: Story = () => { action={{ id: 'a', command: 'c', title: 'Hello', iconURL: ICON_URL }} disabledDuringExecution={true} showLoadingSpinnerDuringExecution={true} - showInlineError={true} /> ) } diff --git a/client/shared/src/actions/ActionItem.test.tsx b/client/shared/src/actions/ActionItem.test.tsx index 8168358c9a4..4b43c160584 100644 --- a/client/shared/src/actions/ActionItem.test.tsx +++ b/client/shared/src/actions/ActionItem.test.tsx @@ -193,32 +193,6 @@ describe('ActionItem', () => { expect(asFragment()).toMatchSnapshot() }) - test('run command with error with showInlineError', async () => { - const { asFragment } = render( - Promise.reject(new Error('x')), - }} - platformContext={NOOP_PLATFORM_CONTEXT} - /> - ) - - // Run command (which will reject with an error). (Use setTimeout to wait for the executeCommand resolution - // to result in the setState call.) - userEvent.click(screen.getByRole('button')) - - await waitFor(() => expect(screen.getByLabelText('Error: x')).toBeInTheDocument()) - - expect(asFragment()).toMatchSnapshot() - }) - describe('"open" command', () => { it('renders as link', () => { jsdom.reconfigure({ url: 'https://example.com/foo' }) diff --git a/client/shared/src/actions/ActionItem.tsx b/client/shared/src/actions/ActionItem.tsx index 1ea6a0ccebd..2d23ec9ca8c 100644 --- a/client/shared/src/actions/ActionItem.tsx +++ b/client/shared/src/actions/ActionItem.tsx @@ -7,7 +7,7 @@ import { from, Subject, Subscription } from 'rxjs' import { catchError, map, mapTo, mergeMap, startWith, tap } from 'rxjs/operators' import { ActionContribution, Evaluated } from '@sourcegraph/client-api' -import { asError, ErrorLike, isErrorLike, isExternalLink, logger } from '@sourcegraph/common' +import { asError, ErrorLike, isExternalLink, logger } from '@sourcegraph/common' import { LoadingSpinner, Button, @@ -92,20 +92,6 @@ export interface ActionItemProps extends ActionItemAction, ActionItemComponentPr */ showLoadingSpinnerDuringExecution?: boolean - /** - * Whether to show the error (if any) from executing the command inline on this component and NOT in the global - * notifications UI component. - * - * This inline error display behavior is intended for actions that are scoped to a particular component. If the - * error were displayed in the global notifications UI component, it might not be clear which of the many - * possible scopes the error applies to. - * - * For example, the hover actions ("Go to definition", "Find references", etc.) use showInlineError == true - * because those actions are scoped to a specific token in a file. The command palette uses showInlineError == - * false because it is a global UI component (and because showing tooltips on menu items would look strange). - */ - showInlineError?: boolean - /** Instead of showing the icon and/or title, show this element. */ title?: JSX.Element | null @@ -146,7 +132,7 @@ export class ActionItem extends React.PureComponent from( this.props.extensionsController - ? this.props.extensionsController.executeCommand(parameters, this.props.showInlineError) + ? this.props.extensionsController.executeCommand(parameters) : Promise.reject( new Error( 'ActionItems commands other than open and invokeFunction-new are deprecated' @@ -278,14 +264,9 @@ export class ActionItem extends React.PureComponent + - -`; - exports[`ActionItem run command with showLoadingSpinnerDuringExecution 1`] = ` - - - - - -`; - exports[`HoverOverlay hover empty 1`] = ``; exports[`HoverOverlay hover error 1`] = ` diff --git a/client/shared/src/hover/actions.test.ts b/client/shared/src/hover/actions.test.ts index 9217834fb5f..64bf4078324 100644 --- a/client/shared/src/hover/actions.test.ts +++ b/client/shared/src/hover/actions.test.ts @@ -1,6 +1,4 @@ -import { Remote } from 'comlink' -import { createMemoryHistory, MemoryHistory, createPath } from 'history' -import { from, Observable, of, Subscription } from 'rxjs' +import { from, Observable, of } from 'rxjs' import { first } from 'rxjs/operators' import { TestScheduler } from 'rxjs/testing' import * as sinon from 'sinon' @@ -13,12 +11,8 @@ import { Position, Range } from '@sourcegraph/extension-api-classes' import { Location } from '@sourcegraph/extension-api-types' import { GraphQLResult, SuccessGraphQLResult } from '@sourcegraph/http-client' -import { ActionItemAction } from '../actions/ActionItem' -import { ExposedToClient } from '../api/client/mainthread-api' -import { FlatExtensionHostAPI } from '../api/contract' import { WorkspaceRootWithMetadata } from '../api/extension/extensionHostApi' import { PlatformContext, URLToFileContext } from '../platform/context' -import { integrationTestContext } from '../testing/testHelpers' import { FileSpec, UIPositionSpec, @@ -26,17 +20,10 @@ import { RepoSpec, RevisionSpec, ViewStateSpec, - toAbsoluteBlobURL, toPrettyBlobURL, } from '../util/url' -import { - getDefinitionURL, - getHoverActionItems, - getHoverActionsContext, - HoverActionsContext, - registerHoverContributions, -} from './actions' +import { getDefinitionURL, getHoverActionsContext, HoverActionsContext } from './actions' import { HoverContext } from './HoverOverlay' const FIXTURE_PARAMS: TextDocumentPositionParameters & URLToFileContext = { @@ -514,294 +501,3 @@ describe('getDefinitionURL', () => { .toPromise() ).resolves.toEqual({ isLoading: false, result: { url: '/r@v/-/blob/f?L2:2#tab=def', multiple: true } })) }) - -describe('registerHoverContributions()', () => { - const subscription = new Subscription() - let history!: MemoryHistory - - let extensionHostAPI!: Promise> - let extensionAPI!: typeof sourcegraph - let exposedToClient!: ExposedToClient - let locationAssign!: sinon.SinonSpy<[string], void> - beforeEach(async () => { - resetAllMemoizationCaches() - - const context = await integrationTestContext(undefined, { - textDocuments: [ - { - languageId: 'x', - uri: 'git://r?c#f', - text: undefined, - }, - ], - roots: [], - viewers: [], - }) - subscription.add(() => context.unsubscribe()) - extensionHostAPI = Promise.resolve(context.extensionHostAPI) - extensionAPI = context.extensionAPI - exposedToClient = context.exposedToClient - - history = createMemoryHistory() - locationAssign = sinon.spy((_url: string) => undefined) - const contributionsSubscription = registerHoverContributions({ - extensionsController: { - extHostAPI: Promise.resolve(extensionHostAPI), - registerCommand: exposedToClient.registerCommand, - }, - platformContext: { urlToFile, requestGraphQL }, - historyOrNavigate: history, - getLocation: () => history.location, - locationAssign, - }) - subscription.add(contributionsSubscription) - await contributionsSubscription.contributionsPromise - }) - afterAll(() => subscription.unsubscribe()) - - describe('getHoverActions()', () => { - const GO_TO_DEFINITION_ACTION: ActionItemAction = { - action: { - command: 'goToDefinition', - commandArguments: ['{"textDocument":{"uri":"git://r?c#f"},"position":{"line":1,"character":1}}'], - id: 'goToDefinition', - title: 'Go to definition', - actionItem: undefined, - category: undefined, - description: undefined, - iconURL: undefined, - }, - active: true, - disabledWhen: false, - altAction: undefined, - } - const GO_TO_DEFINITION_PRELOADED_ACTION: ActionItemAction = { - action: { - command: 'open', - commandArguments: ['/r2@c2/-/blob/f2?L3:3'], - id: 'goToDefinition.preloaded', - title: 'Go to definition', - disabledTitle: 'You are at the definition', - }, - active: true, - disabledWhen: false, - altAction: undefined, - } - const FIND_REFERENCES_ACTION: ActionItemAction = { - action: { - command: 'open', - commandArguments: ['/r@v/-/blob/f?L2:2#tab=references'], - id: 'findReferences', - title: 'Find references', - }, - active: true, - disabledWhen: false, - altAction: undefined, - } - - it('shows goToDefinition (non-preloaded) when the definition is loading', () => - expect( - getHoverActionItems( - { - 'goToDefinition.showLoading': true, - 'goToDefinition.url': null, - 'goToDefinition.notFound': false, - 'goToDefinition.error': false, - 'findReferences.url': null, - hoverPosition: FIXTURE_PARAMS, - hoveredOnDefinition: false, - }, - extensionHostAPI - ).toPromise() - ).resolves.toEqual([GO_TO_DEFINITION_ACTION])) - - it('shows goToDefinition (non-preloaded) when the definition had an error', () => - expect( - getHoverActionItems( - { - 'goToDefinition.showLoading': false, - 'goToDefinition.url': null, - 'goToDefinition.notFound': false, - 'goToDefinition.error': true, - 'findReferences.url': null, - hoverPosition: FIXTURE_PARAMS, - hoveredOnDefinition: false, - }, - extensionHostAPI - ).toPromise() - ).resolves.toEqual([GO_TO_DEFINITION_ACTION])) - - it('hides goToDefinition when the definition was not found', () => - expect( - getHoverActionItems( - { - 'goToDefinition.showLoading': false, - 'goToDefinition.url': null, - 'goToDefinition.notFound': true, - 'goToDefinition.error': false, - 'findReferences.url': null, - hoverPosition: FIXTURE_PARAMS, - hoveredOnDefinition: false, - }, - extensionHostAPI - ).toPromise() - ).resolves.toEqual([])) - - it('shows goToDefinition.preloaded when goToDefinition.url is available', () => - expect( - getHoverActionItems( - { - 'goToDefinition.showLoading': false, - 'goToDefinition.url': '/r2@c2/-/blob/f2?L3:3', - 'goToDefinition.notFound': false, - 'goToDefinition.error': false, - 'findReferences.url': null, - hoverPosition: FIXTURE_PARAMS, - hoveredOnDefinition: false, - }, - extensionHostAPI - ).toPromise() - ).resolves.toEqual([GO_TO_DEFINITION_PRELOADED_ACTION])) - - it('shows findReferences when the definition exists', () => - expect( - getHoverActionItems( - { - 'goToDefinition.showLoading': false, - 'goToDefinition.url': '/r2@c2/-/blob/f2?L3:3', - 'goToDefinition.notFound': false, - 'goToDefinition.error': false, - 'findReferences.url': '/r@v/-/blob/f?L2:2#tab=references', - hoverPosition: FIXTURE_PARAMS, - hoveredOnDefinition: false, - }, - extensionHostAPI - ).toPromise() - ).resolves.toEqual([GO_TO_DEFINITION_PRELOADED_ACTION, FIND_REFERENCES_ACTION])) - - it('hides findReferences when the definition might exist (and is still loading)', () => - expect( - getHoverActionItems( - { - 'goToDefinition.showLoading': true, - 'goToDefinition.url': null, - 'goToDefinition.notFound': false, - 'goToDefinition.error': false, - 'findReferences.url': '/r@v/-/blob/f?L2:2#tab=references', - hoverPosition: FIXTURE_PARAMS, - hoveredOnDefinition: false, - }, - extensionHostAPI - ).toPromise() - ).resolves.toEqual([GO_TO_DEFINITION_ACTION, FIND_REFERENCES_ACTION])) - - it('shows findReferences when the definition had an error', () => - expect( - getHoverActionItems( - { - 'goToDefinition.showLoading': false, - 'goToDefinition.url': null, - 'goToDefinition.notFound': false, - 'goToDefinition.error': true, - 'findReferences.url': '/r@v/-/blob/f?L2:2#tab=references', - hoverPosition: FIXTURE_PARAMS, - hoveredOnDefinition: false, - }, - extensionHostAPI - ).toPromise() - ).resolves.toEqual([GO_TO_DEFINITION_ACTION, FIND_REFERENCES_ACTION])) - - it('does not show findReferences when the definition was not found', () => - expect( - getHoverActionItems( - { - 'goToDefinition.showLoading': false, - 'goToDefinition.url': null, - 'goToDefinition.notFound': true, - 'goToDefinition.error': false, - 'findReferences.url': '/r@v/-/blob/f?L2:2#tab=references', - hoverPosition: FIXTURE_PARAMS, - hoveredOnDefinition: false, - }, - extensionHostAPI - ).toPromise() - ).resolves.toEqual([])) - }) - - describe('goToDefinition command', () => { - test('reports no definition found', async () => { - const definitionSubscription = extensionAPI.languages.registerDefinitionProvider(['*'], { - provideDefinition: () => of([]), - }) - - await expect( - exposedToClient.executeCommand({ command: 'goToDefinition', args: [JSON.stringify(FIXTURE_PARAMS)] }) - ).rejects.toMatchObject({ message: 'No definition found.' }) - - definitionSubscription.unsubscribe() - }) - - test('navigates to an in-app URL using the passed history object', async () => { - jsdom.reconfigure({ url: 'https://sourcegraph.test/r2@c2/-/blob/f1' }) - history.replace('/r2@c2/-/blob/f1') - expect(history).toHaveLength(1) - - const definitionSubscription = extensionAPI.languages.registerDefinitionProvider(['*'], { - provideDefinition: () => of(FIXTURE_LOCATION), - }) - - await exposedToClient.executeCommand({ command: 'goToDefinition', args: [JSON.stringify(FIXTURE_PARAMS)] }) - sinon.assert.notCalled(locationAssign) - expect(history).toHaveLength(2) - expect(createPath(history.location)).toBe('/r2@c2/-/blob/f2?L3:3') - - definitionSubscription.unsubscribe() - }) - - test('navigates to an external URL using the global location object', async () => { - jsdom.reconfigure({ url: 'https://github.test/r2@c2/-/blob/f1' }) - history.replace('/r2@c2/-/blob/f1') - expect(history).toHaveLength(1) - urlToFile.callsFake(toAbsoluteBlobURL.bind(null, 'https://sourcegraph.test')) - - const definitionSubscription = extensionAPI.languages.registerDefinitionProvider(['*'], { - provideDefinition: () => - of([FIXTURE_LOCATION, { ...FIXTURE_LOCATION, uri: new URL('git://r3?v3#f3') }]), - }) - - await exposedToClient.executeCommand({ command: 'goToDefinition', args: [JSON.stringify(FIXTURE_PARAMS)] }) - sinon.assert.calledOnce(locationAssign) - sinon.assert.calledWith(locationAssign, 'https://sourcegraph.test/r@c/-/blob/f?L2:2#tab=def') - expect(history).toHaveLength(1) - - definitionSubscription.unsubscribe() - }) - - test('reports panel already visible', async () => { - const definitionSubscription = extensionAPI.languages.registerDefinitionProvider(['*'], { - provideDefinition: () => - of([FIXTURE_LOCATION, { ...FIXTURE_LOCATION, uri: new URL('git://r3?v3#f3') }]), - }) - - history.push('/r@c/-/blob/f?L2:2#tab=def') - await expect( - exposedToClient.executeCommand({ command: 'goToDefinition', args: [JSON.stringify(FIXTURE_PARAMS)] }) - ).rejects.toMatchObject({ message: 'Multiple definitions shown in panel below.' }) - - definitionSubscription.unsubscribe() - }) - - test('reports already at the definition', async () => { - const definitionSubscription = extensionAPI.languages.registerDefinitionProvider(['*'], { - provideDefinition: () => of([FIXTURE_LOCATION]), - }) - - history.push('/r2@c2/-/blob/f2?L3:3') - await expect( - exposedToClient.executeCommand({ command: 'goToDefinition', args: [JSON.stringify(FIXTURE_PARAMS)] }) - ).rejects.toMatchObject({ message: 'Already at the definition.' }) - - definitionSubscription.unsubscribe() - }) - }) -}) diff --git a/client/shared/src/keyboardShortcuts/keyboardShortcuts.ts b/client/shared/src/keyboardShortcuts/keyboardShortcuts.ts index 97accaaf785..92af98ce01b 100644 --- a/client/shared/src/keyboardShortcuts/keyboardShortcuts.ts +++ b/client/shared/src/keyboardShortcuts/keyboardShortcuts.ts @@ -3,7 +3,6 @@ import { isMacPlatform, isSafari } from '@sourcegraph/common' import { KeyboardShortcut } from '../keyboardShortcuts' type KEYBOARD_SHORTCUT_IDENTIFIERS = - | 'commandPalette' | 'switchTheme' | 'keyboardShortcutsHelp' | 'focusSearch' @@ -17,10 +16,6 @@ type KEYBOARD_SHORTCUT_IDENTIFIERS = export type KEYBOARD_SHORTCUT_MAPPING = Record export const KEYBOARD_SHORTCUTS: KEYBOARD_SHORTCUT_MAPPING = { - commandPalette: { - title: 'Show command palette', - keybindings: [{ held: ['Control'], ordered: ['p'] }, { ordered: ['F1'] }, { held: ['Alt'], ordered: ['x'] }], - }, switchTheme: { title: 'Switch color theme', // use '†' here to make `Alt + t` works on macos diff --git a/client/shared/src/notifications/NotificationItem.module.scss b/client/shared/src/notifications/NotificationItem.module.scss deleted file mode 100644 index d20f578d059..00000000000 --- a/client/shared/src/notifications/NotificationItem.module.scss +++ /dev/null @@ -1,55 +0,0 @@ -.sourcegraph-notification-item { - display: block; - transition: all 300ms ease-in; -} - -.progress { - // important is required to override the sibling class - background: transparent !important; - border-radius: 0; -} - -.progressbar { - height: 0.25rem; - transition: width 0.6s ease; -} - -.body-container { - display: flex; - align-items: flex-start; -} - -.body { - flex: 1; - padding: 0.5rem; - overflow: hidden; - - pre, - code { - overflow-x: auto; - } -} - -.content > :last-child, -.title > :last-child { - margin-bottom: 0; -} - -.close { - cursor: pointer; - flex: 0 0; - /* stylelint-disable-next-line declaration-property-unit-allowed-list */ - font-size: 1.25rem; - line-height: 1; - background-color: transparent; - border-width: 0; - outline: 0 !important; - color: inherit; - opacity: 0.7; - padding: 0.5rem; - - &:hover, - &:focus { - opacity: 1; - } -} diff --git a/client/shared/src/notifications/NotificationItem.story.tsx b/client/shared/src/notifications/NotificationItem.story.tsx deleted file mode 100644 index c66ece080fd..00000000000 --- a/client/shared/src/notifications/NotificationItem.story.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { action } from '@storybook/addon-actions' -import { DecoratorFn, Meta, Story } from '@storybook/react' -import { of } from 'rxjs' - -import { NotificationType } from '@sourcegraph/extension-api-classes' -import { BrandedStory } from '@sourcegraph/wildcard/src/stories' - -import type { NotificationType as NotificationTypeType } from '../codeintel/legacy-extensions/api' - -import { NotificationItem } from './NotificationItem' - -const notificationClassNames = { - [NotificationType.Log]: 'bg-secondary', - [NotificationType.Success]: 'bg-success', - [NotificationType.Info]: 'bg-info', - [NotificationType.Warning]: 'bg-warning', - [NotificationType.Error]: 'bg-danger', -} - -const onDismiss = action('onDismiss') - -const decorator: DecoratorFn = story => ( - {() =>
{story()}
}
-) - -const config: Meta = { - title: 'shared/NotificationItem', - decorators: [decorator], - argTypes: { - message: { - name: 'Message', - control: { type: 'text' }, - defaultValue: 'My *custom* message', - }, - type: { - name: 'type', - control: { - type: 'select', - options: NotificationType as Record, - }, - }, - source: { - name: 'Source', - control: { type: 'text' }, - defaultValue: 'some source', - }, - }, -} -export default config - -export const WithoutProgress: Story = args => { - const message = args.message - const type = args.type - const source = args.source - return ( - - ) -} -WithoutProgress.argTypes = { - type: { - defaultValue: NotificationType.Error, - }, -} -export const WithProgress: Story = args => { - const message = args.message - const type = args.type - const source = args.source - const progressMessage = args.progressMessage - const progressPercentage = args.progressPercentage - return ( - - ) -} -WithProgress.argTypes = { - progressMessage: { - name: 'Progress message', - control: { type: 'text' }, - defaultValue: 'My *custom* progress message', - }, - progressPercentage: { - name: 'Progress % (0-100)', - control: { type: 'number', min: 0, max: 100 }, - defaultValue: 50, - }, - type: { - defaultValue: NotificationType.Info, - }, -} - -WithProgress.storyName = 'With progress' -WithProgress.parameters = { - chromatic: { - enableDarkMode: true, - disableSnapshot: false, - }, -} diff --git a/client/shared/src/notifications/NotificationItem.tsx b/client/shared/src/notifications/NotificationItem.tsx deleted file mode 100644 index 8af3a6856cd..00000000000 --- a/client/shared/src/notifications/NotificationItem.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import * as React from 'react' - -import classNames from 'classnames' -import { from, Subject, Subscription } from 'rxjs' -import { catchError, distinctUntilChanged, map, scan, switchMap } from 'rxjs/operators' - -import { renderMarkdown } from '@sourcegraph/common' -import { Alert } from '@sourcegraph/wildcard' - -import type { NotificationType, Progress } from '../codeintel/legacy-extensions/api' - -import { Notification } from './notification' - -import styles from './NotificationItem.module.scss' - -export interface UnbrandedNotificationItemStyleProps { - notificationItemClassNames: Record -} - -export interface NotificationItemProps { - notification: Notification - onDismiss: (notification: Notification) => void - className?: string - notificationItemStyleProps: UnbrandedNotificationItemStyleProps -} - -interface NotificationItemState { - progress?: Required -} - -/** - * A notification message displayed in a {@link module:./Notifications.Notifications} component. - */ -export class NotificationItem extends React.PureComponent { - private componentUpdates = new Subject() - private subscription = new Subscription() - constructor(props: NotificationItemProps) { - super(props) - this.state = { - progress: props.notification.progress && { - percentage: 0, - message: '', - }, - } - } - public componentDidMount(): void { - this.subscription.add( - this.componentUpdates - .pipe( - map(props => props.notification.progress), - distinctUntilChanged(), - switchMap(progress => - from(progress || []).pipe( - // Hide progress bar and update message if error occurred - // Merge new progress updates with previous - scan>( - (current, { message = current.message, percentage = current.percentage }) => ({ - message, - percentage, - }), - { - percentage: 0, - message: '', - } - ), - catchError(() => [undefined]) - ) - ) - ) - .subscribe(progress => { - this.setState({ progress }) - }) - ) - this.componentUpdates.next(this.props) - } - public componentDidUpdate(): void { - this.componentUpdates.next(this.props) - } - public componentWillUnmount(): void { - this.subscription.unsubscribe() - } - public render(): JSX.Element | null { - const baseAlertClassName = classNames(styles.sourcegraphNotificationItem, this.props.className) - - const { notificationItemStyleProps } = this.props - const alertProps = { - className: classNames( - baseAlertClassName, - notificationItemStyleProps.notificationItemClassNames[this.props.notification.type] - ), - } - - return ( - -
-
-
- {this.state.progress && ( -
- )} -
- {(!this.props.notification.progress || !this.state.progress) && ( - - )} -
- {this.props.notification.progress && this.state.progress && ( -
-
-
- )} - - ) - } - - private onDismiss = (): void => this.props.onDismiss(this.props.notification) -} diff --git a/client/shared/src/notifications/Notifications.module.scss b/client/shared/src/notifications/Notifications.module.scss deleted file mode 100644 index 246daeb5cc4..00000000000 --- a/client/shared/src/notifications/Notifications.module.scss +++ /dev/null @@ -1,7 +0,0 @@ -.sourcegraph-notifications { - position: fixed; - width: 28rem; - top: 82px; - right: 0; - z-index: 90; -} diff --git a/client/shared/src/notifications/Notifications.tsx b/client/shared/src/notifications/Notifications.tsx deleted file mode 100644 index 7fa7c329ab2..00000000000 --- a/client/shared/src/notifications/Notifications.tsx +++ /dev/null @@ -1,211 +0,0 @@ -import * as React from 'react' - -import { uniqueId } from 'lodash' -import { from, merge, Subscription } from 'rxjs' -import { delay, map, mergeMap, switchMap, takeWhile } from 'rxjs/operators' -import { tabbable } from 'tabbable' - -import { asError, logger } from '@sourcegraph/common' - -import { wrapRemoteObservable } from '../api/client/api/common' -import { NotificationType } from '../api/extension/extensionHostApi' -import { syncRemoteSubscription } from '../api/util' -import { RequiredExtensionsControllerProps } from '../extensions/controller' - -import { Notification } from './notification' -import { NotificationItem, NotificationItemProps } from './NotificationItem' - -import styles from './Notifications.module.scss' - -export interface NotificationsProps - extends RequiredExtensionsControllerProps, - Pick {} - -interface NotificationsState { - // TODO(tj): use remote progress observable type - notifications: (Notification & { id: string })[] -} - -const HAS_NOTIFICATIONS_CONTEXT_KEY = 'hasNotifications' - -/** - * A notifications center that displays global, non-modal messages. - */ -export class Notifications extends React.PureComponent { - /** - * The maximum number of notifications at a time. Older notifications are truncated when the length exceeds - * this number. - */ - private static MAX_RETAIN = 7 - - public state: NotificationsState = { - notifications: [], - } - - private subscriptions = new Subscription() - - private notificationsReference = React.createRef() - - public componentDidMount(): void { - // Subscribe to plain notifications - this.subscriptions.add( - from(this.props.extensionsController.extHostAPI) - .pipe( - switchMap(extensionHostAPI => - merge( - wrapRemoteObservable(extensionHostAPI.getPlainNotifications()), - // Subscribe to command error notifications (also plain) - this.props.extensionsController.commandErrors - ) - ), - map(notification => ({ ...notification, id: uniqueId('n') })) - ) - .subscribe(notification => { - this.setState(previousState => ({ - notifications: [...previousState.notifications.slice(-Notifications.MAX_RETAIN), notification], - })) - }) - ) - - // Subscribe to progress notifications. This is more complex to handle than - // plain notifications because the emissions of the progress notification observable - // have to be proxied as well - this.subscriptions.add( - from(this.props.extensionsController.extHostAPI) - .pipe(mergeMap(extensionHostAPI => wrapRemoteObservable(extensionHostAPI.getProgressNotifications()))) - .subscribe(progressNotification => { - // Progress notifications are remote, so property access is asynchronous - progressNotification.baseNotification - .then(baseNotification => { - // Turn ExtensionNotification type into client Notification type - // for NotificationItem to render (and subscribe to progressObservable) - const progressObservable = wrapRemoteObservable(progressNotification.progress) - const notification: Notification & { id: string } = { - ...baseNotification, - progress: progressObservable, - id: uniqueId('n'), - } - - this.setState(previousState => ({ - notifications: [ - ...previousState.notifications.slice(-Notifications.MAX_RETAIN), - notification, - ], - })) - - // Remove this notification once progress is finished - this.subscriptions.add( - progressObservable - .pipe( - takeWhile(({ percentage }) => !percentage || percentage < 100), - delay(1000) - ) - // eslint-disable-next-line rxjs/no-nested-subscribe - .subscribe({ - error: error => { - const erroredNotification = notification - this.setState(({ notifications }) => ({ - notifications: notifications.map(notification => - notification === erroredNotification - ? { - ...notification, - type: NotificationType.Error, - message: asError(error).message, - } - : notification - ), - })) - }, - complete: () => { - const completedNotification = notification - this.setState(previousState => ({ - notifications: previousState.notifications.filter( - notification => notification !== completedNotification - ), - })) - }, - }) - ) - }) - .catch(() => { - // noop. there's no meaningful information to log if accessing - // baseNotification somehow failed - }) - }) - ) - - // Register command to focus notifications. - this.subscriptions.add( - this.props.extensionsController.registerCommand({ - command: 'focusNotifications', - run: () => { - const notificationsElement = this.notificationsReference.current - if (notificationsElement) { - tabbable(notificationsElement)[0]?.focus() - } - return Promise.resolve() - }, - }) - ) - this.subscriptions.add( - syncRemoteSubscription( - this.props.extensionsController.extHostAPI.then(extensionHostAPI => - extensionHostAPI.registerContributions({ - menus: { - commandPalette: [ - { - action: 'focusNotifications', - when: HAS_NOTIFICATIONS_CONTEXT_KEY, - }, - ], - }, - actions: [ - { - id: 'focusNotifications', - title: 'Focus notifications', - command: 'focusNotifications', - }, - ], - }) - ) - ) - ) - } - - public componentDidUpdate(): void { - // Update context to show/hide "Focus notifications" command. - this.props.extensionsController.extHostAPI - .then(extensionHostAPI => - extensionHostAPI.updateContext({ - [HAS_NOTIFICATIONS_CONTEXT_KEY]: this.state.notifications.length > 0, - }) - ) - .catch(error => logger.error('Error updating context for notifications', error)) - } - - public componentWillUnmount(): void { - this.subscriptions.unsubscribe() - } - - public render(): JSX.Element | null { - return ( -
- {this.state.notifications.slice(0, Notifications.MAX_RETAIN).map(notification => ( - - ))} -
- ) - } - - private onDismiss = (dismissedNotification: Notification): void => { - this.setState(previousState => ({ - notifications: previousState.notifications.filter(notification => notification !== dismissedNotification), - })) - } -} diff --git a/client/shared/src/notifications/notification.ts b/client/shared/src/notifications/notification.ts deleted file mode 100644 index 615bbb2b1ed..00000000000 --- a/client/shared/src/notifications/notification.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Observable } from 'rxjs' - -import type { NotificationType, Progress } from '../codeintel/legacy-extensions/api' - -/** - * A notification message to display to the user. - */ -export interface Notification { - /** The message of the notification. */ - message?: string - - /** - * The type of the message. - */ - type: NotificationType - - /** The source of the notification. */ - source?: string - - /** - * Progress updates to show in this notification (progress bar and status messages). - * If this Observable errors, the notification will be changed to an error type. - */ - progress?: Observable -} diff --git a/client/shared/src/platform/context.ts b/client/shared/src/platform/context.ts index a0da4dd63fe..29a7d8e18bb 100644 --- a/client/shared/src/platform/context.ts +++ b/client/shared/src/platform/context.ts @@ -8,7 +8,6 @@ import { GraphQLClient, GraphQLResult } from '@sourcegraph/http-client' import { SettingsEdit } from '../api/client/services/settings' import { ExecutableExtension } from '../api/extension/activation' -import type { InputBoxOptions } from '../codeintel/legacy-extensions/api' import { Scalars } from '../graphql-operations' import { Settings, SettingsCascadeOrError } from '../settings/settings' import { TelemetryService } from '../telemetry/telemetryService' @@ -189,22 +188,6 @@ export interface PlatformContext { * the extension host will not activate any other settings (e.g. extensions from user settings) */ getStaticExtensions?: () => Observable - - /** - * Display a modal message from an extension to the user. - * - * @param message The message to display - * @returns a Promise that resolves when the user dismisses the message - */ - showMessage?(message: string): Promise - - /** - * Displays an input box for an extension that asks the user for input. - * - * @param options Configures the behavior of the input box. - * @returns The string provided by the user, or `undefined` if the input box was canceled. - */ - showInputBox?(options: InputBoxOptions | undefined): Promise } /** diff --git a/client/shared/src/testing/searchTestHelpers.ts b/client/shared/src/testing/searchTestHelpers.ts index c2a4aa88723..39b9bb798d7 100644 --- a/client/shared/src/testing/searchTestHelpers.ts +++ b/client/shared/src/testing/searchTestHelpers.ts @@ -630,7 +630,6 @@ export const extensionsController: Controller = { haveInitialExtensionsLoaded: () => pretendProxySubscribable(of(true)), }) ), - commandErrors: EMPTY, unsubscribe: noop, } diff --git a/client/shared/src/testing/testHelpers.ts b/client/shared/src/testing/testHelpers.ts index c5bcb03f15c..281313246af 100644 --- a/client/shared/src/testing/testHelpers.ts +++ b/client/shared/src/testing/testHelpers.ts @@ -5,7 +5,6 @@ import { throwError, of, Subscription, Unsubscribable, Subscribable } from 'rxjs import * as sourcegraph from 'sourcegraph' import { createExtensionHostClientConnection } from '../api/client/connection' -import { ExposedToClient } from '../api/client/mainthread-api' import { FlatExtensionHostAPI, MainThreadAPI } from '../api/contract' import { InitData, startExtensionHost } from '../api/extension/extensionHost' import { WorkspaceRootWithMetadata } from '../api/extension/extensionHostApi' @@ -40,13 +39,7 @@ const FIXTURE_INIT_DATA: TestInitData = { interface Mocks extends Pick< PlatformContext, - | 'settings' - | 'updateSettings' - | 'getGraphQLClient' - | 'requestGraphQL' - | 'clientApplication' - | 'showMessage' - | 'showInputBox' + 'settings' | 'updateSettings' | 'getGraphQLClient' | 'requestGraphQL' | 'clientApplication' > {} const NOOP_MOCKS: Mocks = { @@ -70,7 +63,6 @@ export async function integrationTestContext( extensionAPI: typeof sourcegraph extensionHostAPI: Remote mainThreadAPI: MainThreadAPI - exposedToClient: ExposedToClient } & Unsubscribable > { const mocks = partialMocks ? { ...NOOP_MOCKS, ...partialMocks } : NOOP_MOCKS @@ -93,11 +85,7 @@ export async function integrationTestContext( clientApplication: 'sourcegraph', } - const { - api: extensionHostAPI, - mainThreadAPI, - exposedToClient, - } = await createExtensionHostClientConnection( + const { api: extensionHostAPI, mainThreadAPI } = await createExtensionHostClientConnection( Promise.resolve({ endpoints: clientEndpoints, subscription: new Subscription(), @@ -116,7 +104,6 @@ export async function integrationTestContext( extensionAPI, extensionHostAPI, mainThreadAPI, - exposedToClient, unsubscribe: () => extensionHost.unsubscribe(), } } diff --git a/client/shared/src/types/string-score/index.d.ts b/client/shared/src/types/string-score/index.d.ts deleted file mode 100644 index 515ca6fbe7b..00000000000 --- a/client/shared/src/types/string-score/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module 'string-score' { - function score(target: string, query: string, fuzzyFactor?: number): number - - export = score -} diff --git a/client/vscode/src/webview/platform/context.ts b/client/vscode/src/webview/platform/context.ts index 73ee3c09ba4..8592a1d9788 100644 --- a/client/vscode/src/webview/platform/context.ts +++ b/client/vscode/src/webview/platform/context.ts @@ -24,8 +24,6 @@ export interface VSCodePlatformContext | 'updateSettings' | 'settings' | 'getGraphQLClient' - | 'showMessage' - | 'showInputBox' | 'getStaticExtensions' | 'telemetryService' | 'clientApplication' @@ -59,8 +57,6 @@ export function createPlatformContext(extensionCoreAPI: Comlink.Remote Promise.resolve(), telemetryService: new EventLogger(extensionCoreAPI), clientApplication: 'other', // TODO add 'vscode-extension' to `clientApplication`, - // TODO showInputBox - // TODO showMessage getStaticExtensions: () => getInlineExtensions(), } diff --git a/client/web/src/components/KeyboardShortcutsHelp/__snapshots__/KeyboardShortcutsHelp.test.tsx.snap b/client/web/src/components/KeyboardShortcutsHelp/__snapshots__/KeyboardShortcutsHelp.test.tsx.snap index ac2a1fda1cc..88823466130 100644 --- a/client/web/src/components/KeyboardShortcutsHelp/__snapshots__/KeyboardShortcutsHelp.test.tsx.snap +++ b/client/web/src/components/KeyboardShortcutsHelp/__snapshots__/KeyboardShortcutsHelp.test.tsx.snap @@ -65,38 +65,6 @@ exports[`KeyboardShortcutsHelp is triggered correctly 1`] = `
    -
  • - Show command palette - - - - Ctrl - - + - - p - - - - or - - F1 - - - - or - - Alt - - + - - x - - - -
  • diff --git a/client/web/src/components/WebHoverOverlay/WebHoverOverlay.fixtures.ts b/client/web/src/components/WebHoverOverlay/WebHoverOverlay.fixtures.ts index b4d173d5622..a179149f92d 100644 --- a/client/web/src/components/WebHoverOverlay/WebHoverOverlay.fixtures.ts +++ b/client/web/src/components/WebHoverOverlay/WebHoverOverlay.fixtures.ts @@ -1,10 +1,5 @@ import { MarkupKind } from '@sourcegraph/extension-api-classes' -import type { - MarkupContent, - Badged, - AggregableBadge, - HoverAlert, -} from '@sourcegraph/shared/src/codeintel/legacy-extensions/api' +import type { MarkupContent, Badged, AggregableBadge } from '@sourcegraph/shared/src/codeintel/legacy-extensions/api' import { FIXTURE_SEMANTIC_BADGE } from '@sourcegraph/shared/src/hover/HoverOverlay.fixtures' export const FIXTURE_CONTENT_LONG_CODE: Badged = { @@ -27,20 +22,3 @@ export const FIXTURE_PARTIAL_BADGE: AggregableBadge = { ...FIXTURE_SEMANTIC_BADGE, text: 'partial semantic', } - -export const FIXTURE_SMALL_TEXT_MARKDOWN_ALERT: HoverAlert = { - summary: { - kind: MarkupKind.Markdown, - value: 'This is an info alert wrapped into a \\ element. Enim esse quis commodo ex. Pariatur tempor laborum officiairure est do est laborum nostrud cillum. Cupidatat id consectetur et eiusmod Loremproident cupidatat ullamco dolor nostrud. Cupidatat sit do dolor aliqua labore adlaboris cillum deserunt dolor. Sunt labore veniam Lorem reprehenderit quis occaecatsint do mollit aliquip. Consectetur mollit mollit magna eiusmod duis ex. Sint nisilabore labore nulla laboris.', - }, - type: 'test-alert-type', -} - -export const FIXTURE_WARNING_MARKDOWN_ALERT: HoverAlert = { - summary: { - kind: MarkupKind.Markdown, - value: "This is a warning alert. [It uses Markdown.](https://sourcegraph.com) `To render things easily`. *Cool!*\n\nIt's a second paragraph.", - }, - type: 'test-alert-type', - iconKind: 'warning', -} diff --git a/client/web/src/components/WebHoverOverlay/WebHoverOverlay.story.tsx b/client/web/src/components/WebHoverOverlay/WebHoverOverlay.story.tsx index d6ace7152b6..ba021c99737 100644 --- a/client/web/src/components/WebHoverOverlay/WebHoverOverlay.story.tsx +++ b/client/web/src/components/WebHoverOverlay/WebHoverOverlay.story.tsx @@ -1,8 +1,6 @@ -import { action } from '@storybook/addon-actions' import { DecoratorFn, Meta, Story } from '@storybook/react' import { registerHighlightContributions } from '@sourcegraph/common' -import { MarkupKind } from '@sourcegraph/extension-api-classes' import { commonProps, FIXTURE_ACTIONS, @@ -18,8 +16,6 @@ import { FIXTURE_CONTENT_LONG_TEXT_ONLY, FIXTURE_CONTENT_MARKDOWN, FIXTURE_PARTIAL_BADGE, - FIXTURE_SMALL_TEXT_MARKDOWN_ALERT, - FIXTURE_WARNING_MARKDOWN_ALERT, } from './WebHoverOverlay.fixtures' import styles from './WebHoverOverlay.story.module.scss' @@ -148,117 +144,33 @@ export const MultipleMarkupContents: Story = () => ( MultipleMarkupContents.storyName = 'Multiple MarkupContents' -export const WithSmallTextAlert: Story = () => ( +export const WithLongMarkdownTextIcon: Story = () => ( -) - -WithSmallTextAlert.storyName = 'With small-text alert' - -export const WithOneLineAlert: Story = () => ( - -) - -WithOneLineAlert.storyName = 'With one-line alert' - -export const WithAlertWithWarningIcon: Story = () => ( - -) - -WithAlertWithWarningIcon.storyName = 'With alert with warning icon' - -export const WithDismissibleAlertWithIcon: Story = () => ( - [Learn more about precise code navigation](https://sourcegraph.com/github.com/sourcegraph/code-intel-extensions/-/blob/shared/indicators.ts#L67)', - }, - type: 'test-alert-type', - iconKind: 'info', - }, - ], - }} - actionsOrError={FIXTURE_ACTIONS} - onAlertDismissed={action('onAlertDismissed')} - /> -) - -WithDismissibleAlertWithIcon.storyName = 'With dismissible alert with icon' - -export const WithLongMarkdownTextAndDismissibleAlertWithIcon: Story = () => ( - ) -WithLongMarkdownTextAndDismissibleAlertWithIcon.storyName = 'With long markdown text and dismissible alert with icon.' +WithLongMarkdownTextIcon.storyName = 'With long markdown text and icon.' -export const MultipleMarkupContentsWithBadgesAndAlerts: Story = () => ( +export const MultipleMarkupContentsWithBadges: Story = () => (
    ) -MultipleMarkupContentsWithBadgesAndAlerts.storyName = 'Multiple MarkupContents with badges and alerts' +MultipleMarkupContentsWithBadges.storyName = 'Multiple MarkupContents with badges' export const WithCloseButton: Story = () => ( ( hoverOrError={{ contents: [FIXTURE_CONTENT, FIXTURE_CONTENT, FIXTURE_CONTENT], aggregatedBadges: [FIXTURE_SEMANTIC_BADGE], - alerts: [FIXTURE_SMALL_TEXT_MARKDOWN_ALERT, FIXTURE_WARNING_MARKDOWN_ALERT], }} actionsOrError={FIXTURE_ACTIONS} - onAlertDismissed={action('onAlertDismissed')} pinOptions={{ showCloseButton: true }} /> ) diff --git a/client/web/src/components/WebHoverOverlay/WebHoverOverlay.tsx b/client/web/src/components/WebHoverOverlay/WebHoverOverlay.tsx index ee5d4e5a04e..cebbe8338ba 100644 --- a/client/web/src/components/WebHoverOverlay/WebHoverOverlay.tsx +++ b/client/web/src/components/WebHoverOverlay/WebHoverOverlay.tsx @@ -1,31 +1,21 @@ -import React, { useCallback, useEffect } from 'react' +import React, { useEffect } from 'react' import classNames from 'classnames' import { Observable } from 'rxjs' import { isErrorLike } from '@sourcegraph/common' import { urlForClientCommandOpen } from '@sourcegraph/shared/src/actions/ActionItem' -import { NotificationType } from '@sourcegraph/shared/src/api/extension/extensionHostApi' import { HoverOverlay, HoverOverlayProps } from '@sourcegraph/shared/src/hover/HoverOverlay' import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings' -import { AlertProps, useLocalStorage } from '@sourcegraph/wildcard' import { HoverThresholdProps } from '../../repo/RepoContainer' import styles from './WebHoverOverlay.module.scss' -const iconKindToAlertVariant: Record = { - [NotificationType.Info]: 'secondary', - [NotificationType.Error]: 'danger', - [NotificationType.Warning]: 'warning', -} - -const getAlertVariant: HoverOverlayProps['getAlertVariant'] = iconKind => iconKindToAlertVariant[iconKind] - export interface WebHoverOverlayProps extends Omit< HoverOverlayProps, - 'className' | 'closeButtonClassName' | 'actionItemClassName' | 'getAlertVariant' | 'actionItemStyleProps' + 'className' | 'closeButtonClassName' | 'actionItemClassName' | 'actionItemStyleProps' >, HoverThresholdProps, SettingsCascadeProps { @@ -41,28 +31,7 @@ export interface WebHoverOverlayProps } export const WebHoverOverlay: React.FunctionComponent> = props => { - const { onAlertDismissed: outerOnAlertDismissed } = props - const [dismissedAlerts, setDismissedAlerts] = useLocalStorage('WebHoverOverlay.dismissedAlerts', []) - const onAlertDismissed = useCallback( - (alertType: string) => { - if (!dismissedAlerts.includes(alertType)) { - setDismissedAlerts([...dismissedAlerts, alertType]) - outerOnAlertDismissed?.(alertType) - } - }, - [dismissedAlerts, setDismissedAlerts, outerOnAlertDismissed] - ) - - let propsToUse = props - if (props.hoverOrError && props.hoverOrError !== 'loading' && !isErrorLike(props.hoverOrError)) { - const filteredAlerts = (props.hoverOrError?.alerts || []).filter( - alert => !alert.type || !dismissedAlerts.includes(alert.type) - ) - propsToUse = { ...props, hoverOrError: { ...props.hoverOrError, alerts: filteredAlerts } } - } - - const { hoverOrError } = propsToUse - const { onHoverShown, hoveredToken } = props + const { hoverOrError, onHoverShown, hoveredToken } = props /** Whether the hover has actual content (that provides value to the user) */ const hoverHasValue = hoverOrError !== 'loading' && !isErrorLike(hoverOrError) && !!hoverOrError?.contents?.length @@ -75,12 +44,10 @@ export const WebHoverOverlay: React.FunctionComponent repositionTooltips(this.view)} pinOptions={{ showCloseButton: pinned, onCloseButtonClick: () => { diff --git a/client/web/src/types/string-score/index.d.ts b/client/web/src/types/string-score/index.d.ts deleted file mode 100644 index 515ca6fbe7b..00000000000 --- a/client/web/src/types/string-score/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module 'string-score' { - function score(target: string, query: string, fuzzyFactor?: number): number - - export = score -} diff --git a/cmd/frontend/graphqlbackend/settings_cascade_test.go b/cmd/frontend/graphqlbackend/settings_cascade_test.go index 3965cb9e91d..8b9687f3168 100644 --- a/cmd/frontend/graphqlbackend/settings_cascade_test.go +++ b/cmd/frontend/graphqlbackend/settings_cascade_test.go @@ -49,16 +49,16 @@ func TestMergeSettings(t *testing.T) { }, { name: "merge bool", left: &schema.Settings{ - AlertsShowPatchUpdates: false, - CodeHostUseNativeTooltips: true, + AlertsShowPatchUpdates: false, + BasicCodeIntelGlobalSearchesEnabled: true, }, right: &schema.Settings{ - AlertsShowPatchUpdates: true, - CodeHostUseNativeTooltips: false, // This is the zero value, so will not override a previous non-zero value + AlertsShowPatchUpdates: true, + BasicCodeIntelGlobalSearchesEnabled: false, // This is the zero value, so will not override a previous non-zero value }, expected: &schema.Settings{ - AlertsShowPatchUpdates: true, - CodeHostUseNativeTooltips: true, + AlertsShowPatchUpdates: true, + BasicCodeIntelGlobalSearchesEnabled: true, }, }, { name: "merge int", diff --git a/doc/integration/browser_extension/references/privacy.md b/doc/integration/browser_extension/references/privacy.md index f04647c2fe4..5503f436e85 100644 --- a/doc/integration/browser_extension/references/privacy.md +++ b/doc/integration/browser_extension/references/privacy.md @@ -10,7 +10,6 @@ The browser extension also does not store sensitive data locally. The informatio - AnonymousUid - Feature flags - - Hover alerts - Client settings - Enable/disable status - Sourcegraph URL diff --git a/package.json b/package.json index 3810f690e0a..3dc87f293db 100644 --- a/package.json +++ b/package.json @@ -461,8 +461,6 @@ "sanitize-html": "^2.0.0", "semver": "^7.3.2", "stream-http": "^3.2.0", - "string-score": "^1.0.1", - "tabbable": "^5.1.5", "tagged-template-noop": "^2.1.1", "ts-key-enum": "^2.0.7", "tslib": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7963dc7d48..2eaad238ba2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -358,12 +358,10 @@ importers: storybook-dark-mode: ^2.0.4 stream-browserify: ^3.0.0 stream-http: ^3.2.0 - string-score: ^1.0.1 string-width: ^4.2.0 style-loader: ^3.3.1 stylelint: ^14.3.0 svgo: ^2.7.0 - tabbable: ^5.1.5 tagged-template-noop: ^2.1.1 term-size: ^2.2.0 terser-webpack-plugin: ^5.3.6 @@ -527,8 +525,6 @@ importers: sanitize-html: 2.3.3 semver: 7.3.8 stream-http: 3.2.0 - string-score: 1.0.1 - tabbable: 5.2.1 tagged-template-noop: 2.1.1 ts-key-enum: 2.0.8 tslib: 2.1.0 @@ -30869,10 +30865,6 @@ packages: strip-ansi: 6.0.1 dev: true - /string-score/1.0.1: - resolution: {integrity: sha512-HRm/tlGZR3NCphwEa+D60qvtTCucu5yybc2S9BI9An/Zq01/r8EOyrKD0wOgZebpijR/iydGP4lPgCzzSiX+Ug==} - dev: false - /string-width/1.0.2: resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==} engines: {node: '>=0.10.0'} diff --git a/schema/schema.go b/schema/schema.go index 25c9f150c24..d48a05a3cd7 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -1989,8 +1989,6 @@ type Settings struct { BasicCodeIntelIndexOnly bool `json:"basicCodeIntel.indexOnly,omitempty"` // BasicCodeIntelUnindexedSearchTimeout description: The timeout (in milliseconds) for un-indexed search requests. BasicCodeIntelUnindexedSearchTimeout float64 `json:"basicCodeIntel.unindexedSearchTimeout,omitempty"` - // CodeHostUseNativeTooltips description: Whether to use the code host's native hover tooltips when they exist (GitHub's jump-to-definition tooltips, for example). - CodeHostUseNativeTooltips bool `json:"codeHost.useNativeTooltips,omitempty"` // CodeIntelDisableRangeQueries description: Whether to fetch multiple precise definitions and references on hover. CodeIntelDisableRangeQueries bool `json:"codeIntel.disableRangeQueries,omitempty"` // CodeIntelDisableSearchBased description: Never fall back to search-based code intelligence. @@ -2094,7 +2092,6 @@ func (v *Settings) UnmarshalJSON(data []byte) error { delete(m, "basicCodeIntel.includeForks") delete(m, "basicCodeIntel.indexOnly") delete(m, "basicCodeIntel.unindexedSearchTimeout") - delete(m, "codeHost.useNativeTooltips") delete(m, "codeIntel.disableRangeQueries") delete(m, "codeIntel.disableSearchBased") delete(m, "codeIntel.mixPreciseAndSearchBasedReferences") diff --git a/schema/settings.schema.json b/schema/settings.schema.json index 496558b3ee4..334459cd833 100644 --- a/schema/settings.schema.json +++ b/schema/settings.schema.json @@ -549,11 +549,6 @@ "enum": ["browser-extension", "native-integration"], "default": "browser-extension" }, - "codeHost.useNativeTooltips": { - "description": "Whether to use the code host's native hover tooltips when they exist (GitHub's jump-to-definition tooltips, for example).", - "type": "boolean", - "default": false - }, "search.hideSuggestions": { "description": "Disable search suggestions below the search bar when constructing queries. Defaults to false.", "type": "boolean", diff --git a/third-party-licenses/ThirdPartyLicenses.csv b/third-party-licenses/ThirdPartyLicenses.csv index d7f4b18deb5..3f57dfc9418 100644 --- a/third-party-licenses/ThirdPartyLicenses.csv +++ b/third-party-licenses/ThirdPartyLicenses.csv @@ -1138,7 +1138,6 @@ Yarn,stable,0.1.8,MIT,"",Approved Yarn,statuses,1.5.0,MIT,"",Approved Yarn,store2,2.12.0,(MIT OR GPL-3.0),http://www.esha.com/,Approved Yarn,stream-http,3.2.0,MIT,https://github.com/jhiesey/stream-http#readme,Approved -Yarn,string-score,1.0.1,MIT,https://github.com/KenPowers/string-score,Approved Yarn,string-width,4.2.3,MIT,sindresorhus.com,Approved Yarn,string_decoder,1.1.1,MIT,https://github.com/nodejs/string_decoder,Approved Yarn,strip-ansi,3.0.1,MIT,sindresorhus.com,Approved @@ -1153,8 +1152,6 @@ Yarn,supports-color,8.1.1,MIT,https://sindresorhus.com,Approved Yarn,supports-preserve-symlinks-flag,1.0.0,MIT,https://github.com/inspect-js/node-supports-preserve-symlinks-flag#readme,Approved Yarn,symbol-observable,4.0.0,MIT,"",Approved Yarn,synchronous-promise,2.0.15,New BSD,https://github.com/fluffynuts,Approved -Yarn,tabbable,4.0.0,MIT,https://github.com/davidtheclark/tabbable#readme,Approved -Yarn,tabbable,5.2.1,MIT,https://github.com/focus-trap/tabbable#readme,Approved Yarn,tagged-template-noop,2.1.1,MIT,https://github.com/lleaff/tagged-template-noop#readme,Approved Yarn,tapable,1.1.3,MIT,https://github.com/webpack/tapable,Approved Yarn,tapable,2.2.0,MIT,https://github.com/webpack/tapable,Approved