Skip to content
Snippets Groups Projects
Commit 73c61cd7 authored by insert's avatar insert
Browse files

Add i18n to incoming requests.

Add icon stacking mask.
parent c15a2f19
No related merge requests found
Subproject commit dad00381aaaafc1ab829816dffc31f0f37ee56a9
Subproject commit 5cad406a2fb09d90803c5604d6f27701c3bf140b
......@@ -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} />
......
......@@ -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>
)
......
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
......
......@@ -150,6 +150,11 @@
display: flex;
flex-shrink: 0;
margin-inline-end: 15px;
svg:not(:first-child) {
position: relative;
margin-left: -32px;
}
}
.details {
......
......@@ -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> }
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment