diff --git a/external/lang b/external/lang index eb880a90254df406b25caf6b969ed3aee3142f6c..0f98b07eb411ec5a9207536f6adc5aa8055e755e 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit eb880a90254df406b25caf6b969ed3aee3142f6c +Subproject commit 0f98b07eb411ec5a9207536f6adc5aa8055e755e diff --git a/package.json b/package.json index 406bd011e38353dd96925e30291d4709a5b02f01..0abe86cb403de3b845d5d063347b6d8789aa0c6e 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "react-router-dom": "^5.2.0", "react-scroll": "^1.8.2", "redux": "^4.1.0", - "revolt.js": "5.0.0-alpha.11", + "revolt.js": "5.0.0-alpha.12", "rimraf": "^3.0.2", "sass": "^1.35.1", "shade-blend-color": "^1.0.0", diff --git a/src/components/common/AutoComplete.tsx b/src/components/common/AutoComplete.tsx index eab39a8c3b98cce4c768d3e4721ec02654e2d824..897b2956044d68725483219b463a09596144fe2a 100644 --- a/src/components/common/AutoComplete.tsx +++ b/src/components/common/AutoComplete.tsx @@ -105,7 +105,7 @@ export function useAutoComplete( const regex = new RegExp(search, "i"); if (type === "emoji") { - // ! FIXME: we should convert it to a Binary Search Tree and use that + // ! TODO: we should convert it to a Binary Search Tree and use that const matches = Object.keys(emojiDictionary) .filter((emoji: string) => emoji.match(regex)) .splice(0, 5); diff --git a/src/components/common/ChannelIcon.tsx b/src/components/common/ChannelIcon.tsx index c020ec372620be30b7bd604814f930f7709145ba..6a13a0bc3b3e9c986ee77c50b5e3e8cf4c9218ec 100644 --- a/src/components/common/ChannelIcon.tsx +++ b/src/components/common/ChannelIcon.tsx @@ -50,7 +50,7 @@ export default observer( } return ( - // ! fixme: replace fallback with <picture /> + <source /> + // ! TODO: replace fallback with <picture /> + <source /> <ImageIconBase {...imgProps} width={size} diff --git a/src/components/common/messaging/Message.tsx b/src/components/common/messaging/Message.tsx index ae9142408b24b291daf12f1bb6f9a6400a551e19..4ba001d67b40ddef51dcc3ae4b59c4b3470706f1 100644 --- a/src/components/common/messaging/Message.tsx +++ b/src/components/common/messaging/Message.tsx @@ -54,19 +54,19 @@ const Message = observer( const head = preferHead || (message.reply_ids && message.reply_ids.length > 0); - // ! FIXME: tell fatal to make this type generic + // ! TODO: tell fatal to make this type generic // bree: Fatal please... const userContext = attachContext ? (attachContextMenu("Menu", { - user: message.author, - contextualChannel: message.channel, + user: message.author_id, + contextualChannel: message.channel_id, }) as any) : undefined; const openProfile = () => openScreen({ id: "profile", user_id: message.author_id }); - // ! FIXME: animate on hover + // ! FIXME(?): animate on hover const [animate, setAnimate] = useState(false); return ( @@ -96,7 +96,7 @@ const Message = observer( attachContext ? attachContextMenu("Menu", { message, - contextualChannel: message.channel, + contextualChannel: message.channel_id, queued, }) : undefined diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index b74c98bd1d36447cd28b1c28e73edc37ee72665c..78a1b1a7fe9558ceff7672ca64752c70d954d716 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -191,8 +191,7 @@ export default function MessageBox({ channel }: Props) { playSound("outbound"); const nonce = ulid(); - // ! FIXME: queued - /*dispatch({ + dispatch({ type: "QUEUE_ADD", nonce, channel: channel._id, @@ -204,7 +203,7 @@ export default function MessageBox({ channel }: Props) { content, replies, }, - });*/ + }); defer(() => SingletonMessageRenderer.jumpToBottom( diff --git a/src/components/navigation/items/ButtonItem.tsx b/src/components/navigation/items/ButtonItem.tsx index 9372c0f05fe588e5be5a11661f1018661c2943a5..f6d64a489f8a7b082a7115bc0431c2ba38b8bd97 100644 --- a/src/components/navigation/items/ButtonItem.tsx +++ b/src/components/navigation/items/ButtonItem.tsx @@ -136,7 +136,7 @@ export const ChannelButton = observer((props: ChannelProps) => { {...divProps} data-active={active} data-alert={typeof alert === "string"} - aria-label={{}} /*FIXME: ADD ARIA LABEL*/ + aria-label={channel.name} className={classNames(styles.item, { [styles.compact]: compact })} onContextMenu={attachContextMenu("Menu", { channel: channel._id, diff --git a/src/components/ui/Modal.tsx b/src/components/ui/Modal.tsx index 4306697eda64587db1f13b7bf51bb24251070a58..d5a472347c60cb542a2dd78d85469d1264565ac6 100644 --- a/src/components/ui/Modal.tsx +++ b/src/components/ui/Modal.tsx @@ -190,7 +190,7 @@ export default function Modal(props: Props) { useEffect(() => { if (!confirmationAction) return; - // ! FIXME: this may be done better if we + // ! TODO: this may be done better if we // ! can focus the button although that // ! doesn't seem to work... function keyDown(e: KeyboardEvent) { diff --git a/src/context/Voice.tsx b/src/context/Voice.tsx index 43fbb9df1110483cd59d832e6cea2c500d5aa075..9c44a0c225e1791c15e89e3787bad6af5b058626 100644 --- a/src/context/Voice.tsx +++ b/src/context/Voice.tsx @@ -95,7 +95,7 @@ export default function Voice({ children }: Props) { return channel; } - // ! FIXME: use configuration to check if voso is enabled + // ! TODO: use configuration to check if voso is enabled // await client.connect("wss://voso.revolt.chat/ws"); await client.connect( "wss://voso.revolt.chat/ws", @@ -138,9 +138,9 @@ export default function Voice({ children }: Props) { switch (type) { case "audio": { if (client?.audioProducer !== undefined) - return console.log("No audio producer."); // ! FIXME: let the user know + return console.log("No audio producer."); // ! TODO: let the user know if (navigator.mediaDevices === undefined) - return console.log("No media devices."); // ! FIXME: let the user know + return console.log("No media devices."); // ! TODO: let the user know const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true, @@ -165,7 +165,7 @@ export default function Voice({ children }: Props) { useEffect(() => { if (!client?.supported()) return; - // ! FIXME: message for fatal: + // ! TODO: message for fatal: // ! get rid of these force updates // ! handle it through state or smth diff --git a/src/context/intermediate/popovers/UserPicker.module.scss b/src/context/intermediate/popovers/UserPicker.module.scss index 56afcf32253d95b4b51b1f5c3c8b6d3d13ab73ac..610de5a7ec568b3ef4072a764ac2ee6cc2982f09 100644 --- a/src/context/intermediate/popovers/UserPicker.module.scss +++ b/src/context/intermediate/popovers/UserPicker.module.scss @@ -4,7 +4,6 @@ max-height: 360px; overflow-y: scroll; - // ! FIXME: very temporary code > label { > span { align-items: flex-start !important; @@ -18,4 +17,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/context/revoltjs/Notifications.tsx b/src/context/revoltjs/Notifications.tsx index 719a3341ee00cfc2e23b6060b037b9f9ef6c843d..b21b6af10befebeee2579fa466e546ba5a90aec0 100644 --- a/src/context/revoltjs/Notifications.tsx +++ b/src/context/revoltjs/Notifications.tsx @@ -1,8 +1,9 @@ -import { autorun } from "mobx"; +import { autorun, reaction } from "mobx"; import { Route, Switch, useHistory, useParams } from "react-router-dom"; import { Presence, RelationshipStatus } from "revolt-api/types/Users"; import { SYSTEM_USER_ID } from "revolt.js"; import { Message } from "revolt.js/dist/maps/Messages"; +import { User } from "revolt.js/dist/maps/Users"; import { decodeTime } from "ulid"; import { useContext, useEffect } from "preact/hooks"; @@ -206,19 +207,18 @@ function Notifier({ options, notifs }: Props) { } } - /*async function relationship(user: User, property: string) { - if (client.user?.status?.presence === Users.Presence.Busy) return; - if (property !== "relationship") return; + async function relationship(user: User) { + if (client.user?.status?.presence === Presence.Busy) return; if (!showNotification) return; let event; switch (user.relationship) { - case Users.Relationship.Incoming: + case RelationshipStatus.Incoming: event = translate("notifications.sent_request", { person: user.username, }); break; - case Users.Relationship.Friend: + case RelationshipStatus.Friend: event = translate("notifications.now_friends", { person: user.username, }); @@ -236,17 +236,15 @@ function Notifier({ options, notifs }: Props) { notif?.addEventListener("click", () => { history.push(`/friends`); }); - }*/ + } useEffect(() => { - // ! FIXME: need event from client about relationship - client.addListener("message", message); - // client.users.addListener("mutation", relationship); + client.addListener("user/relationship", relationship); return () => { client.removeListener("message", message); - // client.users.removeListener("mutation", relationship); + client.removeListener("user/relationship", relationship); }; }, [client, playSound, guild_id, channel_id, showNotification, notifs]); diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index b89b7e88a78d26a9aaf423af6e6f7137b8fe7b54..5a3c4539b440fa15d4be5cc2537140f627daa1b4 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -782,11 +782,15 @@ function ContextMenus(props: Props) { break; case "TextChannel": case "VoiceChannel": - // ! FIXME: add permission for invites - generateAction({ - action: "create_invite", - target: channel, - }); + if ( + channelPermissions & + ChannelPermission.InviteOthers + ) { + generateAction({ + action: "create_invite", + target: channel, + }); + } if ( serverPermissions & diff --git a/src/pages/channels/messaging/MessageRenderer.tsx b/src/pages/channels/messaging/MessageRenderer.tsx index c30d14d8ee9a0a9f7e7ed04afc30d60be3b1b452..94f771e3cc63fd445f4b8e596f83ef1af4ea5ea2 100644 --- a/src/pages/channels/messaging/MessageRenderer.tsx +++ b/src/pages/channels/messaging/MessageRenderer.tsx @@ -2,6 +2,7 @@ import { X } from "@styled-icons/boxicons-regular"; import { RelationshipStatus } from "revolt-api/types/Users"; import { SYSTEM_USER_ID } from "revolt.js"; import { Message as MessageObject } from "revolt.js/dist/maps/Messages"; +import { Message as MessageI } from "revolt.js/dist/maps/Messages"; import styled from "styled-components"; import { decodeTime } from "ulid"; @@ -16,7 +17,7 @@ import { connectState } from "../../../redux/connector"; import { QueuedMessage } from "../../../redux/reducers/queue"; import RequiresOnline from "../../../context/revoltjs/RequiresOnline"; -import { AppContext } from "../../../context/revoltjs/RevoltClient"; +import { AppContext, useClient } from "../../../context/revoltjs/RevoltClient"; import Message from "../../../components/common/messaging/Message"; import { SystemMessage } from "../../../components/common/messaging/SystemMessage"; @@ -48,7 +49,7 @@ const BlockedMessage = styled.div` function MessageRenderer({ id, state, queue, highlight }: Props) { if (state.type !== "RENDER") return null; - const client = useContext(AppContext); + const client = useClient(); const userId = client.user!._id; const [editing, setEditing] = useState<string | undefined>(undefined); @@ -148,7 +149,6 @@ function MessageRenderer({ id, state, queue, highlight }: Props) { />, ); } else { - // ! FIXME: temp solution if (message.author?.relationship === RelationshipStatus.Blocked) { blocked++; } else { @@ -190,23 +190,24 @@ function MessageRenderer({ id, state, queue, highlight }: Props) { previous = { _id: msg.id, - data: { author: userId! }, + author_id: userId!, } as any; } - // ! FIXME: add queued messages back - /* render.push( + render.push( <Message - message={{ - ...msg.data, - replies: msg.data.replies.map((x) => x.id), - }} + message={ + new MessageI(client, { + ...msg.data, + replies: msg.data.replies.map((x) => x.id), + }) + } key={msg.id} queued={msg} head={head} attachContext />, - ); */ + ); } } else { render.push( diff --git a/src/pages/invite/Invite.tsx b/src/pages/invite/Invite.tsx index 056a464afa5164f43600a616a3fe8374899a1dea..42093065b40d987fd12294f172ee04517904915c 100644 --- a/src/pages/invite/Invite.tsx +++ b/src/pages/invite/Invite.tsx @@ -4,9 +4,11 @@ import { useHistory, useParams } from "react-router-dom"; import { RetrievedInvite } from "revolt-api/types/Invites"; import styles from "./Invite.module.scss"; +import { Text } from "preact-i18n"; import { useContext, useEffect, useState } from "preact/hooks"; import { defer } from "../../lib/defer"; +import { TextReact } from "../../lib/i18n"; import RequiresOnline from "../../context/revoltjs/RequiresOnline"; import { @@ -90,12 +92,20 @@ export default function Invite() { <h1>{invite.server_name}</h1> <h2>#{invite.channel_name}</h2> <h3> - Invited by{" "} - <UserIcon - size={24} - attachment={invite.user_avatar} - />{" "} - {invite.user_name} + <TextReact + id="app.special.invite.invited_by" + fields={{ + user: ( + <> + <UserIcon + size={24} + attachment={invite.user_avatar} + />{" "} + {invite.user_name} + </> + ), + }} + /> </h3> <Overline type="error" error={error} /> <Button @@ -140,9 +150,11 @@ export default function Invite() { setProcessing(false); } }}> - {status === ClientStatus.READY - ? "Login to Revolt" - : "Accept Invite"} + {status === ClientStatus.READY ? ( + <Text id="app.special.invite.login" /> + ) : ( + <Text id="app.special.invite.accept" /> + )} </Button> </> )} diff --git a/src/pages/settings/channel/Permissions.tsx b/src/pages/settings/channel/Permissions.tsx index 54d670538d55c50c3a13139e1711280e58a982f6..156708ee67891f974127025504281129316fa80f 100644 --- a/src/pages/settings/channel/Permissions.tsx +++ b/src/pages/settings/channel/Permissions.tsx @@ -1,25 +1,18 @@ import { observer } from "mobx-react-lite"; -import { ChannelPermission } from "revolt.js/dist/api/permissions"; +import { + ChannelPermission, + DEFAULT_PERMISSION_DM, +} from "revolt.js/dist/api/permissions"; import { Channel } from "revolt.js/dist/maps/Channels"; -import { useContext, useEffect, useState } from "preact/hooks"; +import { useEffect, useState } from "preact/hooks"; -import { AppContext, useClient } from "../../../context/revoltjs/RevoltClient"; +import { useClient } from "../../../context/revoltjs/RevoltClient"; import Button from "../../../components/ui/Button"; import Checkbox from "../../../components/ui/Checkbox"; import Tip from "../../../components/ui/Tip"; -// ! FIXME: export from revolt.js -const DEFAULT_PERMISSION_DM = - ChannelPermission.View + - ChannelPermission.SendMessage + - ChannelPermission.ManageChannel + - ChannelPermission.VoiceCall + - ChannelPermission.InviteOthers + - ChannelPermission.EmbedLinks + - ChannelPermission.UploadFiles; - interface Props { channel: Channel; } @@ -27,7 +20,6 @@ interface Props { // ! FIXME: bad code :) export default observer(({ channel }: Props) => { const [selected, setSelected] = useState("default"); - const client = useClient(); type R = { name: string; permissions: number }; const roles: { [key: string]: R } = {}; diff --git a/src/redux/reducers/queue.ts b/src/redux/reducers/queue.ts index ea3437af436616a54ae35536879abdad71cd6bc0..c4059e053c5bb564961b879a847790e1392372d2 100644 --- a/src/redux/reducers/queue.ts +++ b/src/redux/reducers/queue.ts @@ -9,6 +9,10 @@ export interface Reply { } export type QueuedMessageData = { + _id: string; + author: string; + channel: string; + content: string; replies: Reply[]; }; diff --git a/yarn.lock b/yarn.lock index 80442694d5134a805b889583ce516a686dd07ece..f95d6a072060ab94aa70dd7de45cccc0db9c8c76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3570,10 +3570,10 @@ revolt-api@0.5.1-alpha.10-patch.0: resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.1-alpha.10-patch.0.tgz#97d31bec7dfa4573567097443acb059c4feaac20" integrity sha512-UyM890HkGlYNQOxpHuEpUsJHLt8Ujnjg9/zPEDGpbvS4iy0jmHX23Hh8tOCfb/ewxbNrtT3G1HpSWKOneW/vYg== -revolt.js@5.0.0-alpha.11: - version "5.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-5.0.0-alpha.11.tgz#af131150ce37a39b979501c730ec2bee5a4e38a1" - integrity sha512-aOD8IV2DM9Ebq15FVQ2GJDGBaICppk+jP06dW0KlrDeVoE3Hra5CRLHSIRtp2mJN/vh1cH+9eA78jssAlAgwAw== +revolt.js@5.0.0-alpha.12: + version "5.0.0-alpha.12" + resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-5.0.0-alpha.12.tgz#06777f74f6a79161b18e02938a8d60d465395066" + integrity sha512-QqgawsSjrFTKhMA5JBKii6MgOJ4VO2u1GBmjTiKzPR2krnoWHdPSbD7VvD2scMGMPXIaIxU3zA++tyN8mfzIFg== dependencies: axios "^0.19.2" eventemitter3 "^4.0.7"