mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-10 01:03:36 -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";
|
type VoiceStatus = "muted";
|
||||||
interface Props extends IconBaseProps<User> {
|
interface Props extends IconBaseProps<User> {
|
||||||
|
mask?: string;
|
||||||
status?: boolean;
|
status?: boolean;
|
||||||
voice?: VoiceStatus;
|
voice?: VoiceStatus;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +53,7 @@ import fallback from '../assets/user.png';
|
||||||
export default function UserIcon(props: Props & Omit<JSX.SVGAttributes<SVGSVGElement>, keyof Props>) {
|
export default function UserIcon(props: Props & Omit<JSX.SVGAttributes<SVGSVGElement>, keyof Props>) {
|
||||||
const client = useContext(AppContext);
|
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)
|
const iconURL = client.generateFileURL(target?.avatar ?? attachment, { max_side: 256 }, animate)
|
||||||
?? (target ? client.users.getDefaultAvatarURL(target._id) : fallback);
|
?? (target ? client.users.getDefaultAvatarURL(target._id) : fallback);
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ export default function UserIcon(props: Props & Omit<JSX.SVGAttributes<SVGSVGEle
|
||||||
height={size}
|
height={size}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
viewBox="0 0 32 32">
|
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}
|
<img src={iconURL}
|
||||||
draggable={false} />
|
draggable={false} />
|
||||||
|
|
|
@ -12,6 +12,10 @@ export default function Masks() {
|
||||||
<rect x="0" y="0" width="32" height="32" fill="white" />
|
<rect x="0" y="0" width="32" height="32" fill="white" />
|
||||||
<circle cx="27" cy="27" r="7" fill={"black"} />
|
<circle cx="27" cy="27" r="7" fill={"black"} />
|
||||||
</mask>
|
</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>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Text } from "preact-i18n";
|
||||||
import styles from "./UserPicker.module.scss";
|
import styles from "./UserPicker.module.scss";
|
||||||
import { useUsers } from "../../revoltjs/hooks";
|
import { useUsers } from "../../revoltjs/hooks";
|
||||||
import Modal from "../../../components/ui/Modal";
|
import Modal from "../../../components/ui/Modal";
|
||||||
|
@ -14,7 +15,7 @@ export function PendingRequests({ users: ids, onClose }: Props) {
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
visible={true}
|
visible={true}
|
||||||
title={"Pending requests"}
|
title={<Text id="app.special.friends.pending" />}
|
||||||
onClose={onClose}>
|
onClose={onClose}>
|
||||||
<div className={styles.list}>
|
<div className={styles.list}>
|
||||||
{ users
|
{ users
|
||||||
|
|
|
@ -150,6 +150,11 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-inline-end: 15px;
|
margin-inline-end: 15px;
|
||||||
|
|
||||||
|
svg:not(:first-child) {
|
||||||
|
position: relative;
|
||||||
|
margin-left: -32px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.details {
|
.details {
|
||||||
|
|
|
@ -12,6 +12,8 @@ import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
||||||
import { ChevronDown, ChevronRight } from "@styled-icons/boxicons-regular";
|
import { ChevronDown, ChevronRight } from "@styled-icons/boxicons-regular";
|
||||||
import { UserDetail, Conversation, UserPlus } from "@styled-icons/boxicons-solid";
|
import { UserDetail, Conversation, UserPlus } from "@styled-icons/boxicons-solid";
|
||||||
|
import { TextReact } from "../../lib/i18n";
|
||||||
|
import { Children } from "../../types/Preact";
|
||||||
|
|
||||||
export default function Friends() {
|
export default function Friends() {
|
||||||
const { openScreen } = useIntermediate();
|
const { openScreen } = useIntermediate();
|
||||||
|
@ -22,10 +24,10 @@ export default function Friends() {
|
||||||
const friends = users.filter(x => x.relationship === Users.Relationship.Friend);
|
const friends = users.filter(x => x.relationship === Users.Relationship.Friend);
|
||||||
|
|
||||||
const lists = [
|
const lists = [
|
||||||
[ 'app.special.friends.pending', users.filter(x =>
|
[ '', users.filter(x =>
|
||||||
x.relationship === Users.Relationship.Incoming
|
x.relationship === Users.Relationship.Incoming
|
||||||
) ],
|
) ],
|
||||||
[ 'app.special.friends.pending', users.filter(x =>
|
[ 'app.special.friends.sent', users.filter(x =>
|
||||||
x.relationship === Users.Relationship.Outgoing
|
x.relationship === Users.Relationship.Outgoing
|
||||||
) ],
|
) ],
|
||||||
[ 'app.status.online', friends.filter(x =>
|
[ 'app.status.online', friends.filter(x =>
|
||||||
|
@ -39,6 +41,10 @@ export default function Friends() {
|
||||||
) ]
|
) ]
|
||||||
] as [ string, User[] ][];
|
] 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;
|
const isEmpty = lists.reduce((p: number, n) => p + n.length, 0) === 0;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -74,15 +80,20 @@ export default function Friends() {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{ lists[0][1].length > 0 && <div className={styles.pending}
|
{ incoming.length > 0 && <div className={styles.pending}
|
||||||
onClick={() => openScreen({ id: 'pending_requests', users: lists[0][1].map(x => x._id) })}>
|
onClick={() => openScreen({ id: 'pending_requests', users: incoming.map(x => x._id) })}>
|
||||||
<div className={styles.avatars}>
|
<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>
|
||||||
<div className={styles.details}>
|
<div className={styles.details}>
|
||||||
{/* ! FIXME: i18n */}
|
<div><Text id="app.special.friends.pending" /> <span>{ incoming.length }</span></div>
|
||||||
<div className={styles.title}>Pending requests<span>{ lists[0][1].length }</span></div>
|
<span>
|
||||||
<span className={styles.from}>From <span className={styles.user}>{ lists[0][1].map(x => x.username).join(', ') }</span></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>
|
</div>
|
||||||
<ChevronRight size={28} />
|
<ChevronRight size={28} />
|
||||||
</div> }
|
</div> }
|
||||||
|
|
Loading…
Reference in a new issue