2021-07-29 10:51:19 -04:00
|
|
|
import { observer } from "mobx-react-lite";
|
2021-07-05 06:23:23 -04:00
|
|
|
import { User } from "revolt.js";
|
|
|
|
import styled from "styled-components";
|
|
|
|
|
2021-06-21 16:11:53 -04:00
|
|
|
import { Text } from "preact-i18n";
|
2021-07-05 06:23:23 -04:00
|
|
|
import { useContext } from "preact/hooks";
|
|
|
|
|
2021-07-27 06:45:45 -04:00
|
|
|
import { TextReact } from "../../../../lib/i18n";
|
|
|
|
|
2021-07-29 10:51:19 -04:00
|
|
|
import { useData } from "../../../../mobx/State";
|
2021-07-05 06:23:23 -04:00
|
|
|
import { connectState } from "../../../../redux/connector";
|
|
|
|
import { TypingUser } from "../../../../redux/reducers/typing";
|
|
|
|
|
2021-07-29 10:51:19 -04:00
|
|
|
import {
|
|
|
|
AppContext,
|
|
|
|
useClient,
|
|
|
|
} from "../../../../context/revoltjs/RevoltClient";
|
2021-06-21 16:11:53 -04:00
|
|
|
|
2021-07-27 06:45:45 -04:00
|
|
|
import { Username } from "../../user/UserShort";
|
|
|
|
|
2021-06-21 16:11:53 -04:00
|
|
|
interface Props {
|
2021-07-05 06:25:20 -04:00
|
|
|
typing?: TypingUser[];
|
2021-06-21 16:11:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
const Base = styled.div`
|
2021-07-05 06:25:20 -04:00
|
|
|
position: relative;
|
|
|
|
|
|
|
|
> div {
|
|
|
|
height: 24px;
|
|
|
|
margin-top: -24px;
|
|
|
|
position: absolute;
|
|
|
|
|
|
|
|
gap: 8px;
|
|
|
|
display: flex;
|
|
|
|
padding: 0 10px;
|
|
|
|
user-select: none;
|
|
|
|
align-items: center;
|
|
|
|
flex-direction: row;
|
|
|
|
width: calc(100% - 3px);
|
|
|
|
color: var(--secondary-foreground);
|
|
|
|
background: var(--secondary-background);
|
|
|
|
}
|
|
|
|
|
|
|
|
.avatars {
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
img {
|
|
|
|
width: 16px;
|
|
|
|
height: 16px;
|
|
|
|
object-fit: cover;
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
|
|
&:not(:first-child) {
|
|
|
|
margin-left: -4px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.usernames {
|
|
|
|
min-width: 0;
|
|
|
|
font-size: 13px;
|
|
|
|
overflow: hidden;
|
|
|
|
white-space: nowrap;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
}
|
2021-06-21 16:11:53 -04:00
|
|
|
`;
|
|
|
|
|
2021-07-29 10:51:19 -04:00
|
|
|
export const TypingIndicator = observer(({ typing }: Props) => {
|
2021-07-05 06:25:20 -04:00
|
|
|
if (typing && typing.length > 0) {
|
2021-07-29 10:51:19 -04:00
|
|
|
const client = useClient();
|
|
|
|
const store = useData();
|
|
|
|
const users = typing
|
|
|
|
.map((x) => store.users.get(x.id)!)
|
|
|
|
.filter((x) => typeof x !== "undefined");
|
2021-07-05 06:25:20 -04:00
|
|
|
|
|
|
|
users.sort((a, b) =>
|
|
|
|
a._id.toUpperCase().localeCompare(b._id.toUpperCase()),
|
|
|
|
);
|
|
|
|
|
|
|
|
let text;
|
|
|
|
if (users.length >= 5) {
|
|
|
|
text = <Text id="app.main.channel.typing.several" />;
|
|
|
|
} else if (users.length > 1) {
|
2021-07-28 09:04:27 -04:00
|
|
|
const userlist = [...users].map((x) => <Username user={x} />);
|
|
|
|
const user = userlist.pop();
|
|
|
|
|
|
|
|
for (let i = 0; i < userlist.length - 1; i++) {
|
|
|
|
userlist.splice(i * 2 + 1, 0, <>, </>);
|
|
|
|
}
|
|
|
|
|
2021-07-05 06:25:20 -04:00
|
|
|
text = (
|
2021-07-27 06:45:45 -04:00
|
|
|
<TextReact
|
2021-07-05 06:25:20 -04:00
|
|
|
id="app.main.channel.typing.multiple"
|
|
|
|
fields={{
|
2021-07-28 09:04:27 -04:00
|
|
|
user,
|
|
|
|
userlist,
|
2021-07-05 06:25:20 -04:00
|
|
|
}}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
text = (
|
2021-07-27 06:45:45 -04:00
|
|
|
<TextReact
|
2021-07-05 06:25:20 -04:00
|
|
|
id="app.main.channel.typing.single"
|
2021-07-27 06:45:45 -04:00
|
|
|
fields={{ user: <Username user={users[0]} /> }}
|
2021-07-05 06:25:20 -04:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Base>
|
|
|
|
<div>
|
|
|
|
<div className="avatars">
|
|
|
|
{users.map((user) => (
|
|
|
|
<img
|
2021-07-24 12:01:50 -04:00
|
|
|
loading="eager"
|
2021-07-05 06:25:20 -04:00
|
|
|
src={client.users.getAvatarURL(
|
|
|
|
user._id,
|
|
|
|
{ max_side: 256 },
|
|
|
|
true,
|
|
|
|
)}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
<div className="usernames">{text}</div>
|
|
|
|
</div>
|
|
|
|
</Base>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2021-07-29 10:51:19 -04:00
|
|
|
});
|
2021-06-21 16:11:53 -04:00
|
|
|
|
|
|
|
export default connectState<{ id: string }>(TypingIndicator, (state, props) => {
|
2021-07-05 06:25:20 -04:00
|
|
|
return {
|
|
|
|
typing: state.typing && state.typing[props.id],
|
|
|
|
};
|
2021-06-21 16:11:53 -04:00
|
|
|
});
|