Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply CommentThread vscode Plugin API #8870

Merged
merged 1 commit into from
Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/core/src/browser/common-frontend-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1865,6 +1865,14 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
dark: Color.transparent('button.background', 0.5),
light: Color.transparent('button.background', 0.5)
}, description: 'Background color of secondary buttons.'
},
{
id: 'editorGutter.commentRangeForeground',
defaults: {
dark: '#c5c5c5',
light: '#c5c5c5',
hc: '#c5c5c5'
}, description: 'Editor gutter decoration color for commenting ranges.'
}
);
}
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/browser/style/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ blockquote {
margin-left: 8px;
}

.theia-mod-disabled {
opacity: var(--theia-mod-disabled-opacity);
.theia-mod-disabled, .theia-mod-disabled:focus {
opacity: var(--theia-mod-disabled-opacity) !important;
}

.theia-header {
Expand Down Expand Up @@ -161,7 +161,7 @@ blockquote {

button.theia-button, .theia-button {
border: none;
color: var(--theia-button-foreground);
color: var(--theia-button-foreground) !important;
background-color: var(--theia-button-background);
min-width: 65px;
outline: none;
Expand Down
83 changes: 76 additions & 7 deletions packages/monaco/src/browser/monaco-editor-zone-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
*--------------------------------------------------------------------------------------------*/

import { Disposable, DisposableCollection, Event, Emitter } from '@theia/core';
import { TrackedRangeStickiness } from '@theia/editor/lib/browser';

export interface MonacoEditorViewZone extends monaco.editor.IViewZone {
id: string;
}

export class MonacoEditorZoneWidget implements Disposable {

private arrow: Arrow | undefined;

readonly zoneNode = document.createElement('div');
readonly containerNode = document.createElement('div');

Expand All @@ -42,7 +45,7 @@ export class MonacoEditorZoneWidget implements Disposable {
);

constructor(
readonly editor: monaco.editor.IStandaloneCodeEditor
readonly editor: monaco.editor.IStandaloneCodeEditor, readonly showArrow: boolean = true
) {
this.zoneNode.classList.add('zone-widget');
this.containerNode.classList.add('zone-widget-container');
Expand All @@ -53,6 +56,7 @@ export class MonacoEditorZoneWidget implements Disposable {

dispose(): void {
this.toDispose.dispose();
this.hide();
}

protected _options: MonacoEditorZoneWidget.Options | undefined;
Expand All @@ -67,10 +71,10 @@ export class MonacoEditorZoneWidget implements Disposable {
show(options: MonacoEditorZoneWidget.Options): void {
let { afterLineNumber, afterColumn, heightInLines } = this._options = { showFrame: true, ...options };
const lineHeight = this.editor.getOption(monaco.editor.EditorOption.lineHeight);
const maxHeightInLines = (this.editor.getLayoutInfo().height / lineHeight) * .8;
if (heightInLines >= maxHeightInLines) {
heightInLines = maxHeightInLines;
}
// adjust heightInLines to viewport
const maxHeightInLines = Math.max(12, (this.editor.getLayoutInfo().height / lineHeight) * 0.8);
heightInLines = Math.min(heightInLines, maxHeightInLines);
let arrowHeight = 0;
this.toHide.dispose();
this.editor.changeViewZones(accessor => {
this.zoneNode.style.top = '-1000px';
Expand All @@ -92,6 +96,14 @@ export class MonacoEditorZoneWidget implements Disposable {
this.editor.changeViewZones(a => a.removeZone(id));
this.viewZone = undefined;
}));
if (this.showArrow) {
this.arrow = new Arrow(this.editor);
arrowHeight = Math.round(lineHeight / 3);
this.arrow.height = arrowHeight;
this.arrow.show({ lineNumber: options.afterLineNumber, column: 0 });

this.toHide.push(this.arrow);
}
const widget: monaco.editor.IOverlayWidget = {
getId: () => 'editor-zone-widget-' + id,
getDomNode: () => this.zoneNode,
Expand All @@ -102,7 +114,6 @@ export class MonacoEditorZoneWidget implements Disposable {
this.toHide.push(Disposable.create(() => this.editor.removeOverlayWidget(widget)));
});

this.containerNode.style.top = 0 + 'px';
this.containerNode.style.overflow = 'hidden';
this.updateContainerHeight(heightInLines * lineHeight);

Expand All @@ -122,7 +133,7 @@ export class MonacoEditorZoneWidget implements Disposable {
}

protected updateTop(top: number): void {
this.zoneNode.style.top = top + 'px';
this.zoneNode.style.top = top + (this.showArrow ? 6 : 0) + 'px';
}
protected updateHeight(zoneHeight: number): void {
this.zoneNode.style.height = zoneHeight + 'px';
Expand Down Expand Up @@ -166,6 +177,64 @@ export class MonacoEditorZoneWidget implements Disposable {
}

}

class IdGenerator {
private lastId: number;
constructor(private prefix: string) {
this.lastId = 0;
}

nextId(): string {
return this.prefix + (++this.lastId);
}
}

class Arrow implements Disposable {

private readonly idGenerator = new IdGenerator('.arrow-decoration-');

private readonly ruleName = this.idGenerator.nextId();
private decorations: string[] = [];
private _height: number = -1;

constructor(
private readonly _editor: monaco.editor.ICodeEditor
) {}

dispose(): void {
this.hide();
}

set height(value: number) {
if (this._height !== value) {
this._height = value;
this._updateStyle();
}
}

private _updateStyle(): void {
const style = document.createElement('style');
style.type = 'text/css';
style.media = 'screen';
document.getElementsByTagName('head')[0].appendChild(style);
const selector = `.monaco-editor ${this.ruleName}`;
const cssText = `border-style: solid; border-color: transparent transparent var(--theia-peekView-border); border-width:
${this._height}px; bottom: -${this._height}px; margin-left: -${this._height}px; `;
(<CSSStyleSheet>style.sheet).insertRule(selector + '{' + cssText + '}', 0);
}

show(where: monaco.IPosition): void {
this.decorations = this._editor.deltaDecorations(
this.decorations,
[{ range: monaco.Range.fromPositions(where), options: { className: this.ruleName, stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges } }]
);
}

hide(): void {
this._editor.deltaDecorations(this.decorations, []);
}
}

export namespace MonacoEditorZoneWidget {
export interface Options {
afterLineNumber: number,
Expand Down
1 change: 1 addition & 0 deletions packages/monaco/src/browser/style/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
.monaco-editor .zone-widget {
position: absolute;
z-index: 10;
background-color: var(--theia-editorWidget-background);
}

.monaco-editor .zone-widget .zone-widget-container {
Expand Down
97 changes: 97 additions & 0 deletions packages/plugin-ext/src/common/plugin-api-rpc-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import * as theia from '@theia/plugin';
import { UriComponents } from './uri-components';
import { CompletionItemTag } from '../plugin/types-impl';
import { Event as TheiaEvent } from '@theia/core/lib/common/event';
import { URI } from 'vscode-uri';

// Should contains internal Plugin API types

Expand Down Expand Up @@ -562,3 +564,98 @@ export interface AuthenticationProviderInformation {
id: string;
label: string;
}

export interface CommentOptions {
/**
* An optional string to show on the comment input box when it's collapsed.
*/
prompt?: string;

/**
* An optional string to show as placeholder in the comment input box when it's focused.
*/
placeHolder?: string;
}

export enum CommentMode {
Editing = 0,
Preview = 1
}

export interface Comment {
readonly uniqueIdInThread: number;
readonly body: MarkdownString;
readonly userName: string;
readonly userIconPath?: string;
readonly contextValue?: string;
readonly label?: string;
readonly mode?: CommentMode;
}

export enum CommentThreadCollapsibleState {
/**
* Determines an item is collapsed
*/
Collapsed = 0,
/**
* Determines an item is expanded
*/
Expanded = 1
}

export interface CommentInput {
value: string;
uri: URI;
}

export interface CommentThread {
commentThreadHandle: number;
controllerHandle: number;
extensionId?: string;
threadId: string;
resource: string | null;
range: Range;
label: string | undefined;
contextValue: string | undefined;
comments: Comment[] | undefined;
onDidChangeComments: TheiaEvent<Comment[] | undefined>;
collapsibleState?: CommentThreadCollapsibleState;
input?: CommentInput;
onDidChangeInput: TheiaEvent<CommentInput | undefined>;
onDidChangeRange: TheiaEvent<Range>;
onDidChangeLabel: TheiaEvent<string | undefined>;
onDidChangeCollapsibleState: TheiaEvent<CommentThreadCollapsibleState | undefined>;
isDisposed: boolean;
}

export interface CommentThreadChangedEventMain extends CommentThreadChangedEvent {
owner: string;
}

export interface CommentThreadChangedEvent {
/**
* Added comment threads.
*/
readonly added: CommentThread[];

/**
* Removed comment threads.
*/
readonly removed: CommentThread[];

/**
* Changed comment threads.
*/
readonly changed: CommentThread[];
}

export interface CommentingRanges {
readonly resource: URI;
ranges: Range[];
}

export interface CommentInfo {
extensionId?: string;
threads: CommentThread[];
commentingRanges: CommentingRanges;
}
Loading