diff --git a/frontend/src/components/comment_tile.tsx b/frontend/src/components/comment_tile.tsx
index 8c912c1..1c1cffb 100644
--- a/frontend/src/components/comment_tile.tsx
+++ b/frontend/src/components/comment_tile.tsx
@@ -1,6 +1,5 @@
import { useTranslation } from "../utils/i18n";
import { useNavigate } from "react-router";
-import { MdOutlineComment } from "react-icons/md";
import { Comment } from "../network/models";
import { network } from "../network/network";
import Badge from "./badge";
@@ -55,29 +54,66 @@ export function CommentTile({
{new Date(comment.created_at).toLocaleDateString()}
-
+
-
- {comment.content_truncated && (
-
{t("Click to view more")}
- )}
-
- {comment.reply_count > 0 && (
-
-
- {comment.reply_count}
+ {comment.content_truncated ? (
+
+
+ {t("Click to view more")}
- )}
-
+
+ ) : (
+
+ )}
+
);
}
+function CommentReplies({ comment }: { comment: Comment }) {
+ const { t } = useTranslation();
+
+ if (!comment.replies) {
+ return null;
+ }
+
+ return (
+
+ {comment.replies.map((e) => {
+ return (
+
+ {e.user.username}:
+ {CommentToPlainText(e.content)}
+
+ );
+ })}
+ {comment.reply_count > comment.replies.length ? (
+
+ {t("View {count} more replies").replace(
+ "{count}",
+ (comment.reply_count - comment.replies.length).toString(),
+ )}
+
+ ) : null}
+
+ );
+}
+
+function CommentToPlainText(content: string) {
+ // Remove Markdown syntax to convert to plain text
+ return content
+ .replace(/!\[.*?]\(.*?\)/g, "") // Remove images
+ .replace(/\[([^\]]+)]\((.*?)\)/g, "$1") // Convert links to just the text
+ .replace(/[#>*_`~-]/g, "") // Remove other Markdown characters
+ .replace(/\n+/g, " ") // Replace newlines with spaces
+ .trim();
+}
+
export function CommentContent({ content }: { content: string }) {
const lines = content.split("\n");
for (let i = 0; i < lines.length; i++) {
- let line = lines[i];
+ const line = lines[i];
if (!line.endsWith(" ")) {
// Ensure that each line ends with two spaces for Markdown to recognize it as a line break
lines[i] = line + " ";
diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts
index b98a846..34d2df6 100644
--- a/frontend/src/i18n.ts
+++ b/frontend/src/i18n.ts
@@ -254,6 +254,7 @@ export const i18nData = {
"You do not have permission to upload files, please contact the administrator.":
"您没有上传文件的权限,请联系管理员。",
"Private": "私有",
+ "View {count} more replies": "查看另外 {count} 条回复",
},
},
"zh-TW": {
@@ -511,6 +512,7 @@ export const i18nData = {
"You do not have permission to upload files, please contact the administrator.":
"您沒有上傳檔案的權限,請聯繫管理員。",
"Private": "私有",
+ "View {count} more replies": "查看另外 {count} 條回覆",
},
},
};
diff --git a/frontend/src/network/models.ts b/frontend/src/network/models.ts
index 57ff7e1..af79b4b 100644
--- a/frontend/src/network/models.ts
+++ b/frontend/src/network/models.ts
@@ -126,6 +126,7 @@ export interface Comment {
images: Image[];
content_truncated: boolean;
reply_count: number;
+ replies: Comment[];
}
export interface CommentWithResource {
diff --git a/frontend/src/utils/i18n.ts b/frontend/src/utils/i18n.ts
index cb28e5c..13e8f1e 100644
--- a/frontend/src/utils/i18n.ts
+++ b/frontend/src/utils/i18n.ts
@@ -1,7 +1,7 @@
import { createContext, useContext, useMemo } from "react";
function t(data: any, language: string) {
- return (key: string) => {
+ return (key: string): string => {
return data[language]?.["translation"]?.[key] || key;
};
}