chore: cleanup right widget styles & NIP-89 handler
This commit is contained in:
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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>
|
||||
|
@ -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]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
</>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user