Skip to content

Commit

Permalink
feat: implement comment timestamp (#1595)
Browse files Browse the repository at this point in the history
  • Loading branch information
hacke2 authored and bytemain committed Sep 27, 2022
1 parent def6793 commit da3d06f
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 5 deletions.
28 changes: 24 additions & 4 deletions packages/comments/src/browser/comments-item.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@ import { observer } from 'mobx-react-lite';
import React from 'react';

import { Button } from '@opensumi/ide-components';
import { toMarkdownHtml } from '@opensumi/ide-components/lib/utils';
import { useInjectable, localize, IContextKeyService, isUndefined, IMarkdownString } from '@opensumi/ide-core-browser';
import {
useInjectable,
localize,
IContextKeyService,
isUndefined,
IMarkdownString,
toLocalString,
toMarkdownHtml,
} from '@opensumi/ide-core-browser';
import { InlineActionBar } from '@opensumi/ide-core-browser/lib/components/actions';
import { AbstractMenuService, MenuId, IMenu } from '@opensumi/ide-core-browser/lib/menu/next';

Expand All @@ -23,6 +30,16 @@ import { CommentsBody } from './comments-body';
import { CommentsTextArea } from './comments-textarea.view';
import styles from './comments.module.less';

// TODO: 更好的时间格式化组件
const Timestamp: React.FC<{ timestamp: string }> = ({ timestamp }) => {
const formatTimestamp = React.useMemo(() => {
const date = new Date(timestamp);
return toLocalString(date);
}, [timestamp]);

return <span className={styles.comment_item_timestamp}>{formatTimestamp}</span>;
};

const useCommentContext = (
contextKeyService: IContextKeyService,
comment: IThreadComment,
Expand Down Expand Up @@ -95,7 +112,7 @@ const ReplyItem: React.FC<{
thread: ICommentsThread;
}> = observer(({ reply, thread }) => {
const { contextKeyService } = thread;
const { author, label, body, mode } = reply;
const { author, label, body, mode, timestamp } = reply;
const iconUrl = author.iconPath?.toString();
const [textValue, setTextValue, onChangeTextArea, commentContext, commentTitleContext, handleDragFiles] =
useCommentContext(contextKeyService, reply);
Expand All @@ -116,6 +133,7 @@ const ReplyItem: React.FC<{
<>
{iconUrl && <img className={styles.reply_item_icon} src={iconUrl} alt={author.name} />}
<span className={styles.comment_item_author_name}>{author.name}</span>
{timestamp && <Timestamp timestamp={timestamp} />}
{typeof label === 'string' ? <span className={styles.comment_item_label}>{label}</span> : label}
{' : '}
<span className={styles.comment_item_body}>{body}</span>
Expand All @@ -142,6 +160,7 @@ const ReplyItem: React.FC<{
<div>
{iconUrl && <img className={styles.reply_item_icon} src={iconUrl} alt={author.name} />}
<span className={styles.comment_item_author_name}>{author.name}</span>
{timestamp && <Timestamp timestamp={timestamp} />}
{typeof label === 'string' ? <span className={styles.comment_item_label}>{label}</span> : label}
{' : '}
</div>
Expand Down Expand Up @@ -205,7 +224,7 @@ export const CommentItem: React.FC<{
const [showReply, setShowReply] = React.useState(false);
const [replyText, setReplyText] = React.useState('');
const [comment, ...replies] = thread.comments;
const { author, label, body, mode } = comment;
const { author, label, body, mode, timestamp } = comment;
const iconUrl = author.iconPath?.toString();
const [textValue, setTextValue, onChangeTextArea, commentContext, commentTitleContext, handleDragFiles] =
useCommentContext(contextKeyService, comment);
Expand Down Expand Up @@ -240,6 +259,7 @@ export const CommentItem: React.FC<{
<div className={styles.comment_item_head}>
<div className={styles.comment_item_name}>
<span className={styles.comment_item_author_name}>{author.name}</span>
{timestamp && <Timestamp timestamp={timestamp} />}
{typeof label === 'string' ? <span className={styles.comment_item_label}>{label}</span> : label}
</div>
<div className={styles.comment_item_actions}>
Expand Down
6 changes: 6 additions & 0 deletions packages/comments/src/browser/comments.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@
color: var(--descriptionForeground);
}

.comment_item_timestamp {
margin-left: 2px;
line-height: 20px;
color: var(--descriptionForeground);
}

.comment_item_markdown_header {
display: flex;
justify-content: space-between;
Expand Down
4 changes: 4 additions & 0 deletions packages/comments/src/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ export interface IComment {
* 评论 reaction
*/
reactions?: CommentReaction[];
/**
* 评论时间
*/
timestamp?: string;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,47 @@ describe('extension/__tests__/hosted/api/vscode/ext.host.comments.test.ts', () =
);
});

it('comment timestamp', async () => {
const id = 'test_id';
const label = 'test_label';
const body = 'test_body';
const author = 'hacke2';
const $updateCommentThread = jest.spyOn(mainThreadComments, '$updateCommentThread');
const controller = vscodeComments.createCommentController(id, label);
const date = new Date();
const thread = controller.createCommentThread(Uri.file('test'), new types.Range(1, 1, 1, 1), []);
thread.comments = [
{
body,
author: {
name: author,
},
mode: types.CommentMode.Preview,
timestamp: date,
},
];
// 修改属性会加 100ms 的 debounce
await sleep(100);
expect($updateCommentThread).toBeCalledTimes(1);
expect($updateCommentThread).toBeCalledWith(
expect.anything(),
expect.anything(),
expect.anything(),
expect.anything(),
{
comments: [
{
uniqueIdInThread: 1,
body,
userName: author,
mode: types.CommentMode.Preview,
timestamp: date.toJSON(),
},
],
},
);
});

it('dispose', async () => {
const id = 'test_id';
const label = 'test_label';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ export class MainThreadCommentThread implements CommentThread {
iconPath: comment.userIconPath,
},
reactions: comment.commentReactions?.map((reaction) => this.convertToCommentReaction(reaction)),
timestamp: comment.timestamp,
};
}

Expand Down Expand Up @@ -305,6 +306,7 @@ export class MainThreadCommentThread implements CommentThread {
body: comment.body,
userName: comment.author.name,
commentReactions: comment.reactions?.map((reaction) => this.convertToCoreReaction(reaction)),
timestamp: comment.timestamp,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -623,13 +623,17 @@ function convertToModeComment(
mode: vscodeComment.mode,
contextValue: vscodeComment.contextValue,
uniqueIdInThread: commentUniqueId,
body: extHostTypeConverter.fromManyMarkdown([vscodeComment.body])[0],
body:
typeof vscodeComment.body === 'string'
? vscodeComment.body
: extHostTypeConverter.MarkdownString.from(vscodeComment.body),
userName: vscodeComment.author.name,
userIconPath: iconPath,
label: vscodeComment.label,
commentReactions: vscodeComment.reactions
? vscodeComment.reactions.map((reaction) => convertToReaction(reaction))
: undefined,
timestamp: vscodeComment.timestamp?.toJSON(),
};
}

Expand Down
6 changes: 6 additions & 0 deletions packages/types/vscode/typings/vscode.comments.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,12 @@ declare module 'vscode' {
* Label will be rendered next to authorName if exists.
*/
label?: string;

/**
* Optional timestamp that will be displayed in comments.
* The date will be formatted according to the user's locale and settings.
*/
timestamp?: Date;
}

/**
Expand Down
16 changes: 16 additions & 0 deletions packages/utils/src/date.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
import { pad } from './strings';

export function toLocalString(date: Date): string {
return (
date.getFullYear() +
'-' +
pad(date.getMonth() + 1, 2) +
'-' +
pad(date.getDate(), 2) +
' ' +
pad(date.getHours(), 2) +
':' +
pad(date.getMinutes(), 2) +
':' +
pad(date.getSeconds(), 2)
);
}

export function toLocalISOString(date: Date): string {
return (
date.getFullYear() +
Expand Down

0 comments on commit da3d06f

Please sign in to comment.