count in profile page
This commit is contained in:
@ -1,42 +1,15 @@
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import MuteButton from "Element/MuteButton";
|
||||
import BlockButton from "Element/BlockButton";
|
||||
import ProfilePreview from "Element/ProfilePreview";
|
||||
import useModeration from "Hooks/useModeration";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
interface BlockListProps {
|
||||
variant: "muted" | "blocked";
|
||||
}
|
||||
|
||||
export default function BlockList({ variant }: BlockListProps) {
|
||||
const { blocked, muted } = useModeration();
|
||||
export default function BlockList() {
|
||||
const { blocked } = useModeration();
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
{variant === "muted" && (
|
||||
<>
|
||||
<h4>
|
||||
<FormattedMessage {...messages.MuteCount} values={{ n: muted.length }} />
|
||||
</h4>
|
||||
{muted.map(a => {
|
||||
return <ProfilePreview actions={<MuteButton pubkey={a} />} pubkey={a} options={{ about: false }} key={a} />;
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
{variant === "blocked" && (
|
||||
<>
|
||||
<h4>
|
||||
<FormattedMessage {...messages.BlockCount} values={{ n: blocked.length }} />
|
||||
</h4>
|
||||
{blocked.map(a => {
|
||||
return (
|
||||
<ProfilePreview actions={<BlockButton pubkey={a} />} pubkey={a} options={{ about: false }} key={a} />
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
{blocked.map(a => {
|
||||
return <ProfilePreview actions={<BlockButton pubkey={a} />} pubkey={a} options={{ about: false }} key={a} />;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ export default function Copy({ text, maxSize = 32 }: CopyProps) {
|
||||
<div className="flex flex-row copy" onClick={() => copy(text)}>
|
||||
<span className="body">{trimmed}</span>
|
||||
<span className="icon" style={{ color: copied ? "var(--success)" : "var(--highlight)" }}>
|
||||
{copied ? <Check width={13} height={13} /> : <CopyIcon width={13} height={13} />}
|
||||
{copied ? <Check width={14} height={14} /> : <CopyIcon width={14} height={14} />}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,27 +0,0 @@
|
||||
import { useMemo } from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import useFollowersFeed from "Feed/FollowersFeed";
|
||||
import { HexKey } from "@snort/nostr";
|
||||
import { EventKind } from "@snort/nostr";
|
||||
import FollowListBase from "Element/FollowListBase";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
export interface FollowersListProps {
|
||||
pubkey: HexKey;
|
||||
}
|
||||
|
||||
export default function FollowersList({ pubkey }: FollowersListProps) {
|
||||
const { formatMessage } = useIntl();
|
||||
const feed = useFollowersFeed(pubkey);
|
||||
|
||||
const pubkeys = useMemo(() => {
|
||||
const contactLists = feed?.store.notes.filter(
|
||||
a => a.kind === EventKind.ContactList && a.tags.some(b => b[0] === "p" && b[1] === pubkey)
|
||||
);
|
||||
return [...new Set(contactLists?.map(a => a.pubkey))];
|
||||
}, [feed, pubkey]);
|
||||
|
||||
return <FollowListBase pubkeys={pubkeys} title={formatMessage(messages.FollowerCount, { n: pubkeys?.length })} />;
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
import { useMemo } from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import useFollowsFeed from "Feed/FollowsFeed";
|
||||
import { HexKey } from "@snort/nostr";
|
||||
import FollowListBase from "Element/FollowListBase";
|
||||
import { getFollowers } from "Feed/FollowsFeed";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
export interface FollowsListProps {
|
||||
pubkey: HexKey;
|
||||
}
|
||||
|
||||
export default function FollowsList({ pubkey }: FollowsListProps) {
|
||||
const feed = useFollowsFeed(pubkey);
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const pubkeys = useMemo(() => {
|
||||
return getFollowers(feed.store, pubkey);
|
||||
}, [feed, pubkey]);
|
||||
|
||||
return <FollowListBase pubkeys={pubkeys} title={formatMessage(messages.FollowingCount, { n: pubkeys?.length })} />;
|
||||
}
|
@ -1,29 +1,13 @@
|
||||
import "./FollowsYou.css";
|
||||
import { useMemo } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { HexKey } from "@snort/nostr";
|
||||
import { RootState } from "State/Store";
|
||||
import useFollowsFeed from "Feed/FollowsFeed";
|
||||
import { getFollowers } from "Feed/FollowsFeed";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
export interface FollowsYouProps {
|
||||
pubkey: HexKey;
|
||||
followsMe: boolean;
|
||||
}
|
||||
|
||||
export default function FollowsYou({ pubkey }: FollowsYouProps) {
|
||||
export default function FollowsYou({ followsMe }: FollowsYouProps) {
|
||||
const { formatMessage } = useIntl();
|
||||
const feed = useFollowsFeed(pubkey);
|
||||
const loginPubKey = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
|
||||
|
||||
const pubkeys = useMemo(() => {
|
||||
return getFollowers(feed.store, pubkey);
|
||||
}, [feed, pubkey]);
|
||||
|
||||
const followsMe = loginPubKey ? pubkeys.includes(loginPubKey) : false;
|
||||
|
||||
return followsMe ? <span className="follows-you">{formatMessage(messages.FollowsYou)}</span> : null;
|
||||
}
|
||||
|
@ -1,23 +1,17 @@
|
||||
import { useMemo } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { HexKey } from "@snort/nostr";
|
||||
import MuteButton from "Element/MuteButton";
|
||||
import ProfilePreview from "Element/ProfilePreview";
|
||||
import useMutedFeed, { getMuted } from "Feed/MuteList";
|
||||
import useModeration from "Hooks/useModeration";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
export interface MutedListProps {
|
||||
pubkey: HexKey;
|
||||
pubkeys: HexKey[];
|
||||
}
|
||||
|
||||
export default function MutedList({ pubkey }: MutedListProps) {
|
||||
export default function MutedList({ pubkeys }: MutedListProps) {
|
||||
const { isMuted, muteAll } = useModeration();
|
||||
const feed = useMutedFeed(pubkey);
|
||||
const pubkeys = useMemo(() => {
|
||||
return getMuted(feed.store, pubkey);
|
||||
}, [feed, pubkey]);
|
||||
const hasAllMuted = pubkeys.every(isMuted);
|
||||
|
||||
return (
|
||||
|
@ -43,5 +43,6 @@
|
||||
}
|
||||
|
||||
.nip05 .badge {
|
||||
color: var(--highlight);
|
||||
margin: 0.1em 0.2em;
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
import { useQuery } from "react-query";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCircleCheck, faSpinner, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
import "./Nip05.css";
|
||||
import { useQuery } from "react-query";
|
||||
import Badge from "Icons/Badge";
|
||||
import { HexKey } from "@snort/nostr";
|
||||
|
||||
interface NostrJson {
|
||||
@ -59,15 +56,17 @@ const Nip05 = ({ nip05, pubkey, verifyNip = true }: Nip05Params) => {
|
||||
|
||||
return (
|
||||
<div className={`flex nip05${couldNotVerify ? " failed" : ""}`} onClick={ev => ev.stopPropagation()}>
|
||||
{!isDefaultUser && <div className="nick">{`${name}@`}</div>}
|
||||
<span className="domain" data-domain={domain?.toLowerCase()}>
|
||||
{domain}
|
||||
</span>
|
||||
<span className="badge">
|
||||
{isVerified && <FontAwesomeIcon color={"var(--highlight)"} icon={faCircleCheck} size="xs" />}
|
||||
{!isVerified && !couldNotVerify && <FontAwesomeIcon color={"var(--fg-color)"} icon={faSpinner} size="xs" />}
|
||||
{couldNotVerify && <FontAwesomeIcon color={"var(--error)"} icon={faTriangleExclamation} size="xs" />}
|
||||
</span>
|
||||
{!isDefaultUser && isVerified && <div className="nick">{`${name}@`}</div>}
|
||||
{isVerified && (
|
||||
<>
|
||||
<span className="domain" data-domain={domain?.toLowerCase()}>
|
||||
{domain}
|
||||
</span>
|
||||
<span className="badge">
|
||||
<Badge />
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -115,12 +115,12 @@
|
||||
border-bottom-right-radius: 16px;
|
||||
}
|
||||
|
||||
.light .note > .footer .ctx-menu li:hover {
|
||||
.note > .footer .ctx-menu li:hover {
|
||||
color: white;
|
||||
background: #2a2a2a;
|
||||
}
|
||||
|
||||
.note > .footer .ctx-menu li:hover {
|
||||
.light .note > .footer .ctx-menu li:hover {
|
||||
color: white;
|
||||
background: var(--font-secondary-color);
|
||||
}
|
||||
@ -151,6 +151,7 @@
|
||||
|
||||
.reaction-pill .reaction-pill-number {
|
||||
margin-left: 8px;
|
||||
font-feature-settings: "tnum";
|
||||
}
|
||||
|
||||
.reaction-pill.reacted {
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
.relay-settings {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.relay-settings svg:not(:last-child) {
|
||||
@ -25,6 +27,13 @@
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.relay-settings svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.relay-url {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
@ -14,16 +14,17 @@
|
||||
|
||||
.tab {
|
||||
color: var(--font-tertiary-color);
|
||||
border: 1px solid var(--font-tertiary-color);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
line-height: 19px;
|
||||
padding: 8px 12px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 17px;
|
||||
margin-right: 12px;
|
||||
padding: 6px 8px;
|
||||
text-align: center;
|
||||
font-feature-settings: "tnum";
|
||||
}
|
||||
|
||||
.tab:not(:last-of-type) {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.tab.active {
|
||||
@ -40,3 +41,7 @@
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tab:hover {
|
||||
border-color: var(--font-color);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import "./Tabs.css";
|
||||
import useHorizontalScroll from "Hooks/useHorizontalScroll";
|
||||
import { CSSProperties } from "react";
|
||||
|
||||
export interface Tab {
|
||||
text: string;
|
||||
@ -18,9 +19,11 @@ interface TabElementProps extends Omit<TabsProps, "tabs"> {
|
||||
}
|
||||
|
||||
export const TabElement = ({ t, tab, setTab }: TabElementProps) => {
|
||||
const style = { minWidth: `${t.text.length * 0.6}em` } as CSSProperties;
|
||||
return (
|
||||
<div
|
||||
className={`tab ${tab.value === t.value ? "active" : ""} ${t.disabled ? "disabled" : ""}`}
|
||||
style={style}
|
||||
onClick={() => !t.disabled && setTab(t)}>
|
||||
{t.text}
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user