mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-29 02:10:59 -05:00
feat: add test emoji page
This commit is contained in:
parent
a766183f01
commit
b541301cb1
7 changed files with 205 additions and 32 deletions
|
@ -125,7 +125,7 @@
|
||||||
"preact-context-menu": "0.4.1",
|
"preact-context-menu": "0.4.1",
|
||||||
"preact-i18n": "^2.4.0-preactx",
|
"preact-i18n": "^2.4.0-preactx",
|
||||||
"prettier": "^2.3.1",
|
"prettier": "^2.3.1",
|
||||||
"prismjs": "^1.23.0",
|
"prismjs": "^1.28.0",
|
||||||
"qrcode.react": "^3.0.2",
|
"qrcode.react": "^3.0.2",
|
||||||
"react-beautiful-dnd": "^13.1.0",
|
"react-beautiful-dnd": "^13.1.0",
|
||||||
"react-device-detect": "2.2.2",
|
"react-device-detect": "2.2.2",
|
||||||
|
@ -135,7 +135,7 @@
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scroll": "^1.8.2",
|
"react-scroll": "^1.8.2",
|
||||||
"react-virtuoso": "^2.12.0",
|
"react-virtuoso": "^2.12.0",
|
||||||
"revolt.js": "6.0.3",
|
"revolt.js": "6.0.4",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sass": "^1.35.1",
|
"sass": "^1.35.1",
|
||||||
"semver": "^7.3.7",
|
"semver": "^7.3.7",
|
||||||
|
@ -156,5 +156,8 @@
|
||||||
"repository": "https://github.com/revoltchat/revite.git",
|
"repository": "https://github.com/revoltchat/revite.git",
|
||||||
"author": "Paul <paulmakles@gmail.com>",
|
"author": "Paul <paulmakles@gmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"packageManager": "yarn@3.2.0"
|
"packageManager": "yarn@3.2.0",
|
||||||
|
"resolutions": {
|
||||||
|
"@revoltchat/ui": "portal:../components"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ export default function MemberList({
|
||||||
)}
|
)}
|
||||||
{entry.type !== "no_offline" && (
|
{entry.type !== "no_offline" && (
|
||||||
<>
|
<>
|
||||||
{" - "}
|
{" – "}
|
||||||
{entry.users.length}
|
{entry.users.length}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
61
src/components/settings/customisation/EmojiUploader.tsx
Normal file
61
src/components/settings/customisation/EmojiUploader.tsx
Normal file
|
@ -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<string>();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h3>Upload Emoji</h3>
|
||||||
|
<Form
|
||||||
|
schema={{
|
||||||
|
name: "text",
|
||||||
|
file: "custom",
|
||||||
|
}}
|
||||||
|
data={{
|
||||||
|
name: {
|
||||||
|
field: "Name",
|
||||||
|
palette: "secondary",
|
||||||
|
},
|
||||||
|
file: {
|
||||||
|
element: (
|
||||||
|
<FileUploader
|
||||||
|
style="icon"
|
||||||
|
width={100}
|
||||||
|
height={100}
|
||||||
|
fileType="emojis"
|
||||||
|
behaviour="upload"
|
||||||
|
previewAfterUpload
|
||||||
|
maxFileSize={500000}
|
||||||
|
remove={async () => void setFileId("")}
|
||||||
|
onUpload={async (id) => void setFileId(id)}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
submitBtn={{
|
||||||
|
children: "Save",
|
||||||
|
palette: "secondary",
|
||||||
|
disabled: !fileId,
|
||||||
|
}}
|
||||||
|
onSubmit={async ({ name }) => {
|
||||||
|
await server.client.api.put(`/custom/emoji/${fileId}`, {
|
||||||
|
name,
|
||||||
|
parent: { type: "Server", id: server._id },
|
||||||
|
});
|
||||||
|
|
||||||
|
setFileId("");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -17,7 +17,11 @@ import { takeError } from "../error";
|
||||||
|
|
||||||
type BehaviourType =
|
type BehaviourType =
|
||||||
| { behaviour: "ask"; onChange: (file: File) => void }
|
| { behaviour: "ask"; onChange: (file: File) => void }
|
||||||
| { behaviour: "upload"; onUpload: (id: string) => Promise<void> }
|
| {
|
||||||
|
behaviour: "upload";
|
||||||
|
onUpload: (id: string) => Promise<void>;
|
||||||
|
previewAfterUpload?: boolean;
|
||||||
|
}
|
||||||
| {
|
| {
|
||||||
behaviour: "multi";
|
behaviour: "multi";
|
||||||
onChange: (files: File[]) => void;
|
onChange: (files: File[]) => void;
|
||||||
|
@ -48,7 +52,8 @@ type Props = BehaviourType &
|
||||||
| "icons"
|
| "icons"
|
||||||
| "avatars"
|
| "avatars"
|
||||||
| "attachments"
|
| "attachments"
|
||||||
| "banners";
|
| "banners"
|
||||||
|
| "emojis";
|
||||||
maxFileSize: number;
|
maxFileSize: number;
|
||||||
remove: () => Promise<void>;
|
remove: () => Promise<void>;
|
||||||
};
|
};
|
||||||
|
@ -114,6 +119,17 @@ export function FileUploader(props: Props) {
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
|
|
||||||
const [uploading, setUploading] = useState(false);
|
const [uploading, setUploading] = useState(false);
|
||||||
|
const [previewFile, setPreviewFile] = useState<File>(null!);
|
||||||
|
const [generatedPreviewURL, setGeneratedPreviewURL] = useState("");
|
||||||
|
useEffect(() => {
|
||||||
|
if (previewFile) {
|
||||||
|
const url: string = URL.createObjectURL(previewFile);
|
||||||
|
setGeneratedPreviewURL(url);
|
||||||
|
return () => URL.revokeObjectURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
setGeneratedPreviewURL("");
|
||||||
|
}, [previewFile]);
|
||||||
|
|
||||||
function onClick() {
|
function onClick() {
|
||||||
if (uploading) return;
|
if (uploading) return;
|
||||||
|
@ -136,6 +152,10 @@ export function FileUploader(props: Props) {
|
||||||
files[0],
|
files[0],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (props.previewAfterUpload) {
|
||||||
|
setPreviewFile(files[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return modalController.push({
|
return modalController.push({
|
||||||
|
@ -164,7 +184,11 @@ export function FileUploader(props: Props) {
|
||||||
} else {
|
} else {
|
||||||
onClick();
|
onClick();
|
||||||
}
|
}
|
||||||
} else if (props.previewURL) {
|
} else if (props.previewURL || previewFile) {
|
||||||
|
if (previewFile) {
|
||||||
|
setPreviewFile(null!);
|
||||||
|
}
|
||||||
|
|
||||||
props.remove();
|
props.remove();
|
||||||
} else {
|
} else {
|
||||||
onClick();
|
onClick();
|
||||||
|
@ -266,7 +290,11 @@ export function FileUploader(props: Props) {
|
||||||
style={{
|
style={{
|
||||||
backgroundImage:
|
backgroundImage:
|
||||||
style === "icon"
|
style === "icon"
|
||||||
? `url('${previewURL ?? defaultPreview}')`
|
? `url('${
|
||||||
|
generatedPreviewURL ??
|
||||||
|
previewURL ??
|
||||||
|
defaultPreview
|
||||||
|
}')`
|
||||||
: previewURL
|
: previewURL
|
||||||
? `linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url('${previewURL}')`
|
? `linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url('${previewURL}')`
|
||||||
: "none",
|
: "none",
|
||||||
|
@ -288,7 +316,7 @@ export function FileUploader(props: Props) {
|
||||||
<span onClick={removeOrUpload}>
|
<span onClick={removeOrUpload}>
|
||||||
{uploading ? (
|
{uploading ? (
|
||||||
<Text id="app.main.channel.uploading_file" />
|
<Text id="app.main.channel.uploading_file" />
|
||||||
) : props.previewURL ? (
|
) : props.previewURL || previewFile ? (
|
||||||
<Text id="app.settings.actions.remove" />
|
<Text id="app.settings.actions.remove" />
|
||||||
) : (
|
) : (
|
||||||
<Text id="app.settings.actions.upload" />
|
<Text id="app.settings.actions.upload" />
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
Envelope,
|
Envelope,
|
||||||
UserX,
|
UserX,
|
||||||
Trash,
|
Trash,
|
||||||
|
HappyBeaming,
|
||||||
} from "@styled-icons/boxicons-solid";
|
} from "@styled-icons/boxicons-solid";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Route, Switch, useHistory, useParams } from "react-router-dom";
|
import { Route, Switch, useHistory, useParams } from "react-router-dom";
|
||||||
|
@ -22,6 +23,7 @@ import { modalController } from "../../controllers/modals/ModalController";
|
||||||
import { GenericSettings } from "./GenericSettings";
|
import { GenericSettings } from "./GenericSettings";
|
||||||
import { Bans } from "./server/Bans";
|
import { Bans } from "./server/Bans";
|
||||||
import { Categories } from "./server/Categories";
|
import { Categories } from "./server/Categories";
|
||||||
|
import { Emojis } from "./server/Emojis";
|
||||||
import { Invites } from "./server/Invites";
|
import { Invites } from "./server/Invites";
|
||||||
import { Members } from "./server/Members";
|
import { Members } from "./server/Members";
|
||||||
import { Overview } from "./server/Overview";
|
import { Overview } from "./server/Overview";
|
||||||
|
@ -68,6 +70,14 @@ export default observer(() => {
|
||||||
title: <Text id="app.settings.server_pages.roles.title" />,
|
title: <Text id="app.settings.server_pages.roles.title" />,
|
||||||
hideTitle: true,
|
hideTitle: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
category: (
|
||||||
|
<Text id="app.settings.server_pages.customisation.title" />
|
||||||
|
),
|
||||||
|
id: "emojis",
|
||||||
|
icon: <HappyBeaming size={20} />,
|
||||||
|
title: <Text id="app.settings.server_pages.emojis.title" />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
category: (
|
category: (
|
||||||
<Text id="app.settings.server_pages.management.title" />
|
<Text id="app.settings.server_pages.management.title" />
|
||||||
|
@ -116,6 +126,11 @@ export default observer(() => {
|
||||||
<Roles server={server} />
|
<Roles server={server} />
|
||||||
</RequiresOnline>
|
</RequiresOnline>
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route path="/server/:server/settings/emojis">
|
||||||
|
<RequiresOnline>
|
||||||
|
<Emojis server={server} />
|
||||||
|
</RequiresOnline>
|
||||||
|
</Route>
|
||||||
<Route>
|
<Route>
|
||||||
<Overview server={server} />
|
<Overview server={server} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
74
src/pages/settings/server/Emojis.tsx
Normal file
74
src/pages/settings/server/Emojis.tsx
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { Server } from "revolt.js";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
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)`
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
background: var(--secondary-background);
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Preview = styled.img`
|
||||||
|
width: 72px;
|
||||||
|
height: 72px;
|
||||||
|
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.id === server._id,
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Column>
|
||||||
|
<EmojiUploader server={server} />
|
||||||
|
<h3>Emojis – {emoji.length}</h3>
|
||||||
|
<List>
|
||||||
|
{emoji.map((emoji) => (
|
||||||
|
<Emoji key={emoji._id} centred>
|
||||||
|
<Stacked>
|
||||||
|
<Preview src={emoji.imageURL} />
|
||||||
|
</Stacked>
|
||||||
|
<span>{`:${emoji.name}:`}</span>
|
||||||
|
<UserInfo centred>
|
||||||
|
<UserShort user={emoji.creator} />
|
||||||
|
</UserInfo>
|
||||||
|
<Button
|
||||||
|
palette="plain"
|
||||||
|
onClick={() =>
|
||||||
|
modalController.writeText(emoji._id)
|
||||||
|
}>
|
||||||
|
Copy ID
|
||||||
|
</Button>
|
||||||
|
</Emoji>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
});
|
38
yarn.lock
38
yarn.lock
|
@ -2231,9 +2231,9 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@revoltchat/ui@npm:1.0.69":
|
"@revoltchat/ui@portal:../components::locator=client%40workspace%3A.":
|
||||||
version: 1.0.69
|
version: 0.0.0-use.local
|
||||||
resolution: "@revoltchat/ui@npm:1.0.69"
|
resolution: "@revoltchat/ui@portal:../components::locator=client%40workspace%3A."
|
||||||
dependencies:
|
dependencies:
|
||||||
"@styled-icons/boxicons-logos": ^10.38.0
|
"@styled-icons/boxicons-logos": ^10.38.0
|
||||||
"@styled-icons/boxicons-regular": ^10.38.0
|
"@styled-icons/boxicons-regular": ^10.38.0
|
||||||
|
@ -2247,9 +2247,8 @@ __metadata:
|
||||||
react-virtuoso: ^2.12.0
|
react-virtuoso: ^2.12.0
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
revolt.js: "*"
|
revolt.js: "*"
|
||||||
checksum: bb67870911689d7dccd82f96affdb0e3e89b2e688d4a7403ee9bbb6a0245dfc296f35636ababd5ed6b43a3ce26777cee03c453728088b4a29fed350dcc89ea37
|
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: soft
|
||||||
|
|
||||||
"@rollup/plugin-babel@npm:^5.2.0":
|
"@rollup/plugin-babel@npm:^5.2.0":
|
||||||
version: 5.3.0
|
version: 5.3.0
|
||||||
|
@ -3608,7 +3607,7 @@ __metadata:
|
||||||
preact-context-menu: 0.4.1
|
preact-context-menu: 0.4.1
|
||||||
preact-i18n: ^2.4.0-preactx
|
preact-i18n: ^2.4.0-preactx
|
||||||
prettier: ^2.3.1
|
prettier: ^2.3.1
|
||||||
prismjs: ^1.23.0
|
prismjs: ^1.28.0
|
||||||
qrcode.react: ^3.0.2
|
qrcode.react: ^3.0.2
|
||||||
react-beautiful-dnd: ^13.1.0
|
react-beautiful-dnd: ^13.1.0
|
||||||
react-device-detect: 2.2.2
|
react-device-detect: 2.2.2
|
||||||
|
@ -3618,7 +3617,7 @@ __metadata:
|
||||||
react-router-dom: ^5.2.0
|
react-router-dom: ^5.2.0
|
||||||
react-scroll: ^1.8.2
|
react-scroll: ^1.8.2
|
||||||
react-virtuoso: ^2.12.0
|
react-virtuoso: ^2.12.0
|
||||||
revolt.js: 6.0.3
|
revolt.js: 6.0.4
|
||||||
rimraf: ^3.0.2
|
rimraf: ^3.0.2
|
||||||
sass: ^1.35.1
|
sass: ^1.35.1
|
||||||
semver: ^7.3.7
|
semver: ^7.3.7
|
||||||
|
@ -6546,13 +6545,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"prismjs@npm:^1.23.0":
|
|
||||||
version: 1.24.1
|
|
||||||
resolution: "prismjs@npm:1.24.1"
|
|
||||||
checksum: e5d14a4ba56773122039295bd760c72106acc964e04cb9831b9ae7e7a58f67ccac6c053e77e21f1018a3684f31d35bb065c0c81fd4ff00b73b1570c3ace4aef0
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"prismjs@npm:^1.28.0":
|
"prismjs@npm:^1.28.0":
|
||||||
version: 1.28.0
|
version: 1.28.0
|
||||||
resolution: "prismjs@npm:1.28.0"
|
resolution: "prismjs@npm:1.28.0"
|
||||||
|
@ -6995,20 +6987,20 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"revolt-api@npm:0.5.3-7":
|
"revolt-api@npm:0.5.4":
|
||||||
version: 0.5.3-7
|
version: 0.5.4
|
||||||
resolution: "revolt-api@npm:0.5.3-7"
|
resolution: "revolt-api@npm:0.5.4"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@insertish/oapi": 0.1.16
|
"@insertish/oapi": 0.1.16
|
||||||
axios: ^0.26.1
|
axios: ^0.26.1
|
||||||
lodash.defaultsdeep: ^4.6.1
|
lodash.defaultsdeep: ^4.6.1
|
||||||
checksum: acc2f412d1be90f0cfa8a24ba715d8257813762c56ba0e48c649efff349674517036a8fa5939eda61ce31fd64a37f0c54af3d8fae56edf4596f05b10304e090e
|
checksum: bd40acabac1b6c5848b1d6e555297de5aa3e0950a4de67523c4cf986a8037380e3addc5e16babebc8dfa6570cd1d1957efe9a3aaa6a206b9286e5b7f5941d699
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"revolt.js@npm:6.0.3":
|
"revolt.js@npm:6.0.4":
|
||||||
version: 6.0.3
|
version: 6.0.4
|
||||||
resolution: "revolt.js@npm:6.0.3"
|
resolution: "revolt.js@npm:6.0.4"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@insertish/exponential-backoff": 3.1.0-patch.2
|
"@insertish/exponential-backoff": 3.1.0-patch.2
|
||||||
"@insertish/isomorphic-ws": ^4.0.1
|
"@insertish/isomorphic-ws": ^4.0.1
|
||||||
|
@ -7019,10 +7011,10 @@ __metadata:
|
||||||
lodash.isequal: ^4.5.0
|
lodash.isequal: ^4.5.0
|
||||||
long: ^5.2.0
|
long: ^5.2.0
|
||||||
mobx: ^6.3.2
|
mobx: ^6.3.2
|
||||||
revolt-api: 0.5.3-7
|
revolt-api: 0.5.4
|
||||||
ulid: ^2.3.0
|
ulid: ^2.3.0
|
||||||
ws: ^8.2.2
|
ws: ^8.2.2
|
||||||
checksum: cfecbde7a9b795da75bfac3cec05f2aed5fd02cd14fcac1b2fad26285de1b887cf7ccb339e8a63a019f1e83058b041305927e029d7b5eedcc00823582d9a842a
|
checksum: 7e203388c3ca8d715c4fb5b18871f97a8b966ae080bed52b9cdc6f77fdaceafe56085076f55b5cc3a9380de70fffb5b575a5e25a69792d5cb9bfd02c7e0ed426
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue