mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-09 16:53:36 -05:00
merge: pull request #650 from revoltchat/chore/component-migration
This commit is contained in:
commit
3399991824
118 changed files with 797 additions and 2839 deletions
|
@ -90,7 +90,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.34",
|
||||
"@revoltchat/ui": "1.0.36",
|
||||
"@rollup/plugin-replace": "^2.4.2",
|
||||
"@styled-icons/boxicons-logos": "^10.38.0",
|
||||
"@styled-icons/boxicons-regular": "^10.38.0",
|
||||
|
|
|
@ -6,13 +6,11 @@ import styled from "styled-components/macro";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, Checkbox } from "@revoltchat/ui";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
import { SECTION_NSFW } from "../../mobx/stores/Layout";
|
||||
|
||||
import Checkbox from "../ui/Checkbox";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
const Base = styled.div`
|
||||
|
@ -81,10 +79,10 @@ export default observer((props: Props) => {
|
|||
</span>
|
||||
|
||||
<Checkbox
|
||||
checked={layout.getSectionState(SECTION_NSFW, false)}
|
||||
onChange={() => layout.toggleSectionState(SECTION_NSFW, false)}>
|
||||
<Text id="app.main.channel.nsfw.confirm" />
|
||||
</Checkbox>
|
||||
title={<Text id="app.main.channel.nsfw.confirm" />}
|
||||
value={layout.getSectionState(SECTION_NSFW, false)}
|
||||
onChange={() => layout.toggleSectionState(SECTION_NSFW, false)}
|
||||
/>
|
||||
<div className="actions">
|
||||
<Button palette="secondary" onClick={() => history.goBack()}>
|
||||
<Text id="app.special.modals.actions.back" />
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { ChevronDown } from "@styled-icons/boxicons-regular";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
import { Details } from "@revoltchat/ui";
|
||||
|
||||
import Details from "../ui/Details";
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useApplicationState } from "../../mobx/State";
|
||||
import { ComboBox } from "@revoltchat/ui";
|
||||
|
||||
import ComboBox from "../ui/ComboBox";
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import { Language, Languages } from "../../../external/lang/Languages";
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import styled, { css } from "styled-components/macro";
|
|||
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import IconButton from "../ui/IconButton";
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import Tooltip from "./Tooltip";
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@ import { Download, CloudDownload } from "@styled-icons/boxicons-regular";
|
|||
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import { internalSubscribe } from "../../lib/eventEmitter";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import IconButton from "../ui/IconButton";
|
||||
|
||||
import { updateSW } from "../../main";
|
||||
import Tooltip from "./Tooltip";
|
||||
|
||||
|
|
|
@ -5,16 +5,17 @@ import { useTriggerEvents } from "preact-context-menu";
|
|||
import { memo } from "preact/compat";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Category } from "@revoltchat/ui";
|
||||
|
||||
import { internalEmit } from "../../../lib/eventEmitter";
|
||||
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||
|
||||
import { QueuedMessage } from "../../../mobx/stores/MessageQueue";
|
||||
|
||||
import { I18nError } from "../../../context/Locale";
|
||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
||||
import { useClient } from "../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import Overline from "../../ui/Overline";
|
||||
|
||||
import { Children } from "../../../types/Preact";
|
||||
import Markdown from "../../markdown/Markdown";
|
||||
import UserIcon from "../user/UserIcon";
|
||||
|
@ -162,7 +163,9 @@ const Message = observer(
|
|||
{replacement ?? <Markdown content={content} />}
|
||||
{!queued && <InviteList message={message} />}
|
||||
{queued?.error && (
|
||||
<Overline type="error" error={queued.error} />
|
||||
<Category>
|
||||
<I18nError error={queued.error} />
|
||||
</Category>
|
||||
)}
|
||||
{message.attachments?.map((attachment, index) => (
|
||||
<Attachment
|
||||
|
|
|
@ -1,22 +1,15 @@
|
|||
import { Send, ShieldX } from "@styled-icons/boxicons-solid";
|
||||
import Axios, { CancelTokenSource } from "axios";
|
||||
import Long from "long";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import {
|
||||
Channel,
|
||||
DEFAULT_PERMISSION_DIRECT_MESSAGE,
|
||||
DEFAULT_PERMISSION_VIEW_ONLY,
|
||||
Permission,
|
||||
Server,
|
||||
U32_MAX,
|
||||
UserPermission,
|
||||
} from "revolt.js";
|
||||
import { Channel } from "revolt.js";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
import { ulid } from "ulid";
|
||||
|
||||
import { Text } from "preact-i18n";
|
||||
import { useCallback, useContext, useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
|
||||
import { debounce } from "../../../lib/debounce";
|
||||
import { defer } from "../../../lib/defer";
|
||||
|
@ -40,8 +33,6 @@ import {
|
|||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||
import { takeError } from "../../../context/revoltjs/util";
|
||||
|
||||
import IconButton from "../../ui/IconButton";
|
||||
|
||||
import AutoComplete, { useAutoComplete } from "../AutoComplete";
|
||||
import { PermissionTooltip } from "../Tooltip";
|
||||
import FilePreview from "./bars/FilePreview";
|
||||
|
@ -104,7 +95,7 @@ const Blocked = styled.div`
|
|||
`;
|
||||
|
||||
const Action = styled.div`
|
||||
> div {
|
||||
> a {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
display: flex;
|
||||
|
@ -127,7 +118,7 @@ const Action = styled.div`
|
|||
`;
|
||||
|
||||
const FileAction = styled.div`
|
||||
> div {
|
||||
> a {
|
||||
height: 48px;
|
||||
width: 62px;
|
||||
display: flex;
|
||||
|
|
|
@ -11,12 +11,12 @@ import styles from "./AttachmentActions.module.scss";
|
|||
import classNames from "classnames";
|
||||
import { useContext } from "preact/hooks";
|
||||
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import { determineFileSize } from "../../../../lib/fileSize";
|
||||
|
||||
import { AppContext } from "../../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import IconButton from "../../../ui/IconButton";
|
||||
|
||||
interface Props {
|
||||
attachment: API.File;
|
||||
}
|
||||
|
|
|
@ -5,15 +5,14 @@ import styles from "./Attachment.module.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext, useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button, Preloader } from "@revoltchat/ui";
|
||||
|
||||
import RequiresOnline from "../../../../context/revoltjs/RequiresOnline";
|
||||
import {
|
||||
AppContext,
|
||||
StatusContext,
|
||||
} from "../../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import Preloader from "../../../ui/Preloader";
|
||||
import { Button } from "@revoltchat/ui";
|
||||
|
||||
interface Props {
|
||||
attachment: API.File;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import styled from "styled-components/macro";
|
|||
import { Text } from "preact-i18n";
|
||||
import { StateUpdater, useEffect } from "preact/hooks";
|
||||
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import { internalSubscribe } from "../../../../lib/eventEmitter";
|
||||
|
||||
import { useApplicationState } from "../../../../mobx/State";
|
||||
|
@ -14,8 +16,6 @@ import { SECTION_MENTION } from "../../../../mobx/stores/Layout";
|
|||
import { Reply } from "../../../../mobx/stores/MessageQueue";
|
||||
|
||||
import Tooltip from "../../../common/Tooltip";
|
||||
import IconButton from "../../../ui/IconButton";
|
||||
|
||||
import Markdown from "../../../markdown/Markdown";
|
||||
import UserShort from "../../user/UserShort";
|
||||
import { SystemMessage } from "../SystemMessage";
|
||||
|
|
|
@ -7,10 +7,11 @@ import styled, { css } from "styled-components/macro";
|
|||
|
||||
import { useContext, useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, Category, Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { isTouchscreenDevice } from "../../../../lib/isTouchscreenDevice";
|
||||
|
||||
import { I18nError } from "../../../../context/Locale";
|
||||
import {
|
||||
AppContext,
|
||||
ClientStatus,
|
||||
|
@ -19,8 +20,6 @@ import {
|
|||
import { takeError } from "../../../../context/revoltjs/util";
|
||||
|
||||
import ServerIcon from "../../../../components/common/ServerIcon";
|
||||
import Overline from "../../../ui/Overline";
|
||||
import Preloader from "../../../ui/Preloader";
|
||||
|
||||
const EmbedInviteBase = styled.div`
|
||||
width: 400px;
|
||||
|
@ -160,7 +159,11 @@ export function EmbedInvite({ code }: Props) {
|
|||
</Button>
|
||||
)}
|
||||
</EmbedInviteBase>
|
||||
{joinError && <Overline type="error" error={joinError} />}
|
||||
{joinError && (
|
||||
<Category>
|
||||
<I18nError error={joinError} />
|
||||
</Category>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { API } from "revolt.js";
|
|||
|
||||
import styles from "./Embed.module.scss";
|
||||
|
||||
import IconButton from "../../../ui/IconButton";
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
interface Props {
|
||||
embed: API.Image;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { User } from "revolt.js";
|
||||
|
||||
import Checkbox, { CheckboxProps } from "../../ui/Checkbox";
|
||||
import { Checkbox } from "@revoltchat/ui";
|
||||
|
||||
import UserIcon from "./UserIcon";
|
||||
import { Username } from "./UserShort";
|
||||
|
||||
type UserProps = Omit<CheckboxProps, "children"> & { user: User };
|
||||
type UserProps = { value: boolean; onChange: (v: boolean) => void; user: User };
|
||||
|
||||
export default function UserCheckbox({ user, ...props }: UserProps) {
|
||||
return (
|
||||
|
|
|
@ -7,13 +7,12 @@ import styled from "styled-components/macro";
|
|||
import { openContextMenu } from "preact-context-menu";
|
||||
import { Text, Localizer } from "preact-i18n";
|
||||
|
||||
import { Header, IconButton } from "@revoltchat/ui";
|
||||
|
||||
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||
|
||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
||||
|
||||
import Header from "../../ui/Header";
|
||||
import IconButton from "../../ui/IconButton";
|
||||
|
||||
import Tooltip from "../Tooltip";
|
||||
import UserStatus from "./UserStatus";
|
||||
|
||||
|
@ -52,7 +51,7 @@ export default observer(({ user }: Props) => {
|
|||
const { writeClipboard } = useIntermediate();
|
||||
|
||||
return (
|
||||
<Header topBorder placement="secondary">
|
||||
<Header topBorder palette="secondary">
|
||||
<HeaderBase>
|
||||
<Localizer>
|
||||
<Tooltip content={<Text id="app.special.copy_username" />}>
|
||||
|
|
|
@ -3,6 +3,8 @@ import { observer } from "mobx-react-lite";
|
|||
import { useHistory, useLocation } from "react-router";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import ConditionalLink from "../../lib/ConditionalLink";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
@ -10,7 +12,6 @@ import { useApplicationState } from "../../mobx/State";
|
|||
import { useClient } from "../../context/revoltjs/RevoltClient";
|
||||
|
||||
import UserIcon from "../common/user/UserIcon";
|
||||
import IconButton from "../ui/IconButton";
|
||||
|
||||
const Base = styled.div`
|
||||
background: var(--secondary-background);
|
||||
|
|
|
@ -5,23 +5,22 @@ import { User, Channel } from "revolt.js";
|
|||
|
||||
import styles from "./Item.module.scss";
|
||||
import classNames from "classnames";
|
||||
import { Ref } from "preact";
|
||||
import { useTriggerEvents } from "preact-context-menu";
|
||||
import { Localizer, Text } from "preact-i18n";
|
||||
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||
import { stopPropagation } from "../../../lib/stopPropagation";
|
||||
|
||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
||||
|
||||
import { Children } from "../../../types/Preact";
|
||||
import ChannelIcon from "../../common/ChannelIcon";
|
||||
import Tooltip from "../../common/Tooltip";
|
||||
import UserIcon from "../../common/user/UserIcon";
|
||||
import { Username } from "../../common/user/UserShort";
|
||||
import UserStatus from "../../common/user/UserStatus";
|
||||
import IconButton from "../../ui/IconButton";
|
||||
|
||||
import { Children } from "../../../types/Preact";
|
||||
|
||||
type CommonProps = Omit<
|
||||
JSX.HTMLAttributes<HTMLDivElement>,
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext } from "preact/hooks";
|
||||
|
||||
import { Banner } from "@revoltchat/ui";
|
||||
|
||||
import {
|
||||
ClientStatus,
|
||||
StatusContext,
|
||||
useClient,
|
||||
} from "../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import Banner from "../../ui/Banner";
|
||||
|
||||
export default function ConnectionStatus() {
|
||||
const status = useContext(StatusContext);
|
||||
const client = useClient();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { Plus } from "@styled-icons/boxicons-regular";
|
||||
import {
|
||||
Home,
|
||||
UserDetail,
|
||||
|
@ -11,6 +12,8 @@ import styled, { css } from "styled-components/macro";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext, useEffect } from "preact/hooks";
|
||||
|
||||
import { Category, IconButton } from "@revoltchat/ui";
|
||||
|
||||
import ConditionalLink from "../../../lib/ConditionalLink";
|
||||
import PaintCounter from "../../../lib/PaintCounter";
|
||||
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||
|
@ -20,7 +23,6 @@ import { useApplicationState } from "../../../mobx/State";
|
|||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import Category from "../../ui/Category";
|
||||
import placeholderSVG from "../items/placeholder.svg";
|
||||
|
||||
import { GenericSidebarBase, GenericSidebarList } from "../SidebarBase";
|
||||
|
@ -125,15 +127,18 @@ export default observer(() => {
|
|||
</ButtonItem>
|
||||
</Link>
|
||||
)}
|
||||
<Category
|
||||
text={<Text id="app.main.categories.conversations" />}
|
||||
action={() =>
|
||||
openScreen({
|
||||
id: "special_input",
|
||||
type: "create_group",
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Category>
|
||||
<Text id="app.main.categories.conversations" />
|
||||
<IconButton
|
||||
onClick={() =>
|
||||
openScreen({
|
||||
id: "special_input",
|
||||
type: "create_group",
|
||||
})
|
||||
}>
|
||||
<Plus size={16} />
|
||||
</IconButton>
|
||||
</Category>
|
||||
{channels.length === 0 && (
|
||||
<img src={placeholderSVG} loading="eager" />
|
||||
)}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { observer } from "mobx-react-lite";
|
||||
import { Redirect, useParams } from "react-router";
|
||||
import { Server } from "revolt.js";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { Ref } from "preact";
|
||||
import { useTriggerEvents } from "preact-context-menu";
|
||||
import { useEffect } from "preact/hooks";
|
||||
|
||||
import { Category } from "@revoltchat/ui";
|
||||
|
||||
import ConditionalLink from "../../../lib/ConditionalLink";
|
||||
import PaintCounter from "../../../lib/PaintCounter";
|
||||
import { internalEmit } from "../../../lib/eventEmitter";
|
||||
|
@ -18,8 +18,6 @@ import { useClient } from "../../../context/revoltjs/RevoltClient";
|
|||
|
||||
import CollapsibleSection from "../../common/CollapsibleSection";
|
||||
import ServerHeader from "../../common/ServerHeader";
|
||||
import Category from "../../ui/Category";
|
||||
|
||||
import { ChannelButton } from "../items/ButtonItem";
|
||||
import ConnectionStatus from "../items/ConnectionStatus";
|
||||
|
||||
|
@ -126,7 +124,7 @@ export default observer(() => {
|
|||
<CollapsibleSection
|
||||
id={`category_${category.id}`}
|
||||
defaultValue
|
||||
summary={<Category text={category.title} />}>
|
||||
summary={<Category>{category.title}</Category>}>
|
||||
{channels}
|
||||
</CollapsibleSection>,
|
||||
);
|
||||
|
|
|
@ -5,15 +5,11 @@ import styled from "styled-components/macro";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, Category, Error, InputBox, Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { useClient } from "../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import Message from "../../common/messaging/Message";
|
||||
import InputBox from "../../ui/InputBox";
|
||||
import Overline from "../../ui/Overline";
|
||||
import Preloader from "../../ui/Preloader";
|
||||
|
||||
import { GenericSidebarBase, GenericSidebarList } from "../SidebarBase";
|
||||
|
||||
type SearchState =
|
||||
|
@ -103,12 +99,14 @@ export function SearchSidebar({ close }: Props) {
|
|||
<GenericSidebarBase data-scroll-offset="with-padding">
|
||||
<GenericSidebarList>
|
||||
<SearchBase>
|
||||
<Overline type="accent" block hover>
|
||||
<a onClick={close}>« back to members</a>
|
||||
</Overline>
|
||||
<Overline type="subtle" block>
|
||||
<Category>
|
||||
<Error
|
||||
error={<a onClick={close}>« back to members</a>}
|
||||
/>
|
||||
</Category>
|
||||
<Category>
|
||||
<Text id="app.main.channel.search.title" />
|
||||
</Overline>
|
||||
</Category>
|
||||
<InputBox
|
||||
value={query}
|
||||
onKeyDown={(e) => e.key === "Enter" && search()}
|
||||
|
|
|
@ -6,6 +6,14 @@ import pSBC from "shade-blend-color";
|
|||
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import {
|
||||
CategoryButton,
|
||||
Checkbox,
|
||||
ColourSwatches,
|
||||
ComboBox,
|
||||
Radio,
|
||||
} from "@revoltchat/ui";
|
||||
|
||||
import TextAreaAutoSize from "../../lib/TextAreaAutoSize";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
@ -19,12 +27,6 @@ import {
|
|||
MONOSPACE_FONT_KEYS,
|
||||
} from "../../context/Theme";
|
||||
|
||||
import Checkbox from "../ui/Checkbox";
|
||||
import ColourSwatches from "../ui/ColourSwatches";
|
||||
import ComboBox from "../ui/ComboBox";
|
||||
import Radio from "../ui/Radio";
|
||||
import CategoryButton from "../ui/fluent/CategoryButton";
|
||||
|
||||
import { EmojiSelector } from "./appearance/EmojiSelector";
|
||||
import { ThemeBaseSelector } from "./appearance/ThemeBaseSelector";
|
||||
|
||||
|
@ -57,8 +59,7 @@ export const ThemeShopShim = () => {
|
|||
action="chevron"
|
||||
description={
|
||||
<Text id="app.settings.pages.appearance.discover.description" />
|
||||
}
|
||||
hover>
|
||||
}>
|
||||
<Text id="app.settings.pages.appearance.discover.title" />
|
||||
</CategoryButton>
|
||||
</Link>
|
||||
|
@ -119,19 +120,24 @@ export const DisplayCompactShim = () => {
|
|||
</h3>
|
||||
<div /* className={styles.display} */>
|
||||
<Radio
|
||||
title={
|
||||
<Text id="app.settings.pages.appearance.display.default" />
|
||||
}
|
||||
description={
|
||||
<Text id="app.settings.pages.appearance.display.default_description" />
|
||||
}
|
||||
checked>
|
||||
<Text id="app.settings.pages.appearance.display.default" />
|
||||
</Radio>
|
||||
value={true}
|
||||
/>
|
||||
<Radio
|
||||
title={
|
||||
<Text id="app.settings.pages.appearance.display.compact" />
|
||||
}
|
||||
description={
|
||||
<Text id="app.settings.pages.appearance.display.compact_description" />
|
||||
}
|
||||
disabled>
|
||||
<Text id="app.settings.pages.appearance.display.compact" />
|
||||
</Radio>
|
||||
value={false}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -200,13 +206,13 @@ export const DisplayLigaturesShim = observer(() => {
|
|||
return (
|
||||
<>
|
||||
<Checkbox
|
||||
checked={settings.get("appearance:ligatures") ?? false}
|
||||
value={settings.get("appearance:ligatures") ?? false}
|
||||
onChange={(v) => settings.set("appearance:ligatures", v)}
|
||||
title={<Text id="app.settings.pages.appearance.ligatures" />}
|
||||
description={
|
||||
<Text id="app.settings.pages.appearance.ligatures_desc" />
|
||||
}>
|
||||
<Text id="app.settings.pages.appearance.ligatures" />
|
||||
</Checkbox>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
@ -219,13 +225,15 @@ export const ShowSendButtonShim = observer(() => {
|
|||
|
||||
return (
|
||||
<Checkbox
|
||||
checked={settings.get("appearance:show_send_button") ?? false}
|
||||
value={settings.get("appearance:show_send_button") ?? false}
|
||||
onChange={(v) => settings.set("appearance:show_send_button", v)}
|
||||
title={
|
||||
<Text id="app.settings.pages.appearance.appearance_options.show_send" />
|
||||
}
|
||||
description={
|
||||
<Text id="app.settings.pages.appearance.appearance_options.show_send_desc" />
|
||||
}>
|
||||
<Text id="app.settings.pages.appearance.appearance_options.show_send" />
|
||||
</Checkbox>
|
||||
}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -237,13 +245,15 @@ export const DisplaySeasonalShim = observer(() => {
|
|||
|
||||
return (
|
||||
<Checkbox
|
||||
checked={settings.get("appearance:seasonal") ?? true}
|
||||
value={settings.get("appearance:seasonal") ?? true}
|
||||
onChange={(v) => settings.set("appearance:seasonal", v)}
|
||||
title={
|
||||
<Text id="app.settings.pages.appearance.theme_options.seasonal" />
|
||||
}
|
||||
description={
|
||||
<Text id="app.settings.pages.appearance.theme_options.seasonal_desc" />
|
||||
}>
|
||||
<Text id="app.settings.pages.appearance.theme_options.seasonal" />
|
||||
</Checkbox>
|
||||
}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -255,13 +265,15 @@ export const DisplayTransparencyShim = observer(() => {
|
|||
|
||||
return (
|
||||
<Checkbox
|
||||
checked={settings.get("appearance:transparency") ?? true}
|
||||
value={settings.get("appearance:transparency") ?? true}
|
||||
onChange={(v) => settings.set("appearance:transparency", v)}
|
||||
title={
|
||||
<Text id="app.settings.pages.appearance.theme_options.transparency" />
|
||||
}
|
||||
description={
|
||||
<Text id="app.settings.pages.appearance.theme_options.transparency_desc" />
|
||||
}>
|
||||
<Text id="app.settings.pages.appearance.theme_options.transparency" />
|
||||
</Checkbox>
|
||||
}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -2,14 +2,14 @@ import { Pencil } from "@styled-icons/boxicons-regular";
|
|||
import { observer } from "mobx-react-lite";
|
||||
import styled from "styled-components/macro";
|
||||
|
||||
import { InputBox } from "@revoltchat/ui";
|
||||
|
||||
import { useDebounceCallback } from "../../../lib/debounce";
|
||||
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
|
||||
import { Variables } from "../../../context/Theme";
|
||||
|
||||
import InputBox from "../../ui/InputBox";
|
||||
|
||||
const Container = styled.div`
|
||||
row-gap: 8px;
|
||||
display: grid;
|
||||
|
|
|
@ -7,8 +7,7 @@ import styled, { css } from "styled-components";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useMemo } from "preact/hooks";
|
||||
|
||||
import Checkbox from "../../ui/Checkbox";
|
||||
import { OverrideSwitch } from "@revoltchat/ui";
|
||||
import { Checkbox, OverrideSwitch } from "@revoltchat/ui";
|
||||
|
||||
interface PermissionSelectProps {
|
||||
id: keyof typeof Permission;
|
||||
|
@ -136,7 +135,7 @@ export function PermissionSelect({
|
|||
) : (
|
||||
<Checkbox
|
||||
disabled={disabled}
|
||||
checked={state === "Allow"}
|
||||
value={state === "Allow"}
|
||||
onChange={() =>
|
||||
onChange(
|
||||
Long.fromNumber(value, false)
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
import styled from "styled-components/macro";
|
||||
|
||||
export default styled.div`
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
|
||||
color: var(--accent);
|
||||
background: var(--primary-background);
|
||||
`;
|
|
@ -1,55 +0,0 @@
|
|||
import { Plus } from "@styled-icons/boxicons-regular";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
const CategoryBase = styled.div<Pick<Props, "variant">>`
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
|
||||
margin-top: 4px;
|
||||
padding: 6px 0 6px 8px;
|
||||
margin-bottom: 4px;
|
||||
white-space: nowrap;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
svg {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.variant === "uniform" &&
|
||||
css`
|
||||
padding-top: 6px;
|
||||
`}
|
||||
`;
|
||||
|
||||
type Props = Omit<
|
||||
JSX.HTMLAttributes<HTMLDivElement>,
|
||||
"children" | "as" | "action"
|
||||
> & {
|
||||
text: Children;
|
||||
action?: () => void;
|
||||
variant?: "default" | "uniform";
|
||||
};
|
||||
|
||||
export default function Category(props: Props) {
|
||||
const { text, action, ...otherProps } = props;
|
||||
|
||||
return (
|
||||
<CategoryBase {...otherProps}>
|
||||
{text}
|
||||
{action && <Plus size={16} onClick={action} />}
|
||||
</CategoryBase>
|
||||
);
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
import { Check } from "@styled-icons/boxicons-regular";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
export const CheckboxBase = styled.label`
|
||||
gap: 4px;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
margin-top: 20px;
|
||||
align-items: center;
|
||||
border-radius: var(--border-radius);
|
||||
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
user-select: none;
|
||||
|
||||
transition: 0.2s ease all;
|
||||
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.check {
|
||||
background: var(--background);
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
|
||||
&:hover {
|
||||
background: unset;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const CheckboxContent = styled.span`
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
font-size: 14px;
|
||||
gap: 2px;
|
||||
font-weight: 600;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const CheckboxDescription = styled.span`
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
color: var(--secondary-foreground);
|
||||
`;
|
||||
|
||||
export const Checkmark = styled.div<{ checked: boolean; contrast?: boolean }>`
|
||||
margin: 4px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: grid;
|
||||
flex-shrink: 0;
|
||||
place-items: center;
|
||||
transition: 0.2s ease all;
|
||||
border-radius: var(--border-radius);
|
||||
background: var(--secondary-background);
|
||||
|
||||
svg {
|
||||
color: var(--secondary-background);
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.contrast &&
|
||||
css`
|
||||
background: var(--primary-background);
|
||||
|
||||
svg {
|
||||
color: var(--primary-background);
|
||||
}
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.checked &&
|
||||
css`
|
||||
background: var(--accent) !important;
|
||||
`}
|
||||
`;
|
||||
|
||||
export interface CheckboxProps {
|
||||
checked: boolean;
|
||||
disabled?: boolean;
|
||||
contrast?: boolean;
|
||||
className?: string;
|
||||
children?: Children;
|
||||
description?: Children;
|
||||
onChange: (state: boolean) => void;
|
||||
}
|
||||
|
||||
export default function Checkbox(props: CheckboxProps) {
|
||||
return (
|
||||
<CheckboxBase disabled={props.disabled} className={props.className}>
|
||||
<CheckboxContent>
|
||||
<span>{props.children}</span>
|
||||
{props.description && (
|
||||
<CheckboxDescription>
|
||||
{props.description}
|
||||
</CheckboxDescription>
|
||||
)}
|
||||
</CheckboxContent>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={props.checked}
|
||||
onChange={() =>
|
||||
!props.disabled && props.onChange(!props.checked)
|
||||
}
|
||||
/>
|
||||
<Checkmark
|
||||
checked={props.checked}
|
||||
contrast={props.contrast}
|
||||
className="check">
|
||||
<Check size={20} />
|
||||
</Checkmark>
|
||||
</CheckboxBase>
|
||||
);
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
import { Check } from "@styled-icons/boxicons-regular";
|
||||
import { Palette } from "@styled-icons/boxicons-solid";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { RefObject } from "preact";
|
||||
import { useRef } from "preact/hooks";
|
||||
|
||||
import { useDebounceCallback } from "../../lib/debounce";
|
||||
|
||||
interface Props {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
}
|
||||
|
||||
const presets = [
|
||||
[
|
||||
"#7B68EE",
|
||||
"#3498DB",
|
||||
"#1ABC9C",
|
||||
"#F1C40F",
|
||||
"#FF7F50",
|
||||
"#FD6671",
|
||||
"#E91E63",
|
||||
"#D468EE",
|
||||
],
|
||||
[
|
||||
"#594CAD",
|
||||
"#206694",
|
||||
"#11806A",
|
||||
"#C27C0E",
|
||||
"#CD5B45",
|
||||
"#FF424F",
|
||||
"#AD1457",
|
||||
"#954AA8",
|
||||
],
|
||||
];
|
||||
|
||||
const SwatchesBase = styled.div`
|
||||
/*gap: 8px;*/
|
||||
display: flex;
|
||||
|
||||
input {
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: 72px;
|
||||
opacity: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: relative;
|
||||
width: 0;
|
||||
|
||||
div {
|
||||
width: 8px;
|
||||
height: 68px;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
var(--primary-background),
|
||||
transparent
|
||||
);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const Swatch = styled.div<{ type: "small" | "large"; colour: string }>`
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
border-radius: var(--border-radius);
|
||||
background-color: ${(props) => props.colour};
|
||||
|
||||
display: grid;
|
||||
place-items: center;
|
||||
|
||||
&:hover {
|
||||
border: 3px solid var(--foreground);
|
||||
transition: border ease-in-out 0.07s;
|
||||
}
|
||||
|
||||
svg {
|
||||
color: white;
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.type === "small"
|
||||
? css`
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
svg {
|
||||
/*stroke-width: 2;*/
|
||||
}
|
||||
`
|
||||
: css`
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
`}
|
||||
`;
|
||||
|
||||
const Rows = styled.div`
|
||||
gap: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
padding-bottom: 4px;
|
||||
|
||||
> div {
|
||||
gap: 8px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding-inline-start: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function ColourSwatches({ value, onChange }: Props) {
|
||||
const ref = useRef<HTMLInputElement>() as RefObject<HTMLInputElement>;
|
||||
const setValue = useDebounceCallback(
|
||||
(value) => onChange(value as string),
|
||||
[onChange],
|
||||
100,
|
||||
);
|
||||
|
||||
return (
|
||||
<SwatchesBase>
|
||||
<input
|
||||
type="color"
|
||||
value={value}
|
||||
ref={ref}
|
||||
onChange={(ev) => setValue(ev.currentTarget.value)}
|
||||
/>
|
||||
<Swatch
|
||||
colour={value}
|
||||
type="large"
|
||||
onClick={() => ref.current?.click()}>
|
||||
<Palette size={32} />
|
||||
</Swatch>
|
||||
|
||||
<div class="overlay">
|
||||
<div />
|
||||
</div>
|
||||
|
||||
<Rows>
|
||||
{presets.map((row, i) => (
|
||||
<div key={i}>
|
||||
{row.map((swatch, i) => (
|
||||
<Swatch
|
||||
colour={swatch}
|
||||
type="small"
|
||||
key={i}
|
||||
onClick={() => onChange(swatch)}>
|
||||
{swatch === value && <Check size={22} />}
|
||||
</Swatch>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</Rows>
|
||||
</SwatchesBase>
|
||||
);
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
import styled from "styled-components/macro";
|
||||
|
||||
export default styled.select`
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
border-radius: var(--border-radius);
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
font-size: var(--text-size);
|
||||
color: var(--secondary-foreground);
|
||||
background: var(--secondary-background);
|
||||
|
||||
border: none;
|
||||
outline: 2px solid transparent;
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
transition: outline-color 0.2s ease-in-out;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1.5pt var(--accent);
|
||||
}
|
||||
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
`;
|
|
@ -1,53 +0,0 @@
|
|||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { dayjs } from "../../context/Locale";
|
||||
|
||||
const Base = styled.div<{ unread?: boolean }>`
|
||||
height: 0;
|
||||
display: flex;
|
||||
user-select: none;
|
||||
align-items: center;
|
||||
margin: 17px 12px 5px;
|
||||
border-top: thin solid var(--tertiary-foreground);
|
||||
|
||||
time {
|
||||
margin-top: -2px;
|
||||
font-size: 0.6875rem;
|
||||
line-height: 0.6875rem;
|
||||
padding-inline-start: 5px;
|
||||
padding-inline-end: 5px;
|
||||
color: var(--tertiary-foreground);
|
||||
background: var(--primary-background);
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.unread &&
|
||||
css`
|
||||
border-top: thin solid var(--accent);
|
||||
`}
|
||||
`;
|
||||
|
||||
const Unread = styled.div`
|
||||
background: var(--accent);
|
||||
color: var(--accent-contrast);
|
||||
font-size: 7px;
|
||||
padding: 2px 6px;
|
||||
font-size: 10px;
|
||||
border-radius: 60px;
|
||||
font-weight: 600;
|
||||
margin-top: -1px;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
date?: Date;
|
||||
unread?: boolean;
|
||||
}
|
||||
|
||||
export default function DateDivider({ unread, date }: Props) {
|
||||
return (
|
||||
<Base unread={unread}>
|
||||
{unread && <Unread>NEW</Unread>}
|
||||
{date && <time>{dayjs(date).format("LL")}</time>}
|
||||
</Base>
|
||||
);
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||
|
||||
export default styled.details<{ sticky?: boolean; large?: boolean }>`
|
||||
summary {
|
||||
${(props) =>
|
||||
props.sticky &&
|
||||
css`
|
||||
top: 48px;
|
||||
z-index: 10;
|
||||
position: sticky;
|
||||
${() =>
|
||||
isTouchscreenDevice &&
|
||||
css`
|
||||
top: 56px;
|
||||
`}
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.large &&
|
||||
css`
|
||||
/*padding: 5px 0;*/
|
||||
background: var(--primary-background);
|
||||
color: var(--secondary-foreground);
|
||||
|
||||
.padding {
|
||||
/*TOFIX: make this applicable only for the friends list menu, DO NOT REMOVE.*/
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 5px 0;
|
||||
margin: 0.8em 0px 0.4em;
|
||||
cursor: pointer;
|
||||
}
|
||||
`}
|
||||
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
align-items: center;
|
||||
transition: 0.2s opacity;
|
||||
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
|
||||
&::marker,
|
||||
&::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
flex-grow: 1;
|
||||
margin-top: 1px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.padding {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> svg {
|
||||
flex-shrink: 0;
|
||||
margin-inline-end: 4px;
|
||||
transition: 0.2s ease transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:not([open]) {
|
||||
summary {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
summary svg {
|
||||
transform: rotateZ(-90deg);
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -7,6 +7,8 @@ import { observer } from "mobx-react-lite";
|
|||
import { useLocation } from "react-router-dom";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { Header } from "@revoltchat/ui";
|
||||
|
||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
@ -18,82 +20,11 @@ interface Props {
|
|||
topBorder?: boolean;
|
||||
bottomBorder?: boolean;
|
||||
|
||||
background?: boolean;
|
||||
transparent?: boolean;
|
||||
withBackground?: boolean;
|
||||
withTransparency?: boolean;
|
||||
placement: "primary" | "secondary";
|
||||
}
|
||||
|
||||
const Header = styled.div<Props>`
|
||||
gap: 10px;
|
||||
flex: 0 auto;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
padding: 0 16px;
|
||||
font-weight: 600;
|
||||
user-select: none;
|
||||
align-items: center;
|
||||
|
||||
height: var(--header-height);
|
||||
|
||||
background-size: cover !important;
|
||||
background-position: center !important;
|
||||
|
||||
svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.menu {
|
||||
margin-inline-end: 8px;
|
||||
color: var(--secondary-foreground);
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.transparent
|
||||
? css`
|
||||
background-color: rgba(
|
||||
var(--primary-header-rgb),
|
||||
max(var(--min-opacity), 0.75)
|
||||
);
|
||||
backdrop-filter: blur(20px);
|
||||
z-index: 20;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
`
|
||||
: css`
|
||||
background-color: var(--primary-header);
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.background &&
|
||||
css`
|
||||
height: 120px !important;
|
||||
align-items: flex-end;
|
||||
|
||||
text-shadow: 0px 0px 1px black;
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.placement === "secondary" &&
|
||||
css`
|
||||
background-color: var(--secondary-header);
|
||||
padding: 14px;
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.topBorder &&
|
||||
css`
|
||||
border-start-start-radius: 8px;
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.bottomBorder &&
|
||||
css`
|
||||
border-end-start-radius: 8px;
|
||||
`}
|
||||
`;
|
||||
|
||||
export default Header;
|
||||
|
||||
const IconContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -128,7 +59,7 @@ export const PageHeader = observer(
|
|||
return (
|
||||
<Header
|
||||
{...props}
|
||||
placement="primary"
|
||||
palette="primary"
|
||||
topBorder={!visible}
|
||||
bottomBorder={!pathname.includes("/server")}>
|
||||
{!noBurger && <HamburgerAction />}
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
interface Props {
|
||||
rotate?: string;
|
||||
type?: "default" | "circle";
|
||||
}
|
||||
|
||||
const normal = `var(--secondary-foreground)`;
|
||||
const hover = `var(--foreground)`;
|
||||
|
||||
export default styled.div<Props>`
|
||||
z-index: 1;
|
||||
display: grid;
|
||||
cursor: pointer;
|
||||
place-items: center;
|
||||
|
||||
transition: 0.1s ease all;
|
||||
|
||||
fill: ${normal};
|
||||
color: ${normal};
|
||||
|
||||
a {
|
||||
color: ${normal};
|
||||
}
|
||||
|
||||
svg {
|
||||
transition: 0.2s ease transform;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
fill: ${hover};
|
||||
color: ${hover};
|
||||
|
||||
a {
|
||||
color: ${hover};
|
||||
}
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.type === "circle" &&
|
||||
css`
|
||||
padding: 4px;
|
||||
border-radius: var(--border-radius-half);
|
||||
background-color: var(--secondary-header);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--primary-header);
|
||||
}
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.rotate &&
|
||||
css`
|
||||
svg {
|
||||
transform: rotateZ(${props.rotate});
|
||||
}
|
||||
`}
|
||||
`;
|
|
@ -1,41 +0,0 @@
|
|||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
interface Props {
|
||||
readonly contrast?: boolean;
|
||||
}
|
||||
|
||||
export default styled.input<Props>`
|
||||
z-index: 1;
|
||||
font-size: 1rem;
|
||||
padding: 8px 16px;
|
||||
border-radius: var(--border-radius);
|
||||
|
||||
font-family: inherit;
|
||||
color: var(--foreground);
|
||||
background: var(--primary-background);
|
||||
transition: 0.2s ease background-color;
|
||||
|
||||
border: none;
|
||||
outline: 2px solid transparent;
|
||||
transition: outline-color 0.2s ease-in-out;
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background: var(--secondary-background);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1.5pt var(--accent);
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.contrast &&
|
||||
css`
|
||||
color: var(--secondary-foreground);
|
||||
background: var(--secondary-background);
|
||||
|
||||
&:hover {
|
||||
background: var(--hover);
|
||||
}
|
||||
`}
|
||||
`;
|
|
@ -1,9 +0,0 @@
|
|||
import styled from "styled-components/macro";
|
||||
|
||||
export default styled.div`
|
||||
height: 0;
|
||||
opacity: 0.6;
|
||||
flex-shrink: 0;
|
||||
margin: 8px 15px;
|
||||
border-top: 1px solid var(--tertiary-foreground);
|
||||
`;
|
|
@ -1,26 +0,0 @@
|
|||
// This file must be imported and used at least once for SVG masks.
|
||||
|
||||
export default function Masks() {
|
||||
return (
|
||||
<svg width={0} height={0} style={{ position: "fixed" }}>
|
||||
<defs>
|
||||
<mask id="server">
|
||||
<rect x="0" y="0" width="32" height="32" fill="white" />
|
||||
<circle cx="27" cy="5" r="7" fill={"black"} />
|
||||
</mask>
|
||||
<mask id="user">
|
||||
<rect x="0" y="0" width="32" height="32" fill="white" />
|
||||
<circle cx="27" cy="27" r="7" fill={"black"} />
|
||||
</mask>
|
||||
<mask id="session">
|
||||
<rect x="0" y="0" width="32" height="32" fill="white" />
|
||||
<circle cx="26" cy="28" r="10" fill={"black"} />
|
||||
</mask>
|
||||
<mask id="overlap">
|
||||
<rect x="0" y="0" width="32" height="32" fill="white" />
|
||||
<circle cx="32" cy="16" r="18" fill={"black"} />
|
||||
</mask>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
}
|
|
@ -1,263 +0,0 @@
|
|||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import styled, { css, keyframes } from "styled-components/macro";
|
||||
|
||||
import { createPortal, useCallback, useEffect, useState } from "preact/compat";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Props as ButtonProps } from "@revoltchat/ui/esm/components/design/atoms/inputs/Button";
|
||||
|
||||
import { internalSubscribe } from "../../lib/eventEmitter";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
const open = keyframes`
|
||||
0% {opacity: 0;}
|
||||
70% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
`;
|
||||
|
||||
const close = keyframes`
|
||||
0% {opacity: 1;}
|
||||
70% {opacity: 0;}
|
||||
100% {opacity: 0;}
|
||||
`;
|
||||
|
||||
const zoomIn = keyframes`
|
||||
0% {transform: scale(0.5);}
|
||||
98% {transform: scale(1.01);}
|
||||
100% {transform: scale(1);}
|
||||
`;
|
||||
|
||||
const zoomOut = keyframes`
|
||||
0% {transform: scale(1);}
|
||||
100% {transform: scale(0.5);}
|
||||
`;
|
||||
|
||||
const ModalBase = styled.div`
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 9999;
|
||||
position: fixed;
|
||||
max-height: 100%;
|
||||
user-select: none;
|
||||
|
||||
animation-name: ${open};
|
||||
animation-duration: 0.2s;
|
||||
|
||||
display: grid;
|
||||
overflow-y: auto;
|
||||
place-items: center;
|
||||
|
||||
color: var(--foreground);
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
|
||||
&.closing {
|
||||
animation-name: ${close};
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
&.closing > div {
|
||||
animation-name: ${zoomOut};
|
||||
}
|
||||
`;
|
||||
|
||||
const ModalContainer = styled.div`
|
||||
overflow: hidden;
|
||||
max-width: calc(100vw - 20px);
|
||||
border-radius: var(--border-radius);
|
||||
|
||||
animation-name: ${zoomIn};
|
||||
animation-duration: 0.25s;
|
||||
animation-timing-function: cubic-bezier(0.3, 0.3, 0.18, 1.1);
|
||||
`;
|
||||
|
||||
const ModalContent = styled.div<
|
||||
{ [key in "attachment" | "noBackground" | "border" | "padding"]?: boolean }
|
||||
>`
|
||||
text-overflow: ellipsis;
|
||||
border-radius: var(--border-radius);
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
text-transform: uppercase;
|
||||
margin: 0;
|
||||
margin-bottom: 10px;
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
h5 {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--secondary-foreground);
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
> div {
|
||||
margin: 0;
|
||||
color: var(--secondary-foreground);
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
color: var(--tertiary-foreground);
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
!props.noBackground &&
|
||||
css`
|
||||
background: var(--secondary-header);
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.padding &&
|
||||
css`
|
||||
padding: 1rem;
|
||||
min-width: 450px;
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.attachment &&
|
||||
css`
|
||||
border-radius: var(--border-radius) var(--border-radius) 0 0;
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.border &&
|
||||
css`
|
||||
border-radius: var(--border-radius);
|
||||
border: 2px solid var(--secondary-background);
|
||||
`}
|
||||
`;
|
||||
|
||||
const ModalActions = styled.div`
|
||||
gap: 8px;
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
padding: 1rem;
|
||||
background: var(--secondary-background);
|
||||
border-radius: 0 0 var(--border-radius) var(--border-radius);
|
||||
`;
|
||||
|
||||
export type Action = Omit<
|
||||
JSX.HTMLAttributes<HTMLButtonElement>,
|
||||
"as" | "onClick"
|
||||
> & {
|
||||
palette?: ButtonProps["palette"];
|
||||
confirmation?: boolean;
|
||||
onClick: () => void;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
children?: Children;
|
||||
title?: Children;
|
||||
description?: Children;
|
||||
|
||||
disallowClosing?: boolean;
|
||||
noBackground?: boolean;
|
||||
dontModal?: boolean;
|
||||
padding?: boolean;
|
||||
|
||||
onClose?: () => void;
|
||||
actions?: Action[];
|
||||
disabled?: boolean;
|
||||
palette?: ButtonProps["palette"];
|
||||
border?: boolean;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export let isModalClosing = false;
|
||||
|
||||
export default function Modal(props: Props) {
|
||||
if (!props.visible) return null;
|
||||
|
||||
const content = (
|
||||
<ModalContent
|
||||
attachment={!!props.actions}
|
||||
noBackground={props.noBackground}
|
||||
border={props.border}
|
||||
padding={props.padding ?? !props.dontModal}>
|
||||
{props.title && <h3>{props.title}</h3>}
|
||||
|
||||
{props.description && <h5>{props.description}</h5>}
|
||||
{props.children}
|
||||
</ModalContent>
|
||||
);
|
||||
|
||||
if (props.dontModal) {
|
||||
return content;
|
||||
}
|
||||
|
||||
const [animateClose, setAnimateClose] = useState(false);
|
||||
isModalClosing = animateClose;
|
||||
const onClose = useCallback(() => {
|
||||
setAnimateClose(true);
|
||||
setTimeout(() => props.onClose!(), 2e2);
|
||||
}, [setAnimateClose, props]);
|
||||
|
||||
useEffect(() => internalSubscribe("Modal", "close", onClose), [onClose]);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.disallowClosing) return;
|
||||
|
||||
function keyDown(e: KeyboardEvent) {
|
||||
if (e.key === "Escape") {
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
|
||||
document.body.addEventListener("keydown", keyDown);
|
||||
return () => document.body.removeEventListener("keydown", keyDown);
|
||||
}, [props.disallowClosing, onClose]);
|
||||
|
||||
const confirmationAction = props.actions?.find(
|
||||
(action) => action.confirmation,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!confirmationAction) return;
|
||||
|
||||
// ! TODO: this may be done better if we
|
||||
// ! can focus the button although that
|
||||
// ! doesn't seem to work...
|
||||
function keyDown(e: KeyboardEvent) {
|
||||
if (e.key === "Enter") {
|
||||
confirmationAction!.onClick();
|
||||
}
|
||||
}
|
||||
|
||||
document.body.addEventListener("keydown", keyDown);
|
||||
return () => document.body.removeEventListener("keydown", keyDown);
|
||||
}, [confirmationAction]);
|
||||
|
||||
return createPortal(
|
||||
<ModalBase
|
||||
className={animateClose ? "closing" : undefined}
|
||||
onClick={(!props.disallowClosing && props.onClose) || undefined}>
|
||||
<ModalContainer onClick={(e) => (e.cancelBubble = true)}>
|
||||
{content}
|
||||
{props.actions && (
|
||||
<ModalActions>
|
||||
{props.actions.map((x, index) => (
|
||||
<Button
|
||||
palette={props.palette}
|
||||
key={index}
|
||||
{...x}
|
||||
disabled={props.disabled}
|
||||
/>
|
||||
))}
|
||||
</ModalActions>
|
||||
)}
|
||||
</ModalContainer>
|
||||
</ModalBase>,
|
||||
document.body,
|
||||
);
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
type Props = Omit<JSX.HTMLAttributes<HTMLDivElement>, "children" | "as"> & {
|
||||
error?: string;
|
||||
hover?: boolean;
|
||||
block?: boolean;
|
||||
spaced?: boolean;
|
||||
noMargin?: boolean;
|
||||
children?: Children;
|
||||
type?: "default" | "subtle" | "error" | "accent";
|
||||
};
|
||||
|
||||
const OverlineBase = styled.div<Omit<Props, "children" | "error">>`
|
||||
display: inline;
|
||||
transition: 0.2s ease filter;
|
||||
|
||||
${(props) =>
|
||||
props.hover &&
|
||||
css`
|
||||
cursor: pointer;
|
||||
transition: 0.2s ease filter;
|
||||
|
||||
&:hover {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
!props.noMargin &&
|
||||
css`
|
||||
margin: 0.4em 0;
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.spaced &&
|
||||
css`
|
||||
margin-top: 0.8em;
|
||||
`}
|
||||
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--foreground);
|
||||
text-transform: uppercase;
|
||||
|
||||
${(props) =>
|
||||
props.type === "subtle" &&
|
||||
css`
|
||||
font-size: 12px;
|
||||
color: var(--secondary-foreground);
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.type === "error" &&
|
||||
css`
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: var(--error);
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.type === "accent" &&
|
||||
css`
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: var(--accent);
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.block &&
|
||||
css`
|
||||
display: block;
|
||||
`}
|
||||
`;
|
||||
|
||||
export default function Overline(props: Props) {
|
||||
return (
|
||||
<OverlineBase {...props}>
|
||||
{props.children}
|
||||
{props.children && props.error && <> · </>}
|
||||
{props.error && (
|
||||
<Overline type="error">
|
||||
<Text id={`error.${props.error}`}>{props.error}</Text>
|
||||
</Overline>
|
||||
)}
|
||||
</OverlineBase>
|
||||
);
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
import styled, { keyframes } from "styled-components/macro";
|
||||
|
||||
const skSpinner = keyframes`
|
||||
0%, 80%, 100% {
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: scale(1.0);
|
||||
transform: scale(1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const prRing = keyframes`
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
`;
|
||||
|
||||
const PreloaderBase = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.spinner {
|
||||
width: 58px;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
margin: 100px auto 0;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.spinner > div {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background-color: var(--tertiary-foreground);
|
||||
|
||||
border-radius: 100%;
|
||||
display: inline-block;
|
||||
animation: ${skSpinner} 1.4s infinite ease-in-out both;
|
||||
}
|
||||
|
||||
.spinner div:nth-child(1) {
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
.spinner div:nth-child(2) {
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
|
||||
.ring {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
}
|
||||
|
||||
.ring div {
|
||||
width: 32px;
|
||||
margin: 8px;
|
||||
height: 32px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
border: 2px solid #fff;
|
||||
border-radius: var(--border-radius-half);
|
||||
animation: ${prRing} 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||
border-color: #fff transparent transparent transparent;
|
||||
}
|
||||
|
||||
.ring div:nth-child(1) {
|
||||
animation-delay: -0.45s;
|
||||
}
|
||||
|
||||
.ring div:nth-child(2) {
|
||||
animation-delay: -0.3s;
|
||||
}
|
||||
|
||||
.ring div:nth-child(3) {
|
||||
animation-delay: -0.15s;
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
type: "spinner" | "ring";
|
||||
}
|
||||
|
||||
export default function Preloader({ type }: Props) {
|
||||
return (
|
||||
<PreloaderBase>
|
||||
<div class={type}>
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
</div>
|
||||
</PreloaderBase>
|
||||
);
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
import { Circle } from "@styled-icons/boxicons-regular";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
interface Props {
|
||||
children: Children;
|
||||
description?: Children;
|
||||
|
||||
checked?: boolean;
|
||||
disabled?: boolean;
|
||||
onSelect?: () => void;
|
||||
}
|
||||
|
||||
interface BaseProps {
|
||||
selected: boolean;
|
||||
}
|
||||
|
||||
const RadioBase = styled.label<BaseProps>`
|
||||
gap: 4px;
|
||||
z-index: 1;
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
user-select: none;
|
||||
transition: 0.2s ease all;
|
||||
border-radius: var(--border-radius);
|
||||
|
||||
&:hover {
|
||||
background: var(--hover);
|
||||
}
|
||||
|
||||
> input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> div {
|
||||
margin: 4px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
background: var(--foreground);
|
||||
border-radius: var(--border-radius-half);
|
||||
|
||||
svg {
|
||||
color: var(--foreground);
|
||||
/*stroke-width: 2;*/
|
||||
}
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.selected &&
|
||||
css`
|
||||
color: white;
|
||||
cursor: default;
|
||||
background: var(--accent);
|
||||
|
||||
> div {
|
||||
background: white;
|
||||
}
|
||||
|
||||
> div svg {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--accent);
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
const RadioDescription = styled.span<BaseProps>`
|
||||
font-size: 0.8em;
|
||||
font-weight: 400;
|
||||
color: var(--secondary-foreground);
|
||||
|
||||
${(props) =>
|
||||
props.selected &&
|
||||
css`
|
||||
color: white;
|
||||
`}
|
||||
`;
|
||||
|
||||
export default function Radio(props: Props) {
|
||||
const selected = props.checked ?? false;
|
||||
return (
|
||||
<RadioBase
|
||||
selected={selected}
|
||||
disabled={props.disabled}
|
||||
onClick={() =>
|
||||
!props.disabled && props.onSelect && props.onSelect()
|
||||
}>
|
||||
<div>
|
||||
<Circle size={12} />
|
||||
</div>
|
||||
<input type="radio" checked={props.checked} />
|
||||
<span>
|
||||
<span>{props.children}</span>
|
||||
{props.description && (
|
||||
<RadioDescription selected={selected}>
|
||||
{props.description}
|
||||
</RadioDescription>
|
||||
)}
|
||||
</span>
|
||||
</RadioBase>
|
||||
);
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
import { Check, CloudUpload } from "@styled-icons/boxicons-regular";
|
||||
import { Pencil } from "@styled-icons/boxicons-solid";
|
||||
import styled from "styled-components/macro";
|
||||
|
||||
const StatusBase = styled.div`
|
||||
gap: 4px;
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-transform: capitalize;
|
||||
`;
|
||||
|
||||
export type EditStatus = "saved" | "editing" | "saving";
|
||||
interface Props {
|
||||
status: EditStatus;
|
||||
}
|
||||
|
||||
export default function SaveStatus({ status }: Props) {
|
||||
return (
|
||||
<StatusBase>
|
||||
{status === "saved" ? (
|
||||
<Check size={20} />
|
||||
) : status === "editing" ? (
|
||||
<Pencil size={20} />
|
||||
) : (
|
||||
<CloudUpload size={20} />
|
||||
)}
|
||||
{/* FIXME: add i18n */}
|
||||
<span>{status}</span>
|
||||
</StatusBase>
|
||||
);
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
.container {
|
||||
font-size: .875rem;
|
||||
line-height: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
width: 100%;
|
||||
white-space: pre-wrap;
|
||||
|
||||
textarea::placeholder {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.hide {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ghost {
|
||||
width: 100%;
|
||||
white-space: pre-wrap;
|
||||
|
||||
top: 0;
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
export interface TextAreaProps {
|
||||
code?: boolean;
|
||||
padding?: string;
|
||||
lineHeight?: string;
|
||||
hideBorder?: boolean;
|
||||
}
|
||||
|
||||
export const TEXT_AREA_BORDER_WIDTH = 2;
|
||||
export const DEFAULT_TEXT_AREA_PADDING = 16;
|
||||
export const DEFAULT_LINE_HEIGHT = 20;
|
||||
|
||||
export default styled.textarea<TextAreaProps>`
|
||||
width: 100%;
|
||||
resize: none;
|
||||
display: block;
|
||||
color: var(--foreground);
|
||||
background: var(--secondary-background);
|
||||
padding: ${(props) => props.padding ?? "var(--textarea-padding)"};
|
||||
line-height: ${(props) =>
|
||||
props.lineHeight ?? "var(--textarea-line-height)"};
|
||||
|
||||
${(props) =>
|
||||
props.hideBorder &&
|
||||
css`
|
||||
border: none;
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
!props.hideBorder &&
|
||||
css`
|
||||
border-radius: var(--border-radius);
|
||||
transition: border-color 0.2s ease-in-out;
|
||||
border: var(--input-border-width) solid transparent;
|
||||
`}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
|
||||
${(props) =>
|
||||
!props.hideBorder &&
|
||||
css`
|
||||
border: var(--input-border-width) solid var(--accent);
|
||||
`}
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.code
|
||||
? css`
|
||||
font-family: var(--monospace-font), monospace;
|
||||
`
|
||||
: css`
|
||||
font-family: inherit;
|
||||
`}
|
||||
|
||||
font-variant-ligatures: var(--ligatures);
|
||||
`;
|
|
@ -1,72 +0,0 @@
|
|||
import { InfoCircle } from "@styled-icons/boxicons-regular";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
interface Props {
|
||||
warning?: boolean;
|
||||
error?: boolean;
|
||||
}
|
||||
|
||||
export const Separator = styled.div<Props>`
|
||||
height: 1px;
|
||||
width: calc(100% - 10px);
|
||||
background: var(--secondary-header);
|
||||
margin: 18px auto;
|
||||
`;
|
||||
|
||||
export const TipBase = styled.div<Props>`
|
||||
display: flex;
|
||||
padding: 12px;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
|
||||
font-size: 14px;
|
||||
background: var(--primary-header);
|
||||
border-radius: var(--border-radius);
|
||||
border: 2px solid var(--secondary-header);
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
flex-shrink: 0;
|
||||
margin-inline-end: 10px;
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.warning &&
|
||||
css`
|
||||
color: var(--warning);
|
||||
border: 2px solid var(--warning);
|
||||
background: var(--secondary-header);
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.error &&
|
||||
css`
|
||||
color: white;
|
||||
border: 2px solid var(--error);
|
||||
background: var(--error);
|
||||
`}
|
||||
`;
|
||||
|
||||
export default function Tip(
|
||||
props: Props & { children: Children; hideSeparator?: boolean },
|
||||
) {
|
||||
const { children, hideSeparator, ...tipProps } = props;
|
||||
return (
|
||||
<>
|
||||
{!hideSeparator && <Separator />}
|
||||
<TipBase {...tipProps}>
|
||||
<InfoCircle size={20} />
|
||||
<span>{children}</span>
|
||||
</TipBase>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
import {
|
||||
ChevronRight,
|
||||
LinkExternal,
|
||||
Pencil,
|
||||
} from "@styled-icons/boxicons-regular";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { Children } from "../../../types/Preact";
|
||||
|
||||
interface BaseProps {
|
||||
readonly hover?: boolean;
|
||||
readonly account?: boolean;
|
||||
readonly disabled?: boolean;
|
||||
readonly largeDescription?: boolean;
|
||||
}
|
||||
|
||||
const CategoryBase = styled.div<BaseProps>`
|
||||
padding: 9.8px 12px;
|
||||
border-radius: var(--border-radius);
|
||||
margin-bottom: 10px;
|
||||
color: var(--foreground);
|
||||
background: var(--secondary-header);
|
||||
gap: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
overflow: hidden;
|
||||
|
||||
> svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.action {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
|
||||
.title {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.description {
|
||||
${(props) =>
|
||||
props.largeDescription
|
||||
? css`
|
||||
font-size: 14px;
|
||||
`
|
||||
: css`
|
||||
font-size: 11px;
|
||||
`}
|
||||
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
overflow: hidden;
|
||||
font-weight: 500;
|
||||
color: var(--secondary-foreground);
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.hover &&
|
||||
css`
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
transition: 0.1s ease background-color;
|
||||
|
||||
&:hover {
|
||||
background: var(--secondary-background);
|
||||
}
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.disabled &&
|
||||
css`
|
||||
opacity: 0.4;
|
||||
/*.content,
|
||||
.action {
|
||||
color: var(--tertiary-foreground);
|
||||
}*/
|
||||
|
||||
.action {
|
||||
font-size: 14px;
|
||||
}
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.account &&
|
||||
css`
|
||||
height: 54px;
|
||||
|
||||
.content {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
.title {
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
color: var(--secondary-foreground);
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 15px;
|
||||
font-weight: 500 !important;
|
||||
color: var(--foreground);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
interface Props extends BaseProps {
|
||||
icon?: Children;
|
||||
children?: Children;
|
||||
description?: Children;
|
||||
|
||||
onClick?: () => void;
|
||||
action?: "chevron" | "external" | Children;
|
||||
}
|
||||
|
||||
export default function CategoryButton({
|
||||
icon,
|
||||
children,
|
||||
description,
|
||||
account,
|
||||
disabled,
|
||||
onClick,
|
||||
hover,
|
||||
action,
|
||||
}: Props) {
|
||||
return (
|
||||
<CategoryBase
|
||||
hover={hover || typeof onClick !== "undefined"}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
account={account}>
|
||||
{icon}
|
||||
<div class="content">
|
||||
<div className="title">{children}</div>
|
||||
|
||||
<div className="description">{description}</div>
|
||||
</div>
|
||||
<div class="action">
|
||||
{typeof action === "string" ? (
|
||||
action === "chevron" ? (
|
||||
<ChevronRight size={24} />
|
||||
) : (
|
||||
<LinkExternal size={20} />
|
||||
)
|
||||
) : (
|
||||
action
|
||||
)}
|
||||
</div>
|
||||
</CategoryBase>
|
||||
);
|
||||
}
|
|
@ -5,9 +5,11 @@ import update from "dayjs/plugin/updateLocale";
|
|||
import defaultsDeep from "lodash.defaultsdeep";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
import { IntlProvider } from "preact-i18n";
|
||||
import { IntlProvider, Text } from "preact-i18n";
|
||||
import { useCallback, useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Error } from "@revoltchat/ui";
|
||||
|
||||
import { useApplicationState } from "../mobx/State";
|
||||
|
||||
import { Languages } from "../../external/lang/Languages";
|
||||
|
@ -143,3 +145,12 @@ function transformLanguage(source: Dictionary) {
|
|||
|
||||
return obj;
|
||||
}
|
||||
|
||||
export function I18nError({ error, children }: { error: any; children?: any }) {
|
||||
return (
|
||||
<Error
|
||||
error={error ? <Text id={error} children={error} /> : undefined}
|
||||
children={children}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,11 +4,15 @@ import { ContextMenuTrigger } from "preact-context-menu";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { LinkProvider, TextProvider, TrigProvider } from "@revoltchat/ui";
|
||||
import {
|
||||
LinkProvider,
|
||||
Preloader,
|
||||
TextProvider,
|
||||
TrigProvider,
|
||||
} from "@revoltchat/ui";
|
||||
|
||||
import { hydrateState } from "../mobx/State";
|
||||
|
||||
import Preloader from "../components/ui/Preloader";
|
||||
import { Children } from "../types/Preact";
|
||||
import Locale from "./Locale";
|
||||
import Theme from "./Theme";
|
||||
|
|
|
@ -5,13 +5,13 @@ import { API, Channel, Message, Server, User } from "revolt.js";
|
|||
import { createContext } from "preact";
|
||||
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
|
||||
|
||||
import type { Action } from "@revoltchat/ui/esm/components/design/atoms/display/Modal";
|
||||
|
||||
import { internalSubscribe } from "../../lib/eventEmitter";
|
||||
import { determineLink } from "../../lib/links";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import { Action } from "../../components/ui/Modal";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
import Modals from "./Modals";
|
||||
|
||||
|
@ -24,7 +24,7 @@ export type Screen =
|
|||
| { id: "clipboard"; text: string }
|
||||
| { id: "token_reveal"; token: string; username: string }
|
||||
| { id: "external_link_prompt"; link: string }
|
||||
| { id: "sessions", confirm: () => void }
|
||||
| { id: "sessions"; confirm: () => void }
|
||||
| {
|
||||
id: "_prompt";
|
||||
question: Children;
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import { internalEmit } from "../../lib/eventEmitter";
|
||||
|
||||
import { isModalClosing } from "../../components/ui/Modal";
|
||||
|
||||
//import { isModalClosing } from "../../components/ui/Modal";
|
||||
import { Screen } from "./Intermediate";
|
||||
import { ClipboardModal } from "./modals/Clipboard";
|
||||
import { ErrorModal } from "./modals/Error";
|
||||
import { ExternalLinkModal } from "./modals/ExternalLinkPrompt";
|
||||
import { InputModal } from "./modals/Input";
|
||||
import { OnboardingModal } from "./modals/Onboarding";
|
||||
import { PromptModal } from "./modals/Prompt";
|
||||
import { SignedOutModal } from "./modals/SignedOut";
|
||||
import { ExternalLinkModal} from "./modals/ExternalLinkPrompt";
|
||||
import { SessionsModal } from "./modals/SessionsPrompt";
|
||||
import { SignedOutModal } from "./modals/SignedOut";
|
||||
import { TokenRevealModal } from "./modals/TokenReveal";
|
||||
|
||||
export interface Props {
|
||||
|
@ -20,9 +19,9 @@ export interface Props {
|
|||
|
||||
export default function Modals({ screen, openScreen }: Props) {
|
||||
const onClose = () =>
|
||||
isModalClosing || screen.id === "onboarding"
|
||||
? openScreen({ id: "none" })
|
||||
: internalEmit("Modal", "close");
|
||||
//isModalClosing || screen.id === "onboarding"
|
||||
openScreen({ id: "none" });
|
||||
// : internalEmit("Modal", "close");
|
||||
|
||||
switch (screen.id) {
|
||||
case "_prompt":
|
||||
|
|
|
@ -2,8 +2,6 @@ import { useContext } from "preact/hooks";
|
|||
|
||||
import { internalEmit } from "../../lib/eventEmitter";
|
||||
|
||||
import { isModalClosing } from "../../components/ui/Modal";
|
||||
|
||||
import { IntermediateContext, useIntermediate } from "./Intermediate";
|
||||
import { SpecialInputModal } from "./modals/Input";
|
||||
import { SpecialPromptModal } from "./modals/Prompt";
|
||||
|
@ -21,9 +19,9 @@ export default function Popovers() {
|
|||
const { openScreen } = useIntermediate();
|
||||
|
||||
const onClose = () =>
|
||||
isModalClosing
|
||||
? openScreen({ id: "none" })
|
||||
: internalEmit("Modal", "close");
|
||||
//isModalClosing
|
||||
openScreen({ id: "none" });
|
||||
//: internalEmit("Modal", "close");
|
||||
|
||||
switch (screen.id) {
|
||||
case "profile":
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Text } from "preact-i18n";
|
||||
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
|
@ -10,7 +10,6 @@ interface Props {
|
|||
export function ClipboardModal({ onClose, text }: Props) {
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
onClose={onClose}
|
||||
title={<Text id="app.special.modals.clipboard.unavailable" />}
|
||||
actions={[
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Text } from "preact-i18n";
|
||||
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
|
@ -10,7 +10,6 @@ interface Props {
|
|||
export function ErrorModal({ onClose, error }: Props) {
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
onClose={onClose}
|
||||
title={<Text id="app.special.modals.error" />}
|
||||
actions={[
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Text } from "preact-i18n";
|
||||
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
|
||||
import { useIntermediate } from "../Intermediate";
|
||||
|
||||
|
@ -17,7 +17,6 @@ export function ExternalLinkModal({ onClose, link }: Props) {
|
|||
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
onClose={onClose}
|
||||
title={<Text id={"app.special.modals.external_links.title"} />}
|
||||
actions={[
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
import { useHistory } from "react-router";
|
||||
import { Server } from "revolt.js";
|
||||
import { ulid } from "ulid";
|
||||
|
||||
import { Text } from "preact-i18n";
|
||||
import { useContext, useState } from "preact/hooks";
|
||||
|
||||
import InputBox from "../../../components/ui/InputBox";
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import Overline from "../../../components/ui/Overline";
|
||||
import { Category, InputBox, Modal } from "@revoltchat/ui";
|
||||
|
||||
import { Children } from "../../../types/Preact";
|
||||
import { I18nError } from "../../Locale";
|
||||
import { AppContext } from "../../revoltjs/RevoltClient";
|
||||
import { takeError } from "../../revoltjs/util";
|
||||
|
||||
|
@ -36,7 +34,6 @@ export function InputModal({
|
|||
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
title={question}
|
||||
description={description}
|
||||
disabled={processing}
|
||||
|
@ -61,11 +58,15 @@ export function InputModal({
|
|||
]}
|
||||
onClose={onClose}>
|
||||
{field ? (
|
||||
<Overline error={error} block>
|
||||
{field}
|
||||
</Overline>
|
||||
<Category>
|
||||
<I18nError error={error}>{field}</I18nError>
|
||||
</Category>
|
||||
) : (
|
||||
error && <Overline error={error} type="error" block />
|
||||
error && (
|
||||
<Category>
|
||||
<I18nError error={error} />
|
||||
</Category>
|
||||
)
|
||||
)}
|
||||
<InputBox
|
||||
value={value}
|
||||
|
|
|
@ -4,9 +4,8 @@ import styles from "./Onboarding.module.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, Preloader } from "@revoltchat/ui";
|
||||
|
||||
import Preloader from "../../../components/ui/Preloader";
|
||||
import wideSVG from "/assets/wide.svg";
|
||||
|
||||
import FormField from "../../../pages/login/FormField";
|
||||
|
|
|
@ -7,16 +7,15 @@ import styles from "./Prompt.module.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext, useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Category, Modal, InputBox, Radio } from "@revoltchat/ui";
|
||||
import type { Action } from "@revoltchat/ui/esm/components/design/atoms/display/Modal";
|
||||
|
||||
import { TextReact } from "../../../lib/i18n";
|
||||
|
||||
import Message from "../../../components/common/messaging/Message";
|
||||
import UserIcon from "../../../components/common/user/UserIcon";
|
||||
import InputBox from "../../../components/ui/InputBox";
|
||||
import Modal, { Action } from "../../../components/ui/Modal";
|
||||
import Overline from "../../../components/ui/Overline";
|
||||
import Radio from "../../../components/ui/Radio";
|
||||
|
||||
import { Children } from "../../../types/Preact";
|
||||
import { I18nError } from "../../Locale";
|
||||
import { AppContext } from "../../revoltjs/RevoltClient";
|
||||
import { takeError } from "../../revoltjs/util";
|
||||
import { useIntermediate } from "../Intermediate";
|
||||
|
@ -40,12 +39,15 @@ export function PromptModal({
|
|||
}: Props) {
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
title={question}
|
||||
actions={actions}
|
||||
onClose={onClose}
|
||||
disabled={disabled}>
|
||||
{error && <Overline error={error} type="error" />}
|
||||
{error && (
|
||||
<Category>
|
||||
<I18nError error={error} />
|
||||
</Category>
|
||||
)}
|
||||
{content}
|
||||
</Modal>
|
||||
);
|
||||
|
@ -386,9 +388,9 @@ export const SpecialPromptModal = observer((props: SpecialProps) => {
|
|||
id="app.special.modals.prompt.confirm_ban"
|
||||
fields={{ name: props.user?.username }}
|
||||
/>
|
||||
<Overline>
|
||||
<Category>
|
||||
<Text id="app.special.modals.prompt.confirm_ban_reason" />
|
||||
</Overline>
|
||||
</Category>
|
||||
<InputBox
|
||||
value={reason ?? ""}
|
||||
onChange={(e) =>
|
||||
|
@ -453,22 +455,26 @@ export const SpecialPromptModal = observer((props: SpecialProps) => {
|
|||
]}
|
||||
content={
|
||||
<>
|
||||
<Overline block type="subtle">
|
||||
<Category>
|
||||
<Text id="app.main.servers.channel_type" />
|
||||
</Overline>
|
||||
</Category>
|
||||
<Radio
|
||||
checked={type === "Text"}
|
||||
onSelect={() => setType("Text")}>
|
||||
<Text id="app.main.servers.text_channel" />
|
||||
</Radio>
|
||||
title={
|
||||
<Text id="app.main.servers.text_channel" />
|
||||
}
|
||||
value={type === "Text"}
|
||||
onSelect={() => setType("Text")}
|
||||
/>
|
||||
<Radio
|
||||
checked={type === "Voice"}
|
||||
onSelect={() => setType("Voice")}>
|
||||
<Text id="app.main.servers.voice_channel" />
|
||||
</Radio>
|
||||
<Overline block type="subtle">
|
||||
title={
|
||||
<Text id="app.main.servers.voice_channel" />
|
||||
}
|
||||
value={type === "Voice"}
|
||||
onSelect={() => setType("Voice")}
|
||||
/>
|
||||
<Category>
|
||||
<Text id="app.main.servers.channel_name" />
|
||||
</Overline>
|
||||
</Category>
|
||||
<InputBox
|
||||
value={name}
|
||||
onChange={(e) => setName(e.currentTarget.value)}
|
||||
|
@ -524,9 +530,9 @@ export const SpecialPromptModal = observer((props: SpecialProps) => {
|
|||
]}
|
||||
content={
|
||||
<>
|
||||
<Overline block type="subtle">
|
||||
<Category>
|
||||
<Text id="app.main.servers.category_name" />
|
||||
</Overline>
|
||||
</Category>
|
||||
<InputBox
|
||||
value={name}
|
||||
onChange={(e) => setName(e.currentTarget.value)}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Text } from "preact-i18n";
|
||||
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
|
@ -10,7 +10,6 @@ interface Props {
|
|||
export function SessionsModal({ onClose, confirm }: Props) {
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
onClose={onClose}
|
||||
title={<Text id={"app.special.modals.sessions.title"} />}
|
||||
actions={[
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Text } from "preact-i18n";
|
||||
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
|
@ -9,7 +9,6 @@ interface Props {
|
|||
export function SignedOutModal({ onClose }: Props) {
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
onClose={onClose}
|
||||
title={<Text id="app.special.modals.signed_out" />}
|
||||
actions={[
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Text } from "preact-i18n";
|
||||
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
|
@ -11,7 +11,6 @@ interface Props {
|
|||
export function TokenRevealModal({ onClose, token, username }: Props) {
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
onClose={onClose}
|
||||
title={
|
||||
<Text
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Channel } from "revolt.js";
|
|||
|
||||
import styles from "./ChannelInfo.module.scss";
|
||||
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
import Markdown from "../../../components/markdown/Markdown";
|
||||
import { getChannelName } from "../../revoltjs/util";
|
||||
|
@ -24,7 +24,7 @@ export const ChannelInfo = observer(({ channel, onClose }: Props) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<Modal visible={true} onClose={onClose}>
|
||||
<Modal onClose={onClose}>
|
||||
<div className={styles.info}>
|
||||
<div className={styles.header}>
|
||||
<h1>{getChannelName(channel, true)}</h1>
|
||||
|
|
|
@ -4,10 +4,10 @@ import { API } from "revolt.js";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext, useState } from "preact/hooks";
|
||||
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import Overline from "../../../components/ui/Overline";
|
||||
import { Category, Modal } from "@revoltchat/ui";
|
||||
|
||||
import FormField from "../../../pages/login/FormField";
|
||||
import { I18nError } from "../../Locale";
|
||||
import { AppContext } from "../../revoltjs/RevoltClient";
|
||||
import { takeError } from "../../revoltjs/util";
|
||||
|
||||
|
@ -37,7 +37,6 @@ export function CreateBotModal({ onClose, onCreate }: Props) {
|
|||
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
onClose={onClose}
|
||||
title={<Text id="app.special.popovers.create_bot.title" />}
|
||||
actions={[
|
||||
|
@ -70,9 +69,10 @@ export function CreateBotModal({ onClose, onCreate }: Props) {
|
|||
error={errors.name?.message}
|
||||
/>
|
||||
{error && (
|
||||
<Overline type="error" error={error}>
|
||||
<Text id="app.special.popovers.create_bot.failed" />
|
||||
</Overline>
|
||||
<Category>
|
||||
<Text id="app.special.popovers.create_bot.failed" />{" "}
|
||||
· <I18nError error={error} />
|
||||
</Category>
|
||||
)}
|
||||
</form>
|
||||
</Modal>
|
||||
|
|
|
@ -3,10 +3,10 @@ import { API } from "revolt.js";
|
|||
|
||||
import styles from "./ImageViewer.module.scss";
|
||||
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
import AttachmentActions from "../../../components/common/messaging/attachments/AttachmentActions";
|
||||
import EmbedMediaActions from "../../../components/common/messaging/embed/EmbedMediaActions";
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
|
||||
import { useClient } from "../../revoltjs/RevoltClient";
|
||||
|
||||
interface Props {
|
||||
|
@ -28,7 +28,7 @@ export function ImageViewer({ attachment, embed, onClose }: Props) {
|
|||
const client = useClient();
|
||||
|
||||
return (
|
||||
<Modal visible={true} onClose={onClose} noBackground>
|
||||
<Modal onClose={onClose} transparent maxHeight="100vh" maxWidth="100vw">
|
||||
<div className={styles.viewer}>
|
||||
{attachment && (
|
||||
<>
|
||||
|
|
|
@ -3,8 +3,7 @@ import { SubmitHandler, useForm } from "react-hook-form";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext, useState } from "preact/hooks";
|
||||
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import Overline from "../../../components/ui/Overline";
|
||||
import { Category, Error, Modal } from "@revoltchat/ui";
|
||||
|
||||
import FormField from "../../../pages/login/FormField";
|
||||
import { AppContext } from "../../revoltjs/RevoltClient";
|
||||
|
@ -69,13 +68,11 @@ export function ModifyAccountModal({ onClose, field }: Props) {
|
|||
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
onClose={onClose}
|
||||
title={<Text id={`app.special.modals.account.change.${field}`} />}
|
||||
disabled={processing}
|
||||
actions={[
|
||||
{
|
||||
disabled: processing,
|
||||
confirmation: true,
|
||||
onClick: handleSubmit(onSubmit),
|
||||
children:
|
||||
|
@ -140,9 +137,13 @@ export function ModifyAccountModal({ onClose, field }: Props) {
|
|||
disabled={processing}
|
||||
/>
|
||||
{error && (
|
||||
<Overline type="error" error={error}>
|
||||
<Text id="app.special.modals.account.failed" />
|
||||
</Overline>
|
||||
<Category compact>
|
||||
<Error
|
||||
error={
|
||||
<Text id="app.special.modals.account.failed" />
|
||||
}
|
||||
/>
|
||||
</Category>
|
||||
)}
|
||||
</form>
|
||||
</Modal>
|
||||
|
|
|
@ -4,7 +4,7 @@ import { User } from "revolt.js";
|
|||
import styles from "./UserPicker.module.scss";
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
import { Friend } from "../../../pages/friends/Friend";
|
||||
|
||||
|
@ -16,7 +16,6 @@ interface Props {
|
|||
export const PendingRequests = observer(({ users, onClose }: Props) => {
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
title={<Text id="app.special.friends.pending" />}
|
||||
onClose={onClose}>
|
||||
<div className={styles.list}>
|
||||
|
|
|
@ -5,14 +5,10 @@ import styles from "./ServerIdentityModal.module.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, Category, InputBox, Modal } from "@revoltchat/ui";
|
||||
|
||||
import { noop } from "../../../lib/js";
|
||||
|
||||
import InputBox from "../../../components/ui/InputBox";
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import Overline from "../../../components/ui/Overline";
|
||||
|
||||
import { FileUploader } from "../../revoltjs/FileUploads";
|
||||
import { useClient } from "../../revoltjs/RevoltClient";
|
||||
|
||||
|
@ -39,7 +35,6 @@ export const ServerIdentityModal = observer(({ server, onClose }: Props) => {
|
|||
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
title={
|
||||
<Text
|
||||
id={"app.special.popovers.server_identity.title"}
|
||||
|
@ -49,9 +44,9 @@ export const ServerIdentityModal = observer(({ server, onClose }: Props) => {
|
|||
onClose={onClose}>
|
||||
<div className={styles.identityMain}>
|
||||
<div>
|
||||
<Overline type="subtle">
|
||||
<Category>
|
||||
<Text id="app.special.popovers.server_identity.avatar" />
|
||||
</Overline>
|
||||
</Category>
|
||||
<FileUploader
|
||||
width={80}
|
||||
height={80}
|
||||
|
@ -80,9 +75,9 @@ export const ServerIdentityModal = observer(({ server, onClose }: Props) => {
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Overline type="subtle">
|
||||
<Category>
|
||||
<Text id="app.special.popovers.server_identity.nickname" />
|
||||
</Overline>
|
||||
</Category>
|
||||
<InputBox
|
||||
value={nickname}
|
||||
placeholder={client.user!.username}
|
||||
|
|
|
@ -2,9 +2,9 @@ import styles from "./UserPicker.module.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useState } from "preact/hooks";
|
||||
|
||||
import UserCheckbox from "../../../components/common/user/UserCheckbox";
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
import UserCheckbox from "../../../components/common/user/UserCheckbox";
|
||||
import { useClient } from "../../revoltjs/RevoltClient";
|
||||
|
||||
interface Props {
|
||||
|
@ -21,7 +21,6 @@ export function UserPicker(props: Props) {
|
|||
|
||||
return (
|
||||
<Modal
|
||||
visible={true}
|
||||
title={<Text id="app.special.popovers.user_picker.select" />}
|
||||
onClose={props.onClose}
|
||||
actions={[
|
||||
|
@ -42,7 +41,7 @@ export function UserPicker(props: Props) {
|
|||
<UserCheckbox
|
||||
key={x._id}
|
||||
user={x}
|
||||
checked={selected.includes(x._id)}
|
||||
value={selected.includes(x._id)}
|
||||
onChange={(v) => {
|
||||
if (v) {
|
||||
setSelected([...selected, x._id]);
|
||||
|
|
|
@ -15,7 +15,14 @@ import styles from "./UserProfile.module.scss";
|
|||
import { Localizer, Text } from "preact-i18n";
|
||||
import { useContext, useEffect, useLayoutEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import {
|
||||
Button,
|
||||
Category,
|
||||
Error,
|
||||
IconButton,
|
||||
Modal,
|
||||
Preloader,
|
||||
} from "@revoltchat/ui";
|
||||
|
||||
import { noop } from "../../../lib/js";
|
||||
|
||||
|
@ -26,11 +33,6 @@ import UserBadges from "../../../components/common/user/UserBadges";
|
|||
import UserIcon from "../../../components/common/user/UserIcon";
|
||||
import { Username } from "../../../components/common/user/UserShort";
|
||||
import UserStatus from "../../../components/common/user/UserStatus";
|
||||
import IconButton from "../../../components/ui/IconButton";
|
||||
import Modal from "../../../components/ui/Modal";
|
||||
import Overline from "../../../components/ui/Overline";
|
||||
import Preloader from "../../../components/ui/Preloader";
|
||||
|
||||
import Markdown from "../../../components/markdown/Markdown";
|
||||
import {
|
||||
ClientStatus,
|
||||
|
@ -147,13 +149,8 @@ export const UserProfile = observer(
|
|||
const badges = user.badges ?? 0;
|
||||
const flags = user.flags ?? 0;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible
|
||||
border={dummy}
|
||||
padding={false}
|
||||
onClose={onClose}
|
||||
dontModal={dummy}>
|
||||
const children = (
|
||||
<>
|
||||
<div
|
||||
className={styles.header}
|
||||
data-force={profile?.background ? "light" : undefined}
|
||||
|
@ -281,19 +278,19 @@ export const UserProfile = observer(
|
|||
<div>
|
||||
{flags & 1 ? (
|
||||
/** ! FIXME: i18n this area */
|
||||
<Overline type="error" block>
|
||||
User is suspended
|
||||
</Overline>
|
||||
<Category>
|
||||
<Error error="User is suspended" />
|
||||
</Category>
|
||||
) : undefined}
|
||||
{flags & 2 ? (
|
||||
<Overline type="error" block>
|
||||
User deleted their account
|
||||
</Overline>
|
||||
<Category>
|
||||
<Error error="User deleted their account" />
|
||||
</Category>
|
||||
) : undefined}
|
||||
{flags & 4 ? (
|
||||
<Overline type="error" block>
|
||||
User is banned
|
||||
</Overline>
|
||||
<Category>
|
||||
<Error error="User is banned" />
|
||||
</Category>
|
||||
) : undefined}
|
||||
{user.bot ? (
|
||||
<>
|
||||
|
@ -441,6 +438,18 @@ export const UserProfile = observer(
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
if (dummy) return <div>{children}</div>;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
onClose={onClose}
|
||||
nonDismissable={dummy}
|
||||
transparent
|
||||
maxWidth="560px">
|
||||
{children}
|
||||
</Modal>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -7,10 +7,9 @@ import classNames from "classnames";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext, useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { determineFileSize } from "../../lib/fileSize";
|
||||
import { IconButton, Preloader } from "@revoltchat/ui";
|
||||
|
||||
import IconButton from "../../components/ui/IconButton";
|
||||
import Preloader from "../../components/ui/Preloader";
|
||||
import { determineFileSize } from "../../lib/fileSize";
|
||||
|
||||
import { useIntermediate } from "../intermediate/Intermediate";
|
||||
import { AppContext } from "./RevoltClient";
|
||||
|
|
|
@ -4,7 +4,7 @@ import styled from "styled-components/macro";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext } from "preact/hooks";
|
||||
|
||||
import Preloader from "../../components/ui/Preloader";
|
||||
import { Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
import { ClientStatus, StatusContext } from "./RevoltClient";
|
||||
|
|
|
@ -3,7 +3,9 @@ import { observer } from "mobx-react-lite";
|
|||
import { Client } from "revolt.js";
|
||||
|
||||
import { createContext } from "preact";
|
||||
import { useContext, useEffect, useMemo, useState } from "preact/hooks";
|
||||
import { useContext, useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
|
|
|
@ -1,15 +1,4 @@
|
|||
import {
|
||||
At,
|
||||
Bell,
|
||||
BellOff,
|
||||
Check,
|
||||
CheckSquare,
|
||||
ChevronRight,
|
||||
Block,
|
||||
Square,
|
||||
LeftArrowAlt,
|
||||
Trash,
|
||||
} from "@styled-icons/boxicons-regular";
|
||||
import { ChevronRight, Trash } from "@styled-icons/boxicons-regular";
|
||||
import { Cog, UserVoice } from "@styled-icons/boxicons-solid";
|
||||
import { isFirefox } from "react-device-detect";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
@ -24,6 +13,8 @@ import {
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext } from "preact/hooks";
|
||||
|
||||
import { IconButton, LineDivider } from "@revoltchat/ui";
|
||||
|
||||
import { useApplicationState } from "../mobx/State";
|
||||
import { QueuedMessage } from "../mobx/stores/MessageQueue";
|
||||
import { NotificationState } from "../mobx/stores/NotificationOptions";
|
||||
|
@ -39,9 +30,6 @@ import CMNotifications from "./contextmenu/CMNotifications";
|
|||
|
||||
import Tooltip from "../components/common/Tooltip";
|
||||
import UserStatus from "../components/common/user/UserStatus";
|
||||
import IconButton from "../components/ui/IconButton";
|
||||
import LineDivider from "../components/ui/LineDivider";
|
||||
|
||||
import { Children } from "../types/Preact";
|
||||
import { internalEmit } from "./eventEmitter";
|
||||
import { getRenderer } from "./renderer/Singleton";
|
||||
|
@ -492,7 +480,7 @@ export default function ContextMenus() {
|
|||
function pushDivider() {
|
||||
if (lastDivider || elements.length === 0) return;
|
||||
lastDivider = true;
|
||||
elements.push(<LineDivider />);
|
||||
elements.push(<LineDivider compact />);
|
||||
}
|
||||
|
||||
if (server_list) {
|
||||
|
@ -1045,7 +1033,7 @@ export default function ContextMenus() {
|
|||
</MenuItem>
|
||||
</IconButton>
|
||||
</div>
|
||||
<LineDivider />
|
||||
<LineDivider compact />
|
||||
<MenuItem
|
||||
data={{
|
||||
action: "set_presence",
|
||||
|
@ -1082,7 +1070,7 @@ export default function ContextMenus() {
|
|||
<div className="indicator invisible" />
|
||||
<Text id={`app.status.invisible`} />
|
||||
</MenuItem>
|
||||
<LineDivider />
|
||||
<LineDivider compact />
|
||||
<MenuItem
|
||||
data={{ action: "set_status" }}
|
||||
disabled={!isOnline}>
|
||||
|
|
|
@ -3,7 +3,8 @@ import styled from "styled-components/macro";
|
|||
import { RefObject } from "preact";
|
||||
import { useEffect, useLayoutEffect, useRef } from "preact/hooks";
|
||||
|
||||
import TextArea, { TextAreaProps } from "../components/ui/TextArea";
|
||||
import { TextArea } from "@revoltchat/ui";
|
||||
import type { TextAreaProps } from "@revoltchat/ui/esm/components/design/atoms/inputs/TextArea";
|
||||
|
||||
import { internalSubscribe } from "./eventEmitter";
|
||||
import { isTouchscreenDevice } from "./isTouchscreenDevice";
|
||||
|
|
|
@ -15,11 +15,11 @@ import { Server } from "revolt.js";
|
|||
import { ContextMenuWithData, MenuItem } from "preact-context-menu";
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import { LineDivider } from "@revoltchat/ui";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
import { NotificationState } from "../../mobx/stores/NotificationOptions";
|
||||
|
||||
import LineDivider from "../../components/ui/LineDivider";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
interface Action {
|
||||
|
|
|
@ -4,6 +4,8 @@ import { useHistory, useParams } from "react-router-dom";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext, useEffect } from "preact/hooks";
|
||||
|
||||
import { Header } from "@revoltchat/ui";
|
||||
|
||||
import { useIntermediate } from "../context/intermediate/Intermediate";
|
||||
import {
|
||||
AppContext,
|
||||
|
@ -11,8 +13,6 @@ import {
|
|||
StatusContext,
|
||||
} from "../context/revoltjs/RevoltClient";
|
||||
|
||||
import Header from "../components/ui/Header";
|
||||
|
||||
export default function Open() {
|
||||
const history = useHistory();
|
||||
const client = useContext(AppContext);
|
||||
|
@ -22,7 +22,7 @@ export default function Open() {
|
|||
|
||||
if (status !== ClientStatus.ONLINE) {
|
||||
return (
|
||||
<Header placement="primary">
|
||||
<Header palette="primary">
|
||||
<Text id="general.loading" />
|
||||
</Header>
|
||||
);
|
||||
|
@ -72,7 +72,7 @@ export default function Open() {
|
|||
});
|
||||
|
||||
return (
|
||||
<Header placement="primary">
|
||||
<Header palette="primary">
|
||||
<Text id="general.loading" />
|
||||
</Header>
|
||||
);
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Route, Switch } from "react-router-dom";
|
|||
|
||||
import { lazy, Suspense } from "preact/compat";
|
||||
|
||||
import { Masks } from "@revoltchat/ui";
|
||||
import { Masks, Preloader } from "@revoltchat/ui";
|
||||
|
||||
import ErrorBoundary from "../lib/ErrorBoundary";
|
||||
import FakeClient from "../lib/FakeClient";
|
||||
|
@ -10,7 +10,6 @@ import FakeClient from "../lib/FakeClient";
|
|||
import Context from "../context";
|
||||
import { CheckAuth } from "../context/revoltjs/CheckAuth";
|
||||
|
||||
import Preloader from "../components/ui/Preloader";
|
||||
import Invite from "./invite/Invite";
|
||||
|
||||
const Login = lazy(() => import("./login/Login"));
|
||||
|
|
|
@ -1,31 +1,19 @@
|
|||
import {
|
||||
At,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Hash,
|
||||
} from "@styled-icons/boxicons-regular";
|
||||
import { At, Hash } from "@styled-icons/boxicons-regular";
|
||||
import { Notepad, Group } from "@styled-icons/boxicons-solid";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Channel } from "revolt.js";
|
||||
import { User } from "revolt.js";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
import styled from "styled-components/macro";
|
||||
|
||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
import { SIDEBAR_CHANNELS, SIDEBAR_MEMBERS } from "../../mobx/stores/Layout";
|
||||
|
||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
||||
import { getChannelName } from "../../context/revoltjs/util";
|
||||
|
||||
import { useStatusColour } from "../../components/common/user/UserIcon";
|
||||
import UserStatus from "../../components/common/user/UserStatus";
|
||||
import Header, {
|
||||
HamburgerAction,
|
||||
PageHeader,
|
||||
} from "../../components/ui/Header";
|
||||
|
||||
import Markdown from "../../components/markdown/Markdown";
|
||||
import { PageHeader } from "../../components/ui/Header";
|
||||
import HeaderActions from "./actions/HeaderActions";
|
||||
|
||||
export interface ChannelHeaderProps {
|
||||
|
@ -98,7 +86,7 @@ export default observer(({ channel }: ChannelHeaderProps) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<PageHeader icon={icon} transparent>
|
||||
<PageHeader icon={icon} withTransparency>
|
||||
<Info>
|
||||
<span className="name">{name}</span>
|
||||
{isTouchscreenDevice &&
|
||||
|
|
|
@ -11,6 +11,8 @@ import { observer } from "mobx-react-lite";
|
|||
import { useHistory } from "react-router-dom";
|
||||
import styled, { css } from "styled-components/macro";
|
||||
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import { chainedDefer, defer } from "../../../lib/defer";
|
||||
import { internalEmit } from "../../../lib/eventEmitter";
|
||||
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||
|
@ -22,8 +24,6 @@ import { SIDEBAR_MEMBERS } from "../../../mobx/stores/Layout";
|
|||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
||||
|
||||
import UpdateIndicator from "../../../components/common/UpdateIndicator";
|
||||
import IconButton from "../../../components/ui/IconButton";
|
||||
|
||||
import { ChannelHeaderProps } from "../ChannelHeader";
|
||||
|
||||
const Container = styled.div`
|
||||
|
|
|
@ -16,6 +16,8 @@ import {
|
|||
useState,
|
||||
} from "preact/hooks";
|
||||
|
||||
import { Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { defer } from "../../../lib/defer";
|
||||
import { internalEmit, internalSubscribe } from "../../../lib/eventEmitter";
|
||||
import { getRenderer } from "../../../lib/renderer/Singleton";
|
||||
|
@ -28,8 +30,6 @@ import {
|
|||
StatusContext,
|
||||
} from "../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import Preloader from "../../../components/ui/Preloader";
|
||||
|
||||
import ConversationStart from "./ConversationStart";
|
||||
import MessageRenderer from "./MessageRenderer";
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import { X } from "@styled-icons/boxicons-regular";
|
||||
import dayjs from "dayjs";
|
||||
import isEqual from "lodash.isequal";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { API } from "revolt.js";
|
||||
|
@ -11,6 +12,8 @@ import { decodeTime } from "ulid";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { MessageDivider, Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { internalSubscribe, internalEmit } from "../../../lib/eventEmitter";
|
||||
import { ChannelRenderer } from "../../../lib/renderer/Singleton";
|
||||
|
||||
|
@ -21,9 +24,6 @@ import { useClient } from "../../../context/revoltjs/RevoltClient";
|
|||
|
||||
import Message from "../../../components/common/messaging/Message";
|
||||
import { SystemMessage } from "../../../components/common/messaging/SystemMessage";
|
||||
import DateDivider from "../../../components/ui/DateDivider";
|
||||
import Preloader from "../../../components/ui/Preloader";
|
||||
|
||||
import { Children } from "../../../types/Preact";
|
||||
import ConversationStart from "./ConversationStart";
|
||||
import MessageEditor from "./MessageEditor";
|
||||
|
@ -125,7 +125,12 @@ export default observer(({ last_id, renderer, highlight }: Props) => {
|
|||
}
|
||||
|
||||
if (unread || date) {
|
||||
render.push(<DateDivider date={date} unread={unread} />);
|
||||
render.push(
|
||||
<MessageDivider
|
||||
date={dayjs(date).format("LL")}
|
||||
unread={unread}
|
||||
/>,
|
||||
);
|
||||
head = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import { TextReact } from "../../lib/i18n";
|
|||
|
||||
import { AppContext } from "../../context/revoltjs/RevoltClient";
|
||||
|
||||
import Header, { PageHeader } from "../../components/ui/Header";
|
||||
import { PageHeader } from "../../components/ui/Header";
|
||||
|
||||
export default function Developer() {
|
||||
// const voice = useContext(VoiceContext);
|
||||
|
|
|
@ -5,6 +5,8 @@ import styled, { css } from "styled-components/macro";
|
|||
|
||||
import { useEffect, useMemo, useRef, useState } from "preact/hooks";
|
||||
|
||||
import { Header, Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
@ -12,9 +14,6 @@ import { useApplicationState } from "../../mobx/State";
|
|||
import { Overrides } from "../../context/Theme";
|
||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
||||
|
||||
import Header from "../../components/ui/Header";
|
||||
import Preloader from "../../components/ui/Preloader";
|
||||
|
||||
const Container = styled.div`
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
|
@ -164,7 +163,7 @@ export default function Discover() {
|
|||
return (
|
||||
<Container>
|
||||
{isTouchscreenDevice && (
|
||||
<Header placement="primary" transparent>
|
||||
<Header palette="primary" withTransparency>
|
||||
<Compass size={27} />
|
||||
Discover
|
||||
</Header>
|
||||
|
|
|
@ -6,10 +6,11 @@ import { User } from "revolt.js";
|
|||
|
||||
import styles from "./Friend.module.scss";
|
||||
import classNames from "classnames";
|
||||
import { Ref } from "preact";
|
||||
import { useTriggerEvents } from "preact-context-menu";
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import { stopPropagation } from "../../lib/stopPropagation";
|
||||
import { voiceState } from "../../lib/vortex/VoiceState";
|
||||
|
||||
|
@ -17,8 +18,6 @@ import { useIntermediate } from "../../context/intermediate/Intermediate";
|
|||
|
||||
import UserIcon from "../../components/common/user/UserIcon";
|
||||
import UserStatus from "../../components/common/user/UserStatus";
|
||||
import IconButton from "../../components/ui/IconButton";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
interface Props {
|
||||
|
@ -37,7 +36,7 @@ export const Friend = observer(({ user }: Props) => {
|
|||
actions.push(
|
||||
<>
|
||||
<IconButton
|
||||
type="circle"
|
||||
shape="circle"
|
||||
className={classNames(styles.button, styles.success)}
|
||||
onClick={(ev) =>
|
||||
stopPropagation(
|
||||
|
@ -51,7 +50,7 @@ export const Friend = observer(({ user }: Props) => {
|
|||
<PhoneCall size={20} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
type="circle"
|
||||
shape="circle"
|
||||
className={styles.button}
|
||||
onClick={(ev) =>
|
||||
stopPropagation(
|
||||
|
@ -72,7 +71,7 @@ export const Friend = observer(({ user }: Props) => {
|
|||
if (user.relationship === "Incoming") {
|
||||
actions.push(
|
||||
<IconButton
|
||||
type="circle"
|
||||
shape="circle"
|
||||
className={styles.button}
|
||||
onClick={(ev) => stopPropagation(ev, user.addFriend())}>
|
||||
<Plus size={24} />
|
||||
|
@ -93,7 +92,7 @@ export const Friend = observer(({ user }: Props) => {
|
|||
) {
|
||||
actions.push(
|
||||
<IconButton
|
||||
type="circle"
|
||||
shape="circle"
|
||||
className={classNames(
|
||||
styles.button,
|
||||
styles.remove,
|
||||
|
@ -119,7 +118,7 @@ export const Friend = observer(({ user }: Props) => {
|
|||
if (user.relationship === "Blocked") {
|
||||
actions.push(
|
||||
<IconButton
|
||||
type="circle"
|
||||
shape="circle"
|
||||
className={classNames(styles.button, styles.error)}
|
||||
onClick={(ev) => stopPropagation(ev, user.unblockUser())}>
|
||||
<UserX size={24} />
|
||||
|
|
|
@ -7,6 +7,8 @@ import styles from "./Friend.module.scss";
|
|||
import classNames from "classnames";
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import { TextReact } from "../../lib/i18n";
|
||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||
|
||||
|
@ -17,8 +19,6 @@ import CollapsibleSection from "../../components/common/CollapsibleSection";
|
|||
import Tooltip from "../../components/common/Tooltip";
|
||||
import UserIcon from "../../components/common/user/UserIcon";
|
||||
import { PageHeader } from "../../components/ui/Header";
|
||||
import IconButton from "../../components/ui/IconButton";
|
||||
|
||||
import { Children } from "../../types/Preact";
|
||||
import { Friend } from "./Friend";
|
||||
|
||||
|
@ -68,7 +68,10 @@ export default observer(() => {
|
|||
const isEmpty = lists.reduce((p: number, n) => p + n.length, 0) === 0;
|
||||
return (
|
||||
<>
|
||||
<PageHeader icon={<UserDetail size={24} />} transparent noBurger>
|
||||
<PageHeader
|
||||
icon={<UserDetail size={24} />}
|
||||
withTransparency
|
||||
noBurger>
|
||||
<div className={styles.title}>
|
||||
<Text id="app.navigation.tabs.friends" />
|
||||
</div>
|
||||
|
|
|
@ -17,6 +17,8 @@ import "./snow.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext, useMemo } from "preact/hooks";
|
||||
|
||||
import { CategoryButton } from "@revoltchat/ui";
|
||||
|
||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
@ -24,10 +26,10 @@ import { useApplicationState } from "../../mobx/State";
|
|||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
||||
import { AppContext } from "../../context/revoltjs/RevoltClient";
|
||||
|
||||
import { PageHeader } from "../../components/ui/Header";
|
||||
import CategoryButton from "../../components/ui/fluent/CategoryButton";
|
||||
import wideSVG from "/assets/wide.svg";
|
||||
|
||||
import { PageHeader } from "../../components/ui/Header";
|
||||
|
||||
const Overlay = styled.div`
|
||||
display: grid;
|
||||
height: 100%;
|
||||
|
@ -84,7 +86,7 @@ export default observer(() => {
|
|||
</div>
|
||||
)}
|
||||
<div className="content">
|
||||
<PageHeader icon={<HomeIcon size={24} />} transparent>
|
||||
<PageHeader icon={<HomeIcon size={24} />} withTransparency>
|
||||
<Text id="app.navigation.tabs.home" />
|
||||
</PageHeader>
|
||||
<div className={styles.homeScreen}>
|
||||
|
|
|
@ -7,9 +7,8 @@ import styles from "./Invite.module.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext, useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, Category, Error, Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { defer } from "../../lib/defer";
|
||||
import { TextReact } from "../../lib/i18n";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
@ -24,8 +23,6 @@ import { takeError } from "../../context/revoltjs/util";
|
|||
|
||||
import ServerIcon from "../../components/common/ServerIcon";
|
||||
import UserIcon from "../../components/common/user/UserIcon";
|
||||
import Overline from "../../components/ui/Overline";
|
||||
import Preloader from "../../components/ui/Preloader";
|
||||
|
||||
export default function Invite() {
|
||||
const history = useHistory();
|
||||
|
@ -151,7 +148,9 @@ export default function Invite() {
|
|||
}}
|
||||
/>
|
||||
</h3>
|
||||
<Overline type="error" error={error} />
|
||||
<Category>
|
||||
<Error error={error} />
|
||||
</Category>
|
||||
<Button
|
||||
palette="secondary"
|
||||
onClick={async () => {
|
||||
|
|
|
@ -4,16 +4,11 @@ import styled from "styled-components/macro";
|
|||
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, Category, ComboBox, Preloader, Tip } from "@revoltchat/ui";
|
||||
|
||||
import { useClient } from "../../context/revoltjs/RevoltClient";
|
||||
|
||||
import UserIcon from "../../components/common/user/UserIcon";
|
||||
import ComboBox from "../../components/ui/ComboBox";
|
||||
import Overline from "../../components/ui/Overline";
|
||||
import Preloader from "../../components/ui/Preloader";
|
||||
import Tip from "../../components/ui/Tip";
|
||||
|
||||
import Markdown from "../../components/markdown/Markdown";
|
||||
|
||||
const BotInfo = styled.div`
|
||||
|
@ -49,9 +44,7 @@ export default function InviteBot() {
|
|||
|
||||
return (
|
||||
<div style={{ padding: "6em" }}>
|
||||
<Tip warning hideSeparator>
|
||||
This section is under construction.
|
||||
</Tip>
|
||||
<Tip palette="warning">This section is under construction.</Tip>
|
||||
{typeof data === "undefined" && <Preloader type="spinner" />}
|
||||
{data && (
|
||||
<>
|
||||
|
@ -64,7 +57,7 @@ export default function InviteBot() {
|
|||
)}
|
||||
</div>
|
||||
</BotInfo>
|
||||
<Overline type="subtle">Add to server</Overline>
|
||||
<Category>Add to server</Category>
|
||||
<Option>
|
||||
<ComboBox
|
||||
value={server}
|
||||
|
@ -87,7 +80,7 @@ export default function InviteBot() {
|
|||
Add
|
||||
</Button>
|
||||
</Option>
|
||||
<Overline type="subtle">Add to group</Overline>
|
||||
<Category>Add to group</Category>
|
||||
<Option>
|
||||
<ComboBox
|
||||
value={group}
|
||||
|
|
|
@ -2,10 +2,16 @@ import { UseFormMethods } from "react-hook-form";
|
|||
|
||||
import { Text, Localizer } from "preact-i18n";
|
||||
|
||||
import InputBox from "../../components/ui/InputBox";
|
||||
import Overline from "../../components/ui/Overline";
|
||||
import { Category, InputBox } from "@revoltchat/ui";
|
||||
|
||||
type FieldType = "email" | "username" | "password" | "invite" | "current_password";
|
||||
import { I18nError } from "../../context/Locale";
|
||||
|
||||
type FieldType =
|
||||
| "email"
|
||||
| "username"
|
||||
| "password"
|
||||
| "invite"
|
||||
| "current_password";
|
||||
|
||||
type Props = Omit<JSX.HTMLAttributes<HTMLInputElement>, "children" | "as"> & {
|
||||
type: FieldType;
|
||||
|
@ -13,7 +19,7 @@ type Props = Omit<JSX.HTMLAttributes<HTMLInputElement>, "children" | "as"> & {
|
|||
register: UseFormMethods["register"];
|
||||
error?: string;
|
||||
name?: string;
|
||||
}
|
||||
};
|
||||
|
||||
export default function FormField({
|
||||
type,
|
||||
|
@ -26,9 +32,11 @@ export default function FormField({
|
|||
return (
|
||||
<>
|
||||
{showOverline && (
|
||||
<Overline error={error}>
|
||||
<Text id={`login.${type}`} />
|
||||
</Overline>
|
||||
<Category compact>
|
||||
<I18nError error={error}>
|
||||
<Text id={`login.${type}`} />
|
||||
</I18nError>
|
||||
</Category>
|
||||
)}
|
||||
<Localizer>
|
||||
<InputBox
|
||||
|
@ -44,43 +52,43 @@ export default function FormField({
|
|||
type === "invite" || type === "username"
|
||||
? "text"
|
||||
: type === "current_password"
|
||||
? "password"
|
||||
: type
|
||||
? "password"
|
||||
: type
|
||||
}
|
||||
// See https://github.com/mozilla/contain-facebook/issues/783
|
||||
className="fbc-has-badge"
|
||||
ref={register(
|
||||
type === "password" || type === "current_password"
|
||||
? {
|
||||
validate: (value: string) =>
|
||||
value.length === 0
|
||||
? "RequiredField"
|
||||
: value.length < 8
|
||||
? "TooShort"
|
||||
: value.length > 1024
|
||||
? "TooLong"
|
||||
: undefined,
|
||||
}
|
||||
validate: (value: string) =>
|
||||
value.length === 0
|
||||
? "RequiredField"
|
||||
: value.length < 8
|
||||
? "TooShort"
|
||||
: value.length > 1024
|
||||
? "TooLong"
|
||||
: undefined,
|
||||
}
|
||||
: type === "email"
|
||||
? {
|
||||
required: "RequiredField",
|
||||
pattern: {
|
||||
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
|
||||
message: "InvalidEmail",
|
||||
},
|
||||
}
|
||||
: type === "username"
|
||||
? {
|
||||
validate: (value: string) =>
|
||||
value.length === 0
|
||||
? "RequiredField"
|
||||
: value.length < 2
|
||||
? "TooShort"
|
||||
: value.length > 32
|
||||
? "TooLong"
|
||||
: undefined,
|
||||
}
|
||||
: { required: "RequiredField" },
|
||||
? {
|
||||
required: "RequiredField",
|
||||
pattern: {
|
||||
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
|
||||
message: "InvalidEmail",
|
||||
},
|
||||
}
|
||||
: type === "username"
|
||||
? {
|
||||
validate: (value: string) =>
|
||||
value.length === 0
|
||||
? "RequiredField"
|
||||
: value.length < 2
|
||||
? "TooShort"
|
||||
: value.length > 32
|
||||
? "TooLong"
|
||||
: undefined,
|
||||
}
|
||||
: { required: "RequiredField" },
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
|
@ -5,9 +5,9 @@ import styles from "../Login.module.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useEffect } from "preact/hooks";
|
||||
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
import { Preloader } from "@revoltchat/ui";
|
||||
|
||||
import Preloader from "../../../components/ui/Preloader";
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
|
||||
export interface CaptchaProps {
|
||||
onSuccess: (token?: string) => void;
|
||||
|
|
|
@ -6,16 +6,15 @@ import styles from "../Login.module.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, Category, Preloader } from "@revoltchat/ui";
|
||||
import { Tip } from "@revoltchat/ui";
|
||||
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
|
||||
import { I18nError } from "../../../context/Locale";
|
||||
import { takeError } from "../../../context/revoltjs/util";
|
||||
|
||||
import Overline from "../../../components/ui/Overline";
|
||||
import Preloader from "../../../components/ui/Preloader";
|
||||
import WaveSVG from "../../settings/assets/wave.svg";
|
||||
import { Tip } from "@revoltchat/ui";
|
||||
|
||||
import FormField from "../FormField";
|
||||
import { CaptchaBlock, CaptchaProps } from "./CaptchaBlock";
|
||||
|
@ -200,9 +199,11 @@ export const Form = observer(({ page, callback }: Props) => {
|
|||
/>
|
||||
)}
|
||||
{error && (
|
||||
<Overline type="error" error={error}>
|
||||
<Text id={`login.error.${page}`} />
|
||||
</Overline>
|
||||
<Category>
|
||||
<I18nError error={error}>
|
||||
<Text id={`login.error.${page}`} />
|
||||
</I18nError>
|
||||
</Category>
|
||||
)}
|
||||
<Button>
|
||||
<Text
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import { useHistory, useParams } from "react-router-dom";
|
||||
|
||||
import { useContext, useEffect, useState } from "preact/hooks";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Category, Preloader } from "@revoltchat/ui";
|
||||
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
|
||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||
import { I18nError } from "../../../context/Locale";
|
||||
import { takeError } from "../../../context/revoltjs/util";
|
||||
|
||||
import Overline from "../../../components/ui/Overline";
|
||||
import Preloader from "../../../components/ui/Preloader";
|
||||
|
||||
import { Form } from "./Form";
|
||||
|
||||
export function FormResend() {
|
||||
|
@ -42,7 +41,9 @@ export function FormVerify() {
|
|||
}, []);
|
||||
|
||||
return error ? (
|
||||
<Overline type="error" error={error} />
|
||||
<Category>
|
||||
<I18nError error={error} />
|
||||
</Category>
|
||||
) : (
|
||||
<Preloader type="ring" />
|
||||
);
|
||||
|
|
|
@ -7,8 +7,6 @@ import { Text } from "preact-i18n";
|
|||
import { useClient } from "../../context/revoltjs/RevoltClient";
|
||||
import { getChannelName } from "../../context/revoltjs/util";
|
||||
|
||||
import Category from "../../components/ui/Category";
|
||||
|
||||
import { GenericSettings } from "./GenericSettings";
|
||||
import Overview from "./channel/Overview";
|
||||
import Permissions from "./channel/Permissions";
|
||||
|
|
|
@ -5,23 +5,14 @@ import { useHistory, useParams } from "react-router-dom";
|
|||
import styles from "./Settings.module.scss";
|
||||
import classNames from "classnames";
|
||||
import { Text } from "preact-i18n";
|
||||
import {
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "preact/hooks";
|
||||
import { useCallback, useEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
import { Category, Header, IconButton, LineDivider } from "@revoltchat/ui";
|
||||
|
||||
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import Category from "../../components/ui/Category";
|
||||
import Header from "../../components/ui/Header";
|
||||
import IconButton from "../../components/ui/IconButton";
|
||||
import LineDivider from "../../components/ui/LineDivider";
|
||||
|
||||
import ButtonItem from "../../components/navigation/items/ButtonItem";
|
||||
import { Children } from "../../types/Preact";
|
||||
|
||||
|
@ -99,7 +90,7 @@ export function GenericSettings({
|
|||
/>
|
||||
</Helmet>
|
||||
{isTouchscreenDevice && (
|
||||
<Header placement="primary" transparent>
|
||||
<Header palette="primary" withTransparency>
|
||||
{typeof page === "undefined" ? (
|
||||
<>
|
||||
{showExitButton && (
|
||||
|
@ -140,10 +131,9 @@ export function GenericSettings({
|
|||
entry.hidden ? undefined : (
|
||||
<>
|
||||
{entry.category && (
|
||||
<Category
|
||||
variant="uniform"
|
||||
text={entry.category}
|
||||
/>
|
||||
<Category>
|
||||
{entry.category}
|
||||
</Category>
|
||||
)}
|
||||
<ButtonItem
|
||||
active={
|
||||
|
@ -156,7 +146,9 @@ export function GenericSettings({
|
|||
compact>
|
||||
{entry.icon} {entry.title}
|
||||
</ButtonItem>
|
||||
{entry.divider && <LineDivider />}
|
||||
{entry.divider && (
|
||||
<LineDivider compact />
|
||||
)}
|
||||
</>
|
||||
),
|
||||
)}
|
||||
|
|
|
@ -13,13 +13,12 @@ import { Route, Switch, useHistory, useParams } from "react-router-dom";
|
|||
import styles from "./Settings.module.scss";
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import { LineDivider } from "@revoltchat/ui";
|
||||
|
||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
||||
import RequiresOnline from "../../context/revoltjs/RequiresOnline";
|
||||
import { useClient } from "../../context/revoltjs/RevoltClient";
|
||||
|
||||
import Category from "../../components/ui/Category";
|
||||
import LineDivider from "../../components/ui/LineDivider";
|
||||
|
||||
import ButtonItem from "../../components/navigation/items/ButtonItem";
|
||||
import { GenericSettings } from "./GenericSettings";
|
||||
import { Bans } from "./server/Bans";
|
||||
|
|
|
@ -29,6 +29,8 @@ import { openContextMenu } from "preact-context-menu";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext } from "preact/hooks";
|
||||
|
||||
import { LineDivider } from "@revoltchat/ui";
|
||||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import { useIntermediate } from "../../context/intermediate/Intermediate";
|
||||
|
@ -38,8 +40,6 @@ import { AppContext, LogOutContext } from "../../context/revoltjs/RevoltClient";
|
|||
import UserIcon from "../../components/common/user/UserIcon";
|
||||
import { Username } from "../../components/common/user/UserShort";
|
||||
import UserStatus from "../../components/common/user/UserStatus";
|
||||
import LineDivider from "../../components/ui/LineDivider";
|
||||
|
||||
import ButtonItem from "../../components/navigation/items/ButtonItem";
|
||||
import { GIT_BRANCH, GIT_REVISION, REPO_URL } from "../../revision";
|
||||
import { APP_VERSION } from "../../version";
|
||||
|
|
|
@ -5,15 +5,12 @@ import styled from "styled-components/macro";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, Checkbox, InputBox } from "@revoltchat/ui";
|
||||
|
||||
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
|
||||
|
||||
import { FileUploader } from "../../../context/revoltjs/FileUploads";
|
||||
|
||||
import Checkbox from "../../../components/ui/Checkbox";
|
||||
import InputBox from "../../../components/ui/InputBox";
|
||||
|
||||
interface Props {
|
||||
channel: Channel;
|
||||
}
|
||||
|
@ -86,7 +83,7 @@ export default observer(({ channel }: Props) => {
|
|||
)}
|
||||
</h3>
|
||||
<InputBox
|
||||
contrast
|
||||
palette="secondary"
|
||||
value={name}
|
||||
maxLength={32}
|
||||
onChange={(e) => {
|
||||
|
@ -120,14 +117,14 @@ export default observer(({ channel }: Props) => {
|
|||
""
|
||||
) : (
|
||||
<Checkbox
|
||||
checked={nsfw ?? false}
|
||||
value={nsfw ?? false}
|
||||
onChange={(nsfwchange) => {
|
||||
setNSFW(nsfwchange);
|
||||
if (!changed) setChanged(true);
|
||||
}}
|
||||
description="Set this channel to NSFW.">
|
||||
NSFW
|
||||
</Checkbox>
|
||||
title="NSFW"
|
||||
description="Set this channel to NSFW."
|
||||
/>
|
||||
)}
|
||||
<p>
|
||||
<Button onClick={save} palette="secondary" disabled={!changed}>
|
||||
|
|
|
@ -14,7 +14,7 @@ import styles from "./Panes.module.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useContext, useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, CategoryButton, LineDivider, Tip } from "@revoltchat/ui";
|
||||
|
||||
import { stopPropagation } from "../../../lib/stopPropagation";
|
||||
|
||||
|
@ -27,8 +27,6 @@ import {
|
|||
|
||||
import Tooltip from "../../../components/common/Tooltip";
|
||||
import UserIcon from "../../../components/common/user/UserIcon";
|
||||
import Tip from "../../../components/ui/Tip";
|
||||
import CategoryButton from "../../../components/ui/fluent/CategoryButton";
|
||||
|
||||
export const Account = observer(() => {
|
||||
const { openScreen, writeClipboard } = useIntermediate();
|
||||
|
|
|
@ -3,8 +3,9 @@ import { observer } from "mobx-react-lite";
|
|||
import styles from "./Panes.module.scss";
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import CollapsibleSection from "../../../components/common/CollapsibleSection";
|
||||
import { Column } from "@revoltchat/ui";
|
||||
|
||||
import CollapsibleSection from "../../../components/common/CollapsibleSection";
|
||||
import {
|
||||
ThemeBaseSelectorShim,
|
||||
ThemeShopShim,
|
||||
|
@ -37,8 +38,10 @@ export const Appearance = observer(() => {
|
|||
<h3>
|
||||
<Text id="app.settings.pages.appearance.theme_options.title" />
|
||||
</h3>
|
||||
<DisplayTransparencyShim />
|
||||
<DisplaySeasonalShim />
|
||||
<Column>
|
||||
<DisplayTransparencyShim />
|
||||
<DisplaySeasonalShim />
|
||||
</Column>
|
||||
<hr />
|
||||
<DisplayFontShim />
|
||||
<DisplayLigaturesShim />
|
||||
|
|
|
@ -2,14 +2,13 @@ import styles from "./Panes.module.scss";
|
|||
import { Text } from "preact-i18n";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
import { Button, Category, ComboBox, Tip } from "@revoltchat/ui";
|
||||
|
||||
import { stopPropagation } from "../../../lib/stopPropagation";
|
||||
import { voiceState } from "../../../lib/vortex/VoiceState";
|
||||
|
||||
import ComboBox from "../../../components/ui/ComboBox";
|
||||
import Overline from "../../../components/ui/Overline";
|
||||
import Tip from "../../../components/ui/Tip";
|
||||
import { I18nError } from "../../../context/Locale";
|
||||
|
||||
import opusSVG from "../assets/opus_logo.svg";
|
||||
|
||||
{
|
||||
|
@ -96,13 +95,13 @@ export function Audio() {
|
|||
<>
|
||||
<div class={styles.audio}>
|
||||
{!permission && (
|
||||
<Tip error hideSeparator>
|
||||
<Tip palette="error">
|
||||
<Text id="app.settings.pages.audio.tip_grant_permission" />
|
||||
</Tip>
|
||||
)}
|
||||
|
||||
{error && permission === "prompt" && (
|
||||
<Tip error hideSeparator>
|
||||
<Tip palette="error">
|
||||
<Text id="app.settings.pages.audio.tip_retry" />
|
||||
<a onClick={handleAskForPermission}>
|
||||
<Text id="app.settings.pages.audio.button_retry" />
|
||||
|
@ -170,11 +169,9 @@ export function Audio() {
|
|||
</Button>
|
||||
)}
|
||||
{error && error.name === "NotAllowedError" && (
|
||||
<Overline
|
||||
error="AudioPermissionBlock"
|
||||
type="error"
|
||||
block
|
||||
/>
|
||||
<Category>
|
||||
<I18nError error="AudioPermissionBlock" />
|
||||
</Category>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,14 +3,14 @@ import { observer } from "mobx-react-lite";
|
|||
import styles from "./Panes.module.scss";
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import { Checkbox, Column } from "@revoltchat/ui";
|
||||
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
import {
|
||||
AVAILABLE_EXPERIMENTS,
|
||||
EXPERIMENTS,
|
||||
} from "../../../mobx/stores/Experiments";
|
||||
|
||||
import Checkbox from "../../../components/ui/Checkbox";
|
||||
|
||||
export const ExperimentsPage = observer(() => {
|
||||
const experiments = useApplicationState().experiments;
|
||||
|
||||
|
@ -19,15 +19,19 @@ export const ExperimentsPage = observer(() => {
|
|||
<h3>
|
||||
<Text id="app.settings.pages.experiments.features" />
|
||||
</h3>
|
||||
{AVAILABLE_EXPERIMENTS.map((key) => (
|
||||
<Checkbox
|
||||
key={key}
|
||||
checked={experiments.isEnabled(key)}
|
||||
onChange={(enabled) => experiments.setEnabled(key, enabled)}
|
||||
description={EXPERIMENTS[key].description}>
|
||||
{EXPERIMENTS[key].title}
|
||||
</Checkbox>
|
||||
))}
|
||||
<Column>
|
||||
{AVAILABLE_EXPERIMENTS.map((key) => (
|
||||
<Checkbox
|
||||
key={key}
|
||||
value={experiments.isEnabled(key)}
|
||||
onChange={(enabled) =>
|
||||
experiments.setEnabled(key, enabled)
|
||||
}
|
||||
description={EXPERIMENTS[key].description}
|
||||
title={EXPERIMENTS[key].title}
|
||||
/>
|
||||
))}
|
||||
</Column>
|
||||
{AVAILABLE_EXPERIMENTS.length === 0 && (
|
||||
<div className={styles.empty}>
|
||||
<Text id="app.settings.pages.experiments.not_available" />
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Link } from "react-router-dom";
|
|||
import styles from "./Panes.module.scss";
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
import CategoryButton from "../../../components/ui/fluent/CategoryButton";
|
||||
import { CategoryButton } from "@revoltchat/ui";
|
||||
|
||||
export function Feedback() {
|
||||
return (
|
||||
|
@ -15,7 +15,6 @@ export function Feedback() {
|
|||
target="_blank"
|
||||
rel="noreferrer">
|
||||
<CategoryButton
|
||||
hover
|
||||
action="external"
|
||||
icon={<Github size={24} />}
|
||||
description={
|
||||
|
@ -29,7 +28,6 @@ export function Feedback() {
|
|||
target="_blank"
|
||||
rel="noreferrer">
|
||||
<CategoryButton
|
||||
hover
|
||||
action="external"
|
||||
icon={<ListOl size={24} />}
|
||||
description={
|
||||
|
@ -43,7 +41,6 @@ export function Feedback() {
|
|||
target="_blank"
|
||||
rel="noreferrer">
|
||||
<CategoryButton
|
||||
hover
|
||||
action="external"
|
||||
icon={<BugAlt size={24} />}
|
||||
description={
|
||||
|
@ -55,7 +52,6 @@ export function Feedback() {
|
|||
<Link to="/invite/Testers">
|
||||
<a>
|
||||
<CategoryButton
|
||||
hover
|
||||
action="chevron"
|
||||
icon={<Group size={24} />}
|
||||
description="You can report issues and discuss improvements with us directly here.">
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue