From 5e8b9d1f8b3dcb7fe823ddd9153323a12f50fc23 Mon Sep 17 00:00:00 2001 From: jeanp413 Date: Fri, 31 Jul 2020 20:27:53 -0500 Subject: [PATCH 1/2] Fixes #99735 --- .../contrib/feedback/browser/feedback.ts | 74 +++++++++++++------ .../feedback/browser/feedbackStatusbarItem.ts | 35 +++------ 2 files changed, 64 insertions(+), 45 deletions(-) diff --git a/src/vs/workbench/contrib/feedback/browser/feedback.ts b/src/vs/workbench/contrib/feedback/browser/feedback.ts index c251c876ccb..cf81a0d88b8 100644 --- a/src/vs/workbench/contrib/feedback/browser/feedback.ts +++ b/src/vs/workbench/contrib/feedback/browser/feedback.ts @@ -5,8 +5,7 @@ import 'vs/css!./media/feedback'; import * as nls from 'vs/nls'; -import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { Dropdown } from 'vs/base/browser/ui/dropdown/dropdown'; +import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import * as dom from 'vs/base/browser/dom'; import { ICommandService } from 'vs/platform/commands/common/commands'; @@ -24,6 +23,8 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Codicon } from 'vs/base/common/codicons'; +import { Emitter } from 'vs/base/common/event'; +import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; export interface IFeedback { feedback: string; @@ -35,13 +36,16 @@ export interface IFeedbackDelegate { getCharacterLimit(sentiment: number): number; } -export interface IFeedbackDropdownOptions { - contextViewProvider: IContextViewService; +export interface IFeedbackWidgetOptions { feedbackService: IFeedbackDelegate; onFeedbackVisibilityChange?: (visible: boolean) => void; } -export class FeedbackDropdown extends Dropdown { +export class FeedbackWidget extends Disposable { + private visible: boolean | undefined; + private _onDidChangeVisibility = new Emitter(); + readonly onDidChangeVisibility = this._onDidChangeVisibility.event; + private maxFeedbackCharacters: number; private feedback: string = ''; @@ -63,8 +67,9 @@ export class FeedbackDropdown extends Dropdown { private isPure: boolean = true; constructor( - container: HTMLElement, - private options: IFeedbackDropdownOptions, + private options: IFeedbackWidgetOptions, + @IContextViewService private readonly contextViewService: IContextViewService, + @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, @ICommandService private readonly commandService: ICommandService, @ITelemetryService private readonly telemetryService: ITelemetryService, @IIntegrityService private readonly integrityService: IIntegrityService, @@ -73,7 +78,7 @@ export class FeedbackDropdown extends Dropdown { @IProductService productService: IProductService, @IOpenerService private readonly openerService: IOpenerService ) { - super(container, options); + super(); this.feedbackDelegate = options.feedbackService; this.maxFeedbackCharacters = this.feedbackDelegate.getCharacterLimit(this.sentiment); @@ -87,23 +92,18 @@ export class FeedbackDropdown extends Dropdown { this.isPure = false; } }); - - dom.addClass(this.element, 'send-feedback'); - this.element.title = nls.localize('sendFeedback', "Tweet Feedback"); } - protected getAnchor(): HTMLElement | IAnchor { - const position = dom.getDomNodePagePosition(this.element); + private getAnchor(): HTMLElement | IAnchor { + const dimension = this.layoutService.dimension; return { - x: position.left + position.width, // center above the container - y: position.top - 26, // above status bar and beak - width: position.width, - height: position.height + x: dimension.width - 8, + y: dimension.height - 31 }; } - protected renderContents(container: HTMLElement): IDisposable { + private renderContents(container: HTMLElement): IDisposable { const disposables = new DisposableStore(); dom.addClass(container, 'monaco-menu-container'); @@ -380,7 +380,26 @@ export class FeedbackDropdown extends Dropdown { } show(): void { - super.show(); + if (this.visible) { + return; + } + + this.visible = true; + this._onDidChangeVisibility.fire(true); + + this.contextViewService.showContextView({ + getAnchor: () => this.getAnchor(), + + render: (container) => { + return this.renderContents(container); + }, + + onDOMEvent: (e, activeElement) => { + this.onEvent(e, activeElement); + }, + + onHide: () => this.onHide() + }); if (this.options.onFeedbackVisibilityChange) { this.options.onFeedbackVisibilityChange(true); @@ -389,13 +408,17 @@ export class FeedbackDropdown extends Dropdown { this.updateCharCountText(); } - protected onHide(): void { + private onHide(): void { if (this.options.onFeedbackVisibilityChange) { this.options.onFeedbackVisibilityChange(false); } } hide(): void { + if (!this.visible) { + return; + } + if (this.feedbackDescriptionInput) { this.feedback = this.feedbackDescriptionInput.value; } @@ -409,10 +432,17 @@ export class FeedbackDropdown extends Dropdown { this.statusbarService.updateEntryVisibility('status.feedback', false); } - super.hide(); + this.visible = false; + this._onDidChangeVisibility.fire(false); + + this.contextViewService.hideContextView(); } - onEvent(e: Event, activeElement: HTMLElement): void { + isVisible(): boolean { + return !!this.visible; + } + + private onEvent(e: Event, activeElement: HTMLElement): void { if (e instanceof KeyboardEvent) { const keyboardEvent = e; if (keyboardEvent.keyCode === 27) { // Escape diff --git a/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts b/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts index fdbdda8d7f8..d1dcf8d0d8c 100644 --- a/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts +++ b/src/vs/workbench/contrib/feedback/browser/feedbackStatusbarItem.ts @@ -4,8 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable } from 'vs/base/common/lifecycle'; -import { FeedbackDropdown, IFeedback, IFeedbackDelegate } from 'vs/workbench/contrib/feedback/browser/feedback'; -import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { FeedbackWidget, IFeedback, IFeedbackDelegate } from 'vs/workbench/contrib/feedback/browser/feedback'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IProductService } from 'vs/platform/product/common/productService'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; @@ -50,15 +49,13 @@ class TwitterFeedbackService implements IFeedbackDelegate { } export class FeedbackStatusbarConribution extends Disposable implements IWorkbenchContribution { - private dropdown: FeedbackDropdown | undefined; + private widget: FeedbackWidget | undefined; private entry: IStatusbarEntryAccessor | undefined; constructor( @IStatusbarService statusbarService: IStatusbarService, @IProductService productService: IProductService, - @IInstantiationService private instantiationService: IInstantiationService, - @IContextViewService private contextViewService: IContextViewService - ) { + @IInstantiationService private instantiationService: IInstantiationService) { super(); if (productService.sendASmile) { @@ -76,26 +73,18 @@ export class FeedbackStatusbarConribution extends Disposable implements IWorkben } private toggleFeedback(): void { - if (!this.dropdown) { - const statusContainr = document.getElementById('status.feedback'); - if (statusContainr) { - const icon = statusContainr.getElementsByClassName('codicon').item(0) as HTMLElement | null; - if (!icon) { - throw new Error('Could not find icon'); - } - this.dropdown = this._register(this.instantiationService.createInstance(FeedbackDropdown, icon, { - contextViewProvider: this.contextViewService, - feedbackService: this.instantiationService.createInstance(TwitterFeedbackService), - onFeedbackVisibilityChange: visible => this.entry!.update(this.getStatusEntry(visible)) - })); - } + if (!this.widget) { + this.widget = this._register(this.instantiationService.createInstance(FeedbackWidget, { + feedbackService: this.instantiationService.createInstance(TwitterFeedbackService), + onFeedbackVisibilityChange: visible => this.entry!.update(this.getStatusEntry(visible)) + })); } - if (this.dropdown) { - if (!this.dropdown.isVisible()) { - this.dropdown.show(); + if (this.widget) { + if (!this.widget.isVisible()) { + this.widget.show(); } else { - this.dropdown.hide(); + this.widget.hide(); } } } From 0dfb0322e6cd4c0c1c8ff78a78e7b48712a97109 Mon Sep 17 00:00:00 2001 From: jeanp413 Date: Sun, 24 Oct 2021 23:46:20 -0500 Subject: [PATCH 2/2] Minor fix --- src/vs/workbench/contrib/feedback/browser/feedback.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/feedback/browser/feedback.ts b/src/vs/workbench/contrib/feedback/browser/feedback.ts index ae20fdec914..46fc36b304e 100644 --- a/src/vs/workbench/contrib/feedback/browser/feedback.ts +++ b/src/vs/workbench/contrib/feedback/browser/feedback.ts @@ -399,7 +399,9 @@ export class FeedbackWidget extends Disposable { onDOMEvent: (e, activeElement) => { this.onEvent(e, activeElement); - } + }, + + onHide: () => this._onDidChangeVisibility.fire(false) }); this._onDidChangeVisibility.fire(true); @@ -422,8 +424,6 @@ export class FeedbackWidget extends Disposable { this.visible = false; this.contextViewService.hideContextView(); - - this._onDidChangeVisibility.fire(false); } isVisible(): boolean {