chore: cleanup right widget styles & NIP-89 handler

This commit is contained in:
2024-09-19 10:37:11 +01:00
parent 17e8955f54
commit 41c0047f5b
23 changed files with 773 additions and 94 deletions

View File

@ -10,13 +10,14 @@ import { getDisplayNameOrPlaceHolder } from "@/Utils";
interface DisplayNameProps {
pubkey: HexKey;
user?: UserMetadata | undefined;
className?: string;
}
const DisplayName = ({ pubkey, user }: DisplayNameProps) => {
const DisplayName = ({ pubkey, user, className }: DisplayNameProps) => {
const profile = useUserProfile(user ? undefined : pubkey) ?? user;
const [name, isPlaceHolder] = useMemo(() => getDisplayNameOrPlaceHolder(profile, pubkey), [profile, pubkey]);
return <span className={classNames({ placeholder: isPlaceHolder })}>{name}</span>;
return <span className={classNames(className, { placeholder: isPlaceHolder })}>{name}</span>;
};
export default DisplayName;

View File

@ -1,4 +1,5 @@
import { HexKey } from "@snort/system";
import classNames from "classnames";
import { FormattedMessage } from "react-intl";
import AsyncButton from "@/Components/Button/AsyncButton";
@ -17,11 +18,10 @@ export default function FollowButton(props: FollowButtonProps) {
const readonly = useLogin(s => s.readonly);
const control = useFollowsControls();
const isFollowing = control.isFollowing(pubkey);
const baseClassname = props.className ? `${props.className} ` : "";
return (
<AsyncButton
className={isFollowing ? `${baseClassname} secondary` : `${baseClassname} primary`}
className={classNames(props.className, "secondary")}
disabled={readonly}
onClick={async e => {
e.stopPropagation();

View File

@ -2,7 +2,7 @@ import { HexKey } from "@snort/system";
import { ReactNode, useMemo } from "react";
import { FormattedMessage } from "react-intl";
import ProfilePreview from "@/Components/User/ProfilePreview";
import ProfilePreview, { ProfilePreviewProps } from "@/Components/User/ProfilePreview";
import useFollowsControls from "@/Hooks/useFollowControls";
import useLogin from "@/Hooks/useLogin";
@ -13,26 +13,22 @@ export interface FollowListBaseProps {
pubkeys: HexKey[];
title?: ReactNode;
showFollowAll?: boolean;
showAbout?: boolean;
className?: string;
actions?: ReactNode;
profileActions?: (pk: string) => ReactNode;
profilePreviewProps?: Omit<ProfilePreviewProps, "pubkey">;
}
export default function FollowListBase({
pubkeys,
title,
showFollowAll,
showAbout,
className,
actions,
profileActions,
profilePreviewProps,
}: FollowListBaseProps) {
const control = useFollowsControls();
const login = useLogin();
const profilePreviewOptions = useMemo(() => ({ about: showAbout, profileCards: true }), [showAbout]);
async function followAll() {
await control.addFollow(pubkeys);
}
@ -50,13 +46,7 @@ export default function FollowListBase({
)}
<div className={className}>
{pubkeys?.map((a, index) => (
<ProfilePreview
pubkey={a}
key={a}
options={profilePreviewOptions}
actions={profileActions?.(a)}
waitUntilInView={index > 10}
/>
<ProfilePreview pubkey={a} key={a} waitUntilInView={index > 10} {...profilePreviewProps} />
))}
</div>
</div>

View File

@ -1,4 +1,3 @@
import { HexKey, NostrPrefix } from "@snort/system";
import { FormattedMessage } from "react-intl";
import MuteButton from "@/Components/User/MuteButton";
@ -8,7 +7,7 @@ import useModeration from "@/Hooks/useModeration";
import messages from "../messages";
export interface MutedListProps {
pubkeys: HexKey[];
pubkeys: Array<string>;
}
export default function MutedList() {
@ -22,15 +21,15 @@ export default function MutedList() {
</div>
</div>
{muteList?.map(a => {
switch (a.type) {
case NostrPrefix.Profile:
case NostrPrefix.PublicKey: {
const tag = a.toEventTag();
switch (tag?.at(0)) {
case "p": {
return (
<ProfilePreview
actions={<MuteButton pubkey={a.id} />}
pubkey={a.id}
actions={<MuteButton pubkey={tag[1]} />}
pubkey={tag[1]}
options={{ about: false }}
key={a.id}
key={tag[1]}
/>
);
}

View File

@ -22,7 +22,7 @@ export interface ProfileImageProps {
link?: string;
defaultNip?: string;
verifyNip?: boolean;
overrideUsername?: string;
overrideUsername?: ReactNode;
profile?: UserMetadata;
size?: number;
onClick?: (e: React.MouseEvent) => void;
@ -57,12 +57,12 @@ export default function ProfileImage({
const handleMouseEnter = useCallback(() => {
hoverTimeoutRef.current && clearTimeout(hoverTimeoutRef.current);
hoverTimeoutRef.current = setTimeout(() => setIsHovering(true), 100); // Adjust timeout as needed
hoverTimeoutRef.current = setTimeout(() => setIsHovering(true), 100);
}, []);
const handleMouseLeave = useCallback(() => {
hoverTimeoutRef.current && clearTimeout(hoverTimeoutRef.current);
hoverTimeoutRef.current = setTimeout(() => setIsHovering(false), 300); // Adjust timeout as needed
hoverTimeoutRef.current = setTimeout(() => setIsHovering(false), 300);
}, []);
function handleClick(e: React.MouseEvent) {

View File

@ -2,27 +2,25 @@ import "./ProfilePreview.css";
import { HexKey, UserMetadata } from "@snort/system";
import { useUserProfile } from "@snort/system-react";
import { memo, ReactNode } from "react";
import { ReactNode } from "react";
import { useInView } from "react-intersection-observer";
import FollowButton from "@/Components/User/FollowButton";
import ProfileImage from "@/Components/User/ProfileImage";
import ProfileImage, { ProfileImageProps } from "@/Components/User/ProfileImage";
export interface ProfilePreviewProps {
pubkey: HexKey;
options?: {
about?: boolean;
linkToProfile?: boolean;
profileCards?: boolean;
};
subHeader?: ReactNode;
profile?: UserMetadata;
actions?: ReactNode;
className?: string;
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
waitUntilInView?: boolean;
profileImageProps?: Omit<ProfileImageProps, "pubkey" | "profile">;
}
export default memo(function ProfilePreview(props: ProfilePreviewProps) {
export default function ProfilePreview(props: ProfilePreviewProps) {
const pubkey = props.pubkey;
const { ref, inView } = useInView({ triggerOnce: true, rootMargin: "500px" });
const user = useUserProfile(inView ? pubkey : undefined);
@ -50,9 +48,8 @@ export default memo(function ProfilePreview(props: ProfilePreviewProps) {
<ProfileImage
pubkey={pubkey}
profile={props.profile}
link={options.linkToProfile ?? true ? undefined : ""}
subHeader={options.about ? <div className="about">{user?.about}</div> : props.subHeader}
showProfileCard={options.profileCards}
subHeader={options.about && <div className="about">{user?.about}</div>}
{...props.profileImageProps}
/>
{props.actions ?? (
<div className="whitespace-nowrap">
@ -64,4 +61,4 @@ export default memo(function ProfilePreview(props: ProfilePreviewProps) {
</div>
</>
);
});
}