UI updates (#135)
This commit is contained in:
@ -2,8 +2,8 @@
|
||||
border-radius: 50%;
|
||||
height: 210px;
|
||||
width: 210px;
|
||||
background-image: var(--img-url), var(--gray-gradient);
|
||||
border: 2px solid transparent;
|
||||
background-image: var(--img-url);
|
||||
border: 1px solid transparent;
|
||||
background-origin: border-box;
|
||||
background-clip: content-box, border-box;
|
||||
background-size: cover;
|
||||
|
@ -1,15 +1,9 @@
|
||||
.copy {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.copy .body {
|
||||
font-family: monospace;
|
||||
font-size: 14px;
|
||||
background: var(--note-bg);
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--font-color);
|
||||
padding: 2px 4px;
|
||||
border-radius: 10px;
|
||||
margin: 0 4px 0 0;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ export interface CopyProps {
|
||||
export default function Copy({ text, maxSize = 32 }: CopyProps) {
|
||||
const { copy, copied, error } = useCopy();
|
||||
const sliceLength = maxSize / 2
|
||||
const trimmed = text.length > maxSize ? `${text.slice(0, sliceLength)}:${text.slice(-sliceLength)}` : text
|
||||
const trimmed = text.length > maxSize ? `${text.slice(0, sliceLength)}...${text.slice(-sliceLength)}` : text
|
||||
|
||||
return (
|
||||
<div className="flex flex-row copy" onClick={() => copy(text)}>
|
||||
@ -20,7 +20,7 @@ export default function Copy({ text, maxSize = 32 }: CopyProps) {
|
||||
<FontAwesomeIcon
|
||||
icon={copied ? faCheck : faCopy}
|
||||
size="xs"
|
||||
style={{ color: copied ? 'var(--success)' : 'currentColor', marginRight: '2px' }}
|
||||
style={{ color: copied ? 'var(--success)' : 'var(--highlight)', marginRight: '2px' }}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -7,14 +7,12 @@ import { RootState } from "State/Store";
|
||||
|
||||
export interface FollowButtonProps {
|
||||
pubkey: HexKey,
|
||||
className?: string,
|
||||
className?: string
|
||||
}
|
||||
export default function FollowButton(props: FollowButtonProps) {
|
||||
const pubkey = props.pubkey;
|
||||
const publiser = useEventPublisher();
|
||||
const isFollowing = useSelector<RootState, boolean>(s => s.login.follows?.includes(pubkey) ?? false);
|
||||
const baseClassName = isFollowing ? `btn btn-warn follow-button` : `btn btn-success follow-button`
|
||||
const className = props.className ? `${baseClassName} ${props.className}` : `${baseClassName}`;
|
||||
|
||||
async function follow(pubkey: HexKey) {
|
||||
let ev = await publiser.addFollow(pubkey);
|
||||
@ -27,8 +25,8 @@ export default function FollowButton(props: FollowButtonProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className} onClick={() => isFollowing ? unfollow(pubkey) : follow(pubkey)}>
|
||||
<FontAwesomeIcon icon={isFollowing ? faUserMinus : faUserPlus} size="lg" />
|
||||
</div>
|
||||
<button type="button" className={isFollowing ? `${props.className ?? ''} secondary` : props.className} onClick={() => isFollowing ? unfollow(pubkey) : follow(pubkey)}>
|
||||
{isFollowing ? 'Unfollow' : 'Follow'}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,12 @@ export default function FollowListBase({ pubkeys, title }: FollowListBaseProps)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="main-content">
|
||||
<div className="flex mt10">
|
||||
<div className="f-grow">{title}</div>
|
||||
<div className="btn" onClick={() => followAll()}>Follow All</div>
|
||||
<button type="button" onClick={() => followAll()}>Follow All</button>
|
||||
</div>
|
||||
{pubkeys?.map(a => <ProfilePreview pubkey={a} key={a} />)}
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
.follows-you {
|
||||
color: var(--font-color);
|
||||
color: var(--gray-light);
|
||||
font-size: var(--font-size-tiny);
|
||||
margin-left: .2em;
|
||||
font-weight: normal
|
||||
|
@ -1,10 +1,5 @@
|
||||
.lnurl-tip {
|
||||
background-color: var(--note-bg);
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
width: 500px;
|
||||
text-align: center;
|
||||
min-height: 10vh;
|
||||
}
|
||||
|
||||
.lnurl-tip .btn {
|
||||
@ -62,10 +57,3 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media(max-width: 720px) {
|
||||
.lnurl-tip {
|
||||
width: 100vw;
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
|
@ -8,5 +8,20 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999999;
|
||||
z-index: 42;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
background-color: var(--note-bg);
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
width: 500px;
|
||||
min-height: 10vh;
|
||||
}
|
||||
|
||||
@media(max-width: 720px) {
|
||||
.modal-body {
|
||||
width: 100vw;
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,9 @@ export default function Modal(props: ModalProps) {
|
||||
|
||||
return (
|
||||
<div className="modal" onClick={(e) => { e.stopPropagation(); onClose(); }}>
|
||||
<div className="modal-body">
|
||||
{props.children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
.nip05 {
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
margin: .2em;
|
||||
}
|
||||
|
||||
@ -10,50 +9,8 @@
|
||||
}
|
||||
|
||||
.nip05 .nick {
|
||||
color: var(--gray-light);
|
||||
color: var(--font-secondary-color);
|
||||
font-weight: bold;
|
||||
margin-right: .2em;
|
||||
}
|
||||
|
||||
.nip05 .domain {
|
||||
color: var(--gray-superlight);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nip05 .text-gradient {
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
background-color: var(--gray-superlight);
|
||||
}
|
||||
|
||||
.nip05 .domain[data-domain="snort.social"] {
|
||||
background-image: var(--snort-gradient);
|
||||
}
|
||||
|
||||
.nip05 .domain[data-domain="nostrplebs.com"] {
|
||||
background-image: var(--nostrplebs-gradient);
|
||||
}
|
||||
|
||||
.nip05 .domain[data-domain="nostrpurple.com"] {
|
||||
background-image: var(--nostrplebs-gradient);
|
||||
}
|
||||
|
||||
.nip05 .domain[data-domain="nostr.fan"] {
|
||||
background-image: var(--nostrplebs-gradient);
|
||||
}
|
||||
|
||||
.nip05 .domain[data-domain="nostrich.zone"] {
|
||||
background-image: var(--nostrplebs-gradient);
|
||||
}
|
||||
|
||||
.nip05 .domain[data-domain="nostriches.net"] {
|
||||
background-image: var(--nostrplebs-gradient);
|
||||
}
|
||||
|
||||
.nip05 .domain[data-domain="strike.army"] {
|
||||
background-image: var(--strike-army-gradient);
|
||||
}
|
||||
|
||||
.nip05 .badge {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useQuery } from "react-query";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faSpinner, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faCircleCheck, faSpinner, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
import './Nip05.css'
|
||||
import { HexKey } from "Nostr";
|
||||
@ -57,16 +57,20 @@ const Nip05 = (props: Nip05Params) => {
|
||||
const { isVerified, couldNotVerify } = useIsVerified(props.pubkey, props.nip05)
|
||||
|
||||
return (
|
||||
<div className={`flex nip05${couldNotVerify ? " failed" : ""}`}>
|
||||
{!isDefaultUser && (
|
||||
<div className="nick">
|
||||
{name}
|
||||
</div>
|
||||
)}
|
||||
<div className={`domain text-gradient`} data-domain={domain?.toLowerCase()}>
|
||||
{domain}
|
||||
<div className={`flex nip05${couldNotVerify ? " failed" : ""}`} onClick={(ev) => ev.stopPropagation()}>
|
||||
<div className="nick">
|
||||
{isDefaultUser ? (
|
||||
`${domain}`
|
||||
) : `@${name}`}
|
||||
</div>
|
||||
<span className="badge">
|
||||
{isVerified && (
|
||||
<FontAwesomeIcon
|
||||
color={"var(--highlight)"}
|
||||
icon={faCircleCheck}
|
||||
size="xs"
|
||||
/>
|
||||
)}
|
||||
{!isVerified && !couldNotVerify && (
|
||||
<FontAwesomeIcon
|
||||
color={"var(--fg-color)"}
|
||||
|
@ -11,6 +11,14 @@
|
||||
color: var(--font-secondary-color);
|
||||
}
|
||||
|
||||
.note>.header .reply a {
|
||||
color: var(--highlight);
|
||||
}
|
||||
|
||||
.note>.header .reply a:hover {
|
||||
text-decoration-color: var(--highlight);
|
||||
}
|
||||
|
||||
.note>.header>.info {
|
||||
font-size: var(--font-size);
|
||||
white-space: nowrap;
|
||||
@ -18,7 +26,7 @@
|
||||
}
|
||||
|
||||
.note>.body {
|
||||
margin-top: 12px;
|
||||
margin-top: 4px;
|
||||
padding-left: 56px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: pre-wrap;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import "./Note.css";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useCallback, useMemo, ReactNode } from "react";
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
|
||||
import { default as NEvent } from "Nostr/Event";
|
||||
import ProfileImage from "Element/ProfileImage";
|
||||
@ -64,21 +64,57 @@ export default function Note(props: NoteProps) {
|
||||
|
||||
const maxMentions = 2;
|
||||
let replyId = ev.Thread?.ReplyTo?.Event ?? ev.Thread?.Root?.Event;
|
||||
let mentions: string[] = [];
|
||||
let mentions: {pk: string, name: string, link: ReactNode}[] = [];
|
||||
for (let pk of ev.Thread?.PubKeys) {
|
||||
let u = users?.get(pk);
|
||||
const u = users?.get(pk);
|
||||
const npub = hexToBech32("npub", pk)
|
||||
const shortNpub = npub.substring(0, 12);
|
||||
if (u) {
|
||||
mentions.push(u.name ?? hexToBech32("npub", pk).substring(0, 12));
|
||||
mentions.push({
|
||||
pk,
|
||||
name: u.name ?? shortNpub,
|
||||
link: (
|
||||
<Link to={`/p/${npub}`}>
|
||||
{u.name ? `@${u.name}` : shortNpub}
|
||||
</Link>
|
||||
)
|
||||
});
|
||||
} else {
|
||||
mentions.push(hexToBech32("npub", pk).substring(0, 12));
|
||||
mentions.push({
|
||||
pk,
|
||||
name: shortNpub,
|
||||
link: (
|
||||
<Link to={`/p/${npub}`}>
|
||||
{shortNpub}
|
||||
</Link>
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
mentions.sort((a, b) => a.startsWith("npub") ? 1 : -1);
|
||||
mentions.sort((a, b) => a.name.startsWith("npub") ? 1 : -1);
|
||||
let othersLength = mentions.length - maxMentions
|
||||
let pubMentions = mentions.length > maxMentions ? `${mentions?.slice(0, maxMentions).join(", ")} & ${othersLength} other${othersLength > 1 ? 's' : ''}` : mentions?.join(", ");
|
||||
const renderMention = (m: any, idx: number) => {
|
||||
return (
|
||||
<>
|
||||
{idx > 0 && ", "}
|
||||
{m.link}
|
||||
</>
|
||||
)
|
||||
}
|
||||
const pubMentions = mentions.length > maxMentions ? (
|
||||
mentions?.slice(0, maxMentions).map(renderMention)
|
||||
) : mentions?.map(renderMention);
|
||||
const others = mentions.length > maxMentions ? ` & ${othersLength} other${othersLength > 1 ? 's' : ''}` : ''
|
||||
return (
|
||||
<div className="reply">
|
||||
{(pubMentions?.length ?? 0) > 0 ? pubMentions : replyId ? hexToBech32("note", replyId)?.substring(0, 12) : ""}
|
||||
{(mentions?.length ?? 0) > 0 ? (
|
||||
<>
|
||||
{pubMentions}
|
||||
{others}
|
||||
</>
|
||||
) : replyId ? (
|
||||
hexToBech32("note", replyId)?.substring(0, 12) // todo: link
|
||||
) : ""}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -13,23 +13,28 @@
|
||||
.note-creator textarea {
|
||||
outline: none;
|
||||
resize: none;
|
||||
min-height: 40px;
|
||||
background-color: var(--note-bg);
|
||||
border-radius: 10px 10px 0 0;
|
||||
max-width: stretch;
|
||||
min-width: stretch;
|
||||
}
|
||||
|
||||
.note-creator .actions {
|
||||
.note-creator-actions {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.note-creator .attachment {
|
||||
cursor: pointer;
|
||||
padding: 5px 10px;
|
||||
border-radius: 10px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.note-creator-actions button:not(:last-child) {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.note-creator .attachment .error {
|
||||
@ -45,3 +50,26 @@
|
||||
color: var(--font-color);
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
|
||||
.note-create-button {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
background-color: var(--highlight);
|
||||
border: none;
|
||||
border-radius: 100%;
|
||||
position: fixed;
|
||||
bottom: 50px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
@media (min-width: 520px) {
|
||||
.note-create-button {
|
||||
right: 10vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1020px) {
|
||||
.note-create-button {
|
||||
right: 25vw;
|
||||
}
|
||||
}
|
||||
|
@ -4,21 +4,26 @@ import { faPaperclip } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
import "./NoteCreator.css";
|
||||
|
||||
import Plus from "Icons/Plus";
|
||||
import useEventPublisher from "Feed/EventPublisher";
|
||||
import { openFile } from "Util";
|
||||
import VoidUpload from "Feed/VoidUpload";
|
||||
import { FileExtensionRegex } from "Const";
|
||||
import Textarea from "Element/Textarea";
|
||||
import Event, { default as NEvent } from "Nostr/Event";
|
||||
import Modal from "Element/Modal";
|
||||
import { default as NEvent } from "Nostr/Event";
|
||||
|
||||
export interface NoteCreatorProps {
|
||||
show: boolean
|
||||
setShow: (s: boolean) => void
|
||||
replyTo?: NEvent,
|
||||
onSend?: Function,
|
||||
show: boolean,
|
||||
onClose?(): void
|
||||
autoFocus: boolean
|
||||
}
|
||||
|
||||
export function NoteCreator(props: NoteCreatorProps) {
|
||||
const { show, setShow } = props
|
||||
const publisher = useEventPublisher();
|
||||
const [note, setNote] = useState<string>();
|
||||
const [error, setError] = useState<string>();
|
||||
@ -68,14 +73,23 @@ export function NoteCreator(props: NoteCreatorProps) {
|
||||
}
|
||||
}
|
||||
|
||||
function cancel(ev: any) {
|
||||
setShow(false)
|
||||
setNote("")
|
||||
}
|
||||
|
||||
function onSubmit(ev: React.MouseEvent<HTMLButtonElement>) {
|
||||
ev.stopPropagation();
|
||||
sendNote().catch(console.warn);
|
||||
}
|
||||
|
||||
if (!props.show) return null;
|
||||
return (
|
||||
<>
|
||||
<button className="note-create-button" type="button" onClick={() => setShow(!show)}>
|
||||
<Plus />
|
||||
</button>
|
||||
{show && (
|
||||
<Modal onClose={props.onClose}>
|
||||
<div className={`flex note-creator ${props.replyTo ? 'note-reply' : ''}`}>
|
||||
<div className="flex f-col mr10 f-grow">
|
||||
<Textarea
|
||||
@ -85,19 +99,22 @@ export function NoteCreator(props: NoteCreatorProps) {
|
||||
value={note}
|
||||
onFocus={() => setActive(true)}
|
||||
/>
|
||||
{active && note && (
|
||||
<div className="actions flex f-row">
|
||||
<div className="attachment flex f-row">
|
||||
{(error?.length ?? 0) > 0 ? <b className="error">{error}</b> : null}
|
||||
<FontAwesomeIcon icon={faPaperclip} size="xl" onClick={(e) => attachFile()} />
|
||||
</div>
|
||||
<button type="button" className="btn" onClick={onSubmit}>
|
||||
{props.replyTo ? 'Reply' : 'Send'}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div className="attachment">
|
||||
{(error?.length ?? 0) > 0 ? <b className="error">{error}</b> : null}
|
||||
<FontAwesomeIcon icon={faPaperclip} size="xl" onClick={(e) => attachFile()} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="note-creator-actions">
|
||||
<button className="secondary" type="button" onClick={cancel}>
|
||||
Cancel
|
||||
</button>
|
||||
<button type="button" onClick={onSubmit}>
|
||||
{props.replyTo ? 'Reply' : 'Send'}
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,14 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { faHeart, faReply, faThumbsDown, faTrash, faBolt, faRepeat, faEllipsisVertical, faShareNodes, faCopy } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faTrash, faRepeat, faShareNodes, faCopy } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Menu, MenuItem } from '@szhsin/react-menu';
|
||||
|
||||
import Dislike from "Icons/Dislike";
|
||||
import Heart from "Icons/Heart";
|
||||
import Dots from "Icons/Dots";
|
||||
import Zap from "Icons/Zap";
|
||||
import Reply from "Icons/Reply";
|
||||
import { formatShort } from "Number";
|
||||
import useEventPublisher from "Feed/EventPublisher";
|
||||
import { getReactions, hexToBech32, normalizeReaction, Reaction } from "Util";
|
||||
@ -82,7 +87,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
||||
<>
|
||||
<div className="reaction-pill" onClick={() => setTip(true)}>
|
||||
<div className="reaction-pill-icon">
|
||||
<FontAwesomeIcon icon={faBolt} />
|
||||
<Zap />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
@ -114,7 +119,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
||||
<>
|
||||
<div className={`reaction-pill ${hasReacted('+') ? 'reacted' : ''} `} onClick={() => react("+")}>
|
||||
<div className="reaction-pill-icon">
|
||||
<FontAwesomeIcon icon={faHeart} />
|
||||
<Heart />
|
||||
</div>
|
||||
<div className="reaction-pill-number">
|
||||
{formatShort(groupReactions[Reaction.Positive])}
|
||||
@ -148,14 +153,14 @@ export default function NoteFooter(props: NoteFooterProps) {
|
||||
function menuItems() {
|
||||
return (
|
||||
<>
|
||||
{prefs.enableReactions && (<MenuItem onClick={() => react("-")}>
|
||||
<div>
|
||||
<FontAwesomeIcon icon={faThumbsDown} className={hasReacted('-') ? 'reacted' : ''} />
|
||||
|
||||
{prefs.enableReactions && (
|
||||
<MenuItem onClick={() => react("-")}>
|
||||
<Dislike />
|
||||
{formatShort(groupReactions[Reaction.Negative])}
|
||||
</div>
|
||||
Dislike
|
||||
</MenuItem>)}
|
||||
|
||||
Dislike
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem onClick={() => share()}>
|
||||
<FontAwesomeIcon icon={faShareNodes} />
|
||||
Share
|
||||
@ -183,18 +188,18 @@ export default function NoteFooter(props: NoteFooterProps) {
|
||||
return (
|
||||
<>
|
||||
<div className="footer">
|
||||
<div className={`reaction-pill ${reply ? 'reacted' : ''}`} onClick={(e) => setReply(s => !s)}>
|
||||
<div className="reaction-pill-icon">
|
||||
<FontAwesomeIcon icon={faReply} />
|
||||
</div>
|
||||
</div>
|
||||
<Menu menuButton={<div className="reaction-pill">
|
||||
<div className="reaction-pill-icon">
|
||||
<FontAwesomeIcon icon={faEllipsisVertical} />
|
||||
<Dots />
|
||||
</div>
|
||||
</div>} menuClassName="ctx-menu">
|
||||
{menuItems()}
|
||||
</Menu>
|
||||
<div className={`reaction-pill ${reply ? 'reacted' : ''}`} onClick={(e) => setReply(s => !s)}>
|
||||
<div className="reaction-pill-icon">
|
||||
<Reply />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{reactionIcons()}
|
||||
{tipButton()}
|
||||
@ -204,6 +209,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
||||
replyTo={ev}
|
||||
onSend={() => setReply(false)}
|
||||
show={reply}
|
||||
setShow={setReply}
|
||||
/>
|
||||
<LNURLTip svc={author?.lud16 || author?.lud06} onClose={() => setTip(false)} show={tip} />
|
||||
</>
|
||||
|
@ -3,7 +3,7 @@
|
||||
}
|
||||
|
||||
.reaction > .note {
|
||||
margin: 10px 20px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.reaction > .header {
|
||||
|
@ -1,6 +1,6 @@
|
||||
.pfp {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pfp .avatar-wrapper {
|
||||
@ -8,7 +8,6 @@
|
||||
}
|
||||
|
||||
.pfp .avatar {
|
||||
border-width: 1px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
cursor: pointer;
|
||||
@ -23,13 +22,15 @@
|
||||
text-decoration-color: var(--gray-superlight);
|
||||
}
|
||||
|
||||
.pfp .profile-name {
|
||||
.pfp .username {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pfp .nip05 {
|
||||
margin: 0;
|
||||
margin-top: -.2em;
|
||||
.pfp .profile-name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import "./ProfileImage.css";
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
import useProfile from "Feed/ProfileFeed";
|
||||
import { hexToBech32, profileLink } from "Util";
|
||||
import Avatar from "Element/Avatar"
|
||||
@ -30,13 +30,18 @@ export default function ProfileImage({ pubkey, subHeader, showUsername = true, c
|
||||
<div className="avatar-wrapper">
|
||||
<Avatar user={user} onClick={() => navigate(link ?? profileLink(pubkey))} />
|
||||
</div>
|
||||
{showUsername && (<div className="f-grow pointer" onClick={e => { e.stopPropagation(); navigate(link ?? profileLink(pubkey)) }}>
|
||||
<div className="profile-name">
|
||||
<div>{name}</div>
|
||||
{user?.nip05 && <Nip05 nip05={user.nip05} pubkey={user.pubkey} />}
|
||||
{showUsername && (
|
||||
<div className="profile-name f-grow">
|
||||
<div className="username">
|
||||
<Link className="display-name" key={pubkey} to={link ?? profileLink(pubkey)}>
|
||||
{name}
|
||||
</Link>
|
||||
{user?.nip05 && <Nip05 nip05={user.nip05} pubkey={user.pubkey} />}
|
||||
</div>
|
||||
{subHeader ? <>{subHeader}</> : null}
|
||||
</div>
|
||||
<div className="subheader">
|
||||
{subHeader}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
@ -48,12 +48,12 @@
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.nip05 {
|
||||
font-size: 12px;
|
||||
.user-item .nip05 {
|
||||
font-size: var(--font-size-tiny);
|
||||
}
|
||||
|
||||
.emoji-item {
|
||||
font-size: 12px;
|
||||
font-size: var(--font-size-tiny);
|
||||
}
|
||||
|
||||
.emoji-item .emoji {
|
||||
|
@ -2,4 +2,4 @@
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ export default function Timeline({ subject, postsOnly = false, method }: Timelin
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="main-content">
|
||||
{latestFeed.length > 1 && (<div className="card latest-notes pointer" onClick={() => showLatest()}>
|
||||
<FontAwesomeIcon icon={faForward} size="xl"/>
|
||||
|
||||
@ -57,6 +57,6 @@ export default function Timeline({ subject, postsOnly = false, method }: Timelin
|
||||
</div>)}
|
||||
{mainFeed.map(eventElement)}
|
||||
<LoadMore onLoadMore={loadMore} shouldLoadMore={main.end}/>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user