Redesigned people list

This commit is contained in:
Bojan Mojsilovic 2024-04-16 13:05:34 +02:00
parent e359b127a2
commit 20b4bf76da
7 changed files with 366 additions and 66 deletions

View File

@ -90,8 +90,6 @@ const Cashu: Component< { id?: string, token: string, alternative?: boolean, noB
lnurl,
)}&autopay=yes`;
console.log('Redeem: ', url);
window.open(url, 'blank_');
};

View File

@ -0,0 +1,45 @@
import { A } from '@solidjs/router';
import { Component, For, Show } from 'solid-js';
import { useAccountContext } from '../../contexts/AccountContext';
import { hookForDev } from '../../lib/devTools';
import { authorName, nip05Verification, truncateNpub } from '../../stores/profile';
import { PrimalNote, PrimalUser } from '../../types/primal';
import Avatar from '../Avatar/Avatar';
import FollowButton from '../FollowButton/FollowButton';
import MentionedPerson from './MentionedPerson';
import styles from './PeopleList.module.scss';
const MentionedPeople: Component<{
mentioned: PrimalUser[],
label: string,
id?: string,
author: PrimalUser,
}> = (props) => {
const account = useAccountContext();
const author = () => props.author;
const mentioned = () => props.mentioned;
return (
<>
<div class={styles.heading}>{props.label}</div>
<div id="trending_section" class={styles.authorSection}>
<MentionedPerson
person={author()}
/>
<For each={mentioned()}>
{(person) =>
<MentionedPerson
person={person}
/>
}
</For>
</div>
</>
);
}
export default hookForDev(MentionedPeople);

View File

@ -0,0 +1,54 @@
import { A } from '@solidjs/router';
import { Component, For, Show } from 'solid-js';
import { useAccountContext } from '../../contexts/AccountContext';
import { hookForDev } from '../../lib/devTools';
import { authorName, nip05Verification, truncateNpub } from '../../stores/profile';
import { PrimalNote, PrimalUser } from '../../types/primal';
import Avatar from '../Avatar/Avatar';
import FollowButton from '../FollowButton/FollowButton';
import styles from './PeopleList.module.scss';
const MentionedPerson: Component<{
person: PrimalUser,
id?: string,
}> = (props) => {
const account = useAccountContext();
return (
<A href={`/p/${props.person?.npub}`} class={styles.mentionedPerson}>
<div class={styles.header}>
<Avatar
size="sm"
user={props.person}
/>
<div class={styles.content}>
<div class={styles.name}>
{authorName(props.person)}
</div>
<div class={styles.verification} title={props.person?.nip05}>
<Show when={props.person?.nip05}>
<span
class={styles.verifiedBy}
title={props.person?.nip05}
>
{nip05Verification(props.person)}
</span>
</Show>
</div>
</div>
<Show when={account?.publicKey !== props.person?.pubkey || !account?.following.includes(props.person?.pubkey || '')}>
<FollowButton person={props.person} />
</Show>
</div>
<div class={styles.about}>
{props.person.about || ''}
</div>
</A>
);
}
export default hookForDev(MentionedPerson);

View File

@ -5,7 +5,7 @@
width: 100%;
height: 44px;
z-index: 5;
padding-bottom: 22px;
padding-block: 22px;
display:flex;
flex-direction: row;
align-items: center;
@ -25,6 +25,13 @@
}
}
.authorSection {
// position: -webkit-sticky;
// position: sticky;
// top: 0px;
// padding-top: 44px;
}
.trendingSection {
// position: -webkit-sticky;
// position: sticky;
@ -48,6 +55,25 @@
@include heading();
}
@mixin followButton {
grid-area: follow;
align-items: center;
display: flex;
align-items: center;
button {
width: 72px;
height: 28px;
background: var(--brand-gradient);
border-radius: 6px;
padding: 0px;
font-size: 12px;
font-weight: 600;
line-height: 16px;
margin: 0px;
}
}
.peopleList {
margin-bottom: 16px;
display: grid;
@ -79,9 +105,9 @@
.name {
color: var(--text-primary);
font-weight: 400;
font-size: 12px;
line-height: 12px;
font-size: 16px;
font-weight: 700;
line-height: 16px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
@ -117,6 +143,22 @@
overflow: hidden;
}
.about {
font-size: 12px;
line-height: 16px;
font-weight: 400;
color: var(--text-tertiary-2);
overflow: hidden;
display: -webkit-box;
line-clamp: 3;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-ms-box-orient: vertical;
text-overflow: ellipsis;
}
&:hover {
.message, .name, .time {
color: var(--text-primary);
@ -127,25 +169,6 @@
}
}
@mixin followButton {
grid-area: follow;
align-items: center;
display: flex;
align-items: center;
button {
width: 72px;
height: 28px;
background: var(--brand-gradient);
border-radius: 6px;
padding: 0px;
font-size: 12px;
font-weight: 600;
line-height: 16px;
margin: 0px;
}
}
.follow {
@include followButton;
}
@ -168,6 +191,126 @@
}
}
.mentionedPerson {
display: flex;
flex-direction: column;
width: 300px;
gap: 8px;
padding-block: 12px;
border-bottom: 1px solid var(--devider);
text-decoration: none;
.header {
display: flex;
gap: 8px;
align-items: center;
.content {
grid-area: content;
display: flex;
flex-direction: column;
justify-content: center;
gap: 4px;
flex-grow: 1;
.name {
color: var(--text-primary);
font-size: 16px;
font-weight: 700;
line-height: 16px;
max-width: 168px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.verification {
font-size: 15px;
font-weight: 400;
line-height: 16px;
color: var(--text-tertiary-2);
max-width: 168px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.verifiedName {
font-size: 12px;
line-height: 16px;
font-weight: 700;
color: var(--text-tertiary-2);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.npub {
font-size: 12px;
line-height: 16px;
font-weight: 400;
color: var(--text-tertiary-2);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}
.follow {
@include followButton;
}
.unfollow {
@include followButton;
button {
background-color: var(--background-card);
background: linear-gradient(var(--background-card), var(--background-card)) padding-box,
var(--brand-gradient) border-box;
border: 1px solid transparent;
}
}
&:hover {
.name {
text-decoration: underline;
color: var(--text-primary);
}
}
}
.about {
width: 300px;
font-size: 14px;
font-weight: 400;
line-height: 18px;
color: var(--text-tertiary-2);
overflow: hidden;
display: -webkit-box;
line-clamp: 3;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-ms-box-orient: vertical;
text-overflow: ellipsis;
}
&:hover {
.content {
.name {
color: var(--text-primary);
text-decoration: underline;
}
}
cursor: pointer;
}
}
.verifiedIcon {
width:13px;
height: 12px;

View File

@ -3,58 +3,55 @@ import { Component, For, Show } from 'solid-js';
import { useAccountContext } from '../../contexts/AccountContext';
import { hookForDev } from '../../lib/devTools';
import { authorName, nip05Verification, truncateNpub } from '../../stores/profile';
import { PrimalUser } from '../../types/primal';
import { PrimalNote, PrimalUser } from '../../types/primal';
import Avatar from '../Avatar/Avatar';
import FollowButton from '../FollowButton/FollowButton';
import MentionedPeople from './MentionedPeople';
import styles from './PeopleList.module.scss';
import Repliers from './Repliers';
const PeopleList: Component<{ people: PrimalUser[], label: string, id?: string }> = (props) => {
const PeopleList: Component<{
people: PrimalUser[],
label: string,
id?: string,
note?: PrimalNote,
}> = (props) => {
const account = useAccountContext();
const people = () => props.people;
const author = () => props.note?.user;
const mentioned = () => {
if (!props.note) return [];
return props.people.filter(p => p.pubkey !== author()?.pubkey && (props.note?.mentionedUsers || {})[p.pubkey] !== undefined);
};
const repliers = () => {
if (!props.note) return props.people;
return props.people.filter(p => p.pubkey !== author()?.pubkey && (props.note?.mentionedUsers || {})[p.pubkey] === undefined);
}
return (
<div id={props.id} class={styles.stickyWrapper}>
<div class={styles.heading}>{props.label}</div>
<div id="trending_section" class={styles.trendingSection}>
<For each={people()}>
{
(person) =>
<A href={`/p/${person?.npub}`} class={styles.peopleList}>
<div class={styles.avatar}>
<Avatar
size="md"
user={person}
/>
</div>
<div class={styles.content}>
<div class={styles.name}>
{authorName(person)}
</div>
<div class={styles.verification} title={person?.nip05}>
<Show when={person?.nip05}>
<span
class={styles.verifiedBy}
title={person?.nip05}
>
{nip05Verification(person)}
</span>
</Show>
</div>
<div class={styles.npub} title={person?.npub}>
{truncateNpub(person?.npub)}
</div>
</div>
<Show when={account?.publicKey !== person.pubkey || !account?.following.includes(person.pubkey)}>
<FollowButton person={person} />
</Show>
</A>
}
</For>
<div id={props.id} class={styles.stickyWrapper}>
<Show when={author()}>
<MentionedPeople
mentioned={mentioned()}
author={author()}
label="People in this Note"
/>
</Show>
<Show when={repliers().length > 0}>
<Repliers
people={repliers()}
label={props.label}
/>
</Show>
</div>
</div>
);
}

View File

@ -0,0 +1,62 @@
import { A } from '@solidjs/router';
import { Component, For, Show } from 'solid-js';
import { useAccountContext } from '../../contexts/AccountContext';
import { hookForDev } from '../../lib/devTools';
import { authorName, nip05Verification, truncateNpub } from '../../stores/profile';
import { PrimalNote, PrimalUser } from '../../types/primal';
import Avatar from '../Avatar/Avatar';
import FollowButton from '../FollowButton/FollowButton';
import styles from './PeopleList.module.scss';
const Repliers: Component<{
people: PrimalUser[],
label: string,
id?: string,
}> = (props) => {
const account = useAccountContext();
const people = () => props.people;
return (
<>
<div class={styles.heading}>{props.label}</div>
<div id="trending_section" class={styles.trendingSection}>
<For each={people()}>
{
(person) =>
<A href={`/p/${person?.npub}`} class={styles.peopleList}>
<div class={styles.avatar}>
<Avatar
size="md"
user={person}
/>
</div>
<div class={styles.content}>
<div class={styles.name}>
{authorName(person)}
</div>
<div class={styles.verification} title={person?.nip05}>
<Show when={person?.nip05}>
<span
class={styles.verifiedBy}
title={person?.nip05}
>
{nip05Verification(person)}
</span>
</Show>
</div>
</div>
<Show when={account?.publicKey !== person.pubkey || !account?.following.includes(person.pubkey)}>
<FollowButton person={person} />
</Show>
</A>
}
</For>
</div>
</>
);
}
export default hookForDev(Repliers);

View File

@ -160,6 +160,7 @@ const Thread: Component = () => {
<Wormhole to='right_sidebar'>
<PeopleList
note={primaryNote()}
people={people()}
label={intl.formatMessage(t.sidebar)}
/>