Add i18n to incoming requests.

Add icon stacking mask.
This commit is contained in:
Paul 2021-07-02 18:56:00 +01:00
parent c15a2f1968
commit 73c61cd7f8
6 changed files with 34 additions and 12 deletions

2
external/lang vendored

@ -1 +1 @@
Subproject commit dad00381aaaafc1ab829816dffc31f0f37ee56a9
Subproject commit 5cad406a2fb09d90803c5604d6f27701c3bf140b

View file

@ -9,6 +9,7 @@ import { AppContext } from "../../../context/revoltjs/RevoltClient";
type VoiceStatus = "muted";
interface Props extends IconBaseProps<User> {
mask?: string;
status?: boolean;
voice?: VoiceStatus;
}
@ -52,7 +53,7 @@ import fallback from '../assets/user.png';
export default function UserIcon(props: Props & Omit<JSX.SVGAttributes<SVGSVGElement>, keyof Props>) {
const client = useContext(AppContext);
const { target, attachment, size, voice, status, animate, children, as, ...svgProps } = props;
const { target, attachment, size, voice, status, animate, mask, children, as, ...svgProps } = props;
const iconURL = client.generateFileURL(target?.avatar ?? attachment, { max_side: 256 }, animate)
?? (target ? client.users.getDefaultAvatarURL(target._id) : fallback);
@ -62,7 +63,7 @@ export default function UserIcon(props: Props & Omit<JSX.SVGAttributes<SVGSVGEle
height={size}
aria-hidden="true"
viewBox="0 0 32 32">
<foreignObject x="0" y="0" width="32" height="32" mask={props.status ? "url(#user)" : undefined}>
<foreignObject x="0" y="0" width="32" height="32" mask={mask ?? (status ? "url(#user)" : undefined)}>
{
<img src={iconURL}
draggable={false} />

View file

@ -12,6 +12,10 @@ export default function Masks() {
<rect x="0" y="0" width="32" height="32" fill="white" />
<circle cx="27" cy="27" r="7" fill={"black"} />
</mask>
<mask id="overlap">
<rect x="0" y="0" width="32" height="32" fill="white" />
<circle cx="32" cy="16" r="18" fill={"black"} />
</mask>
</defs>
</svg>
)

View file

@ -1,3 +1,4 @@
import { Text } from "preact-i18n";
import styles from "./UserPicker.module.scss";
import { useUsers } from "../../revoltjs/hooks";
import Modal from "../../../components/ui/Modal";
@ -14,7 +15,7 @@ export function PendingRequests({ users: ids, onClose }: Props) {
return (
<Modal
visible={true}
title={"Pending requests"}
title={<Text id="app.special.friends.pending" />}
onClose={onClose}>
<div className={styles.list}>
{ users

View file

@ -150,6 +150,11 @@
display: flex;
flex-shrink: 0;
margin-inline-end: 15px;
svg:not(:first-child) {
position: relative;
margin-left: -32px;
}
}
.details {

View file

@ -12,6 +12,8 @@ import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
import { useIntermediate } from "../../context/intermediate/Intermediate";
import { ChevronDown, ChevronRight } from "@styled-icons/boxicons-regular";
import { UserDetail, Conversation, UserPlus } from "@styled-icons/boxicons-solid";
import { TextReact } from "../../lib/i18n";
import { Children } from "../../types/Preact";
export default function Friends() {
const { openScreen } = useIntermediate();
@ -22,10 +24,10 @@ export default function Friends() {
const friends = users.filter(x => x.relationship === Users.Relationship.Friend);
const lists = [
[ 'app.special.friends.pending', users.filter(x =>
[ '', users.filter(x =>
x.relationship === Users.Relationship.Incoming
) ],
[ 'app.special.friends.pending', users.filter(x =>
[ 'app.special.friends.sent', users.filter(x =>
x.relationship === Users.Relationship.Outgoing
) ],
[ 'app.status.online', friends.filter(x =>
@ -39,6 +41,10 @@ export default function Friends() {
) ]
] as [ string, User[] ][];
const incoming = lists[0][1];
const userlist: Children[] = incoming.map(x => <b>{ x.username }</b>);
for (let i=incoming.length-1;i>0;i--) userlist.splice(i, 0, ', ');
const isEmpty = lists.reduce((p: number, n) => p + n.length, 0) === 0;
return (
<>
@ -74,15 +80,20 @@ export default function Friends() {
</>
)}
{ lists[0][1].length > 0 && <div className={styles.pending}
onClick={() => openScreen({ id: 'pending_requests', users: lists[0][1].map(x => x._id) })}>
{ incoming.length > 0 && <div className={styles.pending}
onClick={() => openScreen({ id: 'pending_requests', users: incoming.map(x => x._id) })}>
<div className={styles.avatars}>
{ lists[0][1].map((x, i) => i < 3 && <UserIcon target={x} size={54} />) }
{ incoming.map((x, i) => i < 3 && <UserIcon target={x} size={64} mask={ i < Math.min(incoming.length - 1, 2) ? "url(#overlap)" : undefined } />) }
</div>
<div className={styles.details}>
{/* ! FIXME: i18n */}
<div className={styles.title}>Pending requests<span>{ lists[0][1].length }</span></div>
<span className={styles.from}>From <span className={styles.user}>{ lists[0][1].map(x => x.username).join(', ') }</span></span>
<div><Text id="app.special.friends.pending" /> <span>{ incoming.length }</span></div>
<span>
{
incoming.length > 3 ? <TextReact id="app.special.friends.from.several" fields={{ userlist: userlist.slice(0, 6), count: incoming.length - 3 }} />
: incoming.length > 1 ? <TextReact id="app.special.friends.from.multiple" fields={{ user: userlist.shift()!, userlist: userlist.slice(1) }} />
: <TextReact id="app.special.friends.from.single" fields={{ user: userlist[0] }} />
}
</span>
</div>
<ChevronRight size={28} />
</div> }