v3: code quality pass, various bug fixes

This commit is contained in:
khannurien
2026-03-23 07:47:49 +00:00
parent d94a319d96
commit fbbbb43258
44 changed files with 1060 additions and 698 deletions

View File

@@ -10,16 +10,13 @@ export function AppHeader(
const { user } = useAuth();
const navigate = useNavigate();
const headerRef = useRef<HTMLElement>(null);
const [_showFab, setShowFab] = useState(false);
const [createModalOpen, setCreateModalOpen] = useState(false);
useEffect(() => {
// IntersectionObserver retained here to support a future floating action button
const el = headerRef.current;
if (!el) return;
const obs = new IntersectionObserver(
([entry]) => setShowFab(!entry.isIntersecting),
{ threshold: 0 },
);
const obs = new IntersectionObserver(() => {}, { threshold: 0 });
obs.observe(el);
return () => obs.disconnect();
}, []);

View File

@@ -1,4 +1,4 @@
import React, { useRef, useState } from "react";
import React, { useMemo, useRef, useState } from "react";
import { Link } from "react-router";
import { API_URL } from "../config/api.ts";
import type { Comment, RawComment, User } from "../model.ts";
@@ -380,7 +380,7 @@ export function CommentThread({
const [submitting, setSubmitting] = useState(false);
const [topLevelError, setTopLevelError] = useState<string | null>(null);
const tree = buildTree(comments);
const tree = useMemo(() => buildTree(comments), [comments]);
const roots = tree.get("root") ?? [];
async function handleTopLevelSubmit(e?: React.FormEvent) {

View File

@@ -1,3 +1,4 @@
import { useMemo } from "react";
import { Link } from "react-router";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
@@ -15,9 +16,25 @@ function preprocessMentions(text: string): string {
return text.replace(/(?<![[(])@([\w]+)/g, "[@$1](/users/$1)");
}
// Static components object — defined once at module scope to avoid recreation on every render
const MARKDOWN_COMPONENTS: React.ComponentProps<typeof ReactMarkdown>["components"] = {
a: ({ href, children: linkChildren }) => {
if (href?.startsWith("/users/")) {
return <Link to={href}>{linkChildren}</Link>;
}
return (
<a href={href} target="_blank" rel="noopener noreferrer">
{linkChildren}
</a>
);
},
};
export function Markdown(
{ children, className, inline = false }: MarkdownProps,
) {
const processed = useMemo(() => preprocessMentions(children), [children]);
return (
<div
className={`md${className ? ` ${className}` : ""}${
@@ -26,20 +43,9 @@ export function Markdown(
>
<ReactMarkdown
remarkPlugins={REMARK_PLUGINS}
components={{
a: ({ href, children: linkChildren }) => {
if (href?.startsWith("/users/")) {
return <Link to={href}>{linkChildren}</Link>;
}
return (
<a href={href} target="_blank" rel="noopener noreferrer">
{linkChildren}
</a>
);
},
}}
components={MARKDOWN_COMPONENTS}
>
{preprocessMentions(children)}
{processed}
</ReactMarkdown>
</div>
);