This commit is contained in:
2024-02-22 14:01:29 +07:00
parent e9ce932646
commit 64286aa354
34 changed files with 899 additions and 354 deletions

View File

@@ -0,0 +1,44 @@
import { ArrowDownIcon, ArrowUpIcon, LoaderIcon } from "@lume/icons";
import { useState } from "react";
import { useNoteContext } from "../provider";
import { useArk } from "@lume/ark";
import { cn } from "@lume/utils";
export function NoteDownvote() {
const ark = useArk();
const event = useNoteContext();
const [reaction, setReaction] = useState<"-" | null>(null);
const [loading, setLoading] = useState(false);
const down = async () => {
// start loading
setLoading(true);
const res = await ark.downvote(event.id, event.pubkey);
if (res) setReaction("-");
// stop loading
setLoading(false);
};
return (
<button
type="button"
onClick={down}
disabled={!!reaction || loading}
className={cn(
"inline-flex size-7 items-center justify-center rounded-full",
reaction === "-"
? "bg-blue-500 text-white"
: "bg-neutral-100 text-neutral-700 hover:bg-blue-500 hover:text-white dark:bg-neutral-900 dark:text-neutral-300",
)}
>
{loading ? (
<LoaderIcon className="size-4 animate-spin" />
) : (
<ArrowDownIcon className="size-4" />
)}
</button>
);
}

View File

@@ -1,66 +1,11 @@
import { ArrowDownIcon, ArrowUpIcon } from "@lume/icons";
import { useState } from "react";
import { useNoteContext } from "../provider";
import { useArk } from "@lume/ark";
import { cn } from "@lume/utils";
import { NoteUpvote } from "./upvote";
import { NoteDownvote } from "./downvote";
export function NoteReaction() {
const ark = useArk();
const event = useNoteContext();
const [reaction, setReaction] = useState<"+" | "-">(null);
const [loading, setLoading] = useState(false);
const up = async () => {
// start loading
setLoading(false);
const res = await ark.upvote(event.id, event.pubkey);
if (res) setReaction("+");
// stop loading
setLoading(true);
};
const down = async () => {
// start loading
setLoading(false);
const res = await ark.downvote(event.id, event.pubkey);
if (res) setReaction("-");
// stop loading
setLoading(true);
};
return (
<div className="inline-flex items-center gap-2">
<button
type="button"
onClick={up}
disabled={!!reaction || loading}
className={cn(
"inline-flex size-7 items-center justify-center rounded-full",
reaction === "+"
? "bg-blue-500 text-white"
: "bg-neutral-100 text-neutral-700 hover:bg-blue-500 hover:text-white dark:bg-neutral-900 dark:text-neutral-300",
)}
>
<ArrowUpIcon className="size-4" />
</button>
<button
type="button"
onClick={down}
disabled={!!reaction || loading}
className={cn(
"inline-flex size-7 items-center justify-center rounded-full",
reaction === "-"
? "bg-blue-500 text-white"
: "bg-neutral-100 text-neutral-700 hover:bg-blue-500 hover:text-white dark:bg-neutral-900 dark:text-neutral-300",
)}
>
<ArrowDownIcon className="size-4" />
</button>
<NoteUpvote />
<NoteDownvote />
</div>
);
}

View File

@@ -0,0 +1,44 @@
import { ArrowUpIcon, LoaderIcon } from "@lume/icons";
import { useState } from "react";
import { useNoteContext } from "../provider";
import { useArk } from "@lume/ark";
import { cn } from "@lume/utils";
export function NoteUpvote() {
const ark = useArk();
const event = useNoteContext();
const [reaction, setReaction] = useState<"+" | null>(null);
const [loading, setLoading] = useState(false);
const up = async () => {
// start loading
setLoading(true);
const res = await ark.upvote(event.id, event.pubkey);
if (res) setReaction("+");
// stop loading
setLoading(false);
};
return (
<button
type="button"
onClick={up}
disabled={!!reaction || loading}
className={cn(
"inline-flex size-7 items-center justify-center rounded-full",
reaction === "+"
? "bg-blue-500 text-white"
: "bg-neutral-100 text-neutral-700 hover:bg-blue-500 hover:text-white dark:bg-neutral-900 dark:text-neutral-300",
)}
>
{loading ? (
<LoaderIcon className="size-4 animate-spin" />
) : (
<ArrowUpIcon className="size-4" />
)}
</button>
);
}

View File

@@ -1,4 +1,3 @@
import { PinIcon } from "@lume/icons";
import { NOSTR_MENTIONS } from "@lume/utils";
import { ReactNode, useMemo } from "react";
import { useTranslation } from "react-i18next";
@@ -6,7 +5,7 @@ import reactStringReplace from "react-string-replace";
import { User } from "../../user";
import { Hashtag } from "./hashtag";
import { MentionUser } from "./user";
import { useEvent } from "@lume/ark";
import { useArk, useEvent } from "@lume/ark";
export function MentionNote({
eventId,
@@ -18,6 +17,7 @@ export function MentionNote({
const { t } = useTranslation();
const { isLoading, isError, data } = useEvent(eventId);
const ark = useArk();
const richContent = useMemo(() => {
if (!data) return "";
@@ -117,17 +117,18 @@ export function MentionNote({
</div>
</User.Root>
</User.Provider>
<div className="line-clamp-4 select-text whitespace-pre-line text-balance px-3 leading-normal">
<div className="line-clamp-4 select-text whitespace-normal text-balance px-3 leading-normal">
{richContent}
</div>
{openable ? (
<div className="flex h-10 items-center justify-between px-3">
<a
href={`/events/${data.id}`}
<button
type="button"
onClick={() => ark.open_thread(data.id)}
className="text-blue-500 hover:text-blue-600"
>
{t("note.showMore")}
</a>
</button>
</div>
) : (
<div className="h-3" />

View File

@@ -34,7 +34,7 @@ export function NoteMenu() {
<DropdownMenu.Trigger asChild>
<button
type="button"
className="text-neutral-500 hover:text-blue-500 dark:text-neutral-400"
className="group inline-flex size-7 items-center justify-center text-neutral-800 dark:text-neutral-200"
>
<HorizontalDotsIcon className="size-5" />
</button>

View File

@@ -22,7 +22,7 @@ export function TextNote({
<Note.Menu />
</div>
<div className="flex gap-3">
<div className="size-10 shrink-0" />
<div className="size-11 shrink-0" />
<div className="min-w-0 flex-1">
<Note.Thread className="mb-2" />
<Note.Content />

View File

@@ -16,7 +16,7 @@ export function NoteUser({ className }: { className?: string }) {
>
<div className="flex gap-3">
<HoverCard.Trigger>
<User.Avatar className="size-10 shrink-0 rounded-full object-cover ring-1 ring-neutral-200/50 dark:ring-neutral-800/50" />
<User.Avatar className="size-11 shrink-0 rounded-full object-cover ring-1 ring-neutral-200/50 dark:ring-neutral-800/50" />
</HoverCard.Trigger>
<div>
<User.Name className="font-semibold leading-tight text-neutral-950 dark:text-neutral-50" />