diff --git a/external/lang b/external/lang
index d4bc47b7..58408da6 160000
--- a/external/lang
+++ b/external/lang
@@ -1 +1 @@
-Subproject commit d4bc47b729c7e69ce97216469692b39f4cd1640e
+Subproject commit 58408da6c4090dd3a7808a663eaa95b8b1da7603
diff --git a/package.json b/package.json
index 77435e5e..7e89c29a 100644
--- a/package.json
+++ b/package.json
@@ -73,7 +73,7 @@
"@hcaptcha/react-hcaptcha": "^0.3.6",
"@insertish/vite-plugin-babel-macros": "^1.0.5",
"@preact/preset-vite": "^2.0.0",
- "@revoltchat/ui": "1.0.70",
+ "@revoltchat/ui": "1.0.72",
"@rollup/plugin-replace": "^2.4.2",
"@styled-icons/boxicons-logos": "^10.38.0",
"@styled-icons/boxicons-regular": "^10.38.0",
@@ -123,7 +123,7 @@
"preact-context-menu": "0.4.1",
"preact-i18n": "^2.4.0-preactx",
"prettier": "^2.3.1",
- "prismjs": "^1.23.0",
+ "prismjs": "^1.28.0",
"qrcode.react": "^3.0.2",
"react-beautiful-dnd": "^13.1.0",
"react-device-detect": "2.2.2",
diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx
index cdae5341..7b76aef9 100644
--- a/src/components/common/messaging/MessageBox.tsx
+++ b/src/components/common/messaging/MessageBox.tsx
@@ -7,13 +7,7 @@ import { ulid } from "ulid";
import { Text } from "preact-i18n";
import { memo } from "preact/compat";
-import {
- useCallback,
- useContext,
- useEffect,
- useMemo,
- useState,
-} from "preact/hooks";
+import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
import { IconButton, Picker } from "@revoltchat/ui";
@@ -28,7 +22,7 @@ import {
SMOOTH_SCROLL_ON_RECEIVE,
} from "../../../lib/renderer/Singleton";
-import { useApplicationState } from "../../../mobx/State";
+import { state, useApplicationState } from "../../../mobx/State";
import { Reply } from "../../../mobx/stores/MessageQueue";
import { emojiDictionary } from "../../../assets/emojis";
@@ -40,8 +34,8 @@ import {
uploadFile,
} from "../../../controllers/client/jsx/legacy/FileUploads";
import { modalController } from "../../../controllers/modals/ModalController";
+import { RenderEmoji } from "../../markdown/plugins/emoji";
import AutoComplete, { useAutoComplete } from "../AutoComplete";
-import Emoji from "../Emoji";
import { PermissionTooltip } from "../Tooltip";
import FilePreview from "./bars/FilePreview";
import ReplyBar from "./bars/ReplyBar";
@@ -149,6 +143,56 @@ const RE_SED = new RegExp("^s/([^])*/([^])*$");
// Tests for code block delimiters (``` at start of line)
const RE_CODE_DELIMITER = new RegExp("^```", "gm");
+const HackAlertThisFileWillBeReplaced = observer(({ channel }: Props) => {
+ const renderEmoji = useMemo(
+ () =>
+ memo(({ emoji }: { emoji: string }) => (
+ {
+ const v = state.draft.get(channel._id);
+ state.draft.set(
+ channel._id,
+ `${v ? `${v} ` : ""}:${emoji}:`,
+ );
+ }}>
+
+
+ )),
+ [],
+ );
+
+ const emojis: Record = {
+ default: Object.keys(emojiDictionary),
+ };
+
+ // ! FIXME: also expose typing from component
+ const categories: any[] = [];
+
+ for (const server of state.ordering.orderedServers) {
+ // ! FIXME: add a separate map on each server for emoji
+ const list = [...channel.client.emojis.values()]
+ .filter((emoji) => emoji.parent.id === server._id)
+ .map((x) => x._id);
+
+ if (list.length > 0) {
+ emojis[server._id] = list;
+ categories.push({
+ id: server._id,
+ name: server.name,
+ iconURL: server.generateIconURL({ max_side: 256 }),
+ });
+ }
+ }
+
+ return (
+
+ );
+});
+
// ! FIXME: add to app config and load from app config
export const CAN_UPLOAD_AT_ONCE = 5;
@@ -312,6 +356,7 @@ export default observer(({ channel }: Props) => {
async function sendFile(content: string) {
if (uploadState.type !== "attached") return;
const attachments: string[] = [];
+ setMessage;
const cancel = Axios.CancelToken.source();
const files = uploadState.files;
@@ -470,26 +515,6 @@ export default observer(({ channel }: Props) => {
: undefined,
});
- const renderEmoji = useMemo(
- () =>
- memo(({ emoji }: { emoji: string }) => (
- {
- const v = state.draft.get(channel._id);
- setMessage(`${v ? `${v} ` : ""}:${emoji}:`);
- }}>
-
-
- )),
- [],
- );
-
return (
<>
@@ -533,10 +558,7 @@ export default observer(({ channel }: Props) => {
/>
{picker && (
-
+
)}
@@ -659,11 +681,6 @@ export default observer(({ channel }: Props) => {
onFocus={onFocus}
onBlur={onBlur}
/>
- {/*
-
-
-
- */}
{state.experiments.isEnabled("picker") && (
setPicker(!picker)}>
diff --git a/src/components/common/user/UserBadges.tsx b/src/components/common/user/UserBadges.tsx
index b8c36e44..b14d8c6a 100644
--- a/src/components/common/user/UserBadges.tsx
+++ b/src/components/common/user/UserBadges.tsx
@@ -16,6 +16,7 @@ enum Badges {
Paw = 128,
EarlyAdopter = 256,
ReservedRelevantJokeBadge1 = 512,
+ ReservedRelevantJokeBadge2 = 1024,
}
const BadgesBase = styled.div`
@@ -135,6 +136,13 @@ export default function UserBadges({ badges, uid }: Props) {
) : (
<>>
)}
+ {badges & Badges.ReservedRelevantJokeBadge2 ? (
+
+
+
+ ) : (
+ <>>
+ )}
{badges & Badges.Paw ? (
diff --git a/src/components/markdown/RemarkRenderer.tsx b/src/components/markdown/RemarkRenderer.tsx
index 26f03b37..02ac472a 100644
--- a/src/components/markdown/RemarkRenderer.tsx
+++ b/src/components/markdown/RemarkRenderer.tsx
@@ -180,7 +180,7 @@ const Container = styled.div<{ largeEmoji: boolean }>`
/**
* Regex for matching execessive blockquotes
*/
-const RE_QUOTE = /(^[>\s][>\s])[>\s]+([^]+$)/gm;
+const RE_QUOTE = /(^(?:>\s){3})[>\s]+(.*$)/gm;
/**
* Regex for matching open angled bracket
diff --git a/src/components/markdown/plugins/emoji.tsx b/src/components/markdown/plugins/emoji.tsx
index f97e85bc..033af2de 100644
--- a/src/components/markdown/plugins/emoji.tsx
+++ b/src/components/markdown/plugins/emoji.tsx
@@ -15,15 +15,19 @@ const Emoji = styled.img`
`;
export function RenderEmoji({ match }: CustomComponentProps) {
+ const url =
+ match in emojiDictionary
+ ? parseEmoji(emojiDictionary[match as keyof typeof emojiDictionary])
+ : clientController.getAvailableClient().emojis!.get(match)!
+ .imageURL;
+
return (
);
}
diff --git a/src/components/navigation/right/MemberList.tsx b/src/components/navigation/right/MemberList.tsx
index 3913c20b..1163fea5 100644
--- a/src/components/navigation/right/MemberList.tsx
+++ b/src/components/navigation/right/MemberList.tsx
@@ -99,7 +99,7 @@ export default function MemberList({
)}
{entry.type !== "no_offline" && (
<>
- {" - "}
+ {" – "}
{entry.users.length}
>
)}
diff --git a/src/components/settings/customisation/EmojiUploader.tsx b/src/components/settings/customisation/EmojiUploader.tsx
new file mode 100644
index 00000000..4a1b42c5
--- /dev/null
+++ b/src/components/settings/customisation/EmojiUploader.tsx
@@ -0,0 +1,61 @@
+import { Server } from "revolt.js";
+
+import { useState } from "preact/hooks";
+
+import { Form } from "@revoltchat/ui";
+
+import { FileUploader } from "../../../controllers/client/jsx/legacy/FileUploads";
+
+interface Props {
+ server: Server;
+}
+
+export function EmojiUploader({ server }: Props) {
+ const [fileId, setFileId] = useState();
+
+ return (
+ <>
+ Upload Emoji
+