mirror of
https://github.com/revoltchat/revite.git
synced 2024-12-23 22:22:07 -05:00
Add i18n to incoming requests.
Add icon stacking mask.
This commit is contained in:
parent
c15a2f1968
commit
73c61cd7f8
6 changed files with 34 additions and 12 deletions
2
external/lang
vendored
2
external/lang
vendored
|
@ -1 +1 @@
|
|||
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>
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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> }
|
||||
|
|
Loading…
Reference in a new issue