Skip to content
Open
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
293 changes: 6 additions & 287 deletions package-lock.json

Large diffs are not rendered by default.

169 changes: 167 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,23 @@
"categories": [
"Other",
"Snippets",
"Debuggers"
"Debuggers",
"Extension Packs",
"Programming Languages"
],
"keywords": [
"todo",
"todolist",
"kanban",
"task",
"project",
"management",
"generate",
"generator",
"template",
"webdev",
"snippet",
"file"
],
"main": "./out/extension.js",
"contributes": {
Expand Down Expand Up @@ -139,8 +155,157 @@
"category": "MDT",
"title": "Open Task Board ✅",
"command": "extension.openTaskBoard"
},
{
"category": "MDT",
"command": "mdt.dispose",
"title": "Remove All Comments"
},
{
"command": "mdt.createNote",
"title": "Create Note",
"enablement": "!commentIsEmpty"
},
{
"command": "mdt.replyNote",
"title": "Reply",
"enablement": "!commentIsEmpty"
},
{
"command": "mdt.editNote",
"title": "Edit",
"icon": {
"dark": "resources/edit_inverse.svg",
"light": "resources/edit.svg"
}
},
{
"command": "mdt.deleteNote",
"title": "Delete",
"icon": {
"dark": "resources/close_inverse.svg",
"light": "resources/close.svg"
}
},
{
"command": "mdt.deleteNoteComment",
"title": "Delete",
"icon": {
"dark": "resources/close_inverse.svg",
"light": "resources/close.svg"
}
},
{
"command": "mdt.saveNote",
"title": "Save"
},
{
"command": "mdt.cancelsaveNote",
"title": "Cancel"
},
{
"command": "mdt.startDraft",
"title": "Start Draft",
"enablement": "!commentIsEmpty"
},
{
"command": "mdt.finishDraft",
"title": "Finish Draft"
}
]
],
"menus": {
"commandPalette": [
{
"command": "mdt.createNote",
"when": "false"
},
{
"command": "mdt.replyNote",
"when": "false"
},
{
"command": "mdt.editNote",
"when": "false"
},
{
"command": "mdt.deleteNote",
"when": "false"
},
{
"command": "mdt.deleteNoteComment",
"when": "false"
},
{
"command": "mdt.saveNote",
"when": "false"
},
{
"command": "mdt.cancelsaveNote",
"when": "false"
},
{
"command": "mdt.startDraft",
"when": "false"
},
{
"command": "mdt.finishDraft",
"when": "false"
}
],
"comments/commentThread/title": [
{
"command": "mdt.deleteNote",
"group": "navigation",
"when": "commentController == comment-mdt && !commentThreadIsEmpty"
}
],
"comments/commentThread/context": [
{
"command": "mdt.createNote",
"group": "inline",
"when": "commentController == comment-mdt && commentThreadIsEmpty"
},
{
"command": "mdt.replyNote",
"group": "inline",
"when": "commentController == comment-mdt && !commentThreadIsEmpty"
},
{
"command": "mdt.startDraft",
"group": "inline",
"when": "commentController == comment-mdt && commentThreadIsEmpty"
},
{
"command": "mdt.finishDraft",
"group": "inline",
"when": "commentController == comment-mdt && commentThread == draft"
}
],
"comments/comment/title": [
{
"command": "mdt.editNote",
"group": "group@1",
"when": "commentController == comment-mdt"
},
{
"command": "mdt.deleteNoteComment",
"group": "group@2",
"when": "commentController == comment-mdt && comment == canDelete"
}
],
"comments/comment/context": [
{
"command": "mdt.cancelsaveNote",
"group": "inline@1",
"when": "commentController == comment-mdt"
},
{
"command": "mdt.saveNote",
"group": "inline@2",
"when": "commentController == comment-mdt"
}
]
}
},
"scripts": {
"vscode:prepublish": "npm run compile",
Expand Down
1 change: 1 addition & 0 deletions resources/close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources/close_inverse.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources/edit.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources/edit_inverse.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import PushNotificationDelegate from './features/push_notification/push_notifica
import DeviceDelegate from './features/device/device_delegate';
import { GistDelegate } from './features/gists/gist_delegate';
import KanbanBoardDelegate from './features/kanban_board/kanban_board_delegate';
import CommentDelegate from './features/comment/comment_delegate';

export function deactivate() { }

Expand All @@ -19,6 +20,7 @@ export function activate(context: ExtensionContext) {
const deviceDelegate = new DeviceDelegate();
const gistDelegate = new GistDelegate();
const kanbanBoardDelegate = new KanbanBoardDelegate();
const commentDelegate = new CommentDelegate();

// Deeplink
createDeeplinkStatusBarItem().show();
Expand Down Expand Up @@ -61,4 +63,7 @@ export function activate(context: ExtensionContext) {
// Kanban Board
context.subscriptions.push(commands.registerCommand(OPEN_KANBAN_BOARD, async (uri: Uri) => kanbanBoardDelegate.openKanbanBoard(context, uri)));

// Comments
commentDelegate.activate(context);

}
149 changes: 149 additions & 0 deletions src/features/comment/comment_delegate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import * as vscode from "vscode";
const { exec, spawn } = require("child_process");
const fs = require('fs');
const path = require('path');

let commentId = 1;

export default class CommentDelegate {

activate(context: vscode.ExtensionContext) {
// A `CommentController` is able to provide comments for documents.
const commentController = vscode.comments.createCommentController('comment-mdt', 'Mobile Dev Tools Comment API');
context.subscriptions.push(commentController);

// A `CommentingRangeProvider` controls where gutter decorations that allow adding comments are shown
commentController.commentingRangeProvider = {
provideCommentingRanges: (document: vscode.TextDocument, token: vscode.CancellationToken) => {
const lineCount = document.lineCount;
return [new vscode.Range(0, 0, lineCount - 1, 0)];
}
};

context.subscriptions.push(vscode.commands.registerCommand('mdt.createNote', (reply: vscode.CommentReply) => {
replyNote(reply);
}));

context.subscriptions.push(vscode.commands.registerCommand('mdt.replyNote', (reply: vscode.CommentReply) => {
replyNote(reply);
}));

context.subscriptions.push(vscode.commands.registerCommand('mdt.startDraft', (reply: vscode.CommentReply) => {
const thread = reply.thread;
thread.contextValue = 'draft';
const newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'Mobile Dev Tools' }, thread);
newComment.label = 'pending';
thread.comments = [...thread.comments, newComment];
}));

context.subscriptions.push(vscode.commands.registerCommand('mdt.finishDraft', (reply: vscode.CommentReply) => {
const thread = reply.thread;

if (!thread) {
return;
}

thread.contextValue = undefined;
thread.collapsibleState = vscode.CommentThreadCollapsibleState.Collapsed;
if (reply.text) {
const newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'Mobile Dev Tools' }, thread);
thread.comments = [...thread.comments, newComment].map(comment => {
comment.label = undefined;
return comment;
});
}
}));

