Style tweaks

This commit is contained in:
Kieran 2023-08-24 16:54:20 +01:00
parent 4e21c4834b
commit 4b85a16904
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
19 changed files with 79 additions and 57 deletions

View File

@ -1,20 +1,21 @@
import "./Avatar.css";
import Nostrich from "nostrich.webp";
import { CSSProperties, useEffect, useState } from "react";
import type { UserMetadata } from "@snort/system";
import useImgProxy from "Hooks/useImgProxy";
import { getDisplayName } from "Element/ProfileImage";
import { defaultAvatar } from "SnortUtils";
interface AvatarProps {
pubkey: string;
user?: UserMetadata;
onClick?: () => void;
size?: number;
image?: string;
}
const Avatar = ({ user, size, onClick, image }: AvatarProps) => {
const [url, setUrl] = useState<string>(Nostrich);
const Avatar = ({ pubkey, user, size, onClick, image }: AvatarProps) => {
const [url, setUrl] = useState("");
const { proxy } = useImgProxy();
useEffect(() => {
@ -23,7 +24,7 @@ const Avatar = ({ user, size, onClick, image }: AvatarProps) => {
const proxyUrl = proxy(url, size ?? 120);
setUrl(proxyUrl);
} else {
setUrl(Nostrich);
setUrl(defaultAvatar(pubkey));
}
}, [user, image]);

View File

@ -22,6 +22,6 @@
margin-bottom: auto;
}
.modal-body button:hover {
.modal-body button.secondary:hover {
background-color: var(--gray);
}

View File

@ -1,7 +1,5 @@
import "./Nip05.css";
import { HexKey } from "@snort/system";
import Icon from "Icons/Icon";
import { useUserProfile } from "@snort/system-react";
export function useIsVerified(pubkey: HexKey, bypassCheck?: boolean) {
@ -28,7 +26,6 @@ const Nip05 = ({ nip05, pubkey, verifyNip = true }: Nip05Params) => {
<span className="domain" data-domain={domain?.toLowerCase()}>
{domain}
</span>
<Icon name="check-verified" className="badge" size={16} />
</>
)}
</div>

View File

@ -81,6 +81,7 @@
width: 48px;
height: 48px;
background-color: var(--highlight);
color: white;
border: none;
border-radius: 100%;
position: fixed;

View File

@ -19,9 +19,6 @@ a.pfp {
}
.pfp .username {
display: flex;
flex-direction: column;
align-items: flex-start;
font-weight: 600;
}

View File

@ -54,11 +54,11 @@ export default function ProfileImage({
return (
<>
<div className="avatar-wrapper">
<Avatar user={user} size={size} />
<Avatar pubkey={pubkey} user={user} size={size} />
</div>
{showUsername && (
<div className="f-ellipsis">
<div className="username">
<div className="flex g4 username">
<div>{name.trim()}</div>
{nip05 && <Nip05 nip05={nip05} pubkey={pubkey} verifyNip={verifyNip} />}
</div>

View File

@ -4,9 +4,11 @@ import { NostrEvent, TaggedNostrEvent } from "@snort/system";
import PageSpinner from "Element/PageSpinner";
import Note from "Element/Note";
import NostrBandApi from "External/NostrBand";
import { useReactions } from "Feed/FeedReactions";
export default function TrendingNotes() {
const [posts, setPosts] = useState<Array<NostrEvent>>();
const related = useReactions("trending", posts?.map(a => a.id) ?? []);
async function loadTrendingNotes() {
const api = new NostrBandApi();
@ -23,7 +25,7 @@ export default function TrendingNotes() {
return (
<>
{posts.map(e => (
<Note key={e.id} data={e as TaggedNostrEvent} related={[]} depth={0} />
<Note key={e.id} data={e as TaggedNostrEvent} related={related?.data ?? []} depth={0} />
))}
</>
);

View File

@ -0,0 +1,25 @@
import { RequestBuilder, EventKind, NoteCollection } from "@snort/system";
import { useRequestBuilder } from "@snort/system-react";
import useLogin from "Hooks/useLogin";
import { useMemo } from "react";
export function useReactions(subId: string, ids: Array<string>, others?: (rb: RequestBuilder) => void) {
const { preferences: pref } = useLogin();
const sub = useMemo(() => {
const rb = new RequestBuilder(subId);
if (ids.length > 0) {
rb.withFilter()
.kinds(
pref.enableReactions
? [EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt]
: [EventKind.ZapReceipt, EventKind.Repost]
)
.tag("e", ids);
}
others?.(rb);
return rb.numFilters > 0 ? rb : null;
}, [ids]);
return useRequestBuilder(NoteCollection, sub);
}

View File

@ -6,6 +6,7 @@ import { unixNow, unwrap, tagFilterOfTextRepost } from "SnortUtils";
import useTimelineWindow from "Hooks/useTimelineWindow";
import useLogin from "Hooks/useLogin";
import { SearchRelays } from "Const";
import { useReactions } from "./FeedReactions";
export interface TimelineFeedOptions {
method: "TIME_RANGE" | "LIMIT_UNTIL";
@ -157,26 +158,13 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
return [];
}
const subNext = useMemo(() => {
const rb = new RequestBuilder(`timeline-related:${subject.type}:${subject.discriminator}`);
const trackingEvents = main.data?.map(a => a.id) ?? [];
if (trackingEvents.length > 0) {
rb.withFilter()
.kinds(
pref.enableReactions
? [EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt]
: [EventKind.ZapReceipt, EventKind.Repost]
)
.tag("e", trackingEvents);
}
const trackingEvents = main.data?.map(a => a.id) ?? [];
const related = useReactions(`timeline-related:${subject.type}:${subject.discriminator}`, trackingEvents, rb => {
const trackingParentEvents = getParentEvents();
if (trackingParentEvents.length > 0) {
rb.withFilter().ids(trackingParentEvents);
}
return rb.numFilters > 0 ? rb : null;
}, [main.data, pref, subject.type]);
const related = useRequestBuilder(NoteCollection, subNext);
});
return {
main: main.data,

View File

@ -77,7 +77,7 @@ export const DefaultPreferences = {
language: "en",
enableReactions: true,
reactionEmoji: "+",
autoLoadMedia: "follows-only",
autoLoadMedia: "all",
theme: "system",
confirmReposts: false,
showDebugMenus: false,

View File

@ -1,9 +1,7 @@
import Nostrich from "nostrich.webp";
import { TaggedNostrEvent, EventKind, MetadataCache } from "@snort/system";
import { getDisplayName } from "Element/ProfileImage";
import { MentionRegex } from "Const";
import { tagFilterOfTextRepost, unwrap } from "SnortUtils";
import { defaultAvatar, tagFilterOfTextRepost, unwrap } from "SnortUtils";
import { UserCache } from "Cache";
import { LoginSession } from "Login";
@ -28,7 +26,7 @@ export async function makeNotification(ev: TaggedNostrEvent): Promise<Notificati
.map(a => unwrap(a));
const fromUser = UserCache.getFromCache(ev.pubkey);
const name = getDisplayName(fromUser, ev.pubkey);
const avatarUrl = fromUser?.picture || Nostrich;
const avatarUrl = fromUser?.picture || defaultAvatar(ev.pubkey);
return {
title: `Reply from ${name}`,
body: replaceTagsWithUser(ev, allUsers).substring(0, 50),

View File

@ -27,7 +27,7 @@ const HashTagsPage = () => {
return (
<>
<div className="main-content">
<div className="main-content p">
<div className="action-heading">
<h2>#{tag}</h2>
{isFollowing ? (

View File

@ -179,6 +179,7 @@ const AccountHeader = () => {
{hasNotifications && <span className="has-unread"></span>}
</Link>
<Avatar
pubkey={publicKey ?? ""}
user={profile}
onClick={() => {
if (profile) {

View File

@ -382,7 +382,7 @@ export default function ProfilePage() {
function avatar() {
return (
<div className="avatar-wrapper w-max">
<Avatar user={user} />
<Avatar pubkey={id ?? ""} user={user} />
<div className="profile-actions">
{renderIcons()}
{!isMe && id && <FollowButton pubkey={id} />}

View File

@ -36,6 +36,7 @@ export default function RootPage() {
{
tab: "following",
path: "/notes",
show: Boolean(pubKey),
element: (
<>
<Icon name="user-v2" />
@ -46,6 +47,7 @@ export default function RootPage() {
{
tab: "trending-notes",
path: "/trending/notes",
show: true,
element: (
<>
<Icon name="fire" />
@ -56,6 +58,7 @@ export default function RootPage() {
{
tab: "conversations",
path: "/conversations",
show: Boolean(pubKey),
element: (
<>
<Icon name="message-chat-circle" />
@ -66,6 +69,7 @@ export default function RootPage() {
{
tab: "trending-people",
path: "/trending/people",
show: true,
element: (
<>
<Icon name="user-up" />
@ -76,6 +80,7 @@ export default function RootPage() {
{
tab: "suggested",
path: "/suggested",
show: Boolean(pubKey),
element: (
<>
<Icon name="thumbs-up" />
@ -86,6 +91,7 @@ export default function RootPage() {
{
tab: "global",
path: "/global",
show: true,
element: (
<>
<Icon name="globe" />
@ -96,12 +102,13 @@ export default function RootPage() {
] as Array<{
tab: RootPage;
path: string;
show: boolean;
element: ReactNode;
}>;
useEffect(() => {
if (location.pathname === "/") {
const t = pubKey ? preferences.defaultRootTab ?? "/notes" : "/global";
const t = pubKey ? preferences.defaultRootTab ?? "/notes" : "/trending/notes";
navigate(t);
} else {
const currentTab = menuItems.find(a => a.path === location.pathname)?.tab;
@ -140,14 +147,16 @@ export default function RootPage() {
<div className="close-menu" />
</MenuItem>
</div>
{menuItems.map(a => (
<MenuItem
onClick={() => {
navigate(a.path);
}}>
{a.element}
</MenuItem>
))}
{menuItems
.filter(a => a.show)
.map(a => (
<MenuItem
onClick={() => {
navigate(a.path);
}}>
{a.element}
</MenuItem>
))}
{tags.item.map(v => (
<MenuItem
onClick={() => {

View File

@ -16,6 +16,7 @@
height: 100%;
background-size: cover;
border-radius: 12px;
background: linear-gradient(90deg, #60a5fa 0%, #a78bfa 100%);
}
.settings .image-settings {

View File

@ -1,5 +1,4 @@
import "./Profile.css";
import Nostrich from "nostrich.webp";
import { useEffect, useState } from "react";
import { FormattedMessage } from "react-intl";
import { useNavigate } from "react-router-dom";
@ -168,7 +167,7 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
{(props.banner ?? true) && (
<div
style={{
backgroundImage: `url(${(banner?.length ?? 0) === 0 ? Nostrich : banner})`,
backgroundImage: (banner?.length ?? 0) > 0 ? `url(${banner})` : undefined,
}}
className="banner">
<AsyncButton type="button" onClick={() => setNewBanner()}>
@ -178,7 +177,7 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
)}
{(props.avatar ?? true) && (
<div className="avatar-stack">
<Avatar user={user} image={picture} />
<Avatar pubkey={id} user={user} image={picture} />
<AsyncButton type="button" className="btn-rnd" onClick={() => setNewAvatar()}>
<Icon name="upload-01" />
</AsyncButton>

View File

@ -505,3 +505,7 @@ export function kvToObject<T>(o: string, sep?: string) {
})
) as T;
}
export function defaultAvatar(input: string) {
return `https://robohash.v0l.io/${input}.png`;
}

View File

@ -123,6 +123,10 @@ code {
margin-left: auto;
margin-right: auto;
}
.main-content {
border: 1px solid var(--gray-superdark);
}
}
.p {
@ -161,9 +165,9 @@ button {
cursor: pointer;
padding: 6px 12px;
font-weight: 600;
color: white;
color: var(--bg-color);
font-size: var(--font-size);
background-color: var(--highlight);
background-color: var(--font-color);
border: none;
border-radius: 16px;
outline: none;
@ -194,8 +198,7 @@ button:disabled:hover {
}
button:hover {
background-color: var(--font-color);
color: var(--bg-color);
background-color: var(--gray-light);
}
button.secondary {
@ -595,10 +598,6 @@ small.xs {
color: var(--highlight);
}
.main-content {
border: 1px solid var(--gray-superdark);
}
.bold {
font-weight: 700;
}