Merge branch 'master' into ben/electron
This commit is contained in:
commit
945d5d57e1
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"account": "monacobuild",
|
||||
"container": "debuggers",
|
||||
"zip": "d98733b/node-debug.zip",
|
||||
"zip": "2985e20/node-debug.zip",
|
||||
"output": ""
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ define([
|
|||
'vs/editor/contrib/parameterHints/browser/parameterHints',
|
||||
'vs/editor/contrib/quickFix/browser/quickFix',
|
||||
'vs/editor/contrib/referenceSearch/browser/referenceSearch',
|
||||
'vs/editor/contrib/rename/browser/rename',
|
||||
'vs/editor/contrib/rename/browser/rename2',
|
||||
'vs/editor/contrib/smartSelect/common/smartSelect',
|
||||
'vs/editor/contrib/smartSelect/common/jumpToBracket',
|
||||
|
|
|
@ -35,7 +35,6 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode {
|
|||
|
||||
// adapters start
|
||||
public autoValidateDelay:number;
|
||||
public occurrencesSupport:Modes.IOccurrencesSupport;
|
||||
public suggestSupport:Modes.ISuggestSupport;
|
||||
public inplaceReplaceSupport:Modes.IInplaceReplaceSupport;
|
||||
public diffSupport:Modes.IDiffSupport;
|
||||
|
@ -63,7 +62,6 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode {
|
|||
this._options = null;
|
||||
|
||||
this.autoValidateDelay = 500;
|
||||
this.occurrencesSupport = this;
|
||||
this.suggestSupport = this;
|
||||
this.inplaceReplaceSupport = this;
|
||||
this.diffSupport = this;
|
||||
|
@ -194,11 +192,6 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode {
|
|||
return true;
|
||||
}
|
||||
|
||||
static $findOccurrences = OneWorkerAttr(AbstractMode, AbstractMode.prototype.findOccurrences);
|
||||
public findOccurrences(resource:URI, position:EditorCommon.IPosition, strict:boolean = false): TPromise<Modes.IOccurence[]> {
|
||||
return this._worker((w) => w.findOccurrences(resource, position, strict));
|
||||
}
|
||||
|
||||
static $navigateValueSet = OneWorkerAttr(AbstractMode, AbstractMode.prototype.navigateValueSet);
|
||||
public navigateValueSet(resource:URI, position:EditorCommon.IRange, up:boolean):TPromise<Modes.IInplaceReplaceSupportResult> {
|
||||
return this._worker((w) => w.inplaceReplaceSupport.navigateValueSet(resource, position, up));
|
||||
|
|
|
@ -177,30 +177,6 @@ export class AbstractModeWorker {
|
|||
return AbstractModeWorker.filter;
|
||||
}
|
||||
|
||||
// ---- occurrences ---------------------------------------------------------------
|
||||
|
||||
public findOccurrences(resource:URI, position:EditorCommon.IPosition, strict?:boolean):TPromise<Modes.IOccurence[]> {
|
||||
|
||||
var model = this.resourceService.get(resource),
|
||||
wordAtPosition = model.getWordAtPosition(position),
|
||||
currentWord = (wordAtPosition ? wordAtPosition.word : ''),
|
||||
result:Modes.IOccurence[] = [];
|
||||
|
||||
var words = model.getAllWordsWithRange(),
|
||||
upperBound = Math.min(1000, words.length); // Limit find occurences to 1000 occurences
|
||||
|
||||
for(var i = 0; i < upperBound; i++) {
|
||||
if(words[i].text === currentWord) {
|
||||
result.push({
|
||||
range: words[i].range,
|
||||
kind: 'text'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return TPromise.as(result);
|
||||
}
|
||||
|
||||
// ---- diff --------------------------------------------------------------------------
|
||||
|
||||
public computeDiff(original:URI, modified:URI, ignoreTrimWhitespace:boolean):TPromise<EditorCommon.ILineChange[]> {
|
||||
|
|
|
@ -22,6 +22,7 @@ import {IContextViewService} from 'vs/platform/contextview/browser/contextView';
|
|||
import {INullService} from 'vs/platform/instantiation/common/instantiation';
|
||||
import {KeyMod, KeyCode} from 'vs/base/common/keyCodes';
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
import {OccurrencesRegistry} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter';
|
||||
|
||||
/**
|
||||
* The Find controller will survive an editor.setModel(..) call
|
||||
|
@ -459,9 +460,18 @@ class MoveSelectionToNextFindMatchAction extends SelectNextFindMatchAction {
|
|||
class SelectHighlightsAction extends EditorAction {
|
||||
|
||||
static ID = 'editor.action.selectHighlights';
|
||||
static COMPAT_ID = 'editor.action.changeAll';
|
||||
|
||||
constructor(descriptor:EditorCommon.IEditorActionDescriptorData, editor:EditorCommon.ICommonCodeEditor, @INullService ns) {
|
||||
super(descriptor, editor, Behaviour.WidgetFocus);
|
||||
let behaviour = Behaviour.WidgetFocus;
|
||||
if (descriptor.id === SelectHighlightsAction.COMPAT_ID) {
|
||||
behaviour |= Behaviour.ShowInContextMenu;
|
||||
}
|
||||
super(descriptor, editor, behaviour);
|
||||
}
|
||||
|
||||
public getGroupId(): string {
|
||||
return '2_change/1_changeAll';
|
||||
}
|
||||
|
||||
public run(): TPromise<boolean> {
|
||||
|
@ -484,20 +494,17 @@ export class SelectionHighlighter implements EditorCommon.IEditorContribution {
|
|||
static ID = 'editor.contrib.selectionHighlighter';
|
||||
|
||||
private editor:EditorCommon.ICommonCodeEditor;
|
||||
private model:EditorCommon.IModel;
|
||||
private decorations:string[];
|
||||
private toDispose:Lifecycle.IDisposable[];
|
||||
|
||||
constructor(editor:EditorCommon.ICommonCodeEditor, @INullService ns) {
|
||||
this.editor = editor;
|
||||
this.model = this.editor.getModel();
|
||||
this.decorations = [];
|
||||
this.toDispose = [];
|
||||
|
||||
this.toDispose.push(editor.addListener2(EditorCommon.EventType.CursorPositionChanged, _ => this._update()));
|
||||
this.toDispose.push(editor.addListener2(EditorCommon.EventType.ModelChanged, (e) => {
|
||||
this.removeDecorations();
|
||||
this.model = this.editor.getModel();
|
||||
}));
|
||||
this.toDispose.push(FindController.getFindController(editor).onStateChanged(() => this._update()));
|
||||
}
|
||||
|
@ -522,10 +529,15 @@ export class SelectionHighlighter implements EditorCommon.IEditorContribution {
|
|||
this.removeDecorations();
|
||||
return;
|
||||
}
|
||||
|
||||
let model = this.editor.getModel();
|
||||
if (r.nextMatch) {
|
||||
// This is an empty selection
|
||||
this.removeDecorations();
|
||||
return;
|
||||
if (OccurrencesRegistry.has(model)) {
|
||||
// Do not interfere with semantic word highlighting in the no selection case
|
||||
this.removeDecorations();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (/^[ \t]+$/.test(r.searchText)) {
|
||||
// whitespace only selection
|
||||
|
@ -538,7 +550,7 @@ export class SelectionHighlighter implements EditorCommon.IEditorContribution {
|
|||
return;
|
||||
}
|
||||
|
||||
let allMatches = this.editor.getModel().findMatches(r.searchText, true, r.isRegex, r.matchCase, r.wholeWord);
|
||||
let allMatches = model.findMatches(r.searchText, true, r.isRegex, r.matchCase, r.wholeWord);
|
||||
allMatches.sort(Range.compareRangesUsingStarts);
|
||||
|
||||
let selections = this.editor.getSelections();
|
||||
|
@ -594,6 +606,11 @@ CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(SelectHighl
|
|||
context: ContextKey.EditorFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_L
|
||||
}));
|
||||
// register SelectHighlightsAction again to replace the now removed Change All action
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(SelectHighlightsAction, SelectHighlightsAction.COMPAT_ID, nls.localize('changeAll.label', "Change All Occurrences"), {
|
||||
context: ContextKey.EditorTextFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.F2
|
||||
}));
|
||||
|
||||
var CONTEXT_FIND_WIDGET_VISIBLE = 'findWidgetVisible';
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
.monaco-editor .linked-editing-placeholder {
|
||||
}
|
||||
|
||||
.monaco-editor .word-level-progress {
|
||||
font-style: italic;
|
||||
|
|
|
@ -1,328 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import 'vs/css!./rename';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import nls = require('vs/nls');
|
||||
import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions';
|
||||
import {EditorAction, Behaviour} from 'vs/editor/common/editorAction';
|
||||
import EditorCommon = require('vs/editor/common/editorCommon');
|
||||
import Modes = require('vs/editor/common/modes');
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import EventEmitter = require('vs/base/common/eventEmitter');
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
import {IMessageService} from 'vs/platform/message/common/message';
|
||||
import {IProgressService, IProgressRunner} from 'vs/platform/progress/common/progress';
|
||||
import {IKeybindingService, IKeybindingContextKey} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {KeyMod, KeyCode} from 'vs/base/common/keyCodes';
|
||||
|
||||
class LinkedEditingController {
|
||||
|
||||
private editor: EditorCommon.ICommonCodeEditor;
|
||||
private listenersToRemove:EventEmitter.ListenerUnbind[];
|
||||
private decorations:string[];
|
||||
private isDisposed: boolean;
|
||||
private _onDispose: () => void;
|
||||
|
||||
constructor(editor: EditorCommon.ICommonCodeEditor, selections: EditorCommon.ISelection[], ranges: EditorCommon.IRange[], onDispose: () => void) {
|
||||
this._onDispose = onDispose;
|
||||
this.editor = editor;
|
||||
this.isDisposed = false;
|
||||
|
||||
// Decorate editing ranges
|
||||
this.editor.changeDecorations((changeAccessor:EditorCommon.IModelDecorationsChangeAccessor) => {
|
||||
var newDecorations: EditorCommon.IModelDeltaDecoration[] = [];
|
||||
for (var i = 0, len = selections.length; i < len; i++) {
|
||||
var className = 'linked-editing-placeholder';
|
||||
newDecorations.push({
|
||||
range: ranges[i],
|
||||
options: {
|
||||
className: className
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.decorations = changeAccessor.deltaDecorations([], newDecorations);
|
||||
});
|
||||
|
||||
// Begin linked editing (multi-cursor)
|
||||
this.editor.setSelections(selections);
|
||||
|
||||
this.listenersToRemove = [];
|
||||
this.listenersToRemove.push(this.editor.addListener(EditorCommon.EventType.CursorPositionChanged, (e:EditorCommon.ICursorPositionChangedEvent) => {
|
||||
if (this.isDisposed) {
|
||||
return;
|
||||
}
|
||||
var cursorCount = 1 + e.secondaryPositions.length;
|
||||
if (cursorCount !== this.decorations.length) {
|
||||
this.dispose();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public onEnterOrEscape(): boolean {
|
||||
if (this.isDisposed) {
|
||||
return;
|
||||
}
|
||||
// Basically cancel multi-cursor
|
||||
this.editor.setSelection(this.editor.getSelection());
|
||||
this.dispose();
|
||||
return true;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (this.isDisposed) {
|
||||
return;
|
||||
}
|
||||
this.isDisposed = true;
|
||||
this._onDispose();
|
||||
|
||||
this.decorations = this.editor.deltaDecorations(this.decorations, []);
|
||||
|
||||
this.listenersToRemove.forEach((element) => {
|
||||
element();
|
||||
});
|
||||
this.listenersToRemove = [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class LocalProgressService implements IProgressService {
|
||||
public serviceId = IProgressService;
|
||||
|
||||
constructor(private _editor:EditorCommon.ICommonCodeEditor) {
|
||||
//
|
||||
}
|
||||
|
||||
showWhile<T>(promise:TPromise<T>, delay?:number):TPromise<T> {
|
||||
|
||||
var decoration: string,
|
||||
delayHandle: number;
|
||||
|
||||
delayHandle = setTimeout(() => {
|
||||
decoration = this._addDecoration();
|
||||
}, delay || 0);
|
||||
|
||||
return promise.then((value) => {
|
||||
clearTimeout(delayHandle);
|
||||
this._removeDecoration(decoration);
|
||||
return value;
|
||||
}, (err) => {
|
||||
clearTimeout(delayHandle);
|
||||
this._removeDecoration(decoration);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
private _addDecoration():string {
|
||||
|
||||
var position = this._editor.getPosition(),
|
||||
word = this._editor.getModel().getWordAtPosition(position),
|
||||
decorationId:string;
|
||||
|
||||
var decorations = this._editor.deltaDecorations([], [{
|
||||
range: {
|
||||
startLineNumber: position.lineNumber,
|
||||
startColumn: word.startColumn,
|
||||
endLineNumber: position.lineNumber,
|
||||
endColumn: word.endColumn
|
||||
},
|
||||
options: {
|
||||
inlineClassName: 'word-level-progress'
|
||||
}
|
||||
}]);
|
||||
|
||||
return decorations[0];
|
||||
}
|
||||
|
||||
private _removeDecoration(decorationId:string):void {
|
||||
if(decorationId) {
|
||||
this._editor.changeDecorations((accessor) => {
|
||||
accessor.deltaDecorations([decorationId], []);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public show(...args:any[]):IProgressRunner {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
}
|
||||
|
||||
export class ChangeAllAction extends EditorAction {
|
||||
|
||||
public static ID = 'editor.action.changeAll';
|
||||
|
||||
private _idPool:number;
|
||||
private _messageService:IMessageService;
|
||||
private _progressService: IProgressService;
|
||||
private _currentController: LinkedEditingController;
|
||||
private _changeAllMode: IKeybindingContextKey<boolean>;
|
||||
|
||||
constructor(descriptor:EditorCommon.IEditorActionDescriptorData, editor:EditorCommon.ICommonCodeEditor, @IMessageService messageService: IMessageService, @IKeybindingService keybindingService: IKeybindingService) {
|
||||
super(descriptor, editor, Behaviour.WidgetFocus | Behaviour.Writeable | Behaviour.ShowInContextMenu | Behaviour.UpdateOnCursorPositionChange);
|
||||
this._idPool = 0;
|
||||
this._messageService = messageService;
|
||||
this._progressService = new LocalProgressService(this.editor);
|
||||
this._currentController = null;
|
||||
this._changeAllMode = keybindingService.createKey(CONTEXT_CHANGE_ALL_MODE, false);
|
||||
}
|
||||
|
||||
public getGroupId(): string {
|
||||
return '2_change/1_changeAll';
|
||||
}
|
||||
|
||||
public isSupported():boolean {
|
||||
var mode = this.editor.getModel().getMode();
|
||||
|
||||
return !!mode && !!mode.occurrencesSupport && super.isSupported();
|
||||
}
|
||||
|
||||
public computeInfos(editor:EditorCommon.ICommonCodeEditor):TPromise<Modes.IOccurence[]> {
|
||||
var selection = editor.getSelection();
|
||||
var position = selection.getStartPosition();
|
||||
var model = editor.getModel();
|
||||
|
||||
return this.editor.getModel().getMode().occurrencesSupport.findOccurrences(model.getAssociatedResource(), position);
|
||||
}
|
||||
|
||||
public run():TPromise<boolean> {
|
||||
|
||||
var myId = ++this._idPool,
|
||||
state = this.editor.captureState(EditorCommon.CodeEditorStateFlag.Position, EditorCommon.CodeEditorStateFlag.Value),
|
||||
capturedSelection = this.editor.getSelection(),
|
||||
infoPromise = this.computeInfos(this.editor);
|
||||
|
||||
if(this._progressService) {
|
||||
this._progressService.showWhile(infoPromise, 500);
|
||||
}
|
||||
|
||||
return infoPromise.then((infos:Modes.IOccurence[]) => {
|
||||
|
||||
if(myId !== this._idPool) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!state.validate(this.editor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(infos.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var ranges = infos.map((info) => {
|
||||
return info.range;
|
||||
});
|
||||
|
||||
this._beginLinkedEditing(ranges, capturedSelection);
|
||||
|
||||
return true;
|
||||
}, (e) => {
|
||||
this._messageService.show(Severity.Info, e);
|
||||
});
|
||||
}
|
||||
|
||||
private _indexOf(ranges:EditorCommon.IRange[], lineNumber: number, column: number): number {
|
||||
var pos = {
|
||||
lineNumber: lineNumber,
|
||||
column: column
|
||||
};
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
if (ranges[i].startLineNumber !== lineNumber) {
|
||||
// Only consider ranges that start on the same line as position
|
||||
continue;
|
||||
}
|
||||
if (Range.containsPosition(ranges[i], pos)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private _beginLinkedEditing(ranges: EditorCommon.IRange[], capturedSelection: EditorCommon.IEditorSelection): void {
|
||||
if (this._currentController) {
|
||||
this._currentController.dispose();
|
||||
this._currentController = null;
|
||||
}
|
||||
var editorSelection = this.editor.getSelection();
|
||||
|
||||
// Try to find a suitable range for the current editor position
|
||||
var foundRangeIndex = this._indexOf(ranges, editorSelection.positionLineNumber, editorSelection.positionColumn);
|
||||
|
||||
if (foundRangeIndex === -1) {
|
||||
// Current editor position is outside of one of these ranges, try again with the original editor position
|
||||
editorSelection = capturedSelection;
|
||||
foundRangeIndex = this._indexOf(ranges, editorSelection.positionLineNumber, editorSelection.positionColumn);
|
||||
|
||||
if (foundRangeIndex === -1) {
|
||||
// These ranges are bogus!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var hasSelectionInFoundRange = false;
|
||||
if (!editorSelection.isEmpty()) {
|
||||
if (Range.containsPosition(ranges[foundRangeIndex], { lineNumber: editorSelection.selectionStartLineNumber, column: editorSelection.selectionStartColumn})) {
|
||||
hasSelectionInFoundRange = true;
|
||||
}
|
||||
}
|
||||
|
||||
var deltaColumnForPosition: number, deltaColumnForStartSelection: number;
|
||||
if (hasSelectionInFoundRange) {
|
||||
deltaColumnForPosition = editorSelection.positionColumn - ranges[foundRangeIndex].startColumn;
|
||||
deltaColumnForStartSelection = editorSelection.selectionStartColumn - ranges[foundRangeIndex].startColumn;
|
||||
} else {
|
||||
deltaColumnForPosition = ranges[foundRangeIndex].endColumn - ranges[foundRangeIndex].startColumn;
|
||||
deltaColumnForStartSelection = 0;
|
||||
}
|
||||
|
||||
var newEditorSelections: EditorCommon.ISelection[] = [];
|
||||
newEditorSelections.push({
|
||||
selectionStartLineNumber: ranges[foundRangeIndex].startLineNumber,
|
||||
selectionStartColumn: ranges[foundRangeIndex].startColumn + deltaColumnForStartSelection,
|
||||
positionLineNumber: ranges[foundRangeIndex].startLineNumber,
|
||||
positionColumn: ranges[foundRangeIndex].startColumn + deltaColumnForPosition,
|
||||
});
|
||||
|
||||
for (var i = 0; i < ranges.length; i++) {
|
||||
if (i !== foundRangeIndex) {
|
||||
newEditorSelections.push({
|
||||
selectionStartLineNumber: ranges[i].startLineNumber,
|
||||
selectionStartColumn: ranges[i].startColumn + deltaColumnForStartSelection,
|
||||
positionLineNumber: ranges[i].startLineNumber,
|
||||
positionColumn: ranges[i].startColumn + deltaColumnForPosition,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this._changeAllMode.set(true);
|
||||
this._currentController = new LinkedEditingController(this.editor, newEditorSelections, ranges, () => {
|
||||
this._changeAllMode.reset();
|
||||
});
|
||||
}
|
||||
|
||||
public leaveChangeAllMode(): void {
|
||||
if (this._currentController) {
|
||||
this._currentController.onEnterOrEscape();
|
||||
this._currentController = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var CONTEXT_CHANGE_ALL_MODE = 'inChangeAllMode';
|
||||
|
||||
var weight = CommonEditorRegistry.commandWeight(30);
|
||||
|
||||
// register actions
|
||||
CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ChangeAllAction, ChangeAllAction.ID, nls.localize('changeAll.label', "Change All Occurrences"), {
|
||||
context: ContextKey.EditorTextFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.F2
|
||||
}));
|
||||
CommonEditorRegistry.registerEditorCommand('leaveChangeAllMode', weight, { primary: KeyCode.Enter, secondary: [KeyCode.Escape] }, true, CONTEXT_CHANGE_ALL_MODE,(ctx, editor, args) => {
|
||||
var action = <ChangeAllAction>editor.getAction(ChangeAllAction.ID);
|
||||
action.leaveChangeAllMode();
|
||||
});
|
|
@ -285,6 +285,7 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> {
|
|||
public referenceSupport: Modes.IReferenceSupport;
|
||||
public logicalSelectionSupport: Modes.ILogicalSelectionSupport;
|
||||
public extraInfoSupport:Modes.IExtraInfoSupport;
|
||||
public occurrencesSupport:Modes.IOccurrencesSupport;
|
||||
public outlineSupport: Modes.IOutlineSupport;
|
||||
public declarationSupport: Modes.IDeclarationSupport;
|
||||
public suggestSupport: Modes.ISuggestSupport;
|
||||
|
@ -305,6 +306,7 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> {
|
|||
{ tokenType: 'punctuation.bracket.css', open: '{', close: '}', isElectric: true }
|
||||
] });
|
||||
|
||||
this.occurrencesSupport = this;
|
||||
this.extraInfoSupport = this;
|
||||
this.referenceSupport = new supports.ReferenceSupport(this, {
|
||||
tokens: [cssTokenTypes.TOKEN_PROPERTY + '.css', cssTokenTypes.TOKEN_VALUE + '.css', cssTokenTypes.TOKEN_SELECTOR_TAG + '.css'],
|
||||
|
@ -344,6 +346,11 @@ export class CSSMode extends AbstractMode<cssWorker.CSSWorker> {
|
|||
return createAsyncDescriptor2('vs/languages/css/common/cssWorker', 'CSSWorker');
|
||||
}
|
||||
|
||||
static $findOccurrences = OneWorkerAttr(CSSMode, CSSMode.prototype.findOccurrences);
|
||||
public findOccurrences(resource:URI, position:EditorCommon.IPosition, strict:boolean = false): WinJS.TPromise<Modes.IOccurence[]> {
|
||||
return this._worker((w) => w.findOccurrences(resource, position, strict));
|
||||
}
|
||||
|
||||
static $findDeclaration = OneWorkerAttr(CSSMode, CSSMode.prototype.findDeclaration);
|
||||
public findDeclaration(resource:URI, position:EditorCommon.IPosition):WinJS.TPromise<Modes.IReference> {
|
||||
return this._worker((w) => w.findDeclaration(resource, position));
|
||||
|
|
|
@ -277,6 +277,7 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
|
|||
public characterPairSupport: Modes.ICharacterPairSupport;
|
||||
|
||||
public extraInfoSupport:Modes.IExtraInfoSupport;
|
||||
public occurrencesSupport:Modes.IOccurrencesSupport;
|
||||
public referenceSupport: Modes.IReferenceSupport;
|
||||
public logicalSelectionSupport: Modes.ILogicalSelectionSupport;
|
||||
public formattingSupport: Modes.IFormattingSupport;
|
||||
|
@ -311,6 +312,7 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
|
|||
|
||||
this.formattingSupport = this;
|
||||
this.extraInfoSupport = this;
|
||||
this.occurrencesSupport = this;
|
||||
this.referenceSupport = new supports.ReferenceSupport(this, {
|
||||
tokens: ['invalid'],
|
||||
findReferences: (resource, position, includeDeclaration) => this.findReferences(resource, position, includeDeclaration)});
|
||||
|
|
|
@ -132,6 +132,7 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend
|
|||
public characterPairSupport: Modes.ICharacterPairSupport;
|
||||
public referenceSupport: Modes.IReferenceSupport;
|
||||
public extraInfoSupport:Modes.IExtraInfoSupport;
|
||||
public occurrencesSupport:Modes.IOccurrencesSupport;
|
||||
public quickFixSupport:Modes.IQuickFixSupport;
|
||||
public logicalSelectionSupport:Modes.ILogicalSelectionSupport;
|
||||
public parameterHintsSupport:Modes.IParameterHintsSupport;
|
||||
|
@ -185,6 +186,7 @@ export class TypeScriptMode<W extends typescriptWorker.TypeScriptWorker2> extend
|
|||
}
|
||||
|
||||
this.extraInfoSupport = this;
|
||||
this.occurrencesSupport = this;
|
||||
this.formattingSupport = this;
|
||||
this.quickFixSupport = this;
|
||||
this.logicalSelectionSupport = this;
|
||||
|
|
|
@ -141,7 +141,6 @@ export interface IEnvironment {
|
|||
};
|
||||
|
||||
sendASmile: {
|
||||
submitUrl: string,
|
||||
reportIssueUrl: string,
|
||||
requestFeatureUrl: string
|
||||
};
|
||||
|
|
|
@ -51,7 +51,6 @@ export interface IProductConfiguration {
|
|||
asimovKey: string;
|
||||
};
|
||||
sendASmile: {
|
||||
submitUrl: string,
|
||||
reportIssueUrl: string,
|
||||
requestFeatureUrl: string
|
||||
};
|
||||
|
|
|
@ -123,7 +123,6 @@ export interface IWindowConfiguration extends env.ICommandLineArguments {
|
|||
asimovKey: string;
|
||||
},
|
||||
sendASmile: {
|
||||
submitUrl: string,
|
||||
reportIssueUrl: string,
|
||||
requestFeatureUrl: string
|
||||
}
|
||||
|
|
|
@ -15,17 +15,17 @@ import {Dropdown} from 'vs/base/browser/ui/dropdown/dropdown';
|
|||
import {IXHRResponse} from 'vs/base/common/http';
|
||||
import {IContextViewService} from 'vs/platform/contextview/browser/contextView';
|
||||
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
|
||||
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
|
||||
|
||||
const STATUS_TIMEOUT = 500;
|
||||
|
||||
export interface IFeedback {
|
||||
feedback: string;
|
||||
alias: string;
|
||||
sentiment: number;
|
||||
}
|
||||
|
||||
export interface IFeedbackService {
|
||||
submitFeedback(feedback: IFeedback): Promise;
|
||||
submitFeedback(feedback: IFeedback): void;
|
||||
}
|
||||
|
||||
export interface IFeedbackDropdownOptions {
|
||||
|
@ -40,9 +40,9 @@ enum FormEvent {
|
|||
};
|
||||
|
||||
export class FeedbackDropdown extends Dropdown {
|
||||
protected static MAX_FEEDBACK_CHARS: number = 140;
|
||||
|
||||
protected feedback: string;
|
||||
protected alias: string;
|
||||
protected sentiment: number;
|
||||
protected aliasEnabled: boolean;
|
||||
protected isSendingFeedback: boolean;
|
||||
|
@ -52,15 +52,18 @@ export class FeedbackDropdown extends Dropdown {
|
|||
|
||||
protected feedbackForm: HTMLFormElement;
|
||||
protected feedbackDescriptionInput: HTMLTextAreaElement;
|
||||
protected feedbackAliasInput: HTMLInputElement;
|
||||
protected smileyInput: Builder;
|
||||
protected frownyInput: Builder;
|
||||
protected sendButton: Builder;
|
||||
|
||||
protected requestFeatureLink: string;
|
||||
protected reportIssueLink: string;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
options: IFeedbackDropdownOptions,
|
||||
@ITelemetryService protected telemetryService: ITelemetryService
|
||||
@ITelemetryService protected telemetryService: ITelemetryService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService
|
||||
) {
|
||||
super(container, {
|
||||
contextViewProvider: options.contextViewProvider,
|
||||
|
@ -76,18 +79,19 @@ export class FeedbackDropdown extends Dropdown {
|
|||
this.feedbackService = options.feedbackService;
|
||||
|
||||
this.feedback = '';
|
||||
this.alias = '';
|
||||
this.aliasEnabled = false;
|
||||
this.sentiment = 1;
|
||||
|
||||
this.feedbackForm = null;
|
||||
this.feedbackDescriptionInput = null;
|
||||
this.feedbackAliasInput = null;
|
||||
|
||||
this.smileyInput = null;
|
||||
this.frownyInput = null;
|
||||
|
||||
this.sendButton = null;
|
||||
|
||||
const env = contextService.getConfiguration().env;
|
||||
this.reportIssueLink = env.sendASmile.reportIssueUrl;
|
||||
this.requestFeatureLink = env.sendASmile.requestFeatureUrl;
|
||||
}
|
||||
|
||||
public renderContents(container: HTMLElement): IDisposable {
|
||||
|
@ -106,10 +110,12 @@ export class FeedbackDropdown extends Dropdown {
|
|||
this.hide();
|
||||
}).appendTo($form);
|
||||
|
||||
$('h3').text(nls.localize("sentiment", "How was your experience?")).appendTo($form);
|
||||
let $content = $('div.content').appendTo($form);
|
||||
|
||||
let $feedbackSentiment = $('div.feedback-sentiment').appendTo($form);
|
||||
let $sentimentContainer = $('div').appendTo($content);
|
||||
$('span').text(nls.localize("sentiment", "How was your experience?")).appendTo($sentimentContainer);
|
||||
|
||||
let $feedbackSentiment = $('div.feedback-sentiment').appendTo($sentimentContainer);
|
||||
|
||||
this.smileyInput = $('div').addClass('sentiment smile').attr({
|
||||
'aria-checked': 'false',
|
||||
|
@ -134,44 +140,49 @@ export class FeedbackDropdown extends Dropdown {
|
|||
this.frownyInput.addClass('checked').attr('aria-checked', 'true');
|
||||
}
|
||||
|
||||
$('h3').text(nls.localize("commentsHeader", "Comments")).appendTo($form);
|
||||
let $contactUs = $('div.contactus').appendTo($content);
|
||||
|
||||
$('span').text(nls.localize("other ways to contact us", "Other ways to contact us")).appendTo($contactUs);
|
||||
|
||||
let $contactUsContainer = $('div.channels').appendTo($contactUs);
|
||||
|
||||
$('div').append($('a').attr('target', '_blank').attr('href', this.reportIssueLink).text(nls.localize("submit a bug", "Submit a bug")))
|
||||
.appendTo($contactUsContainer);
|
||||
|
||||
$('div').append($('a').attr('target', '_blank').attr('href', this.requestFeatureLink).text(nls.localize("request a missing feature", "Request a missing feature")))
|
||||
.appendTo($contactUsContainer);
|
||||
|
||||
let $charCounter = $('span.char-counter').text('(' + FeedbackDropdown.MAX_FEEDBACK_CHARS + ' ' + nls.localize("characters left", "characters left") + ')');
|
||||
|
||||
$('h3').text(nls.localize("tell us why?", "Tell us why?"))
|
||||
.append($charCounter)
|
||||
.appendTo($form);
|
||||
|
||||
this.feedbackDescriptionInput = <HTMLTextAreaElement>$('textarea.feedback-description').attr({
|
||||
rows: 8,
|
||||
rows: 3,
|
||||
maxlength: FeedbackDropdown.MAX_FEEDBACK_CHARS,
|
||||
'aria-label': nls.localize("commentsHeader", "Comments")
|
||||
})
|
||||
.text(this.feedback).attr('required', 'required')
|
||||
.on('keyup', () => {
|
||||
$charCounter.text('(' + (FeedbackDropdown.MAX_FEEDBACK_CHARS - this.feedbackDescriptionInput.value.length) + ' ' + nls.localize("characters left", "characters left") + ')');
|
||||
this.feedbackDescriptionInput.value ? this.sendButton.removeAttribute('disabled') : this.sendButton.attr('disabled', '');
|
||||
})
|
||||
.appendTo($form).domFocus().getHTMLElement();
|
||||
|
||||
let aliasHeaderText = nls.localize('aliasHeader', "Add e-mail address");
|
||||
|
||||
this.feedbackAliasInput = <HTMLInputElement>$('input.feedback-alias')
|
||||
.type('text')
|
||||
.text(aliasHeaderText)
|
||||
.attr('type', 'email')
|
||||
.attr('placeholder', nls.localize('aliasPlaceholder', "Optional e-mail address"))
|
||||
.value(this.alias)
|
||||
.attr('aria-label', aliasHeaderText)
|
||||
.appendTo($form)
|
||||
.getHTMLElement();
|
||||
|
||||
let $buttons = $('div.form-buttons').appendTo($form);
|
||||
|
||||
this.sendButton = this.invoke($('input.send').type('submit').attr('disabled', '').value(nls.localize('send', "Send")).appendTo($buttons), () => {
|
||||
if (this.isSendingFeedback) {
|
||||
return;
|
||||
}
|
||||
this.onSubmit().then(null, function() { });
|
||||
this.onSubmit();
|
||||
});
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
this.feedbackForm = null;
|
||||
this.feedbackDescriptionInput = null;
|
||||
this.feedbackAliasInput = null;
|
||||
this.smileyInput = null;
|
||||
this.frownyInput = null;
|
||||
}
|
||||
|
@ -211,10 +222,6 @@ export class FeedbackDropdown extends Dropdown {
|
|||
this.feedback = this.feedbackDescriptionInput.value;
|
||||
}
|
||||
|
||||
if (this.feedbackAliasInput) {
|
||||
this.alias = this.feedbackAliasInput.value;
|
||||
}
|
||||
|
||||
if (this.autoHideTimeout) {
|
||||
clearTimeout(this.autoHideTimeout);
|
||||
this.autoHideTimeout = null;
|
||||
|
@ -232,24 +239,19 @@ export class FeedbackDropdown extends Dropdown {
|
|||
}
|
||||
}
|
||||
|
||||
protected onSubmit(): Promise {
|
||||
protected onSubmit(): void {
|
||||
if ((this.feedbackForm.checkValidity && !this.feedbackForm.checkValidity())) {
|
||||
return Promise.as(null);
|
||||
return;
|
||||
}
|
||||
|
||||
this.changeFormStatus(FormEvent.SENDING);
|
||||
|
||||
return this.feedbackService.submitFeedback({
|
||||
this.feedbackService.submitFeedback({
|
||||
feedback: this.feedbackDescriptionInput.value,
|
||||
alias: this.feedbackAliasInput.value,
|
||||
sentiment: this.sentiment
|
||||
}).then((response: IXHRResponse) => {
|
||||
setTimeout(() => { this.changeFormStatus(FormEvent.SENT); }, STATUS_TIMEOUT);
|
||||
return '';
|
||||
}, (xhr: IXHRResponse) => {
|
||||
setTimeout(() => { this.changeFormStatus(FormEvent.SEND_ERROR); }, STATUS_TIMEOUT);
|
||||
return Promise.wrapError(new errors.ConnectionError(xhr));
|
||||
});
|
||||
|
||||
this.changeFormStatus(FormEvent.SENT);
|
||||
}
|
||||
|
||||
|
||||
|
@ -282,7 +284,6 @@ export class FeedbackDropdown extends Dropdown {
|
|||
|
||||
protected resetForm(): void {
|
||||
this.feedbackDescriptionInput ? this.feedbackDescriptionInput.value = '' : null;
|
||||
this.feedbackAliasInput ? this.feedbackAliasInput.value = '' : null;
|
||||
this.sentiment = 1;
|
||||
this.aliasEnabled = false;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import {Registry} from 'vs/platform/platform';
|
||||
import * as Flags from 'vs/base/common/flags';
|
||||
import {StatusbarAlignment, IStatusbarRegistry, Extensions, StatusbarItemDescriptor} from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||
import {FeedbackStatusbarItem} from 'vs/workbench/parts/feedback/electron-browser/feedback';
|
||||
import {FeedbackStatusbarItem} from 'vs/workbench/parts/feedback/electron-browser/feedbackStatusbarItem';
|
||||
|
||||
// Register Statusbar item
|
||||
if (Flags.enableSendASmile) {
|
||||
|
|
|
@ -1,251 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import nls = require('vs/nls');
|
||||
import pal = require('vs/base/common/platform');
|
||||
import {Promise} from 'vs/base/common/winjs.base';
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
import {$} from 'vs/base/browser/builder';
|
||||
import {IStatusbarItem} from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||
import {FeedbackDropdown, IFeedback, IFeedbackService, IFeedbackDropdownOptions} from 'vs/workbench/parts/feedback/browser/feedback';
|
||||
import {IContextViewService} from 'vs/platform/contextview/browser/contextView';
|
||||
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
|
||||
import {IRequestService} from 'vs/platform/request/common/request';
|
||||
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
|
||||
import {IWorkspaceContextService} from 'vs/workbench/services/workspace/common/contextService';
|
||||
|
||||
import os = require('os');
|
||||
|
||||
class NativeFeedbackService implements IFeedbackService {
|
||||
|
||||
private serviceUrl: string;
|
||||
private appName: string;
|
||||
private appVersion: string;
|
||||
|
||||
constructor(
|
||||
@IRequestService private requestService: IRequestService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService
|
||||
) {
|
||||
const env = contextService.getConfiguration().env;
|
||||
if (env.sendASmile) {
|
||||
this.serviceUrl = env.sendASmile.submitUrl;
|
||||
}
|
||||
|
||||
this.appName = env.appName;
|
||||
this.appVersion = env.version;
|
||||
}
|
||||
|
||||
public submitFeedback(feedback: IFeedback): Promise {
|
||||
let data = JSON.stringify({
|
||||
version: 1,
|
||||
user: feedback.alias,
|
||||
userType: 'External',
|
||||
text: feedback.feedback,
|
||||
source: 'Send a smile',
|
||||
sentiment: feedback.sentiment,
|
||||
tags: [
|
||||
{ type: 'product', value: this.appName },
|
||||
{ type: 'product-version', value: this.appVersion }
|
||||
]
|
||||
});
|
||||
|
||||
return this.requestService.makeRequest({
|
||||
type: 'POST',
|
||||
url: this.serviceUrl,
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf8',
|
||||
'Content-Length': data.length
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class NativeFeedbackDropdown extends FeedbackDropdown {
|
||||
private static MAX_FEEDBACK_CHARS: number = 140;
|
||||
|
||||
private appVersion: string;
|
||||
private requestFeatureLink: string;
|
||||
private reportIssueLink: string;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
options: IFeedbackDropdownOptions,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService
|
||||
) {
|
||||
super(container, options, telemetryService);
|
||||
|
||||
const env = contextService.getConfiguration().env;
|
||||
this.appVersion = env.version;
|
||||
this.requestFeatureLink = env.sendASmile.requestFeatureUrl;
|
||||
this.reportIssueLink = env.sendASmile.reportIssueUrl;
|
||||
}
|
||||
|
||||
public renderContents(container: HTMLElement): IDisposable {
|
||||
let $form = $('form.feedback-form').attr({
|
||||
action: 'javascript:void(0);',
|
||||
tabIndex: '-1'
|
||||
}).appendTo(container);
|
||||
|
||||
$(container).addClass('monaco-menu-container');
|
||||
|
||||
this.feedbackForm = <HTMLFormElement>$form.getHTMLElement();
|
||||
|
||||
$('h2.title').text(nls.localize("label.sendASmile", "Let us know how we're doing")).appendTo($form);
|
||||
|
||||
this.invoke($('div.cancel'), () => {
|
||||
this.hide();
|
||||
}).appendTo($form);
|
||||
|
||||
let $content = $('div.content').appendTo($form);
|
||||
|
||||
let $sentimentContainer = $('div').appendTo($content);
|
||||
$('span').text(nls.localize("sentiment", "How was your experience?")).appendTo($sentimentContainer);
|
||||
|
||||
let $feedbackSentiment = $('div.feedback-sentiment').appendTo($sentimentContainer);
|
||||
|
||||
|
||||
this.smileyInput = $('div').addClass('sentiment smile').attr({
|
||||
'aria-checked': 'false',
|
||||
'aria-label': nls.localize('smileCaption', "Happy"),
|
||||
'tabindex': 0,
|
||||
'role': 'checkbox'
|
||||
});
|
||||
this.invoke(this.smileyInput, () => { this.setSentiment(true); }).appendTo($feedbackSentiment);
|
||||
|
||||
this.frownyInput = $('div').addClass('sentiment frown').attr({
|
||||
'aria-checked': 'false',
|
||||
'aria-label': nls.localize('frownCaption', "Sad"),
|
||||
'tabindex': 0,
|
||||
'role': 'checkbox'
|
||||
});
|
||||
|
||||
this.invoke(this.frownyInput, () => { this.setSentiment(false); }).appendTo($feedbackSentiment);
|
||||
|
||||
if (this.sentiment === 1) {
|
||||
this.smileyInput.addClass('checked').attr('aria-checked', 'true');
|
||||
} else {
|
||||
this.frownyInput.addClass('checked').attr('aria-checked', 'true');
|
||||
}
|
||||
|
||||
let $contactUs = $('div.contactus').appendTo($content);
|
||||
|
||||
$('span').text(nls.localize("other ways to contact us", "Other ways to contact us")).appendTo($contactUs);
|
||||
|
||||
let $contactUsContainer = $('div.channels').appendTo($contactUs);
|
||||
|
||||
$('div').append($('a').attr('target', '_blank').attr('href', this.getReportIssueLink()).text(nls.localize("submit a bug", "Submit a bug")))
|
||||
.appendTo($contactUsContainer);
|
||||
|
||||
$('div').append($('a').attr('target', '_blank').attr('href', this.requestFeatureLink).text(nls.localize("request a missing feature", "Request a missing feature")))
|
||||
.appendTo($contactUsContainer);
|
||||
|
||||
let $charCounter = $('span.char-counter').text('(' + NativeFeedbackDropdown.MAX_FEEDBACK_CHARS + ' ' + nls.localize("characters left", "characters left") + ')');
|
||||
|
||||
$('h3').text(nls.localize("tell us why?", "Tell us why?"))
|
||||
.append($charCounter)
|
||||
.appendTo($form);
|
||||
|
||||
this.feedbackDescriptionInput = <HTMLTextAreaElement>$('textarea.feedback-description').attr({
|
||||
rows: 3,
|
||||
maxlength: NativeFeedbackDropdown.MAX_FEEDBACK_CHARS,
|
||||
'aria-label': nls.localize("commentsHeader", "Comments")
|
||||
})
|
||||
.text(this.feedback).attr('required', 'required')
|
||||
.on('keyup', () => {
|
||||
$charCounter.text('(' + (NativeFeedbackDropdown.MAX_FEEDBACK_CHARS - this.feedbackDescriptionInput.value.length) + ' ' + nls.localize("characters left", "characters left") + ')');
|
||||
this.feedbackDescriptionInput.value ? this.sendButton.removeAttribute('disabled') : this.sendButton.attr('disabled', '');
|
||||
})
|
||||
.appendTo($form).domFocus().getHTMLElement();
|
||||
|
||||
let aliasHeaderText = nls.localize('aliasHeader', "Add e-mail address");
|
||||
|
||||
this.feedbackAliasInput = <HTMLInputElement>$('input.feedback-alias')
|
||||
.type('text')
|
||||
.text(aliasHeaderText)
|
||||
.attr('type', 'email')
|
||||
.attr('placeholder', nls.localize('aliasPlaceholder', "Optional e-mail address"))
|
||||
.value(this.alias)
|
||||
.attr('aria-label', aliasHeaderText)
|
||||
.appendTo($form)
|
||||
.getHTMLElement();
|
||||
|
||||
let $buttons = $('div.form-buttons').appendTo($form);
|
||||
|
||||
this.sendButton = this.invoke($('input.send').type('submit').attr('disabled', '').value(nls.localize('send', "Send")).appendTo($buttons), () => {
|
||||
if (this.isSendingFeedback) {
|
||||
return;
|
||||
}
|
||||
this.onSubmit().then(null, function() { });
|
||||
});
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
this.feedbackForm = null;
|
||||
this.feedbackDescriptionInput = null;
|
||||
this.feedbackAliasInput = null;
|
||||
this.smileyInput = null;
|
||||
this.frownyInput = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private getReportIssueLink(): string {
|
||||
let reportIssueLink = this.reportIssueLink;
|
||||
let result = reportIssueLink + '&' + this.getReportIssuesQueryString() + '#vscode';
|
||||
return result;
|
||||
}
|
||||
|
||||
private getReportIssuesQueryString(): string {
|
||||
|
||||
let queryString: { [key: string]: any; } = Object.create(null);
|
||||
queryString['version'] = this.appVersion;
|
||||
let platform: number;
|
||||
switch (pal.platform) {
|
||||
case pal.Platform.Windows:
|
||||
platform = 3;
|
||||
break;
|
||||
case pal.Platform.Mac:
|
||||
platform = 2;
|
||||
break;
|
||||
case pal.Platform.Linux:
|
||||
platform = 1;
|
||||
break;
|
||||
default:
|
||||
platform = 0;
|
||||
}
|
||||
|
||||
queryString['platform'] = platform;
|
||||
queryString['osversion'] = os.release();
|
||||
queryString['sessionid'] = this.telemetryService.getSessionId();
|
||||
|
||||
let queryStringArray: string[] = [];
|
||||
for (let p in queryString) {
|
||||
queryStringArray.push(encodeURIComponent(p) + '=' + encodeURIComponent(queryString[p]));
|
||||
}
|
||||
|
||||
let result = queryStringArray.join('&');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export class FeedbackStatusbarItem implements IStatusbarItem {
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IContextViewService private contextViewService: IContextViewService
|
||||
) {
|
||||
}
|
||||
|
||||
public render(element: HTMLElement): IDisposable {
|
||||
return this.instantiationService.createInstance(NativeFeedbackDropdown, element, {
|
||||
contextViewProvider: this.contextViewService,
|
||||
feedbackService: this.instantiationService.createInstance(NativeFeedbackService)
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
import {IStatusbarItem} from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||
import {FeedbackDropdown, IFeedback, IFeedbackService} from 'vs/workbench/parts/feedback/browser/feedback';
|
||||
import {IContextViewService} from 'vs/platform/contextview/browser/contextView';
|
||||
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
|
||||
import {IRequestService} from 'vs/platform/request/common/request';
|
||||
|
||||
import shell = require('shell');
|
||||
|
||||
class TwitterFeedbackService implements IFeedbackService {
|
||||
|
||||
private serviceUrl: string;
|
||||
|
||||
private static TWITTER_URL: string = 'https://twitter.com/intent/tweet';
|
||||
|
||||
public submitFeedback(feedback: IFeedback): void {
|
||||
var queryString = `?${feedback.sentiment === 1 ? 'hashtags=LoveVSCode&' : null}ref_src=twsrc%5Etfw&related=twitterapi%2Ctwitter&text=${feedback.feedback}&tw_p=tweetbutton&via=code`;
|
||||
var url = TwitterFeedbackService.TWITTER_URL + queryString;
|
||||
shell.openExternal(url);
|
||||
}
|
||||
}
|
||||
|
||||
export class FeedbackStatusbarItem implements IStatusbarItem {
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IContextViewService private contextViewService: IContextViewService
|
||||
) {
|
||||
}
|
||||
|
||||
public render(element: HTMLElement): IDisposable {
|
||||
return this.instantiationService.createInstance(FeedbackDropdown, element, {
|
||||
contextViewProvider: this.contextViewService,
|
||||
feedbackService: this.instantiationService.createInstance(TwitterFeedbackService)
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue