diff --git a/external/components b/external/components
index 5e6e4a09..55709411 160000
--- a/external/components
+++ b/external/components
@@ -1 +1 @@
-Subproject commit 5e6e4a09c45baf18dcc44925f0113bad1d732e9c
+Subproject commit 557094115d17a363eb6fb8f27c6e697e049ce623
diff --git a/external/lang b/external/lang
index 8ec1e557..05e7213b 160000
--- a/external/lang
+++ b/external/lang
@@ -1 +1 @@
-Subproject commit 8ec1e5571e3d29a93500c0199f6823d16056b6f8
+Subproject commit 05e7213b2290dfced3d41d54cb85f49670404cf2
diff --git a/src/components/common/messaging/attachments/Reactions.tsx b/src/components/common/messaging/attachments/Reactions.tsx
index 10abd2e6..9d8f0471 100644
--- a/src/components/common/messaging/attachments/Reactions.tsx
+++ b/src/components/common/messaging/attachments/Reactions.tsx
@@ -4,12 +4,15 @@ import {
shift,
useFloating,
} from "@floating-ui/react-dom-interactions";
+import { Plus } from "@styled-icons/boxicons-regular";
import { observer } from "mobx-react-lite";
import { Message } from "revolt.js";
import styled, { css } from "styled-components";
import { createPortal } from "preact/compat";
-import { useCallback, useRef } from "preact/hooks";
+import { useCallback, useRef, useState } from "preact/hooks";
+
+import { IconButton } from "@revoltchat/ui";
import { emojiDictionary } from "../../../../assets/emojis";
import { useClient } from "../../../../controllers/client/ClientController";
@@ -29,6 +32,14 @@ const List = styled.div`
flex-wrap: wrap;
margin-top: 0.2em;
align-items: center;
+
+ .add {
+ display: none;
+ }
+
+ &:hover .add {
+ display: grid;
+ }
`;
/**
@@ -79,6 +90,7 @@ const Reaction = styled.div<{ active: boolean }>`
*/
export const Reactions = observer(({ message }: Props) => {
const client = useClient();
+ const [showPicker, setPicker] = useState(false);
/**
* Render individual reaction entries
@@ -137,6 +149,16 @@ export const Reactions = observer(({ message }: Props) => {
{Array.from(optional, (id) => (
))}
+ {message.channel?.havePermission("React") && (
+
+
+
+
+
+ )}
);
});
diff --git a/src/components/markdown/RemarkRenderer.tsx b/src/components/markdown/RemarkRenderer.tsx
index 94280028..c826dbdc 100644
--- a/src/components/markdown/RemarkRenderer.tsx
+++ b/src/components/markdown/RemarkRenderer.tsx
@@ -184,6 +184,11 @@ const Container = styled.div<{ largeEmoji: boolean }>`
*/
const RE_QUOTE = /(^(?:>\s?){5})[>\s?]+(.*$)/gm;
+/**
+ * Regex for matching multi-line blockquotes
+ */
+const RE_BLOCKQUOTE = /^([^\S\r\n]*>[^\n]+\n?)+/gm;
+
/**
* Regex for matching HTML tags
*/
@@ -214,6 +219,9 @@ function sanitise(content: string) {
// because remark renderer is collapsing empty
// or otherwise whitespace-only lines of text
.replace(RE_EMPTY_LINE, "")
+
+ // Ensure empty line after blockquotes for correct rendering
+ .replace(RE_BLOCKQUOTE, (match) => `${match}\n`)
);
}
diff --git a/src/components/settings/customisation/EmojiUploader.tsx b/src/components/settings/customisation/EmojiUploader.tsx
index 4a1b42c5..108fc27c 100644
--- a/src/components/settings/customisation/EmojiUploader.tsx
+++ b/src/components/settings/customisation/EmojiUploader.tsx
@@ -1,8 +1,9 @@
import { Server } from "revolt.js";
+import { Text } from "preact-i18n";
import { useState } from "preact/hooks";
-import { Form } from "@revoltchat/ui";
+import { Button, Column, Form, FormElement, Row } from "@revoltchat/ui";
import { FileUploader } from "../../../controllers/client/jsx/legacy/FileUploads";
@@ -15,7 +16,9 @@ export function EmojiUploader({ server }: Props) {
return (
<>
-
Upload Emoji
+
+
+
>
);
}
diff --git a/src/pages/settings/server/Emojis.tsx b/src/pages/settings/server/Emojis.tsx
index d5f4b3d1..0dd3cf1d 100644
--- a/src/pages/settings/server/Emojis.tsx
+++ b/src/pages/settings/server/Emojis.tsx
@@ -8,40 +8,24 @@ import { Button, Column, Row, Stacked } from "@revoltchat/ui";
import UserShort from "../../../components/common/user/UserShort";
import { EmojiUploader } from "../../../components/settings/customisation/EmojiUploader";
-import { modalController } from "../../../controllers/modals/ModalController";
interface Props {
server: Server;
}
-const List = styled.div`
- gap: 8px;
- display: flex;
- flex-wrap: wrap;
-`;
-
-const Emoji = styled(Column)`
+const Emoji = styled(Row)`
padding: 8px;
border-radius: var(--border-radius);
background: var(--secondary-background);
`;
const Preview = styled.img`
- width: 72px;
- height: 72px;
+ width: 32px;
+ height: 32px;
object-fit: contain;
border-radius: var(--border-radius);
`;
-const UserInfo = styled(Row)`
- font-size: 12px;
-
- svg {
- width: 14px;
- height: 14px;
- }
-`;
-
export const Emojis = observer(({ server }: Props) => {
const emoji = [...server.client.emojis.values()].filter(
(x) => x.parent.type === "Server" && x.parent.id === server._id,
@@ -57,33 +41,22 @@ export const Emojis = observer(({ server }: Props) => {
{" – "}
{emoji.length}
-
- {emoji.map((emoji) => (
-
-
-
-
- {`:${emoji.name}:`}
-
-
-
-
+ )}
+
+ ))}
);
});