diff --git a/external/lang b/external/lang index b40f8ce53831a590c0ffdd02f8da9fd35b7a3701..ab87bdcf15d60cfb6f3bd52af445456e5fd23e5f 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit b40f8ce53831a590c0ffdd02f8da9fd35b7a3701 +Subproject commit ab87bdcf15d60cfb6f3bd52af445456e5fd23e5f diff --git a/package.json b/package.json index c2d8fb9d09fd43dfbd5a70a93174d30d7e2b1fe1..4a44f8bec988c958d43fd6902ae5dd322e8979a8 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "react-router-dom": "^5.2.0", "react-scroll": "^1.8.2", "redux": "^4.1.0", - "revolt.js": "4.3.3-alpha.17", + "revolt.js": "^4.3.3-alpha.18", "rimraf": "^3.0.2", "sass": "^1.35.1", "shade-blend-color": "^1.0.0", diff --git a/src/components/common/messaging/MessageBase.tsx b/src/components/common/messaging/MessageBase.tsx index 04c3d1d9e589092fe949c528bea8fff8c079f73d..a42f62fb4254c182ad06d88678d5ee65d754c978 100644 --- a/src/components/common/messaging/MessageBase.tsx +++ b/src/components/common/messaging/MessageBase.tsx @@ -172,9 +172,9 @@ export const MessageContent = styled.div` flex-grow: 1; display: flex; // overflow: hidden; - font-size: var(--text-size); flex-direction: column; justify-content: center; + font-size: var(--text-size); `; export const DetailBase = styled.div` diff --git a/src/components/ui/Tip.tsx b/src/components/ui/Tip.tsx index 23621168c77249a94db191e48ac7b84b2d3f97d2..2748cb49bc35b6f22d15f0fc2b235f196eeacc72 100644 --- a/src/components/ui/Tip.tsx +++ b/src/components/ui/Tip.tsx @@ -55,11 +55,13 @@ export const TipBase = styled.div<Props>` `} `; -export default function Tip(props: Props & { children: Children }) { - const { children, ...tipProps } = props; +export default function Tip( + props: Props & { children: Children; hideSeparator?: boolean }, +) { + const { children, hideSeparator, ...tipProps } = props; return ( <> - <Separator /> + {!hideSeparator && <Separator />} <TipBase {...tipProps}> <InfoCircle size={20} /> <span>{props.children}</span> diff --git a/src/pages/settings/ServerSettings.tsx b/src/pages/settings/ServerSettings.tsx index 66c6881d40d0823c449051943cca2a9552af2374..dca442201808c16714cc7acbeebfc47fe09fc1c4 100644 --- a/src/pages/settings/ServerSettings.tsx +++ b/src/pages/settings/ServerSettings.tsx @@ -1,4 +1,4 @@ -import { ListUl, ListCheck } from "@styled-icons/boxicons-regular"; +import { ListUl, ListCheck, ListMinus } from "@styled-icons/boxicons-regular"; import { XSquare, Share, Group } from "@styled-icons/boxicons-solid"; import { Route, useHistory, useParams } from "react-router-dom"; @@ -11,6 +11,7 @@ import Category from "../../components/ui/Category"; import { GenericSettings } from "./GenericSettings"; import { Bans } from "./server/Bans"; +import { Categories } from "./server/Categories"; import { Invites } from "./server/Invites"; import { Members } from "./server/Members"; import { Overview } from "./server/Overview"; @@ -41,6 +42,13 @@ export default function ServerSettings() { <Text id="app.settings.server_pages.overview.title" /> ), }, + { + id: "categories", + icon: <ListMinus size={20} />, + title: ( + <Text id="app.settings.server_pages.categories.title" /> + ), + }, { id: "members", icon: <Group size={20} />, @@ -68,6 +76,9 @@ export default function ServerSettings() { }, ]} children={[ + <Route path="/server/:server/settings/categories"> + <Categories server={server} /> + </Route>, <Route path="/server/:server/settings/members"> <RequiresOnline> <Members server={server} /> diff --git a/src/pages/settings/channel/Permissions.tsx b/src/pages/settings/channel/Permissions.tsx index 5a933c3268310005fd2639b43c57385e26ef1eaa..963694ae00c87ede7027fe37ff77b22429e0099d 100644 --- a/src/pages/settings/channel/Permissions.tsx +++ b/src/pages/settings/channel/Permissions.tsx @@ -83,8 +83,10 @@ export default function Permissions({ channel }: Props) { </Checkbox> ); })} - <h2>channel per??issions</h2> + <h2>channel permissions</h2> {Object.keys(ChannelPermission).map((perm) => { + if (perm === "View") return null; + const value = ChannelPermission[perm as keyof typeof ChannelPermission]; if (value & DEFAULT_PERMISSION_DM) { diff --git a/src/pages/settings/server/Categories.tsx b/src/pages/settings/server/Categories.tsx new file mode 100644 index 0000000000000000000000000000000000000000..8f35bcf17d540317d3314ae90e0aa93a63263a2c --- /dev/null +++ b/src/pages/settings/server/Categories.tsx @@ -0,0 +1,153 @@ +import { XCircle } from "@styled-icons/boxicons-regular"; +import isEqual from "lodash.isequal"; +import { Channels, Servers, Users } from "revolt.js/dist/api/objects"; +import { Route } from "revolt.js/dist/api/routes"; +import { ulid } from "ulid"; + +import styles from "./Panes.module.scss"; +import { Text } from "preact-i18n"; +import { useContext, useEffect, useState } from "preact/hooks"; + +import { AppContext } from "../../../context/revoltjs/RevoltClient"; +import { useChannels } from "../../../context/revoltjs/hooks"; + +import ChannelIcon from "../../../components/common/ChannelIcon"; +import UserIcon from "../../../components/common/user/UserIcon"; +import Button from "../../../components/ui/Button"; +import ComboBox from "../../../components/ui/ComboBox"; +import IconButton from "../../../components/ui/IconButton"; +import InputBox from "../../../components/ui/InputBox"; +import Preloader from "../../../components/ui/Preloader"; +import Tip from "../../../components/ui/Tip"; + +interface Props { + server: Servers.Server; +} + +// ! FIXME: really bad code +export function Categories({ server }: Props) { + const client = useContext(AppContext); + const channels = useChannels(server.channels) as ( + | Channels.TextChannel + | Channels.VoiceChannel + )[]; + + const [cats, setCats] = useState<Servers.Category[]>( + server.categories ?? [], + ); + + const [name, setName] = useState(""); + + return ( + <div> + <Tip warning>This section is under construction.</Tip> + <p> + <Button + contrast + disabled={isEqual(server.categories ?? [], cats)} + onClick={() => + client.servers.edit(server._id, { categories: cats }) + }> + save categories + </Button> + </p> + <h2>categories</h2> + {cats.map((category) => ( + <div style={{ background: "var(--hover)" }} key={category.id}> + <InputBox + value={category.title} + onChange={(e) => + setCats( + cats.map((y) => + y.id === category.id + ? { + ...y, + title: e.currentTarget.value, + } + : y, + ), + ) + } + contrast + /> + <Button + contrast + onClick={() => + setCats(cats.filter((x) => x.id !== category.id)) + }> + delete {category.title} + </Button> + </div> + ))} + <h2>create new</h2> + <p> + <InputBox + value={name} + onChange={(e) => setName(e.currentTarget.value)} + contrast + /> + <Button + contrast + onClick={() => { + setName(""); + setCats([ + ...cats, + { + id: ulid(), + title: name, + channels: [], + }, + ]); + }}> + create + </Button> + </p> + <h2>channels</h2> + {channels.map((channel) => { + return ( + <div + style={{ + display: "flex", + gap: "12px", + alignItems: "center", + }}> + <div style={{ flexShrink: 0 }}> + <ChannelIcon target={channel} size={24} />{" "} + <span>{channel.name}</span> + </div> + <ComboBox + style={{ flexGrow: 1 }} + value={ + cats.find((x) => + x.channels.includes(channel._id), + )?.id ?? "none" + } + onChange={(e) => + setCats( + cats.map((x) => { + return { + ...x, + channels: [ + ...x.channels.filter( + (y) => y !== channel._id, + ), + ...(e.currentTarget.value === + x.id + ? [channel._id] + : []), + ], + }; + }), + ) + }> + <option value="none">Uncategorised</option> + {cats.map((x) => ( + <option value={x.id}>{x.title}</option> + ))} + </ComboBox> + </div> + ); + })} + </div> + ); +} diff --git a/src/revision.ts b/src/revision.ts index b9bf0d03d0bfa41988fe1a0d04430ca5e880acc2..11f7128746ac3ef266c2b58975d70bf16eef9ab2 100644 --- a/src/revision.ts +++ b/src/revision.ts @@ -1,3 +1,4 @@ -export const REPO_URL = "https://gitlab.insrt.uk/revolt/revite/-/commit"; -export const GIT_REVISION = "__GIT_REVISION__"; -export const GIT_BRANCH = "__GIT_BRANCH__"; +export const REPO_URL: string = + "https://gitlab.insrt.uk/revolt/revite/-/commit"; +export const GIT_REVISION: string = "__GIT_REVISION__"; +export const GIT_BRANCH: string = "__GIT_BRANCH__"; diff --git a/ui/ui.tsx b/ui/ui.tsx index cf8f0a7913d6d2c70eeb1eb8cc8363c29bcdf3b8..46123b3a028116e4bd3d9c30f1a7883a3ac1316d 100644 --- a/ui/ui.tsx +++ b/ui/ui.tsx @@ -1,41 +1,49 @@ -import { useState } from 'preact/hooks'; -import styled from 'styled-components'; -import '../src/styles/index.scss' -import { render } from 'preact' +import styled from "styled-components"; -import Theme from '../src/context/Theme'; +import "../src/styles/index.scss"; +import { render } from "preact"; +import { useState } from "preact/hooks"; + +import Theme from "../src/context/Theme"; + +import Banner from "../src/components/ui/Banner"; +import Button from "../src/components/ui/Button"; +import Checkbox from "../src/components/ui/Checkbox"; +import ColourSwatches from "../src/components/ui/ColourSwatches"; +import ComboBox from "../src/components/ui/ComboBox"; +import InputBox from "../src/components/ui/InputBox"; +import Overline from "../src/components/ui/Overline"; +import Radio from "../src/components/ui/Radio"; +import Tip from "../src/components/ui/Tip"; export const UIDemo = styled.div` - gap: 12px; - padding: 12px; - display: flex; - flex-direction: column; - align-items: flex-start; + gap: 12px; + padding: 12px; + display: flex; + flex-direction: column; + align-items: flex-start; `; -import Button from '../src/components/ui/Button'; -import Banner from '../src/components/ui/Banner'; -import Checkbox from '../src/components/ui/Checkbox'; -import ComboBox from '../src/components/ui/ComboBox'; -import InputBox from '../src/components/ui/InputBox'; -import ColourSwatches from '../src/components/ui/ColourSwatches'; -import Tip from '../src/components/ui/Tip'; -import Radio from '../src/components/ui/Radio'; -import Overline from '../src/components/ui/Overline'; - export function UI() { - let [checked, setChecked] = useState(false); - let [colour, setColour] = useState('#FD6671'); - let [selected, setSelected] = useState<'a' | 'b' | 'c'>('a'); + let [checked, setChecked] = useState(false); + let [colour, setColour] = useState("#FD6671"); + let [selected, setSelected] = useState<"a" | "b" | "c">("a"); return ( <> <Button>Button (normal)</Button> <Button contrast>Button (contrast)</Button> <Button error>Button (error)</Button> - <Button contrast error>Button (contrast + error)</Button> + <Button contrast error> + Button (contrast + error) + </Button> <Banner>I am a banner!</Banner> - <Checkbox checked={checked} onChange={setChecked} description="ok gamer">Do you want thing??</Checkbox> + <Checkbox + checked={checked} + onChange={setChecked} + description="ok gamer"> + Do you want thing?? + </Checkbox> <ComboBox> <option>Select an option.</option> <option>1</option> @@ -46,24 +54,35 @@ export function UI() { <InputBox placeholder="Contrast input box..." contrast /> <InputBox value="Input box with value" /> <InputBox value="Contrast with value" contrast /> - <ColourSwatches value={colour} onChange={v => setColour(v)} /> - <Tip>I am a tip! I provide valuable information.</Tip> - <Radio checked={selected === 'a'} onSelect={() => setSelected('a')}>First option</Radio> - <Radio checked={selected === 'b'} onSelect={() => setSelected('b')}>Second option</Radio> - <Radio checked={selected === 'c'} onSelect={() => setSelected('c')}>Last option</Radio> + <ColourSwatches value={colour} onChange={(v) => setColour(v)} /> + <Tip hideSeparator>I am a tip! I provide valuable information.</Tip> + <Radio checked={selected === "a"} onSelect={() => setSelected("a")}> + First option + </Radio> + <Radio checked={selected === "b"} onSelect={() => setSelected("b")}> + Second option + </Radio> + <Radio checked={selected === "c"} onSelect={() => setSelected("c")}> + Last option + </Radio> <Overline>Normal overline</Overline> <Overline type="subtle">Subtle overline</Overline> <Overline type="error">Error overline</Overline> <Overline error="with error">Normal overline</Overline> - <Overline type="subtle" error="with error">Subtle overline</Overline> + <Overline type="subtle" error="with error"> + Subtle overline + </Overline> </> - ) + ); } -render(<> - <Theme> - <UIDemo> - <UI /> - </UIDemo> - </Theme> -</>, document.getElementById('app')!) +render( + <> + <Theme> + <UIDemo> + <UI /> + </UIDemo> + </Theme> + </>, + document.getElementById("app")!, +); diff --git a/yarn.lock b/yarn.lock index db7d5ac6214abc9601a7960530e61194ea03c853..a996624760bf99e22cd542cb2f59b0d5492a9634 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3563,10 +3563,10 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -revolt.js@4.3.3-alpha.17: - version "4.3.3-alpha.17" - resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.17.tgz#0745d251c695840b87e98098bcc4d67c7cc15de5" - integrity sha512-MjxVnkkeX5md5NxZNRS9fl06jsjcDciAxKnbZ2rkBYJofQ94tvr1CYBWvFhS/u/tAR80HAPIEjJVC9HKJDK9Fg== +revolt.js@^4.3.3-alpha.18: + version "4.3.3-alpha.18" + resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.18.tgz#a46cef600099ea22d2f6dc8d09def7e9135839af" + integrity sha512-3QTgX1407bLZEkxkhUsetalUGxcogpFLiTm+mPE3T9bAKgHlTC7y6F5JgHGtmMGWxsjKCDLHgHoAllwGwXJaig== dependencies: "@insertish/mutable" "1.1.0" axios "^0.19.2"