context.subscriptions.push(vscode.commands.registerCommand('mdt.deleteNoteComment', (comment: NoteComment) => {
const thread = comment.parent;
if (!thread) {
return;
}

thread.comments = thread.comments.filter(cmt => (cmt as NoteComment).id !== comment.id);

if (thread.comments.length === 0) {
thread.dispose();
}
}));

context.subscriptions.push(vscode.commands.registerCommand('mdt.deleteNote', (thread: vscode.CommentThread) => {
thread.dispose();
}));

context.subscriptions.push(vscode.commands.registerCommand('mdt.cancelsaveNote', (comment: NoteComment) => {
if (!comment.parent) {
return;
}

comment.parent.comments = comment.parent.comments.map(cmt => {
if ((cmt as NoteComment).id === comment.id) {
cmt.body = (cmt as NoteComment).savedBody;
cmt.mode = vscode.CommentMode.Preview;
}

return cmt;
});
}));

context.subscriptions.push(vscode.commands.registerCommand('mdt.saveNote', (comment: NoteComment) => {
if (!comment.parent) {
return;
}

comment.parent.comments = comment.parent.comments.map(cmt => {
if ((cmt as NoteComment).id === comment.id) {
(cmt as NoteComment).savedBody = cmt.body;
cmt.mode = vscode.CommentMode.Preview;
}

return cmt;
});
}));

context.subscriptions.push(vscode.commands.registerCommand('mdt.editNote', (comment: NoteComment) => {
if (!comment.parent) {
return;
}

comment.parent.comments = comment.parent.comments.map(cmt => {
if ((cmt as NoteComment).id === comment.id) {
cmt.mode = vscode.CommentMode.Editing;
}

return cmt;
});
}));

context.subscriptions.push(vscode.commands.registerCommand('mdt.dispose', () => {
commentController.dispose();
}));

function replyNote(reply: vscode.CommentReply) {
const thread = reply.thread;
const newComment = new NoteComment(reply.text, vscode.CommentMode.Preview, { name: 'Mobile Dev Tools' }, thread, thread.comments.length ? 'canDelete' : undefined);
if (thread.contextValue === 'draft') {
newComment.label = 'pending';
}

thread.comments = [...thread.comments, newComment];
}
}

}

class NoteComment implements vscode.Comment {
id: number;
label: string | undefined;
savedBody: string | vscode.MarkdownString; // for the Cancel button
constructor(
public body: string | vscode.MarkdownString,
public mode: vscode.CommentMode,
public author: vscode.CommentAuthorInformation,
public parent?: vscode.CommentThread,
public contextValue?: string
) {
this.id = ++commentId;
this.savedBody = this.body;
}
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"module": "commonjs",
"target": "es6",
"outDir": "out",
"lib": ["es6"],
"lib": ["es6", "es2020"],
"sourceMap": true,
"rootDir": "src",
"noImplicitAny": false,
Expand Down