From 898288e815992302ec934c6140b879e7d6a973eb Mon Sep 17 00:00:00 2001 From: bree Date: Wed, 23 Jun 2021 13:46:31 -0400 Subject: [PATCH 0001/1462] Restructure `FilePreview` to be less "hacky" --- .../common/messaging/bars/FilePreview.tsx | 89 +++++++++++-------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/src/components/common/messaging/bars/FilePreview.tsx b/src/components/common/messaging/bars/FilePreview.tsx index 8bd55d3a6..44d94f5fd 100644 --- a/src/components/common/messaging/bars/FilePreview.tsx +++ b/src/components/common/messaging/bars/FilePreview.tsx @@ -31,14 +31,6 @@ const Entry = styled.div` display: flex; flex-direction: column; - img { - height: 100px; - margin-bottom: 4px; - border-radius: 4px; - object-fit: contain; - background: var(--secondary-background); - } - &.fade { opacity: 0.4; } @@ -59,27 +51,6 @@ const Entry = styled.div` color: var(--tertiary-foreground); text-align: center; } - - div:first-child { - position: relative; - height: 0; - - div { - display: grid; - height: 100px; - cursor: pointer; - border-radius: 4px; - place-items: center; - - opacity: 0; - transition: 0.1s ease opacity; - background: rgba(0, 0, 0, 0.8); - - &:hover { - opacity: 1; - } - } - } `; const Description = styled.div` @@ -114,13 +85,58 @@ const EmptyEntry = styled.div` } `; +const PreviewBox = styled.div` + display: grid; + grid-template: "main" 100px / minmax(100px, 1fr); + justify-items: center; + + background: var(--primary-background); + + overflow: hidden; + + cursor: pointer; + border-radius: 4px; + + .icon, .overlay { grid-area: main } + + .icon { + height: 100px; + margin-bottom: 4px; + object-fit: contain; + } + + .overlay { + display: grid; + align-items: center; + justify-content: center; + + width: 100%; + height: 100%; + + opacity: 0; + visibility: hidden; + + transition: 0.1s ease opacity; + } + + &:hover { + .overlay { + visibility: visible; + opacity: 1; + background-color: rgba(0, 0, 0, 0.8); + } + } +` + function FileEntry({ file, remove, index }: { file: File, remove?: () => void, index: number }) { if (!file.type.startsWith('image/')) return ( = CAN_UPLOAD_AT_ONCE ? 'fade' : ''}> -
- - - + + + + +
+
{file.name} {determineFileSize(file.size)}
@@ -136,9 +152,10 @@ function FileEntry({ file, remove, index }: { file: File, remove?: () => void, i return ( = CAN_UPLOAD_AT_ONCE ? 'fade' : ''}> - { remove &&
} - {file.name} + + {file.name} +
+
{file.name} {determineFileSize(file.size)}
From 2d761d1e97c8fecc972e128f25201606e5178a01 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 24 Jun 2021 16:22:45 +0100 Subject: [PATCH 0002/1462] Fix: Icons collapsing in flex. Feature: Remember what channel was opened last. Channels: ESC to focus message box / cancel editing. --- src/components/common/IconBase.tsx | 3 ++ .../navigation/left/HomeSidebar.tsx | 29 ++++++++---- .../navigation/left/ServerListSidebar.tsx | 45 +++++++++++-------- .../navigation/left/ServerSidebar.tsx | 21 +++++++-- src/context/Settings.tsx | 2 - src/lib/ConditionalLink.tsx | 15 +++++++ src/pages/channels/actions/HeaderActions.tsx | 2 +- src/pages/channels/messaging/MessageArea.tsx | 2 + .../channels/messaging/MessageEditor.tsx | 16 ++++++- src/redux/index.ts | 4 ++ src/redux/reducers/index.ts | 3 ++ src/redux/reducers/last_opened.ts | 29 ++++++++++++ 12 files changed, 137 insertions(+), 34 deletions(-) create mode 100644 src/lib/ConditionalLink.tsx create mode 100644 src/redux/reducers/last_opened.ts diff --git a/src/components/common/IconBase.tsx b/src/components/common/IconBase.tsx index bebc0a8f8..acb5387ea 100644 --- a/src/components/common/IconBase.tsx +++ b/src/components/common/IconBase.tsx @@ -14,6 +14,8 @@ interface IconModifiers { } export default styled.svg` + flex-shrink: 0; + img { width: 100%; height: 100%; @@ -26,6 +28,7 @@ export default styled.svg` `; export const ImageIconBase = styled.img` + flex-shrink: 0; object-fit: cover; ${ props => !props.square && css` diff --git a/src/components/navigation/left/HomeSidebar.tsx b/src/components/navigation/left/HomeSidebar.tsx index ac05418ee..c0e657e0b 100644 --- a/src/components/navigation/left/HomeSidebar.tsx +++ b/src/components/navigation/left/HomeSidebar.tsx @@ -1,5 +1,5 @@ import { Localizer, Text } from "preact-i18n"; -import { useContext } from "preact/hooks"; +import { useContext, useEffect } from "preact/hooks"; import { Home, Users, Tool, Save } from "@styled-icons/feather"; import Category from '../../ui/Category'; @@ -10,6 +10,7 @@ import { connectState } from "../../../redux/connector"; import ConnectionStatus from '../items/ConnectionStatus'; import { WithDispatcher } from "../../../redux/reducers"; import { Unreads } from "../../../redux/reducers/unreads"; +import ConditionalLink from "../../../lib/ConditionalLink"; import { mapChannelWithUnread, useUnreads } from "./common"; import { Users as UsersNS } from 'revolt.js/dist/api/objects'; import ButtonItem, { ChannelButton } from '../items/ButtonItem'; @@ -37,6 +38,16 @@ function HomeSidebar(props: Props) { if (channel && !obj) return ; if (obj) useUnreads({ ...props, channel: obj }); + useEffect(() => { + if (!channel) return; + + props.dispatcher({ + type: 'LAST_OPENED_SET', + parent: 'home', + child: channel + }); + }, [ channel ]); + const channelsArr = channels .filter(x => x.channel_type !== 'SavedMessages') .map(x => mapChannelWithUnread(x, props.unreads)); @@ -55,13 +66,13 @@ function HomeSidebar(props: Props) { {!isTouchscreenDevice && ( <> - + - - + + - + )} - + - + {import.meta.env.DEV && ( @@ -115,7 +126,7 @@ function HomeSidebar(props: Props) { } return ( - + - + ); })} diff --git a/src/components/navigation/left/ServerListSidebar.tsx b/src/components/navigation/left/ServerListSidebar.tsx index c7e2fc918..4f25f7ddd 100644 --- a/src/components/navigation/left/ServerListSidebar.tsx +++ b/src/components/navigation/left/ServerListSidebar.tsx @@ -8,9 +8,11 @@ import { PlusCircle } from "@styled-icons/feather"; import PaintCounter from "../../../lib/PaintCounter"; import { attachContextMenu } from 'preact-context-menu'; import { connectState } from "../../../redux/connector"; +import { useLocation, useParams } from "react-router-dom"; import { Unreads } from "../../../redux/reducers/unreads"; +import ConditionalLink from "../../../lib/ConditionalLink"; import { Channel, Servers } from "revolt.js/dist/api/objects"; -import { Link, useLocation, useParams } from "react-router-dom"; +import { LastOpened } from "../../../redux/reducers/last_opened"; import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice"; import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { useChannels, useForceUpdate, useServers } from "../../../context/revoltjs/hooks"; @@ -104,9 +106,10 @@ const ServerEntry = styled.div<{ active: boolean, invert?: boolean }>` interface Props { unreads: Unreads; + lastOpened: LastOpened; } -export function ServerListSidebar({ unreads }: Props) { +export function ServerListSidebar({ unreads, lastOpened }: Props) { const ctx = useForceUpdate(); const activeServers = useServers(undefined, ctx) as Servers.Server[]; const channels = (useChannels(undefined, ctx) as Channel[]) @@ -148,31 +151,36 @@ export function ServerListSidebar({ unreads }: Props) { } if (alertCount > 0) homeUnread = 'mention'; + const homeActive = typeof server === 'undefined' && !path.startsWith('/invite'); return ( - - + + - + { - servers.map(entry => - - - - - - - - ) + servers.map(entry => { + const active = entry!._id === server?._id; + const id = lastOpened[entry!._id]; + + return ( + + + + + + + + ) + }) } openScreen({ id: 'special_input', type: 'create_server' })}> @@ -187,7 +195,8 @@ export default connectState( ServerListSidebar, state => { return { - unreads: state.unreads + unreads: state.unreads, + lastOpened: state.lastOpened }; } ); diff --git a/src/components/navigation/left/ServerSidebar.tsx b/src/components/navigation/left/ServerSidebar.tsx index 03f175c35..d987af1ee 100644 --- a/src/components/navigation/left/ServerSidebar.tsx +++ b/src/components/navigation/left/ServerSidebar.tsx @@ -15,6 +15,8 @@ import PaintCounter from "../../../lib/PaintCounter"; import styled from "styled-components"; import { attachContextMenu } from 'preact-context-menu'; import ServerHeader from "../../common/ServerHeader"; +import { useEffect } from "preact/hooks"; +import ConditionalLink from "../../../lib/ConditionalLink"; interface Props { unreads: Unreads; @@ -51,24 +53,37 @@ function ServerSidebar(props: Props & WithDispatcher) { .map(x => mapChannelWithUnread(x, props.unreads)); const channel = channels.find(x => x?._id === channel_id); + if (channel_id && !channel) return ; if (channel) useUnreads({ ...props, channel }, ctx); + useEffect(() => { + if (!channel_id) return; + + props.dispatcher({ + type: 'LAST_OPENED_SET', + parent: server_id!, + child: channel_id! + }); + }, [ channel_id ]); + return ( {channels.map(entry => { + const active = channel?._id === entry._id; + return ( - + - + ); })} diff --git a/src/context/Settings.tsx b/src/context/Settings.tsx index 92737e41f..58e05deb2 100644 --- a/src/context/Settings.tsx +++ b/src/context/Settings.tsx @@ -24,11 +24,9 @@ interface Props { } function Settings({ settings, children }: Props) { - console.info(settings.notification); const play = useMemo(() => { const enabled: SoundOptions = defaultsDeep(settings.notification ?? {}, DEFAULT_SOUNDS); return (sound: Sounds) => { - console.info('check if we can play sound', enabled[sound]); if (enabled[sound]) { playSound(sound); } diff --git a/src/lib/ConditionalLink.tsx b/src/lib/ConditionalLink.tsx new file mode 100644 index 000000000..b739219dc --- /dev/null +++ b/src/lib/ConditionalLink.tsx @@ -0,0 +1,15 @@ +import { Link, LinkProps } from "react-router-dom"; + +type Props = LinkProps & JSX.HTMLAttributes & { + active: boolean +}; + +export default function ConditionalLink(props: Props) { + const { active, ...linkProps } = props; + + if (active) { + return { props.children }; + } else { + return ; + } +} diff --git a/src/pages/channels/actions/HeaderActions.tsx b/src/pages/channels/actions/HeaderActions.tsx index 6916361bc..368f603fc 100644 --- a/src/pages/channels/actions/HeaderActions.tsx +++ b/src/pages/channels/actions/HeaderActions.tsx @@ -35,7 +35,7 @@ export default function HeaderActions({ channel, toggleSidebar }: ChannelHeaderP ) } - { channel.channel_type === "Group" && !isTouchscreenDevice && ( + { (channel.channel_type === "Group" || channel.channel_type === "TextChannel") && !isTouchscreenDevice && ( diff --git a/src/pages/channels/messaging/MessageArea.tsx b/src/pages/channels/messaging/MessageArea.tsx index 11cc849bc..9753abcdc 100644 --- a/src/pages/channels/messaging/MessageArea.tsx +++ b/src/pages/channels/messaging/MessageArea.tsx @@ -12,6 +12,7 @@ import { IntermediateContext } from "../../../context/intermediate/Intermediate" import { ClientStatus, StatusContext } from "../../../context/revoltjs/RevoltClient"; import { useContext, useEffect, useLayoutEffect, useRef, useState } from "preact/hooks"; import { defer } from "../../../lib/defer"; +import { internalEmit } from "../../../lib/eventEmitter"; const Area = styled.div` height: 100%; @@ -246,6 +247,7 @@ export function MessageArea({ id }: Props) { function keyUp(e: KeyboardEvent) { if (e.key === "Escape" && !focusTaken) { SingletonMessageRenderer.jumpToBottom(id, true); + internalEmit("TextArea", "focus", "message"); } } diff --git a/src/pages/channels/messaging/MessageEditor.tsx b/src/pages/channels/messaging/MessageEditor.tsx index 3d93a7531..b46a10ab2 100644 --- a/src/pages/channels/messaging/MessageEditor.tsx +++ b/src/pages/channels/messaging/MessageEditor.tsx @@ -1,9 +1,10 @@ import styled from "styled-components"; -import { useContext, useState } from "preact/hooks"; +import { useContext, useEffect, useState } from "preact/hooks"; import TextAreaAutoSize from "../../../lib/TextAreaAutoSize"; import { MessageObject } from "../../../context/revoltjs/util"; import { AppContext } from "../../../context/revoltjs/RevoltClient"; import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice"; +import { IntermediateContext } from "../../../context/intermediate/Intermediate"; const EditorBase = styled.div` display: flex; @@ -38,6 +39,7 @@ interface Props { export default function MessageEditor({ message, finish }: Props) { const [ content, setContent ] = useState(message.content as string ?? ''); + const { focusTaken } = useContext(IntermediateContext); const client = useContext(AppContext); async function save() { @@ -55,6 +57,18 @@ export default function MessageEditor({ message, finish }: Props) { } } + // ? Stop editing when pressing ESC. + useEffect(() => { + function keyUp(e: KeyboardEvent) { + if (e.key === "Escape" && !focusTaken) { + finish(); + } + } + + document.body.addEventListener("keyup", keyUp); + return () => document.body.removeEventListener("keyup", keyUp); + }, [focusTaken]); + return ( { drafts, sync, experiments, + lastOpened } = store.getState() as State; localForage.setItem("state", { @@ -63,5 +66,6 @@ store.subscribe(() => { drafts, sync, experiments, + lastOpened }); }); diff --git a/src/redux/reducers/index.ts b/src/redux/reducers/index.ts index a5e81c652..6c84f87fa 100644 --- a/src/redux/reducers/index.ts +++ b/src/redux/reducers/index.ts @@ -11,6 +11,7 @@ import { typing, TypingAction } from "./typing"; import { drafts, DraftAction } from "./drafts"; import { sync, SyncAction } from "./sync"; import { experiments, ExperimentsAction } from "./experiments"; +import { lastOpened, LastOpenedAction } from "./last_opened"; export default combineReducers({ config, @@ -23,6 +24,7 @@ export default combineReducers({ drafts, sync, experiments, + lastOpened }); export type Action = @@ -36,6 +38,7 @@ export type Action = | DraftAction | SyncAction | ExperimentsAction + | LastOpenedAction | { type: "__INIT"; state: State }; export type WithDispatcher = { dispatcher: (action: Action) => void }; diff --git a/src/redux/reducers/last_opened.ts b/src/redux/reducers/last_opened.ts new file mode 100644 index 000000000..0b29a156a --- /dev/null +++ b/src/redux/reducers/last_opened.ts @@ -0,0 +1,29 @@ +export interface LastOpened { + [key: string]: string +} + +export type LastOpenedAction = + | { type: undefined } + | { + type: "LAST_OPENED_SET"; + parent: string; + child: string; + } + | { + type: "RESET"; + }; + +export function lastOpened(state = {} as LastOpened, action: LastOpenedAction): LastOpened { + switch (action.type) { + case "LAST_OPENED_SET": { + return { + ...state, + [action.parent]: action.child + } + } + case "RESET": + return {}; + default: + return state; + } +} From b724b9aec2c5b0ca742c82673613d15227668245 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 24 Jun 2021 16:43:37 +0100 Subject: [PATCH 0003/1462] Fix: Emojis showing through spoilers. Fix: Copy ID copies wrong ID. Messaging: Add context menu to avatar / username. --- external/lang | 2 +- src/components/common/messaging/Message.tsx | 10 +++++++--- src/components/common/messaging/MessageBase.tsx | 14 +++++++++++++- src/components/common/user/UserShort.tsx | 4 ++-- src/components/markdown/Markdown.module.scss | 10 +++++++++- src/components/navigation/items/ButtonItem.tsx | 3 +-- src/lib/ContextMenus.tsx | 2 +- 7 files changed, 34 insertions(+), 11 deletions(-) diff --git a/external/lang b/external/lang index 755f35fcd..099fb7413 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 755f35fcdd769f15a68512403074a584441f3fc6 +Subproject commit 099fb74131c60955e8226ce0a290cb22e959d7d6 diff --git a/src/components/common/messaging/Message.tsx b/src/components/common/messaging/Message.tsx index 781c4e950..8c71ae63e 100644 --- a/src/components/common/messaging/Message.tsx +++ b/src/components/common/messaging/Message.tsx @@ -32,6 +32,8 @@ function Message({ attachContext, message, contrast, content: replacement, head: const content = message.content as string; const head = preferHead || (message.replies && message.replies.length > 0); + const userContext = attachContext ? attachContextMenu('Menu', { user: message.author, contextualChannel: message.channel }) : undefined as any; // ! FIXME: tell fatal to make this type generic + return ( <> { message.replies?.map((message_id, index) => ) } @@ -44,12 +46,14 @@ function Message({ attachContext, message, contrast, content: replacement, head: onContextMenu={attachContext ? attachContextMenu('Menu', { message, contextualChannel: message.channel, queued }) : undefined}> { head ? - : + : } - { head && - + { head && + + + } { replacement ?? } diff --git a/src/components/common/messaging/MessageBase.tsx b/src/components/common/messaging/MessageBase.tsx index 435c2f11f..de70edcee 100644 --- a/src/components/common/messaging/MessageBase.tsx +++ b/src/components/common/messaging/MessageBase.tsx @@ -53,11 +53,19 @@ export default styled.div` color: var(--error); ` } - .author { + .detail { gap: 8px; display: flex; align-items: center; } + + .author { + cursor: pointer; + + &:hover { + text-decoration: underline; + } + } .copy { width: 0; @@ -89,6 +97,10 @@ export const MessageInfo = styled.div` color: var(--tertiary-foreground); } + svg { + cursor: pointer; + } + time { opacity: 0; } diff --git a/src/components/common/user/UserShort.tsx b/src/components/common/user/UserShort.tsx index 0dda8d3c6..69a15fd39 100644 --- a/src/components/common/user/UserShort.tsx +++ b/src/components/common/user/UserShort.tsx @@ -2,8 +2,8 @@ import { User } from "revolt.js"; import UserIcon from "./UserIcon"; import { Text } from "preact-i18n"; -export function Username({ user }: { user?: User }) { - return { user?.username ?? }; +export function Username({ user, ...otherProps }: { user?: User } & JSX.HTMLAttributes) { + return { user?.username ?? }; } export default function UserShort({ user, size }: { user?: User, size?: number }) { diff --git a/src/components/markdown/Markdown.module.scss b/src/components/markdown/Markdown.module.scss index 2f13352ac..de439a348 100644 --- a/src/components/markdown/Markdown.module.scss +++ b/src/components/markdown/Markdown.module.scss @@ -115,15 +115,23 @@ padding: 0 2px; cursor: pointer; user-select: none; - color: transparent; border-radius: 4px; + color: transparent; background: #151515; + > * { + opacity: 0; + } + &:global(.shown) { cursor: auto; user-select: all; color: var(--foreground); background: var(--secondary-background); + + > * { + opacity: 1; + } } } diff --git a/src/components/navigation/items/ButtonItem.tsx b/src/components/navigation/items/ButtonItem.tsx index 31c29fbe0..42792b7b4 100644 --- a/src/components/navigation/items/ButtonItem.tsx +++ b/src/components/navigation/items/ButtonItem.tsx @@ -97,8 +97,7 @@ export function ChannelButton({ active, alert, alertCount, channel, user, compac const { openScreen } = useIntermediate(); return ( -
diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index 358ed937f..89bdf8f49 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -562,7 +562,7 @@ function ContextMenus(props: WithDispatcher) { } } - let id = server?._id ?? channel?._id ?? user?._id ?? message?._id; + let id = sid ?? cid ?? uid ?? message?._id; if (id) { pushDivider(); From 2d9d3c489c391f6d3404f41e2122303a952b33f4 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 24 Jun 2021 16:57:12 +0100 Subject: [PATCH 0004/1462] Fix: Remove padding on user profile. Modals: Allow all modals to be closed by ESC (permitting). Fix: Handle closing DMs properly. Stop propagation too. --- src/components/navigation/items/ButtonItem.tsx | 6 +++--- src/components/navigation/left/HomeSidebar.tsx | 3 +++ src/components/ui/Modal.tsx | 16 +++++++++++++++- .../intermediate/popovers/ImageViewer.tsx | 11 ----------- .../intermediate/popovers/UserProfile.tsx | 7 +++---- src/context/revoltjs/hooks.ts | 5 ++--- src/lib/stopPropagation.ts | 1 + 7 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/components/navigation/items/ButtonItem.tsx b/src/components/navigation/items/ButtonItem.tsx index 42792b7b4..d4e198207 100644 --- a/src/components/navigation/items/ButtonItem.tsx +++ b/src/components/navigation/items/ButtonItem.tsx @@ -12,6 +12,7 @@ import { attachContextMenu } from 'preact-context-menu'; import { Channels, Users } from "revolt.js/dist/api/objects"; import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice"; import { useIntermediate } from '../../../context/intermediate/Intermediate'; +import { stopPropagation } from '../../../lib/stopPropagation'; interface CommonProps { active?: boolean @@ -70,9 +71,8 @@ export function UserButton({ active, alert, alertCount, user, context, channel } )} {alert &&
{ alertCount }
} { !isTouchscreenDevice && channel && - openScreen({ id: 'special_prompt', type: 'close_dm', target: channel })}> + stopPropagation(e) && openScreen({ id: 'special_prompt', type: 'close_dm', target: channel })}> } diff --git a/src/components/navigation/left/HomeSidebar.tsx b/src/components/navigation/left/HomeSidebar.tsx index c0e657e0b..d9ea7190e 100644 --- a/src/components/navigation/left/HomeSidebar.tsx +++ b/src/components/navigation/left/HomeSidebar.tsx @@ -117,8 +117,11 @@ function HomeSidebar(props: Props) { {channelsArr.map(x => { let user; if (x.channel_type === 'DirectMessage') { + if (!x.active) return null; + let recipient = client.channels.getRecipient(x._id); user = users.find(x => x?._id === recipient); + if (!user) { console.warn(`Skipped DM ${x._id} because user was missing.`); return null; diff --git a/src/components/ui/Modal.tsx b/src/components/ui/Modal.tsx index 26197b2be..2faecdec3 100644 --- a/src/components/ui/Modal.tsx +++ b/src/components/ui/Modal.tsx @@ -98,6 +98,7 @@ interface Props { disallowClosing?: boolean; noBackground?: boolean; dontModal?: boolean; + padding?: boolean; onClose: () => void; actions?: Action[]; @@ -114,7 +115,7 @@ export default function Modal(props: Props) { attachment={!!props.actions} noBackground={props.noBackground} border={props.border} - padding={!props.dontModal}> + padding={props.padding ?? !props.dontModal}> {props.title &&

{props.title}

} {props.children} @@ -124,6 +125,19 @@ export default function Modal(props: Props) { return content; } + useEffect(() => { + if (props.disallowClosing) return; + + function keyDown(e: KeyboardEvent) { + if (e.key === "Escape") { + props.onClose(); + } + } + + document.body.addEventListener("keydown", keyDown); + return () => document.body.removeEventListener("keydown", keyDown); + }, [ props.disallowClosing, props.onClose ]); + let confirmationAction = props.actions?.find(action => action.confirmation); useEffect(() => { if (!confirmationAction) return; diff --git a/src/context/intermediate/popovers/ImageViewer.tsx b/src/context/intermediate/popovers/ImageViewer.tsx index e42d6ca1e..d0cf0cfc1 100644 --- a/src/context/intermediate/popovers/ImageViewer.tsx +++ b/src/context/intermediate/popovers/ImageViewer.tsx @@ -22,17 +22,6 @@ export function ImageViewer({ attachment, embed, onClose }: Props) { if (attachment && attachment.metadata.type !== "Image") return null; const client = useContext(AppContext); - useEffect(() => { - function keyDown(e: KeyboardEvent) { - if (e.key === "Escape") { - onClose(); - } - } - - document.body.addEventListener("keydown", keyDown); - return () => document.body.removeEventListener("keydown", keyDown); - }, []); - return (
diff --git a/src/context/intermediate/popovers/UserProfile.tsx b/src/context/intermediate/popovers/UserProfile.tsx index 385829a7f..afcc83451 100644 --- a/src/context/intermediate/popovers/UserProfile.tsx +++ b/src/context/intermediate/popovers/UserProfile.tsx @@ -116,12 +116,11 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) { const badges = (user.badges ?? 0) | (decodeTime(user._id) < 1623751765790 ? Badges.EarlyAdopter : 0); return ( - + dontModal={dummy}>
{}; } @@ -85,7 +84,7 @@ export function useDMs(context?: HookContext) { function mutation(target: string) { let channel = ctx.client.channels.get(target); if (channel) { - if ((channel.channel_type === 'DirectMessage' && channel.active) || channel.channel_type === 'Group') { + if (channel.channel_type === 'DirectMessage' || channel.channel_type === 'Group') { ctx.forceUpdate(); } } @@ -99,7 +98,7 @@ export function useDMs(context?: HookContext) { return map .toArray() - .filter(x => (x.channel_type === 'DirectMessage' && x.active) || x.channel_type === 'Group' || x.channel_type === 'SavedMessages') as (Channels.GroupChannel | Channels.DirectMessageChannel | Channels.SavedMessagesChannel)[]; + .filter(x => x.channel_type === 'DirectMessage' || x.channel_type === 'Group' || x.channel_type === 'SavedMessages') as (Channels.GroupChannel | Channels.DirectMessageChannel | Channels.SavedMessagesChannel)[]; } export function useUserPermission(id: string, context?: HookContext) { diff --git a/src/lib/stopPropagation.ts b/src/lib/stopPropagation.ts index 98c9fa604..df4d95337 100644 --- a/src/lib/stopPropagation.ts +++ b/src/lib/stopPropagation.ts @@ -1,4 +1,5 @@ export const stopPropagation = (ev: JSX.TargetedMouseEvent, _consume?: any) => { ev.preventDefault(); ev.stopPropagation(); + return true; }; From 9724181d2802753419791f1a68d422dd331616ff Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 24 Jun 2021 17:06:16 +0100 Subject: [PATCH 0005/1462] Fix: Set global emoji pack. Fix: Use conditional links for bottom navigation. Fix: Margin error on queued messages. --- src/components/common/messaging/Message.tsx | 2 +- src/components/navigation/BottomNavigation.tsx | 12 ++++++------ src/components/ui/Button.tsx | 1 + src/redux/reducers/settings.ts | 3 ++- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/components/common/messaging/Message.tsx b/src/components/common/messaging/Message.tsx index 8c71ae63e..d504f9667 100644 --- a/src/components/common/messaging/Message.tsx +++ b/src/components/common/messaging/Message.tsx @@ -38,7 +38,7 @@ function Message({ attachContext, message, contrast, content: replacement, head: <> { message.replies?.map((message_id, index) => ) } 0)} contrast={contrast} sending={typeof queued !== 'undefined'} mention={message.mentions?.includes(client.user!._id)} diff --git a/src/components/navigation/BottomNavigation.tsx b/src/components/navigation/BottomNavigation.tsx index 6a9ffd40f..4afa8f9b7 100644 --- a/src/components/navigation/BottomNavigation.tsx +++ b/src/components/navigation/BottomNavigation.tsx @@ -1,9 +1,9 @@ -import styled, { css } from "styled-components"; -import { Link } from "react-router-dom"; import IconButton from "../ui/IconButton"; import UserIcon from "../common/user/UserIcon"; +import styled, { css } from "styled-components"; import { useSelf } from "../../context/revoltjs/hooks"; import { useHistory, useLocation } from "react-router"; +import ConditionalLink from "../../lib/ConditionalLink"; import { MessageCircle, Users } from "@styled-icons/feather"; const NavigationBase = styled.div` @@ -54,18 +54,18 @@ export default function BottomNavigation() { ); diff --git a/src/components/ui/Button.tsx b/src/components/ui/Button.tsx index 2f3231430..9c4b3a2bd 100644 --- a/src/components/ui/Button.tsx +++ b/src/components/ui/Button.tsx @@ -10,6 +10,7 @@ export default styled.button` padding: 8px; font-size: 16px; text-align: center; + font-family: 'Open Sans', sans-serif; transition: 0.2s ease opacity; transition: 0.2s ease background-color; diff --git a/src/redux/reducers/settings.ts b/src/redux/reducers/settings.ts index bcab75c24..a37d7ef14 100644 --- a/src/redux/reducers/settings.ts +++ b/src/redux/reducers/settings.ts @@ -2,6 +2,7 @@ import { filter } from "."; import { SyncUpdateAction } from "./sync"; import { Sounds } from "../../assets/sounds/Audio"; import { Theme, ThemeOptions } from "../../context/Theme"; +import { setEmojiPack } from "../../components/common/Emoji"; export type SoundOptions = { [key in Sounds]?: boolean @@ -57,7 +58,7 @@ export function settings( state = {} as Settings, action: SettingsAction ): Settings { - // setEmojiPack(state.appearance?.emojiPack ?? 'mutant'); + setEmojiPack(state.appearance?.emojiPack ?? 'mutant'); switch (action.type) { case "SETTINGS_SET_THEME": From e81db175764af27d6bea3eaf29510d331ab5e26b Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 24 Jun 2021 17:09:34 +0100 Subject: [PATCH 0006/1462] Fix: Editor would not open "delete_message". Fix: Clear status if empty string given. --- src/context/intermediate/modals/Input.tsx | 2 +- src/pages/channels/messaging/MessageEditor.tsx | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/context/intermediate/modals/Input.tsx b/src/context/intermediate/modals/Input.tsx index b5897375f..68e009377 100644 --- a/src/context/intermediate/modals/Input.tsx +++ b/src/context/intermediate/modals/Input.tsx @@ -119,7 +119,7 @@ export function SpecialInputModal(props: SpecialProps) { client.users.editUser({ status: { ...client.user?.status, - text + text: text.trim().length > 0 ? text : undefined } }) } diff --git a/src/pages/channels/messaging/MessageEditor.tsx b/src/pages/channels/messaging/MessageEditor.tsx index b46a10ab2..e177736cb 100644 --- a/src/pages/channels/messaging/MessageEditor.tsx +++ b/src/pages/channels/messaging/MessageEditor.tsx @@ -1,10 +1,10 @@ import styled from "styled-components"; -import { useContext, useEffect, useState } from "preact/hooks"; import TextAreaAutoSize from "../../../lib/TextAreaAutoSize"; import { MessageObject } from "../../../context/revoltjs/util"; +import { useContext, useEffect, useState } from "preact/hooks"; import { AppContext } from "../../../context/revoltjs/RevoltClient"; import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice"; -import { IntermediateContext } from "../../../context/intermediate/Intermediate"; +import { IntermediateContext, useIntermediate } from "../../../context/intermediate/Intermediate"; const EditorBase = styled.div` display: flex; @@ -40,6 +40,7 @@ interface Props { export default function MessageEditor({ message, finish }: Props) { const [ content, setContent ] = useState(message.content as string ?? ''); const { focusTaken } = useContext(IntermediateContext); + const { openScreen } = useIntermediate(); const client = useContext(AppContext); async function save() { From 94ee5d8f9666312c7e7189af687d00d933ea29c3 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 24 Jun 2021 17:29:01 +0100 Subject: [PATCH 0007/1462] Fix: Make settings not jump around. Fix: Auto-complete font size. --- src/components/common/AutoComplete.tsx | 2 ++ src/pages/settings/Settings.module.scss | 6 +++--- src/pages/settings/panes/Panes.module.scss | 3 +-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/common/AutoComplete.tsx b/src/components/common/AutoComplete.tsx index 50adce4e8..e384c4bcf 100644 --- a/src/components/common/AutoComplete.tsx +++ b/src/components/common/AutoComplete.tsx @@ -330,8 +330,10 @@ const Base = styled.div` padding: 6px; border: none; display: flex; + font-size: 1em; cursor: pointer; border-radius: 6px; + align-items: center; flex-direction: row; background: transparent; color: var(--foreground); diff --git a/src/pages/settings/Settings.module.scss b/src/pages/settings/Settings.module.scss index 4f095c0ec..82f5ba034 100644 --- a/src/pages/settings/Settings.module.scss +++ b/src/pages/settings/Settings.module.scss @@ -65,7 +65,7 @@ background: var(--primary-background); .sidebar { - flex-grow: 1; + flex: 2; display: flex; flex-shrink: 0; overflow-y: scroll; @@ -114,7 +114,7 @@ } .content { - flex-grow: 2; + flex: 3; max-width: 740px; padding: 60px 2em; overflow-y: scroll; @@ -155,7 +155,7 @@ } .action { - flex-grow: 1; + flex: 1; flex-shrink: 0; padding: 60px 8px; color: var(--tertiary-background); diff --git a/src/pages/settings/panes/Panes.module.scss b/src/pages/settings/panes/Panes.module.scss index 59fe76ce6..d1c2a5040 100644 --- a/src/pages/settings/panes/Panes.module.scss +++ b/src/pages/settings/panes/Panes.module.scss @@ -74,14 +74,13 @@ .appearance { .theme { + min-width: 0; display: flex; flex-direction: column; - width: 100%; } .themes { gap: 8px; - width: 100%; display: flex; img { From a315875886e6df5c85e36a84cc80889bdabd50cb Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 24 Jun 2021 20:40:22 +0100 Subject: [PATCH 0008/1462] Remove prompt again. --- src/context/intermediate/Intermediate.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/context/intermediate/Intermediate.tsx b/src/context/intermediate/Intermediate.tsx index f64accea9..3c4f66a79 100644 --- a/src/context/intermediate/Intermediate.tsx +++ b/src/context/intermediate/Intermediate.tsx @@ -116,7 +116,7 @@ export default function Intermediate(props: Props) { screen.id } /** By specifying a key, we reset state whenever switching screen. */ /> - { if (action === 'POP') { @@ -128,7 +128,7 @@ export default function Intermediate(props: Props) { return true; }} - /> + />*/} ); From 380a36c26e27480e202352abc6295795a917e727 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 24 Jun 2021 20:53:12 +0100 Subject: [PATCH 0009/1462] Fix: Onboarding would not appear due to content pushing it out of the way. --- src/context/intermediate/Intermediate.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context/intermediate/Intermediate.tsx b/src/context/intermediate/Intermediate.tsx index 3c4f66a79..12f0e442a 100644 --- a/src/context/intermediate/Intermediate.tsx +++ b/src/context/intermediate/Intermediate.tsx @@ -108,7 +108,7 @@ export default function Intermediate(props: Props) { return ( - {props.children} + { screen.id !== 'onboarding' && props.children } Date: Thu, 24 Jun 2021 21:07:07 +0100 Subject: [PATCH 0010/1462] Fix: Load Theme early for onboarding. --- index.html | 5 ++++ src/context/index.tsx | 24 ++++++++++--------- .../modals/Onboarding.module.scss | 3 +++ src/styles/_page.scss | 2 +- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/index.html b/index.html index 20826661a..c83d63f4a 100644 --- a/index.html +++ b/index.html @@ -11,4 +11,9 @@
+ diff --git a/src/context/index.tsx b/src/context/index.tsx index 6bb0de8fd..4cbbb76bd 100644 --- a/src/context/index.tsx +++ b/src/context/index.tsx @@ -13,17 +13,19 @@ export default function Context({ children }: { children: Children }) { return ( - - - - - - {children} - - - - - + + + + + + + {children} + + + + + + ); diff --git a/src/context/intermediate/modals/Onboarding.module.scss b/src/context/intermediate/modals/Onboarding.module.scss index f3ed2dde9..93f5e4b99 100644 --- a/src/context/intermediate/modals/Onboarding.module.scss +++ b/src/context/intermediate/modals/Onboarding.module.scss @@ -1,4 +1,5 @@ .onboarding { + height: 100vh; display: flex; align-items: center; flex-direction: column; @@ -7,7 +8,9 @@ flex: 1; &.header { + gap: 8px; padding: 3em; + display: flex; text-align: center; h1 { diff --git a/src/styles/_page.scss b/src/styles/_page.scss index c99320ab4..124e530ab 100644 --- a/src/styles/_page.scss +++ b/src/styles/_page.scss @@ -9,9 +9,9 @@ html { // contain: content; - background: var(--background); background-size: cover !important; background-repeat: no-repeat !important; + background-color: var(--background) !important; } html, From fa3f756ae78e6ad1b1facb5ca7485370a36c1fbf Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 24 Jun 2021 22:06:30 +0100 Subject: [PATCH 0011/1462] Fix: Notification settings not affecting playSound --- src/context/Settings.tsx | 2 +- src/context/revoltjs/Notifications.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/context/Settings.tsx b/src/context/Settings.tsx index 58e05deb2..7f834feae 100644 --- a/src/context/Settings.tsx +++ b/src/context/Settings.tsx @@ -25,7 +25,7 @@ interface Props { function Settings({ settings, children }: Props) { const play = useMemo(() => { - const enabled: SoundOptions = defaultsDeep(settings.notification ?? {}, DEFAULT_SOUNDS); + const enabled: SoundOptions = defaultsDeep(settings.notification?.sounds ?? {}, DEFAULT_SOUNDS); return (sound: Sounds) => { if (enabled[sound]) { playSound(sound); diff --git a/src/context/revoltjs/Notifications.tsx b/src/context/revoltjs/Notifications.tsx index 7f7fe11f3..51f610b83 100644 --- a/src/context/revoltjs/Notifications.tsx +++ b/src/context/revoltjs/Notifications.tsx @@ -192,7 +192,7 @@ function Notifier(props: Props) { client.removeListener("message", message); client.users.removeListener("mutation", relationship); }; - }, [client, guild_id, channel_id, showNotification]); + }, [client, playSound, guild_id, channel_id, showNotification]); useEffect(() => { function visChange() { From 809c2f1d18d608708d8458ce568aac3af1c1805d Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 24 Jun 2021 23:59:46 +0100 Subject: [PATCH 0012/1462] Feature: Basic notification options implementation --- external/lang | 2 +- src/context/intermediate/Intermediate.tsx | 4 +- src/context/revoltjs/Notifications.tsx | 31 +++++++--- src/context/revoltjs/SyncManager.tsx | 9 ++- src/lib/ContextMenus.tsx | 75 +++++++++++++++++++++-- src/pages/settings/panes/Sync.tsx | 1 + src/redux/index.ts | 8 ++- src/redux/reducers/index.ts | 5 +- src/redux/reducers/notifications.ts | 56 +++++++++++++++++ src/redux/reducers/sync.ts | 5 +- 10 files changed, 172 insertions(+), 24 deletions(-) create mode 100644 src/redux/reducers/notifications.ts diff --git a/external/lang b/external/lang index 099fb7413..9cc46c3a4 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 099fb74131c60955e8226ce0a290cb22e959d7d6 +Subproject commit 9cc46c3a4abab74e17e56597db10e2c16ac0f9b5 diff --git a/src/context/intermediate/Intermediate.tsx b/src/context/intermediate/Intermediate.tsx index 12f0e442a..e96a72a3b 100644 --- a/src/context/intermediate/Intermediate.tsx +++ b/src/context/intermediate/Intermediate.tsx @@ -116,7 +116,7 @@ export default function Intermediate(props: Props) { screen.id } /** By specifying a key, we reset state whenever switching screen. */ /> - {/* { if (action === 'POP') { @@ -128,7 +128,7 @@ export default function Intermediate(props: Props) { return true; }} - />*/} + />
); diff --git a/src/context/revoltjs/Notifications.tsx b/src/context/revoltjs/Notifications.tsx index 51f610b83..d9f4f1f9a 100644 --- a/src/context/revoltjs/Notifications.tsx +++ b/src/context/revoltjs/Notifications.tsx @@ -8,9 +8,11 @@ import { connectState } from "../../redux/connector"; import { Message, SYSTEM_USER_ID, User } from "revolt.js"; import { NotificationOptions } from "../../redux/reducers/settings"; import { Route, Switch, useHistory, useParams } from "react-router-dom"; +import { getNotificationState, Notifications } from "../../redux/reducers/notifications"; interface Props { options?: NotificationOptions; + notifs: Notifications; } const notifications: { [key: string]: Notification } = {}; @@ -24,9 +26,9 @@ async function createNotification(title: string, options: globalThis.Notificatio } } -function Notifier(props: Props) { +function Notifier({ options, notifs }: Props) { const translate = useTranslation(); - const showNotification = props.options?.desktopEnabled ?? false; + const showNotification = options?.desktopEnabled ?? false; const client = useContext(AppContext); const { guild: guild_id, channel: channel_id } = useParams<{ @@ -39,17 +41,27 @@ function Notifier(props: Props) { async function message(msg: Message) { if (msg.author === client.user!._id) return; if (msg.channel === channel_id && document.hasFocus()) return; - if (client.user?.status?.presence === Users.Presence.Busy) return; - - playSound('message'); - if (!showNotification) return; + if (client.user!.status?.presence === Users.Presence.Busy) return; const channel = client.channels.get(msg.channel); const author = client.users.get(msg.author); + if (!channel) return; if (author?.relationship === Users.Relationship.Blocked) return; + const notifState = getNotificationState(notifs, channel); + switch (notifState) { + case 'muted': + case 'none': return; + case 'mention': { + if (!msg.mentions?.includes(client.user!._id)) return; + } + } + + playSound('message'); + if (!showNotification) return; + let title; - switch (channel?.channel_type) { + switch (channel.channel_type) { case "SavedMessages": return; case "DirectMessage": @@ -192,7 +204,7 @@ function Notifier(props: Props) { client.removeListener("message", message); client.users.removeListener("mutation", relationship); }; - }, [client, playSound, guild_id, channel_id, showNotification]); + }, [client, playSound, guild_id, channel_id, showNotification, notifs]); useEffect(() => { function visChange() { @@ -217,7 +229,8 @@ const NotifierComponent = connectState( Notifier, state => { return { - options: state.settings.notification + options: state.settings.notification, + notifs: state.notifications }; }, true diff --git a/src/context/revoltjs/SyncManager.tsx b/src/context/revoltjs/SyncManager.tsx index 95361cc5e..d3fd7ca7a 100644 --- a/src/context/revoltjs/SyncManager.tsx +++ b/src/context/revoltjs/SyncManager.tsx @@ -9,6 +9,7 @@ import { useContext, useEffect } from "preact/hooks"; import { connectState } from "../../redux/connector"; import { WithDispatcher } from "../../redux/reducers"; import { Settings } from "../../redux/reducers/settings"; +import { Notifications } from "../../redux/reducers/notifications"; import { AppContext, ClientStatus, StatusContext } from "./RevoltClient"; import { ClientboundNotification } from "revolt.js/dist/websocket/notifications"; import { DEFAULT_ENABLED_SYNC, SyncData, SyncKeys, SyncOptions } from "../../redux/reducers/sync"; @@ -16,7 +17,8 @@ import { DEFAULT_ENABLED_SYNC, SyncData, SyncKeys, SyncOptions } from "../../red type Props = WithDispatcher & { settings: Settings, locale: Language, - sync: SyncOptions + sync: SyncOptions, + notifications: Notifications }; var lastValues: { [key in SyncKeys]?: any } = { }; @@ -78,7 +80,7 @@ function SyncManager(props: Props) { } let disabled = props.sync.disabled ?? []; - for (let [key, object] of [ ['appearance', props.settings.appearance], ['theme', props.settings.theme], ['locale', props.locale] ] as [SyncKeys, any][]) { + for (let [key, object] of [ ['appearance', props.settings.appearance], ['theme', props.settings.theme], ['locale', props.locale], ['notifications', props.notifications] ] as [SyncKeys, any][]) { useEffect(() => { if (disabled.indexOf(key) === -1) { if (typeof lastValues[key] !== 'undefined') { @@ -117,7 +119,8 @@ export default connectState( return { settings: state.settings, locale: state.locale, - sync: state.sync + sync: state.sync, + notifications: state.notifications }; }, true diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index 89bdf8f49..875e9a440 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -5,7 +5,8 @@ import { Attachment, Channels, Message, Servers, Users } from "revolt.js/dist/ap import { ContextMenu, ContextMenuWithData, - MenuItem + MenuItem, + openContextMenu } from "preact-context-menu"; import { ChannelPermission, ServerPermission, UserPermission } from "revolt.js/dist/api/permissions"; import { QueuedMessage } from "../redux/reducers/queue"; @@ -18,6 +19,9 @@ import { Children } from "../types/Preact"; import LineDivider from "../components/ui/LineDivider"; import { connectState } from "../redux/connector"; import { internalEmit } from "./eventEmitter"; +import { AtSign, Bell, BellOff, Check, CheckSquare, ChevronRight, Slash, Square } from "@styled-icons/feather"; +import { getNotificationState, Notifications, NotificationState } from "../redux/reducers/notifications"; +import { ArrowLeft } from "@styled-icons/bootstrap"; interface ContextMenuData { user?: string; @@ -68,11 +72,17 @@ type Action = | { action: "close_dm"; target: Channels.DirectMessageChannel } | { action: "leave_server"; target: Servers.Server } | { action: "delete_server"; target: Servers.Server } + | { action: "open_notification_options", channel: Channels.Channel } | { action: "open_channel_settings", id: string } | { action: "open_server_settings", id: string } - | { action: "open_server_channel_settings", server: string, id: string }; + | { action: "open_server_channel_settings", server: string, id: string } + | { action: "set_notification_state", key: string, state?: NotificationState }; -function ContextMenus(props: WithDispatcher) { +type Props = WithDispatcher & { + notifications: Notifications +}; + +function ContextMenus(props: Props) { const { openScreen, writeClipboard } = useIntermediate(); const client = useContext(AppContext); const userId = client.user!._id; @@ -301,9 +311,24 @@ function ContextMenus(props: WithDispatcher) { case "ban_member": case "kick_member": openScreen({ id: "special_prompt", type: data.action, target: data.target, user: data.user }); break; + case "open_notification_options": { + openContextMenu("NotificationOptions", { channel: data.channel }); + break; + } + case "open_channel_settings": history.push(`/channel/${data.id}/settings`); break; case "open_server_channel_settings": history.push(`/server/${data.server}/channel/${data.id}/settings`); break; case "open_server_settings": history.push(`/server/${data.id}/settings`); break; + + case "set_notification_state": { + const { key, state } = data; + if (state) { + props.dispatcher({ type: "NOTIFICATIONS_SET", key, state }); + } else { + props.dispatcher({ type: "NOTIFICATIONS_REMOVE", key }); + } + break; + } } })().catch(err => { openScreen({ id: "error", error: takeError(err) }); @@ -567,6 +592,10 @@ function ContextMenus(props: WithDispatcher) { pushDivider(); if (channel) { + if (channel.channel_type !== 'VoiceChannel') { + generateAction({ action: "open_notification_options", channel }, undefined, undefined, ); + } + switch (channel.channel_type) { case 'Group': // ! generateAction({ action: "create_invite", target: channel }); FIXME: add support for group invites @@ -669,14 +698,50 @@ function ContextMenus(props: WithDispatcher) { )} + + {({ channel }: { channel: Channels.Channel }) => { + const state = props.notifications[channel._id]; + const actual = getNotificationState(props.notifications, channel); + + let elements: Children[] = [ + + +
+ { (state !== undefined) && } + { (state === undefined) && } +
+
+ ]; + + function generate(key: string, icon: Children) { + elements.push( + + { icon } + + { (state === undefined && actual === key) &&
} + { (state === key) &&
} +
+ ); + } + + generate('all', ); + generate('mention', ); + generate('muted', ); + generate('none', ); + + return elements; + }} +
); } export default connectState( ContextMenus, - () => { - return {}; + state => { + return { + notifications: state.notifications + }; }, true ); diff --git a/src/pages/settings/panes/Sync.tsx b/src/pages/settings/panes/Sync.tsx index e56312869..ad7c84f82 100644 --- a/src/pages/settings/panes/Sync.tsx +++ b/src/pages/settings/panes/Sync.tsx @@ -20,6 +20,7 @@ export function Component(props: Props & WithDispatcher) { ['appearance', 'appearance.title'], ['theme', 'appearance.theme'], ['locale', 'language.title'] + // notifications sync is always-on ] as [ SyncKeys, string ][]).map( ([ key, title ]) => { drafts, sync, experiments, - lastOpened + lastOpened, + notifications } = store.getState() as State; localForage.setItem("state", { @@ -66,6 +69,7 @@ store.subscribe(() => { drafts, sync, experiments, - lastOpened + lastOpened, + notifications }); }); diff --git a/src/redux/reducers/index.ts b/src/redux/reducers/index.ts index 6c84f87fa..fe47ccbdc 100644 --- a/src/redux/reducers/index.ts +++ b/src/redux/reducers/index.ts @@ -12,6 +12,7 @@ import { drafts, DraftAction } from "./drafts"; import { sync, SyncAction } from "./sync"; import { experiments, ExperimentsAction } from "./experiments"; import { lastOpened, LastOpenedAction } from "./last_opened"; +import { notifications, NotificationsAction } from "./notifications"; export default combineReducers({ config, @@ -24,7 +25,8 @@ export default combineReducers({ drafts, sync, experiments, - lastOpened + lastOpened, + notifications }); export type Action = @@ -39,6 +41,7 @@ export type Action = | SyncAction | ExperimentsAction | LastOpenedAction + | NotificationsAction | { type: "__INIT"; state: State }; export type WithDispatcher = { dispatcher: (action: Action) => void }; diff --git a/src/redux/reducers/notifications.ts b/src/redux/reducers/notifications.ts new file mode 100644 index 000000000..2ca5b030c --- /dev/null +++ b/src/redux/reducers/notifications.ts @@ -0,0 +1,56 @@ +import { Channel } from "revolt.js"; + +export type NotificationState = 'all' | 'mention' | 'none' | 'muted'; + +export type Notifications = { + [key: string]: NotificationState +} + +export const DEFAULT_STATES: { [key in Channel['channel_type']]: NotificationState } = { + 'SavedMessages': 'all', + 'DirectMessage': 'all', + 'Group': 'all', + 'TextChannel': 'mention', + 'VoiceChannel': 'mention' +}; + +export function getNotificationState(notifications: Notifications, channel: Channel) { + return notifications[channel._id] ?? DEFAULT_STATES[channel.channel_type]; +} + +export type NotificationsAction = + | { type: undefined } + | { + type: "NOTIFICATIONS_SET"; + key: string; + state: NotificationState; + } + | { + type: "NOTIFICATIONS_REMOVE"; + key: string; + } + | { + type: "RESET"; + }; + +export function notifications( + state = {} as Notifications, + action: NotificationsAction +): Notifications { + switch (action.type) { + case "NOTIFICATIONS_SET": + return { + ...state, + [action.key]: action.state + }; + case "NOTIFICATIONS_REMOVE": + { + const { [action.key]: _, ...newState } = state; + return newState; + } + case "RESET": + return {}; + default: + return state; + } +} diff --git a/src/redux/reducers/sync.ts b/src/redux/reducers/sync.ts index 1e2d4a319..0e2c8111b 100644 --- a/src/redux/reducers/sync.ts +++ b/src/redux/reducers/sync.ts @@ -1,19 +1,22 @@ import { AppearanceOptions } from "./settings"; import { Language } from "../../context/Locale"; import { ThemeOptions } from "../../context/Theme"; +import { Notifications } from "./notifications"; -export type SyncKeys = "theme" | "appearance" | "locale"; +export type SyncKeys = "theme" | "appearance" | "locale" | "notifications"; export interface SyncData { locale?: Language; theme?: ThemeOptions; appearance?: AppearanceOptions; + notifications?: Notifications; } export const DEFAULT_ENABLED_SYNC: SyncKeys[] = [ "theme", "appearance", "locale", + "notifications" ]; export interface SyncOptions { disabled?: SyncKeys[]; From 5c0e14b6cacb9eb5dd24e93466391e2b7f87a901 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 25 Jun 2021 12:37:59 +0100 Subject: [PATCH 0013/1462] Notifications: Block muted channels from push notifs. --- src/context/revoltjs/Notifications.tsx | 10 ++------- src/redux/reducers/auth.ts | 2 +- src/redux/reducers/locale.ts | 2 +- src/redux/reducers/notifications.ts | 18 +++++++++++++++- src/redux/reducers/queue.ts | 2 +- src/redux/reducers/server_config.ts | 2 +- src/redux/reducers/settings.ts | 6 +++--- src/redux/reducers/sync.ts | 8 +++---- src/redux/reducers/unreads.ts | 2 +- src/sw.ts | 30 +++++++++++++++++++------- 10 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/context/revoltjs/Notifications.tsx b/src/context/revoltjs/Notifications.tsx index d9f4f1f9a..7becc006e 100644 --- a/src/context/revoltjs/Notifications.tsx +++ b/src/context/revoltjs/Notifications.tsx @@ -8,7 +8,7 @@ import { connectState } from "../../redux/connector"; import { Message, SYSTEM_USER_ID, User } from "revolt.js"; import { NotificationOptions } from "../../redux/reducers/settings"; import { Route, Switch, useHistory, useParams } from "react-router-dom"; -import { getNotificationState, Notifications } from "../../redux/reducers/notifications"; +import { getNotificationState, Notifications, shouldNotify } from "../../redux/reducers/notifications"; interface Props { options?: NotificationOptions; @@ -49,13 +49,7 @@ function Notifier({ options, notifs }: Props) { if (author?.relationship === Users.Relationship.Blocked) return; const notifState = getNotificationState(notifs, channel); - switch (notifState) { - case 'muted': - case 'none': return; - case 'mention': { - if (!msg.mentions?.includes(client.user!._id)) return; - } - } + if (!shouldNotify(notifState, msg, client.user!._id)) return; playSound('message'); if (!showNotification) return; diff --git a/src/redux/reducers/auth.ts b/src/redux/reducers/auth.ts index 38cd4df73..c309e4f83 100644 --- a/src/redux/reducers/auth.ts +++ b/src/redux/reducers/auth.ts @@ -1,4 +1,4 @@ -import { Auth } from "revolt.js/dist/api/objects"; +import type { Auth } from "revolt.js/dist/api/objects"; export interface AuthState { accounts: { diff --git a/src/redux/reducers/locale.ts b/src/redux/reducers/locale.ts index 416da63cf..6146dd53e 100644 --- a/src/redux/reducers/locale.ts +++ b/src/redux/reducers/locale.ts @@ -1,5 +1,5 @@ import { Language } from "../../context/Locale"; -import { SyncUpdateAction } from "./sync"; +import type { SyncUpdateAction } from "./sync"; export type LocaleAction = | { type: undefined } diff --git a/src/redux/reducers/notifications.ts b/src/redux/reducers/notifications.ts index 2ca5b030c..6ffd352e1 100644 --- a/src/redux/reducers/notifications.ts +++ b/src/redux/reducers/notifications.ts @@ -1,4 +1,5 @@ -import { Channel } from "revolt.js"; +import type { Channel, Message } from "revolt.js"; +import type { SyncUpdateAction } from "./sync"; export type NotificationState = 'all' | 'mention' | 'none' | 'muted'; @@ -18,6 +19,18 @@ export function getNotificationState(notifications: Notifications, channel: Chan return notifications[channel._id] ?? DEFAULT_STATES[channel.channel_type]; } +export function shouldNotify(state: NotificationState, message: Message, user_id: string) { + switch (state) { + case 'muted': + case 'none': return false; + case 'mention': { + if (!message.mentions?.includes(user_id)) return false; + } + } + + return true; +} + export type NotificationsAction = | { type: undefined } | { @@ -29,6 +42,7 @@ export type NotificationsAction = type: "NOTIFICATIONS_REMOVE"; key: string; } + | SyncUpdateAction | { type: "RESET"; }; @@ -48,6 +62,8 @@ export function notifications( const { [action.key]: _, ...newState } = state; return newState; } + case "SYNC_UPDATE": + return action.update.notifications?.[1] ?? state; case "RESET": return {}; default: diff --git a/src/redux/reducers/queue.ts b/src/redux/reducers/queue.ts index 3bcbec581..ef64578ed 100644 --- a/src/redux/reducers/queue.ts +++ b/src/redux/reducers/queue.ts @@ -1,4 +1,4 @@ -import { MessageObject } from "../../context/revoltjs/util"; +import type { MessageObject } from "../../context/revoltjs/util"; export enum QueueStatus { SENDING = "sending", diff --git a/src/redux/reducers/server_config.ts b/src/redux/reducers/server_config.ts index 9e14fb0b1..6046c5d10 100644 --- a/src/redux/reducers/server_config.ts +++ b/src/redux/reducers/server_config.ts @@ -1,4 +1,4 @@ -import { Core } from "revolt.js/dist/api/objects"; +import type { Core } from "revolt.js/dist/api/objects"; export type ConfigAction = | { type: undefined } diff --git a/src/redux/reducers/settings.ts b/src/redux/reducers/settings.ts index a37d7ef14..bd7e82202 100644 --- a/src/redux/reducers/settings.ts +++ b/src/redux/reducers/settings.ts @@ -1,7 +1,7 @@ import { filter } from "."; -import { SyncUpdateAction } from "./sync"; -import { Sounds } from "../../assets/sounds/Audio"; -import { Theme, ThemeOptions } from "../../context/Theme"; +import type { SyncUpdateAction } from "./sync"; +import type { Sounds } from "../../assets/sounds/Audio"; +import type { Theme, ThemeOptions } from "../../context/Theme"; import { setEmojiPack } from "../../components/common/Emoji"; export type SoundOptions = { diff --git a/src/redux/reducers/sync.ts b/src/redux/reducers/sync.ts index 0e2c8111b..099d98d6a 100644 --- a/src/redux/reducers/sync.ts +++ b/src/redux/reducers/sync.ts @@ -1,7 +1,7 @@ -import { AppearanceOptions } from "./settings"; -import { Language } from "../../context/Locale"; -import { ThemeOptions } from "../../context/Theme"; -import { Notifications } from "./notifications"; +import type { AppearanceOptions } from "./settings"; +import type { Language } from "../../context/Locale"; +import type { ThemeOptions } from "../../context/Theme"; +import type { Notifications } from "./notifications"; export type SyncKeys = "theme" | "appearance" | "locale" | "notifications"; diff --git a/src/redux/reducers/unreads.ts b/src/redux/reducers/unreads.ts index 290afdcbd..1f1b2fb15 100644 --- a/src/redux/reducers/unreads.ts +++ b/src/redux/reducers/unreads.ts @@ -1,4 +1,4 @@ -import { Sync } from "revolt.js/dist/api/objects"; +import type { Sync } from "revolt.js/dist/api/objects"; export interface Unreads { [key: string]: Partial>; diff --git a/src/sw.ts b/src/sw.ts index 268481645..7d58aba38 100644 --- a/src/sw.ts +++ b/src/sw.ts @@ -3,6 +3,9 @@ import { precacheAndRoute } from 'workbox-precaching' import { Server } from 'revolt.js/dist/api/objects' import { Channel, Message, User } from 'revolt.js' import { IDBPDatabase, openDB } from 'idb' +import { getItem } from 'localforage' +import type { State } from './redux' +import { getNotificationState, shouldNotify } from './redux/reducers/notifications' declare let self: ServiceWorkerGlobalScope @@ -34,12 +37,18 @@ function decodeTime(id: string) { return time; } -const base_url = `https://autumn.revolt.chat`; self.addEventListener("push", event => { async function process() { if (event.data === null) return; let data: Message = event.data.json(); + let item = await localStorage.getItem('state'); + if (!item) return; + + const state: State = JSON.parse(item); + const autumn_url = state.config.features.autumn.url; + const user_id = state.auth.active!; + let db: IDBPDatabase; try { // Match RevoltClient.tsx#L55 @@ -65,19 +74,24 @@ self.addEventListener("push", event => { } } + let channel = await get('channels', data.channel); + let user = await get('users', data.author); + + if (channel) { + const notifs = getNotificationState(state.notifications, channel); + if (!shouldNotify(notifs, data, user_id)) return; + } + + let title = `@${data.author}`; + let username = user?.username ?? data.author; let image; if (data.attachments) { let attachment = data.attachments[0]; if (attachment.metadata.type === "Image") { - image = `${base_url}/${attachment.tag}/${attachment._id}`; + image = `${autumn_url}/${attachment.tag}/${attachment._id}`; } } - let title = `@${data.author}`; - let channel = await get('channels', data.channel); - let user = await get('users', data.author); - let username = user?.username ?? data.author; - switch (channel?.channel_type) { case "SavedMessages": break; case "DirectMessage": title = `@${username}`; break; @@ -97,7 +111,7 @@ self.addEventListener("push", event => { } await self.registration.showNotification(title, { - icon: user?.avatar ? `${base_url}/${user.avatar.tag}/${user.avatar._id}` : `https://api.revolt.chat/users/${data.author}/default_avatar`, + icon: user?.avatar ? `${autumn_url}/${user.avatar.tag}/${user.avatar._id}` : `https://api.revolt.chat/users/${data.author}/default_avatar`, image, body: typeof data.content === "string" ? data.content : JSON.stringify(data.content), timestamp: decodeTime(data._id), From 90713b3c5d01fb024b7a54fc062c367b0325509e Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 26 Jun 2021 09:45:07 +0100 Subject: [PATCH 0014/1462] Support replying to files, show icon in reply. --- src/components/common/messaging/Message.tsx | 6 +++--- .../common/messaging/attachments/MessageReply.tsx | 10 ++++++++-- src/components/common/messaging/bars/ReplyBar.tsx | 14 ++++++++++---- src/lib/ContextMenus.tsx | 10 +++++----- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/components/common/messaging/Message.tsx b/src/components/common/messaging/Message.tsx index d504f9667..0c5369493 100644 --- a/src/components/common/messaging/Message.tsx +++ b/src/components/common/messaging/Message.tsx @@ -35,9 +35,9 @@ function Message({ attachContext, message, contrast, content: replacement, head: const userContext = attachContext ? attachContextMenu('Menu', { user: message.author, contextualChannel: message.channel }) : undefined as any; // ! FIXME: tell fatal to make this type generic return ( - <> +
{ message.replies?.map((message_id, index) => ) } - 0)} contrast={contrast} sending={typeof queued !== 'undefined'} @@ -64,7 +64,7 @@ function Message({ attachContext, message, contrast, content: replacement, head: ) } - +
) } diff --git a/src/components/common/messaging/attachments/MessageReply.tsx b/src/components/common/messaging/attachments/MessageReply.tsx index 0d7c0691c..74952ea2e 100644 --- a/src/components/common/messaging/attachments/MessageReply.tsx +++ b/src/components/common/messaging/attachments/MessageReply.tsx @@ -2,7 +2,7 @@ import { Text } from "preact-i18n"; import UserShort from "../../user/UserShort"; import styled, { css } from "styled-components"; import Markdown from "../../../markdown/Markdown"; -import { CornerUpRight } from "@styled-icons/feather"; +import { CornerUpRight, File } from "@styled-icons/feather"; import { useUser } from "../../../../context/revoltjs/hooks"; import { useRenderState } from "../../../../lib/renderer/Singleton"; @@ -22,7 +22,12 @@ export const ReplyBase = styled.div<{ head?: boolean, fail?: boolean, preview?: align-items: center; color: var(--secondary-foreground); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + svg { + flex-shrink: 0; color: var(--tertiary-foreground); } @@ -59,7 +64,8 @@ export function MessageReply({ index, channel, id }: Props) { - + { message.attachments && message.attachments.length > 0 && } + ) } diff --git a/src/components/common/messaging/bars/ReplyBar.tsx b/src/components/common/messaging/bars/ReplyBar.tsx index 33a2da4f1..bfc550e48 100644 --- a/src/components/common/messaging/bars/ReplyBar.tsx +++ b/src/components/common/messaging/bars/ReplyBar.tsx @@ -1,14 +1,15 @@ +import { Text } from "preact-i18n"; import styled from "styled-components"; import UserShort from "../../user/UserShort"; +import IconButton from "../../../ui/IconButton"; import Markdown from "../../../markdown/Markdown"; -import { AtSign, CornerUpRight, XCircle } from "@styled-icons/feather"; import { StateUpdater, useEffect } from "preact/hooks"; import { ReplyBase } from "../attachments/MessageReply"; import { Reply } from "../../../../redux/reducers/queue"; import { useUsers } from "../../../../context/revoltjs/hooks"; import { internalSubscribe } from "../../../../lib/eventEmitter"; import { useRenderState } from "../../../../lib/renderer/Singleton"; -import IconButton from "../../../ui/IconButton"; +import { AtSign, CornerUpRight, File, XCircle } from "@styled-icons/feather"; interface Props { channel: string, @@ -58,7 +59,11 @@ export default function ReplyBar({ channel, replies, setReplies }: Props) {
{ replies.map((reply, index) => { let message = messages.find(x => reply.id === x._id); - if (!message) return; + // ! FIXME: better solution would be to + // ! have a hook for resolving messages from + // ! render state along with relevant users + // -> which then fetches any unknown messages + if (!message) return ; let user = users.find(x => message!.author === x?._id); if (!user) return; @@ -68,7 +73,8 @@ export default function ReplyBar({ channel, replies, setReplies }: Props) { - + { message.attachments && message.attachments.length > 0 && } + setReplies(replies.map((_, i) => i === index ? { ..._, mention: !_.mention } : _))}> diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index 875e9a440..3636bdffc 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -502,15 +502,15 @@ function ContextMenus(props: Props) { } if (message && !queued) { + generateAction({ + action: "reply_message", + id: message._id + }); + if ( typeof message.content === "string" && message.content.length > 0 ) { - generateAction({ - action: "reply_message", - id: message._id - }); - generateAction({ action: "quote_message", content: message.content From b42cf8108878fc9fa6c92deadab6dc644c6b5eaf Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 26 Jun 2021 10:34:48 +0100 Subject: [PATCH 0015/1462] Fix: "Modify Account" did not have access to client --- external/lang | 2 +- src/context/intermediate/Intermediate.tsx | 2 +- src/context/intermediate/Modals.tsx | 3 --- src/context/intermediate/Popovers.tsx | 3 +++ .../intermediate/{modals => popovers}/ModifyAccount.tsx | 0 5 files changed, 5 insertions(+), 5 deletions(-) rename src/context/intermediate/{modals => popovers}/ModifyAccount.tsx (100%) diff --git a/external/lang b/external/lang index 9cc46c3a4..47182fb71 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 9cc46c3a4abab74e17e56597db10e2c16ac0f9b5 +Subproject commit 47182fb7112f82efa61ffe2856f25ca19c78b8c5 diff --git a/src/context/intermediate/Intermediate.tsx b/src/context/intermediate/Intermediate.tsx index e96a72a3b..ff723c0b9 100644 --- a/src/context/intermediate/Intermediate.tsx +++ b/src/context/intermediate/Intermediate.tsx @@ -15,7 +15,6 @@ export type Screen = | { id: "signed_out" } | { id: "error"; error: string } | { id: "clipboard"; text: string } -| { id: "modify_account"; field: "username" | "email" | "password" } | { id: "_prompt"; question: Children; content?: Children; actions: Action[] } | ({ id: "special_prompt" } & ( { type: "leave_group", target: Channels.GroupChannel } | @@ -49,6 +48,7 @@ export type Screen = // Pop-overs | { id: "image_viewer"; attachment?: Attachment; embed?: EmbedImage; } +| { id: "modify_account"; field: "username" | "email" | "password" } | { id: "profile"; user_id: string } | { id: "channel_info"; channel_id: string } | { diff --git a/src/context/intermediate/Modals.tsx b/src/context/intermediate/Modals.tsx index b6035595c..e825bcbc9 100644 --- a/src/context/intermediate/Modals.tsx +++ b/src/context/intermediate/Modals.tsx @@ -6,7 +6,6 @@ import { PromptModal } from "./modals/Prompt"; import { SignedOutModal } from "./modals/SignedOut"; import { ClipboardModal } from "./modals/Clipboard"; import { OnboardingModal } from "./modals/Onboarding"; -import { ModifyAccountModal } from "./modals/ModifyAccount"; export interface Props { screen: Screen; @@ -27,8 +26,6 @@ export default function Modals({ screen, openScreen }: Props) { return ; case "clipboard": return ; - case "modify_account": - return ; case "onboarding": return ; } diff --git a/src/context/intermediate/Popovers.tsx b/src/context/intermediate/Popovers.tsx index f91b02dce..73d2337eb 100644 --- a/src/context/intermediate/Popovers.tsx +++ b/src/context/intermediate/Popovers.tsx @@ -7,6 +7,7 @@ import { SpecialPromptModal } from "./modals/Prompt"; import { UserProfile } from "./popovers/UserProfile"; import { ImageViewer } from "./popovers/ImageViewer"; import { ChannelInfo } from "./popovers/ChannelInfo"; +import { ModifyAccountModal } from "./popovers/ModifyAccount"; export default function Popovers() { const { screen } = useContext(IntermediateContext); @@ -23,6 +24,8 @@ export default function Popovers() { return ; case "channel_info": return ; + case "modify_account": + return ; case "special_prompt": return ; case "special_input": diff --git a/src/context/intermediate/modals/ModifyAccount.tsx b/src/context/intermediate/popovers/ModifyAccount.tsx similarity index 100% rename from src/context/intermediate/modals/ModifyAccount.tsx rename to src/context/intermediate/popovers/ModifyAccount.tsx From fbda68cbf87b9a294586b50b67a9d3650b723b4d Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 26 Jun 2021 11:23:28 +0100 Subject: [PATCH 0016/1462] Fix notifications playing in servers. --- src/context/revoltjs/Notifications.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/context/revoltjs/Notifications.tsx b/src/context/revoltjs/Notifications.tsx index 7becc006e..dc90617be 100644 --- a/src/context/revoltjs/Notifications.tsx +++ b/src/context/revoltjs/Notifications.tsx @@ -233,6 +233,9 @@ const NotifierComponent = connectState( export default function Notifications() { return ( + + + From 7300452953f4dfb02bff926f40c0428eb2362bf5 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 26 Jun 2021 11:59:21 +0100 Subject: [PATCH 0017/1462] Add FUNDING.yml for GH --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..5b405a7fd --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +ko_fi: insertish \ No newline at end of file From b6cb3cfd6e4f8a972560606ddc083b79058a0508 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 26 Jun 2021 22:16:43 +0100 Subject: [PATCH 0018/1462] Handle permissions in message box. --- external/lang | 2 +- package.json | 2 +- .../common/messaging/MessageBox.tsx | 34 +++++++++++++++---- yarn.lock | 8 ++--- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/external/lang b/external/lang index 47182fb71..456777fcf 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 47182fb7112f82efa61ffe2856f25ca19c78b8c5 +Subproject commit 456777fcf68daaa3d1a5ceb6442f222cdc9e415d diff --git a/package.json b/package.json index b6235533f..3c7113141 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "react-scroll": "^1.8.2", "react-tippy": "^1.4.0", "redux": "^4.1.0", - "revolt.js": "4.3.2-patch.1", + "revolt.js": "4.3.3-alpha.1", "rimraf": "^3.0.2", "sass": "^1.35.1", "shade-blend-color": "^1.0.0", diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index 86463d3a3..ea8391a51 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -1,18 +1,23 @@ import { ulid } from "ulid"; +import { Text } from "preact-i18n"; import { Channel } from "revolt.js"; import styled from "styled-components"; import { defer } from "../../../lib/defer"; import IconButton from "../../ui/IconButton"; -import { Send } from '@styled-icons/feather'; +import { Send, X } from '@styled-icons/feather'; import { debounce } from "../../../lib/debounce"; import Axios, { CancelTokenSource } from "axios"; import { useTranslation } from "../../../lib/i18n"; import { Reply } from "../../../redux/reducers/queue"; import { connectState } from "../../../redux/connector"; +import { SoundContext } from "../../../context/Settings"; import { WithDispatcher } from "../../../redux/reducers"; import { takeError } from "../../../context/revoltjs/util"; import TextAreaAutoSize from "../../../lib/TextAreaAutoSize"; +import AutoComplete, { useAutoComplete } from "../AutoComplete"; +import { ChannelPermission } from "revolt.js/dist/api/permissions"; import { AppContext } from "../../../context/revoltjs/RevoltClient"; +import { useChannelPermission } from "../../../context/revoltjs/hooks"; import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice"; import { internalEmit, internalSubscribe } from "../../../lib/eventEmitter"; import { useCallback, useContext, useEffect, useState } from "preact/hooks"; @@ -22,8 +27,6 @@ import { SingletonMessageRenderer, SMOOTH_SCROLL_ON_RECEIVE } from "../../../lib import ReplyBar from "./bars/ReplyBar"; import FilePreview from './bars/FilePreview'; -import AutoComplete, { useAutoComplete } from "../AutoComplete"; -import { SoundContext } from "../../../context/Settings"; type Props = WithDispatcher & { channel: Channel; @@ -48,6 +51,14 @@ const Base = styled.div` } `; +const Blocked = styled.div` + padding: 15px 0; + line-height: 20px; + user-select: none; + font-size: .875rem; + color: var(--tertiary-foreground); +`; + const Action = styled.div` display: grid; place-items: center; @@ -65,6 +76,15 @@ function MessageBox({ channel, draft, dispatcher }: Props) { const client = useContext(AppContext); const translate = useTranslation(); + const permissions = useChannelPermission(channel._id); + if (!(permissions & ChannelPermission.SendMessage)) { + return ( + + + + ) + } + function setMessage(content?: string) { if (content) { dispatcher({ @@ -272,7 +292,7 @@ function MessageBox({ channel, draft, dispatcher }: Props) { }} /> - + { (permissions & ChannelPermission.UploadFiles) ? - + : undefined } - + { isTouchscreenDevice && - + } ) diff --git a/yarn.lock b/yarn.lock index 182a62772..595a23ce5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3412,10 +3412,10 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -revolt.js@4.3.2-patch.1: - version "4.3.2-patch.1" - resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.2-patch.1.tgz#0c4190f0a640951636c6f2577c9298418b06917f" - integrity sha512-XAu2JeYc2+OFLM56WktGT/4tAyvjibmNL5oGc5pPZEjl0DnoIxPE96CZPe+35ZCX9bEiuoX378Fwfmfe3uN7sw== +revolt.js@4.3.3-alpha.1: + version "4.3.3-alpha.1" + resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.1.tgz#b60a18e5cbe9f2c569e7f46974450931826e10d4" + integrity sha512-MxjTOWqg83cLYdpuqLCl3nOTD+jFxSSjrnvczuijam1YjeZ3IB27C6G4Qar3BwMn7B+zH8MgEDecW3YBmKBpIw== dependencies: "@insertish/mutable" "1.1.0" axios "^0.19.2" From f459772c2004165dd5ef6ddd2316f480415fdacc Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 27 Jun 2021 00:14:58 +0100 Subject: [PATCH 0019/1462] Render server categories. --- package.json | 2 +- .../navigation/left/ServerSidebar.tsx | 59 ++++++++++++------- yarn.lock | 8 +-- 3 files changed, 44 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 3c7113141..6878f1e8e 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "react-scroll": "^1.8.2", "react-tippy": "^1.4.0", "redux": "^4.1.0", - "revolt.js": "4.3.3-alpha.1", + "revolt.js": "4.3.3-alpha.2", "rimraf": "^3.0.2", "sass": "^1.35.1", "shade-blend-color": "^1.0.0", diff --git a/src/components/navigation/left/ServerSidebar.tsx b/src/components/navigation/left/ServerSidebar.tsx index d987af1ee..2b8bcb778 100644 --- a/src/components/navigation/left/ServerSidebar.tsx +++ b/src/components/navigation/left/ServerSidebar.tsx @@ -1,14 +1,10 @@ -import { Link } from "react-router-dom"; -import { Settings } from "@styled-icons/feather"; import { Redirect, useParams } from "react-router"; import { ChannelButton } from "../items/ButtonItem"; import { Channels } from "revolt.js/dist/api/objects"; -import { ServerPermission } from "revolt.js/dist/api/permissions"; import { Unreads } from "../../../redux/reducers/unreads"; import { WithDispatcher } from "../../../redux/reducers"; -import { useChannels, useForceUpdate, useServer, useServerPermission } from "../../../context/revoltjs/hooks"; +import { useChannels, useForceUpdate, useServer } from "../../../context/revoltjs/hooks"; import { mapChannelWithUnread, useUnreads } from "./common"; -import Header from '../../ui/Header'; import ConnectionStatus from '../items/ConnectionStatus'; import { connectState } from "../../../redux/connector"; import PaintCounter from "../../../lib/PaintCounter"; @@ -16,6 +12,7 @@ import styled from "styled-components"; import { attachContextMenu } from 'preact-context-menu'; import ServerHeader from "../../common/ServerHeader"; import { useEffect } from "preact/hooks"; +import Category from "../../ui/Category"; import ConditionalLink from "../../../lib/ConditionalLink"; interface Props { @@ -66,26 +63,48 @@ function ServerSidebar(props: Props & WithDispatcher) { }); }, [ channel_id ]); + let uncategorised = new Set(server.channels); + let elements = []; + function addChannel(id: string) { + const entry = channels.find(x => x._id === id); + if (!entry) return; + + const active = channel?._id === entry._id; + + return ( + + + + ); + } + + if (server.categories) { + for (let category of server.categories) { + elements.push(); + + for (let id of category.channels) { + uncategorised.delete(id); + elements.push(addChannel(id)); + } + } + } + + for (let id of uncategorised) { + elements.unshift(addChannel(id)); + } + return ( - {channels.map(entry => { - const active = channel?._id === entry._id; - - return ( - - - - ); - })} + { elements } diff --git a/yarn.lock b/yarn.lock index 595a23ce5..fbe2cb2a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3412,10 +3412,10 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -revolt.js@4.3.3-alpha.1: - version "4.3.3-alpha.1" - resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.1.tgz#b60a18e5cbe9f2c569e7f46974450931826e10d4" - integrity sha512-MxjTOWqg83cLYdpuqLCl3nOTD+jFxSSjrnvczuijam1YjeZ3IB27C6G4Qar3BwMn7B+zH8MgEDecW3YBmKBpIw== +revolt.js@4.3.3-alpha.2: + version "4.3.3-alpha.2" + resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.2.tgz#1fb876205d74712c45e5f022624ac8d176ab01a1" + integrity sha512-/irTDDtBj63yQtpBk1asnqCNacc+HQXcz0jBOBk1VaOeDsjE6lTO2tGue6wFAG76AL89z9bziQbHIa6cQmWIjg== dependencies: "@insertish/mutable" "1.1.0" axios "^0.19.2" From fa61d93151d1d0ffeddc713634785880bfc3be9f Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 27 Jun 2021 10:05:32 +0100 Subject: [PATCH 0020/1462] Remove feather / bootstrap icons in favour of boxicons. (This build will fail.) --- external/lang | 2 +- package.json | 5 +++-- yarn.lock | 20 ++++++++++++++------ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/external/lang b/external/lang index 456777fcf..9406c734c 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 456777fcf68daaa3d1a5ceb6442f222cdc9e415d +Subproject commit 9406c734ca2cb7b65eefcf926d9e829f9a2056d7 diff --git a/package.json b/package.json index 6878f1e8e..80c9b1a03 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,9 @@ "@hcaptcha/react-hcaptcha": "^0.3.6", "@preact/preset-vite": "^2.0.0", "@rollup/plugin-replace": "^2.4.2", - "@styled-icons/bootstrap": "^10.34.0", - "@styled-icons/feather": "^10.34.0", + "@styled-icons/boxicons-logos": "^10.34.0", + "@styled-icons/boxicons-regular": "^10.34.0", + "@styled-icons/boxicons-solid": "^10.34.0", "@styled-icons/simple-icons": "^10.33.0", "@traptitech/markdown-it-katex": "^3.4.3", "@traptitech/markdown-it-spoiler": "^1.1.6", diff --git a/yarn.lock b/yarn.lock index fbe2cb2a8..60c61c5af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1082,18 +1082,26 @@ estree-walker "^2.0.1" picomatch "^2.2.2" -"@styled-icons/bootstrap@^10.34.0": +"@styled-icons/boxicons-logos@^10.34.0": version "10.34.0" - resolved "https://registry.yarnpkg.com/@styled-icons/bootstrap/-/bootstrap-10.34.0.tgz#d9142e9eb70dc437f7ef62ffc40168e1ae13ab12" - integrity sha512-UpzdVUR7r9BNqEfPrMchJdgMZEg9eXQxLQJUXM0ouvbI5o9j21/y1dGameO4PZtYbutT/dWv5O6y24z5JWzd5w== + resolved "https://registry.yarnpkg.com/@styled-icons/boxicons-logos/-/boxicons-logos-10.34.0.tgz#3bb38d4c695893be24b2ef1ff1500eabb395842b" + integrity sha512-BukvDfVWarIZ2y33QYFTEcS8K1//A2Timo0zZDpQCx8uMVGOb45ZMV/BqNn38pXdbVT1/KpbUoD8GmsGE7M5mw== dependencies: "@babel/runtime" "^7.14.0" "@styled-icons/styled-icon" "^10.6.3" -"@styled-icons/feather@^10.34.0": +"@styled-icons/boxicons-regular@^10.34.0": version "10.34.0" - resolved "https://registry.yarnpkg.com/@styled-icons/feather/-/feather-10.34.0.tgz#fdef1b4231e1ff6cfe454da741161f532788177b" - integrity sha512-UdhKaUC8T98V5H4WEh+UBRfVT7ZTcPpgUUrXlRM2CWanuNIUKpIjj0SKhsnkuprqtzV1L6s3Koa40VTfpG9LYQ== + resolved "https://registry.yarnpkg.com/@styled-icons/boxicons-regular/-/boxicons-regular-10.34.0.tgz#1ea058d8e02d4e74421441816f82a84064f0e7dc" + integrity sha512-w9fcgS0PyZLKHe7woJU/CUSY85/HgLE4btUzRGkLXOMT1dPT/mMV+O0cZEJvFMKQJJDPRJ1poiFbHgnmJ2tFwA== + dependencies: + "@babel/runtime" "^7.14.0" + "@styled-icons/styled-icon" "^10.6.3" + +"@styled-icons/boxicons-solid@^10.34.0": + version "10.34.0" + resolved "https://registry.yarnpkg.com/@styled-icons/boxicons-solid/-/boxicons-solid-10.34.0.tgz#4f31b873a1d52c85230f86eb7106c04f416a12c9" + integrity sha512-0DTsuysRgIO/XoSq5sFPeknnidLzhTEmaG5uJuLmCPBw78VjxNt6DQFRcn8ytn+ba5Qhu+Ps3Km8nbY7Zf14/g== dependencies: "@babel/runtime" "^7.14.0" "@styled-icons/styled-icon" "^10.6.3" From 38be8f8fcc7e6f70283a5c615c8920f2abadee62 Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Sun, 27 Jun 2021 12:17:59 +0200 Subject: [PATCH 0021/1462] Update: Changed icon pack to Boxicons --- src/components/common/ChannelIcon.tsx | 4 +-- src/components/common/ServerHeader.tsx | 4 +-- .../common/messaging/MessageBox.tsx | 2 +- .../attachments/AttachmentActions.tsx | 16 +++++----- .../messaging/attachments/MessageReply.tsx | 6 ++-- .../common/messaging/bars/FilePreview.tsx | 4 +-- .../common/messaging/bars/JumpToBottom.tsx | 4 +-- .../common/messaging/bars/ReplyBar.tsx | 6 ++-- .../messaging/embed/EmbedMediaActions.tsx | 4 +-- src/components/common/user/UserHeader.tsx | 4 +-- src/components/common/user/UserIcon.tsx | 4 +-- .../navigation/BottomNavigation.tsx | 6 ++-- .../navigation/items/ButtonItem.tsx | 4 +-- .../navigation/left/HomeSidebar.tsx | 6 ++-- .../navigation/left/ServerListSidebar.tsx | 6 ++-- src/components/ui/Category.tsx | 2 +- src/components/ui/Checkbox.tsx | 3 +- src/components/ui/ColourSwatches.tsx | 7 ++-- src/components/ui/IconButton.tsx | 4 +-- src/components/ui/Radio.tsx | 6 ++-- src/components/ui/Tip.tsx | 4 +-- .../intermediate/popovers/ChannelInfo.tsx | 2 +- .../intermediate/popovers/UserProfile.tsx | 11 +++---- src/context/revoltjs/FileUploads.tsx | 2 +- src/context/revoltjs/RequiresOnline.tsx | 2 +- src/lib/ContextMenus.tsx | 9 +++--- src/pages/channels/ChannelHeader.tsx | 10 +++--- src/pages/channels/actions/HeaderActions.tsx | 6 ++-- src/pages/channels/voice/VoiceHeader.tsx | 6 ++-- src/pages/friends/Friend.tsx | 4 +-- src/pages/friends/Friends.tsx | 2 +- src/pages/invite/Invite.tsx | 4 +-- src/pages/login/forms/Form.tsx | 4 +-- src/pages/settings/ChannelSettings.tsx | 4 +-- src/pages/settings/GenericSettings.tsx | 4 +-- src/pages/settings/ServerSettings.tsx | 11 ++++--- src/pages/settings/Settings.tsx | 32 +++++++++---------- src/pages/settings/panes/Account.tsx | 6 ++-- src/pages/settings/panes/Sessions.tsx | 2 +- src/pages/settings/server/Invites.tsx | 2 +- 40 files changed, 113 insertions(+), 116 deletions(-) diff --git a/src/components/common/ChannelIcon.tsx b/src/components/common/ChannelIcon.tsx index fb4d1a508..c0d596ed5 100644 --- a/src/components/common/ChannelIcon.tsx +++ b/src/components/common/ChannelIcon.tsx @@ -1,6 +1,6 @@ import { useContext } from "preact/hooks"; import { Channels } from "revolt.js/dist/api/objects"; -import { Hash, Volume2 } from "@styled-icons/feather"; +import { Hash, VolumeFull } from "@styled-icons/boxicons-regular"; import { ImageIconBase, IconBaseProps } from "./IconBase"; import { AppContext } from "../../context/revoltjs/RevoltClient"; @@ -21,7 +21,7 @@ export default function ChannelIcon(props: Props & Omit + ) } else { return ( diff --git a/src/components/common/ServerHeader.tsx b/src/components/common/ServerHeader.tsx index e2a89df81..de7a39f6e 100644 --- a/src/components/common/ServerHeader.tsx +++ b/src/components/common/ServerHeader.tsx @@ -2,7 +2,7 @@ import Header from "../ui/Header"; import styled from "styled-components"; import { Link } from "react-router-dom"; import IconButton from "../ui/IconButton"; -import { Settings } from "@styled-icons/feather"; +import { Cog } from "@styled-icons/boxicons-solid"; import { Server } from "revolt.js/dist/api/objects"; import { ServerPermission } from "revolt.js/dist/api/permissions"; import { HookContext, useServerPermission } from "../../context/revoltjs/hooks"; @@ -30,7 +30,7 @@ export default function ServerHeader({ server, ctx }: Props) { { (permissions & ServerPermission.ManageServer) > 0 &&
- +
} diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index ea8391a51..da1fe6946 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -4,7 +4,7 @@ import { Channel } from "revolt.js"; import styled from "styled-components"; import { defer } from "../../../lib/defer"; import IconButton from "../../ui/IconButton"; -import { Send, X } from '@styled-icons/feather'; +import { Send, X } from '@styled-icons/boxicons-regular'; import { debounce } from "../../../lib/debounce"; import Axios, { CancelTokenSource } from "axios"; import { useTranslation } from "../../../lib/i18n"; diff --git a/src/components/common/messaging/attachments/AttachmentActions.tsx b/src/components/common/messaging/attachments/AttachmentActions.tsx index cf701ad89..f667f1631 100644 --- a/src/components/common/messaging/attachments/AttachmentActions.tsx +++ b/src/components/common/messaging/attachments/AttachmentActions.tsx @@ -4,7 +4,7 @@ import IconButton from '../../../ui/IconButton'; import { Attachment } from "revolt.js/dist/api/objects"; import { determineFileSize } from '../../../../lib/fileSize'; import { AppContext } from '../../../../context/revoltjs/RevoltClient'; -import { Download, ExternalLink, File, Headphones, Video } from '@styled-icons/feather'; +import { Download, LinkExternal, File, Headphone, Video } from '@styled-icons/boxicons-regular'; interface Props { attachment: Attachment; @@ -30,7 +30,7 @@ export default function AttachmentActions({ attachment }: Props) {
- + @@ -43,14 +43,14 @@ export default function AttachmentActions({ attachment }: Props) { case 'Audio': return ( @@ -58,14 +58,14 @@ export default function AttachmentActions({ attachment }: Props) { case 'Video': return (
-
@@ -73,14 +73,14 @@ export default function AttachmentActions({ attachment }: Props) { default: return (
- +
{filename} {filesize}
- +
diff --git a/src/components/common/messaging/attachments/MessageReply.tsx b/src/components/common/messaging/attachments/MessageReply.tsx index 74952ea2e..701953854 100644 --- a/src/components/common/messaging/attachments/MessageReply.tsx +++ b/src/components/common/messaging/attachments/MessageReply.tsx @@ -2,7 +2,7 @@ import { Text } from "preact-i18n"; import UserShort from "../../user/UserShort"; import styled, { css } from "styled-components"; import Markdown from "../../../markdown/Markdown"; -import { CornerUpRight, File } from "@styled-icons/feather"; +import { Reply, File } from "@styled-icons/boxicons-regular"; import { useUser } from "../../../../context/revoltjs/hooks"; import { useRenderState } from "../../../../lib/renderer/Singleton"; @@ -52,7 +52,7 @@ export function MessageReply({ index, channel, id }: Props) { if (!message) { return ( - + ) @@ -62,7 +62,7 @@ export function MessageReply({ index, channel, id }: Props) { return ( - + { message.attachments && message.attachments.length > 0 && } diff --git a/src/components/common/messaging/bars/FilePreview.tsx b/src/components/common/messaging/bars/FilePreview.tsx index 44d94f5fd..9f0a98c4c 100644 --- a/src/components/common/messaging/bars/FilePreview.tsx +++ b/src/components/common/messaging/bars/FilePreview.tsx @@ -3,7 +3,7 @@ import styled from "styled-components"; import { CAN_UPLOAD_AT_ONCE, UploadState } from "../MessageBox"; import { useEffect, useState } from 'preact/hooks'; import { determineFileSize } from '../../../../lib/fileSize'; -import { XCircle, Plus, Share, X, FileText } from "@styled-icons/feather"; +import { XCircle, Plus, Share, X, File } from "@styled-icons/boxicons-regular"; interface Props { state: UploadState, @@ -133,7 +133,7 @@ function FileEntry({ file, remove, index }: { file: File, remove?: () => void, i = CAN_UPLOAD_AT_ONCE ? 'fade' : ''}> - +
diff --git a/src/components/common/messaging/bars/JumpToBottom.tsx b/src/components/common/messaging/bars/JumpToBottom.tsx index 14b9a9735..ff0f52787 100644 --- a/src/components/common/messaging/bars/JumpToBottom.tsx +++ b/src/components/common/messaging/bars/JumpToBottom.tsx @@ -1,6 +1,6 @@ import { Text } from "preact-i18n"; import styled from "styled-components"; -import { ArrowDown } from "@styled-icons/feather"; +import { DownArrow } from "@styled-icons/boxicons-regular"; import { SingletonMessageRenderer, useRenderState } from "../../../../lib/renderer/Singleton"; const Bar = styled.div` @@ -46,7 +46,7 @@ export default function JumpToBottom({ id }: { id: string }) {
SingletonMessageRenderer.jumpToBottom(id, true)}>
-
+
) diff --git a/src/components/common/messaging/bars/ReplyBar.tsx b/src/components/common/messaging/bars/ReplyBar.tsx index bfc550e48..7ef641739 100644 --- a/src/components/common/messaging/bars/ReplyBar.tsx +++ b/src/components/common/messaging/bars/ReplyBar.tsx @@ -9,7 +9,7 @@ import { Reply } from "../../../../redux/reducers/queue"; import { useUsers } from "../../../../context/revoltjs/hooks"; import { internalSubscribe } from "../../../../lib/eventEmitter"; import { useRenderState } from "../../../../lib/renderer/Singleton"; -import { AtSign, CornerUpRight, File, XCircle } from "@styled-icons/feather"; +import { At, Reply as ReplyIcon, File, XCircle } from "@styled-icons/boxicons-regular"; interface Props { channel: string, @@ -71,7 +71,7 @@ export default function ReplyBar({ channel, replies, setReplies }: Props) { return ( - + { message.attachments && message.attachments.length > 0 && } @@ -79,7 +79,7 @@ export default function ReplyBar({ channel, replies, setReplies }: Props) { setReplies(replies.map((_, i) => i === index ? { ..._, mention: !_.mention } : _))}> - { reply.mention ? 'ON' : 'OFF' } + { reply.mention ? 'ON' : 'OFF' } setReplies(replies.filter((_, i) => i !== index))}> diff --git a/src/components/common/messaging/embed/EmbedMediaActions.tsx b/src/components/common/messaging/embed/EmbedMediaActions.tsx index 9c119443f..ab3d71442 100644 --- a/src/components/common/messaging/embed/EmbedMediaActions.tsx +++ b/src/components/common/messaging/embed/EmbedMediaActions.tsx @@ -1,6 +1,6 @@ import styles from './Embed.module.scss'; import IconButton from '../../../ui/IconButton'; -import { ExternalLink } from '@styled-icons/feather'; +import { LinkExternal } from '@styled-icons/boxicons-regular'; import { EmbedImage } from "revolt.js/dist/api/objects"; interface Props { @@ -18,7 +18,7 @@ export default function EmbedMediaActions({ embed }: Props) {
- +
diff --git a/src/components/common/user/UserHeader.tsx b/src/components/common/user/UserHeader.tsx index 848e8ce84..dcd7630cc 100644 --- a/src/components/common/user/UserHeader.tsx +++ b/src/components/common/user/UserHeader.tsx @@ -8,7 +8,7 @@ import styled from "styled-components"; import { Localizer } from 'preact-i18n'; import { Link } from "react-router-dom"; import IconButton from "../../ui/IconButton"; -import { Settings } from "@styled-icons/feather"; +import { Cog } from "@styled-icons/boxicons-solid"; import { openContextMenu } from "preact-context-menu"; import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice"; import { useIntermediate } from "../../../context/intermediate/Intermediate"; @@ -76,7 +76,7 @@ export default function UserHeader({ user }: Props) { { !isTouchscreenDevice &&
- +
} diff --git a/src/components/common/user/UserIcon.tsx b/src/components/common/user/UserIcon.tsx index 65418b719..85064c545 100644 --- a/src/components/common/user/UserIcon.tsx +++ b/src/components/common/user/UserIcon.tsx @@ -1,6 +1,6 @@ import { User } from "revolt.js"; import { useContext } from "preact/hooks"; -import { MicOff } from "@styled-icons/feather"; +import { MicrophoneOff } from "@styled-icons/boxicons-regular"; import styled, { css } from "styled-components"; import { Users } from "revolt.js/dist/api/objects"; import { ThemeContext } from "../../../context/Theme"; @@ -83,7 +83,7 @@ export default function UserIcon(props: Props & Omit - {props.voice === "muted" && } + {props.voice === "muted" && } )} diff --git a/src/components/navigation/BottomNavigation.tsx b/src/components/navigation/BottomNavigation.tsx index 4afa8f9b7..c88fa2d31 100644 --- a/src/components/navigation/BottomNavigation.tsx +++ b/src/components/navigation/BottomNavigation.tsx @@ -4,7 +4,7 @@ import styled, { css } from "styled-components"; import { useSelf } from "../../context/revoltjs/hooks"; import { useHistory, useLocation } from "react-router"; import ConditionalLink from "../../lib/ConditionalLink"; -import { MessageCircle, Users } from "@styled-icons/feather"; +import { MessageRounded, Group } from "@styled-icons/boxicons-regular"; const NavigationBase = styled.div` z-index: 10; @@ -50,13 +50,13 @@ export default function BottomNavigation() { } } }}> - +
diff --git a/src/components/navigation/items/ButtonItem.tsx b/src/components/navigation/items/ButtonItem.tsx index d4e198207..6f82c5d35 100644 --- a/src/components/navigation/items/ButtonItem.tsx +++ b/src/components/navigation/items/ButtonItem.tsx @@ -3,7 +3,7 @@ import styles from "./Item.module.scss"; import Tooltip from '../../common/Tooltip'; import IconButton from '../../ui/IconButton'; import { Localizer, Text } from "preact-i18n"; -import { X, Zap } from "@styled-icons/feather"; +import { X, Crown } from "@styled-icons/boxicons-regular"; import { Children } from "../../../types/Preact"; import UserIcon from '../../common/user/UserIcon'; import ChannelIcon from '../../common/ChannelIcon'; @@ -65,7 +65,7 @@ export function UserButton({ active, alert, alertCount, user, context, channel } } > - + )} diff --git a/src/components/navigation/left/HomeSidebar.tsx b/src/components/navigation/left/HomeSidebar.tsx index d9ea7190e..13daf2649 100644 --- a/src/components/navigation/left/HomeSidebar.tsx +++ b/src/components/navigation/left/HomeSidebar.tsx @@ -1,6 +1,6 @@ import { Localizer, Text } from "preact-i18n"; import { useContext, useEffect } from "preact/hooks"; -import { Home, Users, Tool, Save } from "@styled-icons/feather"; +import { Home, Group, Wrench, Save } from "@styled-icons/boxicons-regular"; import Category from '../../ui/Category'; import PaintCounter from "../../../lib/PaintCounter"; @@ -83,7 +83,7 @@ function HomeSidebar(props: Props) { ) !== "undefined" ? 'unread' : undefined } > - + @@ -98,7 +98,7 @@ function HomeSidebar(props: Props) { {import.meta.env.DEV && ( - + diff --git a/src/components/navigation/left/ServerListSidebar.tsx b/src/components/navigation/left/ServerListSidebar.tsx index 4f25f7ddd..75d472563 100644 --- a/src/components/navigation/left/ServerListSidebar.tsx +++ b/src/components/navigation/left/ServerListSidebar.tsx @@ -4,7 +4,7 @@ import { mapChannelWithUnread } from "./common"; import styled, { css } from "styled-components"; import ServerIcon from "../../common/ServerIcon"; import { Children } from "../../../types/Preact"; -import { PlusCircle } from "@styled-icons/feather"; +import { Plus } from "@styled-icons/boxicons-regular"; import PaintCounter from "../../../lib/PaintCounter"; import { attachContextMenu } from 'preact-context-menu'; import { connectState } from "../../../redux/connector"; @@ -51,7 +51,7 @@ function Icon({ children, unread, size }: { children: Children, unread?: 'mentio } const ServersBase = styled.div` - width: 52px; + width: 72px; height: 100%; display: flex; flex-direction: column; @@ -183,7 +183,7 @@ export function ServerListSidebar({ unreads, lastOpened }: Props) { }) } openScreen({ id: 'special_input', type: 'create_server' })}> - + diff --git a/src/components/ui/Category.tsx b/src/components/ui/Category.tsx index 4b6712259..2889e2f4b 100644 --- a/src/components/ui/Category.tsx +++ b/src/components/ui/Category.tsx @@ -1,6 +1,6 @@ import styled, { css } from "styled-components"; import { Children } from "../../types/Preact"; -import { Plus } from "@styled-icons/feather"; +import { Plus } from "@styled-icons/boxicons-regular"; const CategoryBase = styled.div>` font-size: 12px; diff --git a/src/components/ui/Checkbox.tsx b/src/components/ui/Checkbox.tsx index e7cd62b96..32020bace 100644 --- a/src/components/ui/Checkbox.tsx +++ b/src/components/ui/Checkbox.tsx @@ -1,4 +1,4 @@ -import { Check } from "@styled-icons/feather"; +import { Check } from "@styled-icons/boxicons-regular"; import { Children } from "../../types/Preact"; import styled, { css } from "styled-components"; @@ -59,7 +59,6 @@ const Checkmark = styled.div<{ checked: boolean }>` svg { color: var(--secondary-background); - stroke-width: 2; } ${(props) => diff --git a/src/components/ui/ColourSwatches.tsx b/src/components/ui/ColourSwatches.tsx index e6e2478ee..cbc13bd28 100644 --- a/src/components/ui/ColourSwatches.tsx +++ b/src/components/ui/ColourSwatches.tsx @@ -1,7 +1,6 @@ import { useRef } from "preact/hooks"; -import { Check } from "@styled-icons/feather"; +import { Check, Pencil } from "@styled-icons/boxicons-regular"; import styled, { css } from "styled-components"; -import { Pencil } from "@styled-icons/bootstrap"; interface Props { value: string; @@ -68,7 +67,7 @@ const Swatch = styled.div<{ type: "small" | "large"; colour: string }>` height: 30px; svg { - stroke-width: 2; + /*stroke-width: 2;*/ } ` : css` @@ -118,7 +117,7 @@ export default function ColourSwatches({ value, onChange }: Props) { onClick={() => onChange(swatch)} > {swatch === value && ( - + )} ))} diff --git a/src/components/ui/IconButton.tsx b/src/components/ui/IconButton.tsx index 497f287cb..a0c757840 100644 --- a/src/components/ui/IconButton.tsx +++ b/src/components/ui/IconButton.tsx @@ -15,7 +15,7 @@ export default styled.div` fill: ${normal}; color: ${normal}; - stroke: ${normal}; + /*stroke: ${normal};*/ a { color: ${normal}; @@ -24,7 +24,7 @@ export default styled.div` &:hover { fill: ${hover}; color: ${hover}; - stroke: ${hover}; + /*stroke: ${hover};*/ a { color: ${hover}; diff --git a/src/components/ui/Radio.tsx b/src/components/ui/Radio.tsx index d6beb9a47..e988bbc94 100644 --- a/src/components/ui/Radio.tsx +++ b/src/components/ui/Radio.tsx @@ -1,6 +1,6 @@ import { Children } from "../../types/Preact"; import styled, { css } from "styled-components"; -import { CircleFill } from "@styled-icons/bootstrap"; +import { Circle } from "@styled-icons/boxicons-regular"; interface Props { children: Children; @@ -48,7 +48,7 @@ const RadioBase = styled.label` svg { color: var(--foreground); - stroke-width: 2; + /*stroke-width: 2;*/ } } @@ -95,7 +95,7 @@ export default function Radio(props: Props) { } >
- +
diff --git a/src/components/ui/Tip.tsx b/src/components/ui/Tip.tsx index b65ccc65b..5ca878349 100644 --- a/src/components/ui/Tip.tsx +++ b/src/components/ui/Tip.tsx @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { Info } from "@styled-icons/feather"; +import { InfoCircle } from "@styled-icons/boxicons-regular"; import { Children } from "../../types/Preact"; export const TipBase = styled.div` @@ -29,7 +29,7 @@ export const TipBase = styled.div` export default function Tip(props: { children: Children }) { return ( - + {props.children} ); diff --git a/src/context/intermediate/popovers/ChannelInfo.tsx b/src/context/intermediate/popovers/ChannelInfo.tsx index 2abce2fcb..8b0b7ddb4 100644 --- a/src/context/intermediate/popovers/ChannelInfo.tsx +++ b/src/context/intermediate/popovers/ChannelInfo.tsx @@ -1,4 +1,4 @@ -import { X } from "@styled-icons/feather"; +import { X } from "@styled-icons/boxicons-regular"; import styles from "./ChannelInfo.module.scss"; import Modal from "../../../components/ui/Modal"; import { getChannelName } from "../../revoltjs/util"; diff --git a/src/context/intermediate/popovers/UserProfile.tsx b/src/context/intermediate/popovers/UserProfile.tsx index afcc83451..22167c5c9 100644 --- a/src/context/intermediate/popovers/UserProfile.tsx +++ b/src/context/intermediate/popovers/UserProfile.tsx @@ -6,7 +6,6 @@ import Modal from "../../../components/ui/Modal"; import { Route } from "revolt.js/dist/api/routes"; import { Users } from "revolt.js/dist/api/objects"; import { useIntermediate } from "../Intermediate"; -import { CashStack } from "@styled-icons/bootstrap"; import Preloader from "../../../components/ui/Preloader"; import Tooltip from '../../../components/common/Tooltip'; import IconButton from "../../../components/ui/IconButton"; @@ -15,7 +14,7 @@ import { UserPermission } from "revolt.js/dist/api/permissions"; import UserIcon from '../../../components/common/user/UserIcon'; import ChannelIcon from '../../../components/common/ChannelIcon'; import UserStatus from '../../../components/common/user/UserStatus'; -import { Mail, Edit, UserPlus, Shield } from "@styled-icons/feather"; +import { Envelope, Edit, UserPlus, Shield, Money } from "@styled-icons/boxicons-regular"; import { useContext, useEffect, useLayoutEffect, useState } from "preact/hooks"; import { AppContext, ClientStatus, StatusContext } from "../../revoltjs/RevoltClient"; import { useChannels, useForceUpdate, useUserPermission, useUsers } from "../../revoltjs/hooks"; @@ -160,7 +159,7 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) { onClose(); history.push(`/open/${user_id}`); }}> - + @@ -172,13 +171,13 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) { if (dummy) return; history.push(`/settings/profile`); }}> - + )} {(user.relationship === Users.Relationship.Incoming || user.relationship === Users.Relationship.None) && ( client.users.addFriend(user.username)}> - + )}
@@ -255,7 +254,7 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) { } > - + ) : ( <> diff --git a/src/context/revoltjs/FileUploads.tsx b/src/context/revoltjs/FileUploads.tsx index 4be51c166..ab9156b04 100644 --- a/src/context/revoltjs/FileUploads.tsx +++ b/src/context/revoltjs/FileUploads.tsx @@ -8,7 +8,7 @@ import { useContext, useEffect, useState } from "preact/hooks"; import Preloader from "../../components/ui/Preloader"; import { determineFileSize } from "../../lib/fileSize"; import IconButton from '../../components/ui/IconButton'; -import { Edit, Plus, X, XCircle } from "@styled-icons/feather"; +import { Edit, Plus, X, XCircle } from "@styled-icons/boxicons-regular"; import { useIntermediate } from "../intermediate/Intermediate"; type Props = { diff --git a/src/context/revoltjs/RequiresOnline.tsx b/src/context/revoltjs/RequiresOnline.tsx index 20779e5f2..ff2dd1999 100644 --- a/src/context/revoltjs/RequiresOnline.tsx +++ b/src/context/revoltjs/RequiresOnline.tsx @@ -2,7 +2,7 @@ import { Text } from "preact-i18n"; import styled from "styled-components"; import { useContext } from "preact/hooks"; import { Children } from "../../types/Preact"; -import { WifiOff } from "@styled-icons/feather"; +import { WifiOff } from "@styled-icons/boxicons-regular"; import Preloader from "../../components/ui/Preloader"; import { ClientStatus, StatusContext } from "./RevoltClient"; diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index 3636bdffc..c1844451d 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -19,9 +19,8 @@ import { Children } from "../types/Preact"; import LineDivider from "../components/ui/LineDivider"; import { connectState } from "../redux/connector"; import { internalEmit } from "./eventEmitter"; -import { AtSign, Bell, BellOff, Check, CheckSquare, ChevronRight, Slash, Square } from "@styled-icons/feather"; +import { At, Bell, BellOff, Check, CheckSquare, ChevronRight, Block, Square, LeftArrowAlt } from "@styled-icons/boxicons-regular"; import { getNotificationState, Notifications, NotificationState } from "../redux/reducers/notifications"; -import { ArrowLeft } from "@styled-icons/bootstrap"; interface ContextMenuData { user?: string; @@ -718,16 +717,16 @@ function ContextMenus(props: Props) { { icon } - { (state === undefined && actual === key) &&
} + { (state === undefined && actual === key) &&
} { (state === key) &&
}
); } generate('all', ); - generate('mention', ); + generate('mention', ); generate('muted', ); - generate('none', ); + generate('none', ); return elements; }} diff --git a/src/pages/channels/ChannelHeader.tsx b/src/pages/channels/ChannelHeader.tsx index 24a23f3f8..6834c18b1 100644 --- a/src/pages/channels/ChannelHeader.tsx +++ b/src/pages/channels/ChannelHeader.tsx @@ -7,7 +7,7 @@ import Markdown from "../../components/markdown/Markdown"; import { getChannelName } from "../../context/revoltjs/util"; import UserStatus from "../../components/common/user/UserStatus"; import { AppContext } from "../../context/revoltjs/RevoltClient"; -import { Save, AtSign, Users, Hash } from "@styled-icons/feather"; +import { Save, At, Group, Hash } from "@styled-icons/boxicons-regular"; import { useStatusColour } from "../../components/common/user/UserIcon"; import { useIntermediate } from "../../context/intermediate/Intermediate"; @@ -57,18 +57,18 @@ export default function ChannelHeader({ channel, toggleSidebar }: ChannelHeaderP let icon, recipient; switch (channel.channel_type) { case "SavedMessages": - icon = ; + icon = ; break; case "DirectMessage": - icon = ; + icon = ; const uid = client.channels.getRecipient(channel._id); recipient = client.users.get(uid); break; case "Group": - icon = ; + icon = ; break; case "TextChannel": - icon = ; + icon = ; break; } diff --git a/src/pages/channels/actions/HeaderActions.tsx b/src/pages/channels/actions/HeaderActions.tsx index 368f603fc..d3f7eeeab 100644 --- a/src/pages/channels/actions/HeaderActions.tsx +++ b/src/pages/channels/actions/HeaderActions.tsx @@ -6,7 +6,7 @@ import { AppContext } from "../../../context/revoltjs/RevoltClient"; import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice"; import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { VoiceContext, VoiceOperationsContext, VoiceStatus } from "../../../context/Voice"; -import { UserPlus, Settings, Sidebar as SidebarIcon, PhoneCall, PhoneOff } from "@styled-icons/feather"; +import { UserPlus, Cog, Sidebar as SidebarIcon, PhoneCall, PhoneOutgoing } from "@styled-icons/boxicons-regular"; export default function HeaderActions({ channel, toggleSidebar }: ChannelHeaderProps) { const { openScreen } = useIntermediate(); @@ -30,7 +30,7 @@ export default function HeaderActions({ channel, toggleSidebar }: ChannelHeaderP
history.push(`/channel/${channel._id}/settings`)}> - + ) } @@ -55,7 +55,7 @@ function VoiceActions({ channel }: Pick) { if (voice.roomId === channel._id) { return ( - + ) } else { diff --git a/src/pages/channels/voice/VoiceHeader.tsx b/src/pages/channels/voice/VoiceHeader.tsx index b99b0f0b1..d20a6c329 100644 --- a/src/pages/channels/voice/VoiceHeader.tsx +++ b/src/pages/channels/voice/VoiceHeader.tsx @@ -1,7 +1,7 @@ import { Text } from "preact-i18n"; import styled from "styled-components"; import { useContext } from "preact/hooks"; -import { BarChart } from "@styled-icons/bootstrap"; +import { BarChart } from "@styled-icons/boxicons-regular"; import Button from "../../../components/ui/Button"; import UserIcon from "../../../components/common/user/UserIcon"; import { useForceUpdate, useSelf, useUsers } from "../../../context/revoltjs/hooks"; @@ -93,7 +93,7 @@ export default function VoiceHeader({ id }: Props) { )}
- + { status === VoiceStatus.CONNECTED && }
@@ -145,7 +145,7 @@ export default function VoiceHeader({ id }: Props) { )}
- + { voice.status === VoiceStatus.CONNECTED && }
diff --git a/src/pages/friends/Friend.tsx b/src/pages/friends/Friend.tsx index bcacd2995..a33c342dc 100644 --- a/src/pages/friends/Friend.tsx +++ b/src/pages/friends/Friend.tsx @@ -3,7 +3,7 @@ import { Link } from "react-router-dom"; import styles from "./Friend.module.scss"; import { useContext } from "preact/hooks"; import { Children } from "../../types/Preact"; -import { X, Plus, Mail } from "@styled-icons/feather"; +import { X, Plus, Envelope } from "@styled-icons/boxicons-regular"; import IconButton from "../../components/ui/IconButton"; import { attachContextMenu } from "preact-context-menu"; import { User, Users } from "revolt.js/dist/api/objects"; @@ -30,7 +30,7 @@ export function Friend({ user }: Props) { - + ); diff --git a/src/pages/friends/Friends.tsx b/src/pages/friends/Friends.tsx index 9460f8e46..c331f34a6 100644 --- a/src/pages/friends/Friends.tsx +++ b/src/pages/friends/Friends.tsx @@ -1,5 +1,5 @@ import styles from "./Friend.module.scss"; -import { UserPlus } from "@styled-icons/feather"; +import { UserPlus } from "@styled-icons/boxicons-regular"; import { Friend } from "./Friend"; import { Text } from "preact-i18n"; diff --git a/src/pages/invite/Invite.tsx b/src/pages/invite/Invite.tsx index 080f3cbd8..8fc2a1f3b 100644 --- a/src/pages/invite/Invite.tsx +++ b/src/pages/invite/Invite.tsx @@ -1,6 +1,6 @@ import styles from './Invite.module.scss'; import Button from '../../components/ui/Button'; -import { ArrowLeft } from "@styled-icons/feather"; +import { LeftArrowAlt } from "@styled-icons/boxicons-regular"; import Overline from '../../components/ui/Overline'; import { Invites } from "revolt.js/dist/api/objects"; import Preloader from '../../components/ui/Preloader'; @@ -44,7 +44,7 @@ export default function Invite() { return (
- history.push('/')} /> + history.push('/')} />
{ !processing && diff --git a/src/pages/login/forms/Form.tsx b/src/pages/login/forms/Form.tsx index 5d8911b38..d1e0e8c4b 100644 --- a/src/pages/login/forms/Form.tsx +++ b/src/pages/login/forms/Form.tsx @@ -5,7 +5,7 @@ import styles from "../Login.module.scss"; import { useForm } from "react-hook-form"; import { MailProvider } from "./MailProvider"; import { useContext, useState } from "preact/hooks"; -import { CheckCircle, Mail } from "@styled-icons/feather"; +import { CheckCircle, Envelope } from "@styled-icons/boxicons-regular"; import { takeError } from "../../../context/revoltjs/util"; import { CaptchaBlock, CaptchaProps } from "./CaptchaBlock"; import { AppContext } from "../../../context/revoltjs/RevoltClient"; @@ -109,7 +109,7 @@ export function Form({ page, callback }: Props) {
{client.configuration?.features.email ? ( <> - +

diff --git a/src/pages/settings/ChannelSettings.tsx b/src/pages/settings/ChannelSettings.tsx index cd4b0f477..4039779e4 100644 --- a/src/pages/settings/ChannelSettings.tsx +++ b/src/pages/settings/ChannelSettings.tsx @@ -1,5 +1,5 @@ import { Text } from "preact-i18n"; -import { List } from "@styled-icons/feather"; +import { ListUl } from "@styled-icons/boxicons-regular"; import Category from "../../components/ui/Category"; import { GenericSettings } from "./GenericSettings"; import { getChannelName } from "../../context/revoltjs/util"; @@ -30,7 +30,7 @@ export default function ChannelSettings() { { category: , id: 'overview', - icon: , + icon: , title: } ]} diff --git a/src/pages/settings/GenericSettings.tsx b/src/pages/settings/GenericSettings.tsx index 89579f4cb..e32c79397 100644 --- a/src/pages/settings/GenericSettings.tsx +++ b/src/pages/settings/GenericSettings.tsx @@ -6,7 +6,7 @@ import Header from '../../components/ui/Header'; import Category from '../../components/ui/Category'; import IconButton from "../../components/ui/IconButton"; import LineDivider from "../../components/ui/LineDivider"; -import { ArrowLeft, X, XCircle } from "@styled-icons/feather"; +import { LeftArrowAlt, X, XCircle } from "@styled-icons/boxicons-regular"; import { Switch, useHistory, useParams } from "react-router-dom"; import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice"; import ButtonItem from "../../components/navigation/items/ButtonItem"; @@ -65,7 +65,7 @@ export function GenericSettings({ pages, switchPage, category, custom, children, ) : ( <> switchPage()}> - + , id: 'overview', - icon: , + icon: , title: }, { id: 'members', - icon: , + icon: , title: "Members" }, { id: 'invites', - icon: , + icon: , title: "Invites" }, { id: 'bans', - icon: , + icon: , title: "Bans" } ]} diff --git a/src/pages/settings/Settings.tsx b/src/pages/settings/Settings.tsx index 58be985a8..76e99e216 100644 --- a/src/pages/settings/Settings.tsx +++ b/src/pages/settings/Settings.tsx @@ -10,16 +10,16 @@ import { Bell, Box, Coffee, - Gitlab, Globe, Image, LogOut, - RefreshCw, + Sync as SyncIcon, Shield, ToggleRight, User -} from "@styled-icons/feather"; -import { Megaphone } from "@styled-icons/bootstrap"; +} from "@styled-icons/boxicons-regular"; +import { Megaphone } from "@styled-icons/boxicons-solid"; +import { Gitlab } from "@styled-icons/boxicons-logos"; import { GIT_BRANCH, GIT_REVISION, REPO_URL } from "../../revision"; import LineDivider from "../../components/ui/LineDivider"; import RequiresOnline from "../../context/revoltjs/RequiresOnline"; @@ -54,49 +54,49 @@ export default function Settings() { { category: , id: 'account', - icon: , + icon: , title: }, { id: 'profile', - icon: , + icon: , title: }, { id: 'sessions', - icon: , + icon: , title: }, { category: , id: 'appearance', - icon: , + icon: , title: }, { id: 'notifications', - icon: , + icon: , title: }, { id: 'language', - icon: , + icon: , title: }, { id: 'sync', - icon: , + icon: , title: }, { divider: true, id: 'experiments', - icon: , + icon: , title: }, { id: 'feedback', - icon: , + icon: , title: } ]} @@ -122,13 +122,13 @@ export default function Settings() { target="_blank" > - + , - + , @@ -138,7 +138,7 @@ export default function Settings() { className={styles.logOut} compact > - + ,
diff --git a/src/pages/settings/panes/Account.tsx b/src/pages/settings/panes/Account.tsx index b3f7e61cc..1fc80c251 100644 --- a/src/pages/settings/panes/Account.tsx +++ b/src/pages/settings/panes/Account.tsx @@ -5,7 +5,7 @@ import Button from "../../../components/ui/Button"; import { Users } from "revolt.js/dist/api/objects"; import { Link, useHistory } from "react-router-dom"; import Overline from "../../../components/ui/Overline"; -import { AtSign, Key, Mail } from "@styled-icons/feather"; +import { At, Key, Envelope } from "@styled-icons/boxicons-regular"; import { useContext, useEffect, useState } from "preact/hooks"; import UserIcon from "../../../components/common/user/UserIcon"; import { useForceUpdate, useSelf } from "../../../context/revoltjs/hooks"; @@ -54,8 +54,8 @@ export function Account() {
{[ - ["username", user.username, ], - ["email", email, ], + ["username", user.username, ], + ["email", email, ], ["password", "*****", ] ].map(([field, value, icon]) => (
diff --git a/src/pages/settings/panes/Sessions.tsx b/src/pages/settings/panes/Sessions.tsx index e0501d7f7..b9bccc4b9 100644 --- a/src/pages/settings/panes/Sessions.tsx +++ b/src/pages/settings/panes/Sessions.tsx @@ -9,7 +9,7 @@ import Preloader from "../../../components/ui/Preloader"; import { useContext, useEffect, useState } from "preact/hooks"; import { AppContext } from "../../../context/revoltjs/RevoltClient"; -import { HelpCircle } from "@styled-icons/feather"; +import { HelpCircle } from "@styled-icons/boxicons-regular"; import { Android, Firefoxbrowser, diff --git a/src/pages/settings/server/Invites.tsx b/src/pages/settings/server/Invites.tsx index 21e033709..1b3723574 100644 --- a/src/pages/settings/server/Invites.tsx +++ b/src/pages/settings/server/Invites.tsx @@ -1,5 +1,5 @@ import styles from './Panes.module.scss'; -import { XCircle } from "@styled-icons/feather"; +import { XCircle } from "@styled-icons/boxicons-regular"; import { useEffect, useState } from "preact/hooks"; import Preloader from "../../../components/ui/Preloader"; import IconButton from "../../../components/ui/IconButton"; From 99643c546117cba2aa14b451d6beb2820e209e22 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 27 Jun 2021 21:54:31 +0100 Subject: [PATCH 0022/1462] Migrate to @tippyjs/react from react-tippy. Fix strokes on home sidebar. Add tooltips on servers. Fix reply SVG direction. --- package.json | 2 +- src/components/common/Tooltip.tsx | 25 ++++++--------- .../messaging/attachments/MessageReply.tsx | 1 + .../navigation/items/Item.module.scss | 2 -- .../navigation/left/ServerListSidebar.tsx | 9 ++++-- src/main.tsx | 2 +- src/styles/index.scss | 16 +++++++++- yarn.lock | 31 ++++++++++++------- 8 files changed, 52 insertions(+), 36 deletions(-) diff --git a/package.json b/package.json index 80c9b1a03..4c732d7d5 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "@styled-icons/boxicons-regular": "^10.34.0", "@styled-icons/boxicons-solid": "^10.34.0", "@styled-icons/simple-icons": "^10.33.0", + "@tippyjs/react": "^4.2.5", "@traptitech/markdown-it-katex": "^3.4.3", "@traptitech/markdown-it-spoiler": "^1.1.6", "@types/lodash.defaultsdeep": "^4.6.6", @@ -76,7 +77,6 @@ "react-redux": "^7.2.4", "react-router-dom": "^5.2.0", "react-scroll": "^1.8.2", - "react-tippy": "^1.4.0", "redux": "^4.1.0", "revolt.js": "4.3.3-alpha.2", "rimraf": "^3.0.2", diff --git a/src/components/common/Tooltip.tsx b/src/components/common/Tooltip.tsx index db4a6c7b4..9bf320e57 100644 --- a/src/components/common/Tooltip.tsx +++ b/src/components/common/Tooltip.tsx @@ -1,26 +1,19 @@ -import styled from "styled-components"; import { Children } from "../../types/Preact"; -import { Position, Tooltip as TooltipCore, TooltipProps } from "react-tippy"; +import Tippy, { TippyProps } from '@tippyjs/react'; -type Props = Omit & { - position?: Position; +type Props = Omit & { children: Children; content: Children; } -const TooltipBase = styled.div` - padding: 8px; - font-size: 12px; - border-radius: 4px; - color: var(--foreground); - background: var(--secondary-background); -`; - export default function Tooltip(props: Props) { + const { children, content, ...tippyProps } = props; + return ( - {props.content}} /> + + {/* + // @ts-expect-error */} +
{ children }
+
); } diff --git a/src/components/common/messaging/attachments/MessageReply.tsx b/src/components/common/messaging/attachments/MessageReply.tsx index 701953854..269cba4b4 100644 --- a/src/components/common/messaging/attachments/MessageReply.tsx +++ b/src/components/common/messaging/attachments/MessageReply.tsx @@ -28,6 +28,7 @@ export const ReplyBase = styled.div<{ head?: boolean, fail?: boolean, preview?: svg { flex-shrink: 0; + transform: scaleX(-1); color: var(--tertiary-foreground); } diff --git a/src/components/navigation/items/Item.module.scss b/src/components/navigation/items/Item.module.scss index 27116ebcb..afb54073e 100644 --- a/src/components/navigation/items/Item.module.scss +++ b/src/components/navigation/items/Item.module.scss @@ -15,7 +15,6 @@ transition: .1s ease-in-out background-color; color: var(--tertiary-foreground); - stroke: var(--tertiary-foreground); &.normal { height: 38px; @@ -117,7 +116,6 @@ &[data-alert="true"], &[data-active="true"], &:hover { color: var(--foreground); - stroke: var(--foreground); .subText { color: var(--secondary-foreground) !important; diff --git a/src/components/navigation/left/ServerListSidebar.tsx b/src/components/navigation/left/ServerListSidebar.tsx index 75d472563..e4886e107 100644 --- a/src/components/navigation/left/ServerListSidebar.tsx +++ b/src/components/navigation/left/ServerListSidebar.tsx @@ -18,6 +18,7 @@ import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { useChannels, useForceUpdate, useServers } from "../../../context/revoltjs/hooks"; import logoSVG from '../../../assets/logo.svg'; +import Tooltip from "../../common/Tooltip"; function Icon({ children, unread, size }: { children: Children, unread?: 'mention' | 'unread', size: number }) { return ( @@ -174,9 +175,11 @@ export function ServerListSidebar({ unreads, lastOpened }: Props) { - - - + + + + + ) diff --git a/src/main.tsx b/src/main.tsx index 99a9414d5..fbb4a2bc3 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -11,8 +11,8 @@ const updateSW = registerSW({ }, }) -import { render } from "preact"; import "./styles/index.scss"; +import { render } from "preact"; import { App } from "./pages/app"; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion diff --git a/src/styles/index.scss b/src/styles/index.scss index 4508966e9..e0b7574e7 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -3,4 +3,18 @@ @import "fonts"; @import "page"; -@import "react-overlapping-panels/dist" +@import "react-overlapping-panels/dist"; +@import "tippy.js/dist/tippy.css"; + +.tippy-box { + background: var(--secondary-background); +} + +.tippy-content { + padding: 8px; + font-size: 12px; +} + +.tippy-arrow { + color: var(--secondary-background); +} diff --git a/yarn.lock b/yarn.lock index 60c61c5af..3fb7ff58e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1001,6 +1001,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@popperjs/core@^2.8.3": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353" + integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q== + "@preact/preset-vite@^2.0.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@preact/preset-vite/-/preset-vite-2.1.0.tgz#66934767ca0b49c1ea1cc00e82d3d43f2caba7d1" @@ -1130,6 +1135,13 @@ ejs "^2.6.1" magic-string "^0.25.0" +"@tippyjs/react@^4.2.5": + version "4.2.5" + resolved "https://registry.yarnpkg.com/@tippyjs/react/-/react-4.2.5.tgz#9b5837db93a1cac953962404df906aef1a18e80d" + integrity sha512-YBLgy+1zznBNbx4JOoOdFXWMLXjBh9hLPwRtq3s8RRdrez2l3tPBRt2m2909wZd9S1KUeKjOOYYsnitccI9I3A== + dependencies: + tippy.js "^6.3.1" + "@traptitech/markdown-it-katex@^3.4.3": version "3.4.3" resolved "https://registry.yarnpkg.com/@traptitech/markdown-it-katex/-/markdown-it-katex-3.4.3.tgz#23dacbd276ac748409a189550e0ecd764cfde8cf" @@ -3102,11 +3114,6 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== -popper.js@^1.11.1: - version "1.16.1" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== - postcss-value-parser@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" @@ -3297,13 +3304,6 @@ react-side-effect@^2.1.0: resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.1.tgz#66c5701c3e7560ab4822a4ee2742dee215d72eb3" integrity sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ== -react-tippy@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/react-tippy/-/react-tippy-1.4.0.tgz#e8a8b4085ec985e5c94fe128918b733b588a1465" - integrity sha512-r/hM5XK9Ztr2ZY7IWKuRmISTlUPS/R6ddz6PO2EuxCgW+4JBcGZRPU06XcVPRDCOIiio8ryBQFrXMhFMhsuaHA== - dependencies: - popper.js "^1.11.1" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -3799,6 +3799,13 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +tippy.js@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.1.tgz#3788a007be7015eee0fd589a66b98fb3f8f10181" + integrity sha512-JnFncCq+rF1dTURupoJ4yPie5Cof978inW6/4S6kmWV7LL9YOSEVMifED3KdrVPEG+Z/TFH2CDNJcQEfaeuQww== + dependencies: + "@popperjs/core" "^2.8.3" + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" From 539ed402ee7af673d6c8693b3503fa8daa74f686 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 27 Jun 2021 22:35:36 +0100 Subject: [PATCH 0023/1462] Attempted implementation of new sidebar style. --- .../navigation/left/ServerListSidebar.tsx | 87 +++++++++++++++---- 1 file changed, 71 insertions(+), 16 deletions(-) diff --git a/src/components/navigation/left/ServerListSidebar.tsx b/src/components/navigation/left/ServerListSidebar.tsx index e4886e107..440866022 100644 --- a/src/components/navigation/left/ServerListSidebar.tsx +++ b/src/components/navigation/left/ServerListSidebar.tsx @@ -52,7 +52,7 @@ function Icon({ children, unread, size }: { children: Children, unread?: 'mentio } const ServersBase = styled.div` - width: 72px; + width: 56px; height: 100%; display: flex; flex-direction: column; @@ -68,7 +68,6 @@ const ServerList = styled.div` overflow-y: scroll; padding-bottom: 48px; flex-direction: column; - border-inline-end: 2px solid var(--sidebar-active); scrollbar-width: none; @@ -82,21 +81,75 @@ const ServerList = styled.div` `; const ServerEntry = styled.div<{ active: boolean, invert?: boolean }>` - height: 44px; - padding: 4px; - margin: 2px 0 2px 4px; + height: 58px; + display: flex; + align-items: center; + justify-content: flex-end; + + > * { + // outline: 1px solid red; + } - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; + > div, > svg { + width: 46px; + height: 46px; + display: grid; + place-items: center; + + border-start-start-radius: 50%; + border-end-start-radius: 50%; - img { - width: 32px; - height: 32px; + ${ props => props.active && css` + background: var(--accent); + ` } } - ${ props => props.active && css` - background: var(--sidebar-active); - ` } + span { + width: 6px; + height: 46px; + + ${ props => props.active && css` + background: var(--accent); + + &::before, &::after { + // outline: 1px solid blue; + } + + &::before { + content: ""; + display: block; + position: relative; + + width: 31px; + height: 72px; + margin-top: -72px; + margin-left: -25px; + z-index: -1; + + background: var(--background); + border-bottom-right-radius: 32px; + + box-shadow: 0 32px 0 0 var(--accent); + } + + /*&::after { + content: ""; + display: block; + position: relative; + + width: 31px; + height: 72px; + margin-top: 100px; + margin-left: -25px; + z-index: -2; + + background: var(--background); + border-bottom-left-radius: 32px; + + box-shadow: 0 -32px 0 0 var(--accent); + }*/ + ` } + } ${ props => props.active && props.invert && css` img { @@ -159,12 +212,13 @@ export function ServerListSidebar({ unreads, lastOpened }: Props) { - + + - + {/**/} { servers.map(entry => { const active = entry!._id === server?._id; @@ -176,10 +230,11 @@ export function ServerListSidebar({ unreads, lastOpened }: Props) { active={active} onContextMenu={attachContextMenu('Menu', { server: entry!._id })}> - + + ) From 9248ba01a28fe5db7f65f5f6d755d5cb763430ce Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Mon, 28 Jun 2021 09:55:05 +0200 Subject: [PATCH 0024/1462] Fix: Small update to categories and icons --- src/components/common/messaging/MessageBox.tsx | 15 ++++++++++++--- src/components/ui/Category.tsx | 7 ++++++- src/pages/settings/ServerSettings.tsx | 2 +- src/pages/settings/Settings.tsx | 14 +++++++------- src/pages/settings/panes/Experiments.tsx | 5 ++++- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index da1fe6946..62bfea5fb 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -24,6 +24,7 @@ import { useCallback, useContext, useEffect, useState } from "preact/hooks"; import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { FileUploader, grabFiles, uploadFile } from "../../../context/revoltjs/FileUploads"; import { SingletonMessageRenderer, SMOOTH_SCROLL_ON_RECEIVE } from "../../../lib/renderer/Singleton"; +import { ShieldX } from "@styled-icons/boxicons-regular"; import ReplyBar from "./bars/ReplyBar"; import FilePreview from './bars/FilePreview'; @@ -52,11 +53,16 @@ const Base = styled.div` `; const Blocked = styled.div` - padding: 15px 0; - line-height: 20px; + display: flex; + padding: 14px 0; user-select: none; font-size: .875rem; color: var(--tertiary-foreground); + + svg { + flex-shrink: 0; + margin-right: 8px; + } `; const Action = styled.div` @@ -80,7 +86,10 @@ function MessageBox({ channel, draft, dispatcher }: Props) { if (!(permissions & ChannelPermission.SendMessage)) { return ( - + + + + ) } diff --git a/src/components/ui/Category.tsx b/src/components/ui/Category.tsx index 2889e2f4b..7fae78e48 100644 --- a/src/components/ui/Category.tsx +++ b/src/components/ui/Category.tsx @@ -8,7 +8,7 @@ const CategoryBase = styled.div>` text-transform: uppercase; margin-top: 4px; - padding: 6px 10px; + padding: 6px 0; margin-bottom: 4px; white-space: nowrap; @@ -22,6 +22,11 @@ const CategoryBase = styled.div>` cursor: pointer; } + &:first-child { + margin-top: 0; + padding-top: 0; + } + ${ props => props.variant === 'uniform' && css` padding-top: 6px; ` } diff --git a/src/pages/settings/ServerSettings.tsx b/src/pages/settings/ServerSettings.tsx index ecf750cee..ca8940055 100644 --- a/src/pages/settings/ServerSettings.tsx +++ b/src/pages/settings/ServerSettings.tsx @@ -30,7 +30,7 @@ export default function ServerSettings() { , + category: , //TOFIX: Just add the server.name as a string, otherwise it makes a duplicate category id: 'overview', icon: , title: diff --git a/src/pages/settings/Settings.tsx b/src/pages/settings/Settings.tsx index 76e99e216..0141409db 100644 --- a/src/pages/settings/Settings.tsx +++ b/src/pages/settings/Settings.tsx @@ -8,17 +8,17 @@ import { GenericSettings } from "./GenericSettings"; import { Route, useHistory } from "react-router-dom"; import { Bell, - Box, + Palette, Coffee, Globe, - Image, + IdCard, LogOut, Sync as SyncIcon, Shield, - ToggleRight, + Vial, User } from "@styled-icons/boxicons-regular"; -import { Megaphone } from "@styled-icons/boxicons-solid"; +import { Brush, Megaphone } from "@styled-icons/boxicons-solid"; import { Gitlab } from "@styled-icons/boxicons-logos"; import { GIT_BRANCH, GIT_REVISION, REPO_URL } from "../../revision"; import LineDivider from "../../components/ui/LineDivider"; @@ -59,7 +59,7 @@ export default function Settings() { }, { id: 'profile', - icon: , + icon: , title: }, { @@ -70,7 +70,7 @@ export default function Settings() { { category: , id: 'appearance', - icon: , + icon: , title: }, { @@ -91,7 +91,7 @@ export default function Settings() { { divider: true, id: 'experiments', - icon: , + icon: , title: }, { diff --git a/src/pages/settings/panes/Experiments.tsx b/src/pages/settings/panes/Experiments.tsx index 2922be83c..41e5885db 100644 --- a/src/pages/settings/panes/Experiments.tsx +++ b/src/pages/settings/panes/Experiments.tsx @@ -36,7 +36,10 @@ export function Component(props: Props & WithDispatcher) { } { AVAILABLE_EXPERIMENTS.length === 0 && - +
+ +
+ }
); From ef62740f585fd477f9760878362052cc8a16c0fc Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Mon, 28 Jun 2021 10:32:55 +0200 Subject: [PATCH 0025/1462] Fix: More fixes for the message box and settings --- index.html | 34 +++++++++---------- .../common/messaging/MessageBox.tsx | 3 +- src/pages/settings/panes/Experiments.tsx | 2 +- src/pages/settings/panes/Panes.module.scss | 10 ++++++ 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/index.html b/index.html index c83d63f4a..11218d2d3 100644 --- a/index.html +++ b/index.html @@ -1,19 +1,19 @@ - - - - - - REVOLT - - -
- - - - + + + + + + REVOLT + + +
+ + + + \ No newline at end of file diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index 62bfea5fb..e122b089f 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -54,6 +54,7 @@ const Base = styled.div` const Blocked = styled.div` display: flex; + align-items: center; padding: 14px 0; user-select: none; font-size: .875rem; @@ -87,7 +88,7 @@ function MessageBox({ channel, draft, dispatcher }: Props) { return ( - + diff --git a/src/pages/settings/panes/Experiments.tsx b/src/pages/settings/panes/Experiments.tsx index 41e5885db..5d3d6ee95 100644 --- a/src/pages/settings/panes/Experiments.tsx +++ b/src/pages/settings/panes/Experiments.tsx @@ -11,7 +11,7 @@ interface Props { export function Component(props: Props & WithDispatcher) { return ( -
+

diff --git a/src/pages/settings/panes/Panes.module.scss b/src/pages/settings/panes/Panes.module.scss index d1c2a5040..307dc37fb 100644 --- a/src/pages/settings/panes/Panes.module.scss +++ b/src/pages/settings/panes/Panes.module.scss @@ -373,3 +373,13 @@ display: flex; flex-direction: column; } + +.experiments { /* TOFIX: Center the "No new experiments available at this time" text without having a scrollbar */ + height: 100%; + .empty { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + } +} \ No newline at end of file From 843ae5a082f953f5da058ef1122757d5f3f8804c Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Mon, 28 Jun 2021 11:12:19 +0200 Subject: [PATCH 0026/1462] Small fixes --- src/components/common/messaging/MessageBox.tsx | 6 +++++- src/pages/settings/server/Invites.tsx | 7 +++++++ src/pages/settings/server/Panes.module.scss | 11 ++++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index e122b089f..404e48e19 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -1,5 +1,6 @@ import { ulid } from "ulid"; import { Text } from "preact-i18n"; +import Tooltip from "../Tooltip"; import { Channel } from "revolt.js"; import styled from "styled-components"; import { defer } from "../../../lib/defer"; @@ -28,6 +29,7 @@ import { ShieldX } from "@styled-icons/boxicons-regular"; import ReplyBar from "./bars/ReplyBar"; import FilePreview from './bars/FilePreview'; +import { Styleshare } from "@styled-icons/simple-icons"; type Props = WithDispatcher & { channel: Channel; @@ -88,7 +90,9 @@ function MessageBox({ channel, draft, dispatcher }: Props) { return ( - + Permissions Required
Send messages
} placement="top"> + + diff --git a/src/pages/settings/server/Invites.tsx b/src/pages/settings/server/Invites.tsx index 1b3723574..a80c07c34 100644 --- a/src/pages/settings/server/Invites.tsx +++ b/src/pages/settings/server/Invites.tsx @@ -1,3 +1,4 @@ +import { Text } from "preact-i18n"; import styles from './Panes.module.scss'; import { XCircle } from "@styled-icons/boxicons-regular"; import { useEffect, useState } from "preact/hooks"; @@ -27,6 +28,12 @@ export function Invites({ server }: Props) { return (
+
+ Invite Code + Invitor + Channel + Revoke +
{ typeof invites === 'undefined' && } { invites?.map( diff --git a/src/pages/settings/server/Panes.module.scss b/src/pages/settings/server/Panes.module.scss index 7f518a68b..ba25ba08e 100644 --- a/src/pages/settings/server/Panes.module.scss +++ b/src/pages/settings/server/Panes.module.scss @@ -18,9 +18,18 @@ display: flex; flex-direction: column; + .subtitle { + display: flex; + justify-content: space-between; + font-size: 13px; + text-transform: uppercase; + color: var(--secondary-foreground); + font-weight: 700; + } + .invite { gap: 8px; - padding: 8px; + padding: 10px; display: flex; align-items: center; flex-direction: row; From bb5336f19170eabb944c9963d8cbf10155883a01 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 28 Jun 2021 10:17:38 +0100 Subject: [PATCH 0027/1462] Add PWA update indicator. --- src/components/common/UpdateIndicator.tsx | 25 ++++++++++++++++++++ src/lib/eventEmitter.ts | 1 + src/main.tsx | 10 ++++---- src/pages/channels/actions/HeaderActions.tsx | 2 ++ 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 src/components/common/UpdateIndicator.tsx diff --git a/src/components/common/UpdateIndicator.tsx b/src/components/common/UpdateIndicator.tsx new file mode 100644 index 000000000..982b73dac --- /dev/null +++ b/src/components/common/UpdateIndicator.tsx @@ -0,0 +1,25 @@ +import { updateSW } from "../../main"; +import IconButton from "../ui/IconButton"; +import { ThemeContext } from "../../context/Theme"; +import { Download } from "@styled-icons/boxicons-regular"; +import { internalSubscribe } from "../../lib/eventEmitter"; +import { useContext, useEffect, useState } from "preact/hooks"; + +var pendingUpdate = false; + +export default function UpdateIndicator() { + const [ pending, setPending ] = useState(pendingUpdate); + + useEffect(() => { + return internalSubscribe('PWA', 'update', () => setPending(true)); + }); + + if (!pending) return; + const theme = useContext(ThemeContext); + + return ( + updateSW(true)}> + + + ) +} diff --git a/src/lib/eventEmitter.ts b/src/lib/eventEmitter.ts index 669ad37af..ae0ae52e8 100644 --- a/src/lib/eventEmitter.ts +++ b/src/lib/eventEmitter.ts @@ -20,3 +20,4 @@ export function internalEmit(ns: string, event: string, ...args: any[]) { // - MessageBox/append // - TextArea/focus // - ReplyBar/add +// - PWA/update diff --git a/src/main.tsx b/src/main.tsx index fbb4a2bc3..02c4364bb 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,9 +1,9 @@ -import { registerSW } from 'virtual:pwa-register' -const updateSW = registerSW({ +import { registerSW } from 'virtual:pwa-register'; +import { internalEmit } from './lib/eventEmitter'; + +export const updateSW = registerSW({ onNeedRefresh() { - // ! FIXME: temp - updateSW(true); - // show a prompt to user + internalEmit('PWA', 'update'); }, onOfflineReady() { console.info('Ready to work offline.'); diff --git a/src/pages/channels/actions/HeaderActions.tsx b/src/pages/channels/actions/HeaderActions.tsx index d3f7eeeab..e0bfcdd0f 100644 --- a/src/pages/channels/actions/HeaderActions.tsx +++ b/src/pages/channels/actions/HeaderActions.tsx @@ -4,6 +4,7 @@ import { ChannelHeaderProps } from "../ChannelHeader"; import IconButton from "../../../components/ui/IconButton"; import { AppContext } from "../../../context/revoltjs/RevoltClient"; import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice"; +import UpdateIndicator from "../../../components/common/UpdateIndicator"; import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { VoiceContext, VoiceOperationsContext, VoiceStatus } from "../../../context/Voice"; import { UserPlus, Cog, Sidebar as SidebarIcon, PhoneCall, PhoneOutgoing } from "@styled-icons/boxicons-regular"; @@ -15,6 +16,7 @@ export default function HeaderActions({ channel, toggleSidebar }: ChannelHeaderP return ( <> + { channel.channel_type === "Group" && ( <> From d52d4b35ee3d449e943e098ff603be20a9013774 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 28 Jun 2021 10:25:51 +0100 Subject: [PATCH 0028/1462] Independent tooltip for missing permissions. --- external/lang | 2 +- src/components/common/Tooltip.tsx | 23 +++++++++++++++++++ .../common/messaging/MessageBox.tsx | 6 ++--- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/external/lang b/external/lang index 9406c734c..03b206f60 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 9406c734ca2cb7b65eefcf926d9e829f9a2056d7 +Subproject commit 03b206f608b071eb26a099657d9619d32f2bb264 diff --git a/src/components/common/Tooltip.tsx b/src/components/common/Tooltip.tsx index 9bf320e57..86be55cc0 100644 --- a/src/components/common/Tooltip.tsx +++ b/src/components/common/Tooltip.tsx @@ -1,3 +1,5 @@ +import { Text } from "preact-i18n"; +import styled from "styled-components"; import { Children } from "../../types/Preact"; import Tippy, { TippyProps } from '@tippyjs/react'; @@ -17,3 +19,24 @@ export default function Tooltip(props: Props) { ); } + +const PermissionTooltipBase = styled.div` + display: flex; + align-items: center; + flex-direction: column; + + code { + font-family: 'Fira Mono'; + } +`; + +export function PermissionTooltip(props: Omit & { permission: string }) { + const { permission, ...tooltipProps } = props; + + return ( + + + { permission } + } {...tooltipProps} /> + ) +} diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index 404e48e19..a8bd63027 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -1,6 +1,6 @@ import { ulid } from "ulid"; import { Text } from "preact-i18n"; -import Tooltip from "../Tooltip"; +import Tooltip, { PermissionTooltip } from "../Tooltip"; import { Channel } from "revolt.js"; import styled from "styled-components"; import { defer } from "../../../lib/defer"; @@ -90,9 +90,9 @@ function MessageBox({ channel, draft, dispatcher }: Props) { return ( - Permissions Required
Send messages
} placement="top"> + - + From 71672101e4877a60f55cbaf4b7f4f577f0d4aa4e Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Mon, 28 Jun 2021 11:27:24 +0200 Subject: [PATCH 0029/1462] Fix: Small fixes for RTL items --- src/components/ui/Tip.tsx | 2 +- src/pages/channels/voice/VoiceHeader.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ui/Tip.tsx b/src/components/ui/Tip.tsx index 5ca878349..910bb7f13 100644 --- a/src/components/ui/Tip.tsx +++ b/src/components/ui/Tip.tsx @@ -22,7 +22,7 @@ export const TipBase = styled.div` svg { flex-shrink: 0; - margin-right: 10px; + margin-inline-end: 10px; } `; diff --git a/src/pages/channels/voice/VoiceHeader.tsx b/src/pages/channels/voice/VoiceHeader.tsx index d20a6c329..16894650e 100644 --- a/src/pages/channels/voice/VoiceHeader.tsx +++ b/src/pages/channels/voice/VoiceHeader.tsx @@ -29,7 +29,7 @@ const VoiceBase = styled.div` user-select: none; svg { - margin-right: 4px; + margin-inline-end: 4px; cursor: help; } } From 8d346c188c2a15a9c25b0aae2973f0c21ca5cd19 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 28 Jun 2021 10:29:56 +0100 Subject: [PATCH 0030/1462] Set update indicator default state properly. --- src/components/common/UpdateIndicator.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/common/UpdateIndicator.tsx b/src/components/common/UpdateIndicator.tsx index 982b73dac..d6730eb6f 100644 --- a/src/components/common/UpdateIndicator.tsx +++ b/src/components/common/UpdateIndicator.tsx @@ -6,6 +6,7 @@ import { internalSubscribe } from "../../lib/eventEmitter"; import { useContext, useEffect, useState } from "preact/hooks"; var pendingUpdate = false; +internalSubscribe('PWA', 'update', () => pendingUpdate = true); export default function UpdateIndicator() { const [ pending, setPending ] = useState(pendingUpdate); From 66b25ecb5872b8add937cddb7dd3108cbbbab6a1 Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Mon, 28 Jun 2021 11:36:37 +0200 Subject: [PATCH 0031/1462] Fix: Small changes to tooltip --- external/lang | 2 +- src/components/common/Tooltip.tsx | 9 +++++++-- src/components/common/messaging/MessageBox.tsx | 2 +- src/pages/settings/panes/Panes.module.scss | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/external/lang b/external/lang index 03b206f60..d21756175 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 03b206f608b071eb26a099657d9619d32f2bb264 +Subproject commit d217561756c7f397f177e43911c247497107c515 diff --git a/src/components/common/Tooltip.tsx b/src/components/common/Tooltip.tsx index 86be55cc0..c8497e409 100644 --- a/src/components/common/Tooltip.tsx +++ b/src/components/common/Tooltip.tsx @@ -24,7 +24,12 @@ const PermissionTooltipBase = styled.div` display: flex; align-items: center; flex-direction: column; - + span { + font-weight: 700; + text-transform: uppercase; + color: var(--secondary-foreground); + font-size: 11px; + } code { font-family: 'Fira Mono'; } @@ -35,7 +40,7 @@ export function PermissionTooltip(props: Omit & { permission: return ( - + { permission } } {...tooltipProps} /> ) diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index a8bd63027..1141d9aa1 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -64,7 +64,7 @@ const Blocked = styled.div` svg { flex-shrink: 0; - margin-right: 8px; + margin-inline-end: 8px; } `; diff --git a/src/pages/settings/panes/Panes.module.scss b/src/pages/settings/panes/Panes.module.scss index 307dc37fb..4695af59e 100644 --- a/src/pages/settings/panes/Panes.module.scss +++ b/src/pages/settings/panes/Panes.module.scss @@ -231,7 +231,7 @@ flex-shrink: 0; border-radius: 4px; overflow: hidden; - margin-right: 4px; + margin-inline-end: 4px; //TOFIX - Looks wonky on Chromium border: 1px solid black; From 745977367d102a23d8419d1f7868281a12905203 Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 29 Jun 2021 22:21:26 +0100 Subject: [PATCH 0032/1462] Fix: Placeholder would overflow sidebar. --- src/components/navigation/SidebarBase.tsx | 2 +- src/components/navigation/left/HomeSidebar.tsx | 4 +++- src/context/revoltjs/RevoltClient.tsx | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/navigation/SidebarBase.tsx b/src/components/navigation/SidebarBase.tsx index 4cf8b1a72..c751d7f77 100644 --- a/src/components/navigation/SidebarBase.tsx +++ b/src/components/navigation/SidebarBase.tsx @@ -27,7 +27,7 @@ export const GenericSidebarList = styled.div` flex-grow: 1; overflow-y: scroll; - > svg { + > img { width: 100%; } `; diff --git a/src/components/navigation/left/HomeSidebar.tsx b/src/components/navigation/left/HomeSidebar.tsx index 13daf2649..98cbc6e92 100644 --- a/src/components/navigation/left/HomeSidebar.tsx +++ b/src/components/navigation/left/HomeSidebar.tsx @@ -21,6 +21,8 @@ import { Link, Redirect, useLocation, useParams } from "react-router-dom"; import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { useDMs, useForceUpdate, useUsers } from "../../../context/revoltjs/hooks"; +import placeholderSVG from "../items/placeholder.svg"; + type Props = WithDispatcher & { unreads: Unreads; } @@ -113,7 +115,7 @@ function HomeSidebar(props: Props) { action={() => openScreen({ id: "special_input", type: "create_group" })} /> - {channelsArr.length === 0 && } + {channelsArr.length === 0 && } {channelsArr.map(x => { let user; if (x.channel_type === 'DirectMessage') { diff --git a/src/context/revoltjs/RevoltClient.tsx b/src/context/revoltjs/RevoltClient.tsx index 85bec3b7a..5ca77857a 100644 --- a/src/context/revoltjs/RevoltClient.tsx +++ b/src/context/revoltjs/RevoltClient.tsx @@ -112,7 +112,7 @@ function Context({ auth, children, dispatcher }: Props) { logout: async shouldRequest => { dispatcher({ type: "LOGOUT" }); - delete client.user; + client.reset(); dispatcher({ type: "RESET" }); openScreen({ id: "none" }); From 5034a405c57c42269a290b280d1b01a4b2e6e991 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 30 Jun 2021 20:06:42 +0100 Subject: [PATCH 0033/1462] Handle updates of members for permissions. --- external/lang | 2 +- package.json | 2 +- src/context/revoltjs/events.ts | 2 ++ src/context/revoltjs/hooks.ts | 30 ++++++++++++++++++++++++++++-- yarn.lock | 8 ++++---- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/external/lang b/external/lang index d21756175..0dc9e46b3 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit d217561756c7f397f177e43911c247497107c515 +Subproject commit 0dc9e46b376621b8af99784a7134fb8648cc3701 diff --git a/package.json b/package.json index 4c732d7d5..d22d51509 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "react-router-dom": "^5.2.0", "react-scroll": "^1.8.2", "redux": "^4.1.0", - "revolt.js": "4.3.3-alpha.2", + "revolt.js": "4.3.3-alpha.4", "rimraf": "^3.0.2", "sass": "^1.35.1", "shade-blend-color": "^1.0.0", diff --git a/src/context/revoltjs/events.ts b/src/context/revoltjs/events.ts index 21472bdd3..806ddcef4 100644 --- a/src/context/revoltjs/events.ts +++ b/src/context/revoltjs/events.ts @@ -112,6 +112,7 @@ export function registerEvents({ client.users.addListener('mutation', logMutation); client.servers.addListener('mutation', logMutation); client.channels.addListener('mutation', logMutation); + client.servers.members.addListener('mutation', logMutation); } const online = () => { @@ -142,6 +143,7 @@ export function registerEvents({ client.users.removeListener('mutation', logMutation); client.servers.removeListener('mutation', logMutation); client.channels.removeListener('mutation', logMutation); + client.servers.members.removeListener('mutation', logMutation); } window.removeEventListener("online", online); diff --git a/src/context/revoltjs/hooks.ts b/src/context/revoltjs/hooks.ts index 987a9d53f..f57038bbd 100644 --- a/src/context/revoltjs/hooks.ts +++ b/src/context/revoltjs/hooks.ts @@ -117,10 +117,29 @@ export function useUserPermission(id: string, context?: HookContext) { export function useChannelPermission(id: string, context?: HookContext) { const ctx = useForceUpdate(context); + const channel = ctx.client.channels.get(id); + const server = (channel && (channel.channel_type === 'TextChannel' || channel.channel_type === 'VoiceChannel')) ? channel.server : undefined; + const mutation = (target: string) => (target === id) && ctx.forceUpdate(); + const mutationServer = (target: string) => (target === server) && ctx.forceUpdate(); + const mutationMember = (target: string) => (target.substr(26) === ctx.client.user!._id) && ctx.forceUpdate(); + useEffect(() => { ctx.client.channels.addListener("update", mutation); - return () => ctx.client.channels.removeListener("update", mutation); + + if (server) { + ctx.client.servers.addListener("update", mutationServer); + ctx.client.servers.members.addListener("update", mutationMember); + } + + return () => { + ctx.client.channels.removeListener("update", mutation); + + if (server) { + ctx.client.servers.removeListener("update", mutationServer); + ctx.client.servers.members.removeListener("update", mutationMember); + } + } }, [id]); let calculator = new PermissionCalculator(ctx.client); @@ -131,9 +150,16 @@ export function useServerPermission(id: string, context?: HookContext) { const ctx = useForceUpdate(context); const mutation = (target: string) => (target === id) && ctx.forceUpdate(); + const mutationMember = (target: string) => (target.substr(26) === ctx.client.user!._id) && ctx.forceUpdate(); + useEffect(() => { ctx.client.servers.addListener("update", mutation); - return () => ctx.client.servers.removeListener("update", mutation); + ctx.client.servers.members.addListener("update", mutationMember); + + return () => { + ctx.client.servers.removeListener("update", mutation); + ctx.client.servers.members.removeListener("update", mutationMember); + } }, [id]); let calculator = new PermissionCalculator(ctx.client); diff --git a/yarn.lock b/yarn.lock index 3fb7ff58e..b3a3e352c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3420,10 +3420,10 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -revolt.js@4.3.3-alpha.2: - version "4.3.3-alpha.2" - resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.2.tgz#1fb876205d74712c45e5f022624ac8d176ab01a1" - integrity sha512-/irTDDtBj63yQtpBk1asnqCNacc+HQXcz0jBOBk1VaOeDsjE6lTO2tGue6wFAG76AL89z9bziQbHIa6cQmWIjg== +revolt.js@4.3.3-alpha.4: + version "4.3.3-alpha.4" + resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.4.tgz#7d393c9016a9d89151b1c091f6b02bc193b3a553" + integrity sha512-d6SGjRKFDlWG5fEveaVf0DRGb8d0RW8iv1E0kEG0W3R138KdeWCK8zUU0H+ykUdd5OjS7ESBKaEcwSP2BXMRSA== dependencies: "@insertish/mutable" "1.1.0" axios "^0.19.2" From 89e4566febf4e20d7673b352ba53e6c38799602d Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 30 Jun 2021 21:28:56 +0100 Subject: [PATCH 0034/1462] View roles in server settings. --- src/pages/settings/ServerSettings.tsx | 9 ++++- src/pages/settings/server/Roles.tsx | 54 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/pages/settings/server/Roles.tsx diff --git a/src/pages/settings/ServerSettings.tsx b/src/pages/settings/ServerSettings.tsx index ca8940055..5d34d01da 100644 --- a/src/pages/settings/ServerSettings.tsx +++ b/src/pages/settings/ServerSettings.tsx @@ -3,7 +3,7 @@ import Category from "../../components/ui/Category"; import { GenericSettings } from "./GenericSettings"; import { useServer } from "../../context/revoltjs/hooks"; import { Route, useHistory, useParams } from "react-router-dom"; -import { ListUl, Share, Group } from "@styled-icons/boxicons-regular"; +import { ListUl, Share, Group, ListCheck } from "@styled-icons/boxicons-regular"; import { XSquare } from "@styled-icons/boxicons-solid"; import RequiresOnline from "../../context/revoltjs/RequiresOnline"; @@ -11,6 +11,7 @@ import { Overview } from "./server/Overview"; import { Members } from "./server/Members"; import { Invites } from "./server/Invites"; import { Bans } from "./server/Bans"; +import { Roles } from "./server/Roles"; export default function ServerSettings() { const { server: sid } = useParams<{ server: string; }>(); @@ -49,12 +50,18 @@ export default function ServerSettings() { id: 'bans', icon: , title: "Bans" + }, + { + id: 'roles', + icon: , + title: "Roles" } ]} children={[ , , , + , ]} category="server_pages" diff --git a/src/pages/settings/server/Roles.tsx b/src/pages/settings/server/Roles.tsx new file mode 100644 index 000000000..308c6e665 --- /dev/null +++ b/src/pages/settings/server/Roles.tsx @@ -0,0 +1,54 @@ +import { useEffect, useState } from "preact/hooks"; +import Button from "../../../components/ui/Button"; +import { Servers } from "revolt.js/dist/api/objects"; +import Checkbox from "../../../components/ui/Checkbox"; +import { ServerPermission } from "revolt.js/dist/api/permissions"; + +interface Props { + server: Servers.Server; +} + +export function Roles({ server }: Props) { + const [ selected, setSelected ] = useState('default'); + + const roles = server.roles ?? {}; + const keys = [ 'default', ...Object.keys(roles) ]; + + const defaultRole = { name: 'Default', permissions: server.default_permissions }; + const selectedRole: Servers.Role = selected === 'default' ? defaultRole : roles[selected]; + + if (!selectedRole) { + useEffect(() => setSelected('default'), [ ]); + return null; + } + + return ( +
+

select role

+ { keys + .map(id => { + let role: Servers.Role = id === 'default' ? defaultRole : roles[id]; + + return ( + selected && setSelected(id)}> + { role.name } + + ) + }) + } + +

permmissions

+ { Object.keys(ServerPermission) + .map(perm => { + let value = ServerPermission[perm as keyof typeof ServerPermission]; + + return ( + 0} onChange={() => {}}> + { perm } + + ) + }) + } +
+ ); +} From 6082b2191bad87c0a3a5a6b3fb491775ae85b38e Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 1 Jul 2021 13:42:53 +0100 Subject: [PATCH 0035/1462] Finish up new sidebar active. Add rounded corners to sidebar. --- src/components/common/ServerHeader.tsx | 3 +- src/components/common/user/UserHeader.tsx | 2 +- .../navigation/left/ServerListSidebar.tsx | 32 ++++++------------- .../navigation/left/ServerSidebar.tsx | 2 ++ src/components/ui/Header.tsx | 6 ++++ src/context/Theme.tsx | 3 -- src/pages/settings/panes/Appearance.tsx | 1 - src/pages/settings/server/Roles.tsx | 18 +++++++++-- src/styles/_variables.scss | 3 ++ src/styles/index.scss | 1 + 10 files changed, 40 insertions(+), 31 deletions(-) create mode 100644 src/styles/_variables.scss diff --git a/src/components/common/ServerHeader.tsx b/src/components/common/ServerHeader.tsx index de7a39f6e..4ed11aa07 100644 --- a/src/components/common/ServerHeader.tsx +++ b/src/components/common/ServerHeader.tsx @@ -21,7 +21,8 @@ export default function ServerHeader({ server, ctx }: Props) { const bannerURL = ctx.client.servers.getBannerURL(server._id, { width: 480 }, true); return ( -
diff --git a/src/components/common/user/UserHeader.tsx b/src/components/common/user/UserHeader.tsx index dcd7630cc..e93f3fd2e 100644 --- a/src/components/common/user/UserHeader.tsx +++ b/src/components/common/user/UserHeader.tsx @@ -52,7 +52,7 @@ export default function UserHeader({ user }: Props) { } return ( -
+
` border-end-start-radius: 50%; ${ props => props.active && css` - background: var(--accent); + background: var(--sidebar-active); ` } } @@ -109,13 +110,13 @@ const ServerEntry = styled.div<{ active: boolean, invert?: boolean }>` height: 46px; ${ props => props.active && css` - background: var(--accent); + background: var(--sidebar-active); &::before, &::after { // outline: 1px solid blue; } - &::before { + &::before, &::after { content: ""; display: block; position: relative; @@ -129,25 +130,12 @@ const ServerEntry = styled.div<{ active: boolean, invert?: boolean }>` background: var(--background); border-bottom-right-radius: 32px; - box-shadow: 0 32px 0 0 var(--accent); + box-shadow: 0 32px 0 0 var(--sidebar-active); } - /*&::after { - content: ""; - display: block; - position: relative; - - width: 31px; - height: 72px; - margin-top: 100px; - margin-left: -25px; - z-index: -2; - - background: var(--background); - border-bottom-left-radius: 32px; - - box-shadow: 0 -32px 0 0 var(--accent); - }*/ + &::after { + transform: scaleY(-1) translateY(-118px); + } ` } } @@ -213,12 +201,12 @@ export function ServerListSidebar({ unreads, lastOpened }: Props) { - + - {/**/} + { servers.map(entry => { const active = entry!._id === server?._id; diff --git a/src/components/navigation/left/ServerSidebar.tsx b/src/components/navigation/left/ServerSidebar.tsx index 2b8bcb778..2d10ce2a2 100644 --- a/src/components/navigation/left/ServerSidebar.tsx +++ b/src/components/navigation/left/ServerSidebar.tsx @@ -26,6 +26,8 @@ const ServerBase = styled.div` flex-shrink: 0; flex-direction: column; background: var(--secondary-background); + + border-start-start-radius: 8px; `; const ServerList = styled.div` diff --git a/src/components/ui/Header.tsx b/src/components/ui/Header.tsx index cb17b8c56..2b2c0d3c3 100644 --- a/src/components/ui/Header.tsx +++ b/src/components/ui/Header.tsx @@ -1,6 +1,7 @@ import styled, { css } from "styled-components"; interface Props { + borders?: boolean; background?: boolean; placement: 'primary' | 'secondary' } @@ -30,4 +31,9 @@ export default styled.div` background-color: var(--secondary-header); padding: 14px; ` } + + ${ props => props.borders && css` + border-start-start-radius: 8px; + border-end-start-radius: 8px; + ` } `; diff --git a/src/context/Theme.tsx b/src/context/Theme.tsx index 22c7a357e..bb496da0d 100644 --- a/src/context/Theme.tsx +++ b/src/context/Theme.tsx @@ -16,7 +16,6 @@ export type Variables = | "warning" | "error" | "hover" - | "sidebar-active" | "scrollbar-thumb" | "scrollbar-track" | "primary-background" @@ -58,7 +57,6 @@ export const PRESETS: { [key: string]: Theme } = { warning: "#FAA352", error: "#F06464", hover: "rgba(0, 0, 0, 0.2)", - "sidebar-active": "#FD6671", "scrollbar-thumb": "#CA525A", "scrollbar-track": "transparent", "primary-background": "#FFFFFF", @@ -86,7 +84,6 @@ export const PRESETS: { [key: string]: Theme } = { warning: "#FAA352", error: "#F06464", hover: "rgba(0, 0, 0, 0.1)", - "sidebar-active": "#FD6671", "scrollbar-thumb": "#CA525A", "scrollbar-track": "transparent", "primary-background": "#242424", diff --git a/src/pages/settings/panes/Appearance.tsx b/src/pages/settings/panes/Appearance.tsx index 8ee5dd408..b0ed1dae9 100644 --- a/src/pages/settings/panes/Appearance.tsx +++ b/src/pages/settings/panes/Appearance.tsx @@ -49,7 +49,6 @@ export function Component(props: Props & WithDispatcher) { function setAccent(accent: string) { setOverride({ accent, - "sidebar-active": accent, "scrollbar-thumb": pSBC(-0.2, accent) }); } diff --git a/src/pages/settings/server/Roles.tsx b/src/pages/settings/server/Roles.tsx index 308c6e665..47e820230 100644 --- a/src/pages/settings/server/Roles.tsx +++ b/src/pages/settings/server/Roles.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "preact/hooks"; import Button from "../../../components/ui/Button"; import { Servers } from "revolt.js/dist/api/objects"; import Checkbox from "../../../components/ui/Checkbox"; -import { ServerPermission } from "revolt.js/dist/api/permissions"; +import { ChannelPermission, ServerPermission } from "revolt.js/dist/api/permissions"; interface Props { server: Servers.Server; @@ -37,13 +37,25 @@ export function Roles({ server }: Props) { }) } -

permmissions

+

server permmissions

{ Object.keys(ServerPermission) .map(perm => { let value = ServerPermission[perm as keyof typeof ServerPermission]; return ( - 0} onChange={() => {}}> + >> 0) & value) > 0} onChange={() => {}}> + { perm } + + ) + }) + } +

channel permmissions

+ { Object.keys(ChannelPermission) + .map(perm => { + let value = ChannelPermission[perm as keyof typeof ChannelPermission]; + + return ( + >> 0) & value) > 0} onChange={() => {}}> { perm } ) diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss new file mode 100644 index 000000000..3335848c3 --- /dev/null +++ b/src/styles/_variables.scss @@ -0,0 +1,3 @@ +:root { + --sidebar-active: var(--secondary-background); +} diff --git a/src/styles/index.scss b/src/styles/index.scss index e0b7574e7..4fb88f540 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -1,3 +1,4 @@ +@import "variables"; @import "context-menu"; @import "elements"; @import "fonts"; From d34efc1e69e2c8d08e9ee704b9a022a3b199af5e Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 1 Jul 2021 17:36:34 +0100 Subject: [PATCH 0036/1462] Add permissions / roles settings. --- external/lang | 2 +- package.json | 2 +- src/components/ui/Tip.tsx | 28 +++++-- src/pages/settings/ChannelSettings.tsx | 24 +++++- src/pages/settings/channel/Overview.tsx | 10 ++- src/pages/settings/channel/Permissions.tsx | 91 ++++++++++++++++++++++ src/pages/settings/panes/Feedback.tsx | 10 ++- src/pages/settings/panes/Profile.tsx | 18 +++-- src/pages/settings/server/Bans.tsx | 2 + src/pages/settings/server/Members.tsx | 35 ++++++++- src/pages/settings/server/Overview.tsx | 8 +- src/pages/settings/server/Roles.tsx | 41 ++++++++-- yarn.lock | 8 +- 13 files changed, 239 insertions(+), 40 deletions(-) create mode 100644 src/pages/settings/channel/Permissions.tsx diff --git a/external/lang b/external/lang index 0dc9e46b3..588b882a3 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 0dc9e46b376621b8af99784a7134fb8648cc3701 +Subproject commit 588b882a3acca644c2f65b67cd341c88fd97989d diff --git a/package.json b/package.json index d22d51509..a89609945 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "react-router-dom": "^5.2.0", "react-scroll": "^1.8.2", "redux": "^4.1.0", - "revolt.js": "4.3.3-alpha.4", + "revolt.js": "4.3.3-alpha.6", "rimraf": "^3.0.2", "sass": "^1.35.1", "shade-blend-color": "^1.0.0", diff --git a/src/components/ui/Tip.tsx b/src/components/ui/Tip.tsx index 910bb7f13..489572b91 100644 --- a/src/components/ui/Tip.tsx +++ b/src/components/ui/Tip.tsx @@ -1,8 +1,13 @@ -import styled from "styled-components"; -import { InfoCircle } from "@styled-icons/boxicons-regular"; import { Children } from "../../types/Preact"; +import styled, { css } from "styled-components"; +import { InfoCircle } from "@styled-icons/boxicons-regular"; + +interface Props { + warning?: boolean + error?: boolean +} -export const TipBase = styled.div` +export const TipBase = styled.div` display: flex; padding: 12px; overflow: hidden; @@ -24,11 +29,24 @@ export const TipBase = styled.div` 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: var(--error); + border: 2px solid var(--error); + background: var(--secondary-header); + ` } `; -export default function Tip(props: { children: Children }) { +export default function Tip(props: Props & { children: Children }) { + const { children, ...tipProps } = props; return ( - + {props.children} diff --git a/src/pages/settings/ChannelSettings.tsx b/src/pages/settings/ChannelSettings.tsx index 4039779e4..aed5ca695 100644 --- a/src/pages/settings/ChannelSettings.tsx +++ b/src/pages/settings/ChannelSettings.tsx @@ -1,12 +1,13 @@ import { Text } from "preact-i18n"; -import { ListUl } from "@styled-icons/boxicons-regular"; import Category from "../../components/ui/Category"; import { GenericSettings } from "./GenericSettings"; import { getChannelName } from "../../context/revoltjs/util"; import { Route, useHistory, useParams } from "react-router-dom"; +import { ListCheck, ListUl } from "@styled-icons/boxicons-regular"; import { useChannel, useForceUpdate } from "../../context/revoltjs/hooks"; -import { Overview } from "./channel/Overview"; +import Overview from "./channel/Overview"; +import Permissions from "./channel/Permissions"; export default function ChannelSettings() { const { channel: cid } = useParams<{ channel: string; }>(); @@ -17,10 +18,17 @@ export default function ChannelSettings() { const history = useHistory(); function switchPage(to?: string) { + let base_url; + switch (channel?.channel_type) { + case 'TextChannel': + case 'VoiceChannel': base_url = `/server/${channel.server}/channel/${cid}/settings`; break; + default: base_url = `/channel/${cid}/settings`; + } + if (to) { - history.replace(`/channel/${cid}/settings/${to}`); + history.replace(`${base_url}/${to}`); } else { - history.replace(`/channel/${cid}/settings`); + history.replace(base_url); } } @@ -32,9 +40,17 @@ export default function ChannelSettings() { id: 'overview', icon: , title: + }, + { + id: 'permissions', + icon: , + title: } ]} children={[ + , + , + ]} category="channel_pages" diff --git a/src/pages/settings/channel/Overview.tsx b/src/pages/settings/channel/Overview.tsx index 60e8cce27..f41f123bd 100644 --- a/src/pages/settings/channel/Overview.tsx +++ b/src/pages/settings/channel/Overview.tsx @@ -12,7 +12,7 @@ interface Props { channel: Channels.GroupChannel | Channels.TextChannel | Channels.VoiceChannel; } -export function Overview({ channel }: Props) { +export default function Overview({ channel }: Props) { const client = useContext(AppContext); const [name, setName] = useState(channel.name); @@ -81,9 +81,11 @@ export function Overview({ channel }: Props) { if (!changed) setChanged(true) }} /> - +

+ +

); } diff --git a/src/pages/settings/channel/Permissions.tsx b/src/pages/settings/channel/Permissions.tsx new file mode 100644 index 000000000..7fc8c2e69 --- /dev/null +++ b/src/pages/settings/channel/Permissions.tsx @@ -0,0 +1,91 @@ +import Tip from "../../../components/ui/Tip"; +import Button from "../../../components/ui/Button"; +import { Channels } from "revolt.js/dist/api/objects"; +import Checkbox from "../../../components/ui/Checkbox"; +import { useServer } from "../../../context/revoltjs/hooks"; +import { useContext, useEffect, useState } from "preact/hooks"; +import { ChannelPermission } from "revolt.js/dist/api/permissions"; +import { AppContext } from "../../../context/revoltjs/RevoltClient"; + +// ! FIXME: export from revolt.js +const DEFAULT_PERMISSION_DM = ChannelPermission.View + + ChannelPermission.SendMessage + + ChannelPermission.ManageChannel + + ChannelPermission.VoiceCall + + ChannelPermission.InviteOthers + + ChannelPermission.EmbedLinks + + ChannelPermission.UploadFiles; + +interface Props { + channel: Channels.GroupChannel | Channels.TextChannel | Channels.VoiceChannel; +} + +// ! FIXME: bad code :) +export default function Permissions({ channel }: Props) { + const [ selected, setSelected ] = useState('default'); + const client = useContext(AppContext); + + type R = { name: string, permissions: number }; + let roles: { [key: string]: R } = {}; + if (channel.channel_type !== 'Group') { + const server = useServer(channel.server); + const a = server?.roles ?? {}; + for (let b of Object.keys(a)) { + roles[b] = { + name: a[b].name, + permissions: a[b].permissions[1] + }; + } + } + + const keys = [ 'default', ...Object.keys(roles) ]; + + const defaultRole = { name: 'Default', permissions: (channel.channel_type === 'Group' ? channel.permissions : channel.default_permissions) ?? DEFAULT_PERMISSION_DM }; + const selectedRole = selected === 'default' ? defaultRole : roles[selected]; + + if (!selectedRole) { + useEffect(() => setSelected('default'), [ ]); + return null; + } + + const [ p, setPerm ] = useState(selectedRole.permissions >>> 0); + + useEffect(() => { + setPerm(selectedRole.permissions >>> 0); + }, [ selected, selectedRole.permissions ]); + + return ( +
+ This section is under construction. +

select role

+ { selected } + { keys + .map(id => { + let role: R = id === 'default' ? defaultRole : roles[id]; + + return ( + selected && setSelected(id)}> + { role.name } + + ) + }) + } +

channel per??issions

+ { Object.keys(ChannelPermission) + .map(perm => { + let value = ChannelPermission[perm as keyof typeof ChannelPermission]; + if (value & DEFAULT_PERMISSION_DM) { + return ( + 0} onChange={c => setPerm(c ? (p | value) : (p ^ value))}> + { perm } + + ) + } + }) + } + +
+ ); +} diff --git a/src/pages/settings/panes/Feedback.tsx b/src/pages/settings/panes/Feedback.tsx index 8aeeafe21..66d21cd69 100644 --- a/src/pages/settings/panes/Feedback.tsx +++ b/src/pages/settings/panes/Feedback.tsx @@ -69,7 +69,7 @@ export function Feedback() { } setChecked("__other_option__")}> setDescription(ev.currentTarget.value)} /> - +

+ +

); } diff --git a/src/pages/settings/panes/Profile.tsx b/src/pages/settings/panes/Profile.tsx index 148f1b478..39902c0c3 100644 --- a/src/pages/settings/panes/Profile.tsx +++ b/src/pages/settings/panes/Profile.tsx @@ -113,14 +113,16 @@ export function Profile() { intl.dictionary )} /> - +

+ +

); } diff --git a/src/pages/settings/server/Bans.tsx b/src/pages/settings/server/Bans.tsx index 7d8a1590f..5ec7c0f05 100644 --- a/src/pages/settings/server/Bans.tsx +++ b/src/pages/settings/server/Bans.tsx @@ -1,3 +1,4 @@ +import Tip from "../../../components/ui/Tip"; import { Servers } from "revolt.js/dist/api/objects"; import { useContext, useEffect, useState } from "preact/hooks"; import { AppContext } from "../../../context/revoltjs/RevoltClient"; @@ -17,6 +18,7 @@ export function Bans({ server }: Props) { return (
+ This section is under construction. { bans?.map(x =>
{x._id.user}: {x.reason ?? 'no reason'}
) }
); diff --git a/src/pages/settings/server/Members.tsx b/src/pages/settings/server/Members.tsx index d4fb3c832..b569e71af 100644 --- a/src/pages/settings/server/Members.tsx +++ b/src/pages/settings/server/Members.tsx @@ -1,13 +1,17 @@ import { useEffect, useState } from "preact/hooks"; import { Servers } from "revolt.js/dist/api/objects"; +import Checkbox from "../../../components/ui/Checkbox"; +import Tip from "../../../components/ui/Tip"; import { useForceUpdate, useUsers } from "../../../context/revoltjs/hooks"; interface Props { server: Servers.Server; } +// ! FIXME: bad code :) export function Members({ server }: Props) { const [members, setMembers] = useState(undefined); + const ctx = useForceUpdate(); const users = useUsers(members?.map(x => x._id.user) ?? [], ctx); @@ -18,7 +22,36 @@ export function Members({ server }: Props) { return (
- { members && members.length > 0 && users?.map(x => x &&
@{x.username}
) } + This section is under construction. + { members && members.length > 0 && users?.map(x => x &&
+
+
+
+ + @{x.username} + { server.roles && Object.keys(server.roles).map(id => { + let role = server.roles?.[id]!; + let member = members.find(y => x._id === y._id.user)!; + + return ( + { + let roles = (member.roles ?? []).filter(z => z !== id); + if (selected) roles.push(id); + + ctx.client.servers.members.editMember(server._id, x._id, { roles }); + setMembers( + [ + ...members.filter(e => e._id.user !== x._id), + { + ...member, + roles + } + ] + ); + }}>{ role.name } + ) + }) } +
) }
); } diff --git a/src/pages/settings/server/Overview.tsx b/src/pages/settings/server/Overview.tsx index d6d0c2842..fe530276a 100644 --- a/src/pages/settings/server/Overview.tsx +++ b/src/pages/settings/server/Overview.tsx @@ -76,9 +76,11 @@ export function Overview({ server }: Props) { if (!changed) setChanged(true) }} /> - +

+ +

diff --git a/src/pages/settings/server/Roles.tsx b/src/pages/settings/server/Roles.tsx index 47e820230..5d530c1dc 100644 --- a/src/pages/settings/server/Roles.tsx +++ b/src/pages/settings/server/Roles.tsx @@ -1,15 +1,20 @@ -import { useEffect, useState } from "preact/hooks"; +import Tip from "../../../components/ui/Tip"; import Button from "../../../components/ui/Button"; import { Servers } from "revolt.js/dist/api/objects"; +import InputBox from "../../../components/ui/InputBox"; import Checkbox from "../../../components/ui/Checkbox"; +import { useContext, useEffect, useState } from "preact/hooks"; +import { AppContext } from "../../../context/revoltjs/RevoltClient"; import { ChannelPermission, ServerPermission } from "revolt.js/dist/api/permissions"; interface Props { server: Servers.Server; } +// ! FIXME: bad code :) export function Roles({ server }: Props) { const [ selected, setSelected ] = useState('default'); + const client = useContext(AppContext); const roles = server.roles ?? {}; const keys = [ 'default', ...Object.keys(roles) ]; @@ -21,10 +26,26 @@ export function Roles({ server }: Props) { useEffect(() => setSelected('default'), [ ]); return null; } + + const [ p, setPerm ] = useState([ + selectedRole.permissions[0] >>> 0, + selectedRole.permissions[1] >>> 0, + ]); + + useEffect(() => { + setPerm([ + selectedRole.permissions[0] >>> 0, + selectedRole.permissions[1] >>> 0, + ]); + }, [ selected, selectedRole.permissions ]); + + const [ name, setName ] = useState(''); return (
+ This section is under construction.

select role

+ { selected } { keys .map(id => { let role: Servers.Role = id === 'default' ? defaultRole : roles[id]; @@ -36,14 +57,21 @@ export function Roles({ server }: Props) { ) }) } - -

server permmissions

+
+ setName(e.currentTarget.value)} /> + +

serverm permmissions

{ Object.keys(ServerPermission) .map(perm => { let value = ServerPermission[perm as keyof typeof ServerPermission]; return ( - >> 0) & value) > 0} onChange={() => {}}> + 0} onChange={c => setPerm([ c ? (p[0] | value) : (p[0] ^ value), p[1] ])}> { perm } ) @@ -55,12 +83,15 @@ export function Roles({ server }: Props) { let value = ChannelPermission[perm as keyof typeof ChannelPermission]; return ( - >> 0) & value) > 0} onChange={() => {}}> + >> 0) & value) > 0} onChange={c => setPerm([ p[0], c ? (p[1] | value) : (p[1] ^ value) ])}> { perm } ) }) } +
); } diff --git a/yarn.lock b/yarn.lock index b3a3e352c..1a95434bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3420,10 +3420,10 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -revolt.js@4.3.3-alpha.4: - version "4.3.3-alpha.4" - resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.4.tgz#7d393c9016a9d89151b1c091f6b02bc193b3a553" - integrity sha512-d6SGjRKFDlWG5fEveaVf0DRGb8d0RW8iv1E0kEG0W3R138KdeWCK8zUU0H+ykUdd5OjS7ESBKaEcwSP2BXMRSA== +revolt.js@4.3.3-alpha.6: + version "4.3.3-alpha.6" + resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.6.tgz#054e685a5c0dac2c7ae3e2aa454d1965218cb2b0" + integrity sha512-u1/xf+YSQr8DbKsO0raym+F05R75bqYadrPWaIie3m2s2p7ZWeamHlfWIKJlmDO5AL+Lg3xoZWoLwuRHrD1K/Q== dependencies: "@insertish/mutable" "1.1.0" axios "^0.19.2" From c2c6f910fb5e5e1e02510fc8f716a2806050b4cd Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Thu, 1 Jul 2021 18:54:11 +0200 Subject: [PATCH 0037/1462] Fix: small fixes for members sidebar --- external/lang | 2 +- .../common/messaging/MessageBox.tsx | 2 +- .../navigation/items/Item.module.scss | 7 ++- src/pages/settings/server/Members.tsx | 44 +++++-------------- src/pages/settings/server/Panes.module.scss | 21 +++++++++ 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/external/lang b/external/lang index 588b882a3..4ef733354 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 588b882a3acca644c2f65b67cd341c88fd97989d +Subproject commit 4ef73335436f3118d660cec24ff7972d3ccd5984 diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index 1141d9aa1..19ab5ce92 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -64,7 +64,7 @@ const Blocked = styled.div` svg { flex-shrink: 0; - margin-inline-end: 8px; + margin-inline-end: 10px; } `; diff --git a/src/components/navigation/items/Item.module.scss b/src/components/navigation/items/Item.module.scss index afb54073e..fb855f0ab 100644 --- a/src/components/navigation/items/Item.module.scss +++ b/src/components/navigation/items/Item.module.scss @@ -17,11 +17,15 @@ color: var(--tertiary-foreground); &.normal { - height: 38px; + height: 42px; } &.compact { height: 32px; + + &[data-mobile="true"] { // TOFIX: make sure this works on mobile + height: 50px; + } } &.user { @@ -65,6 +69,7 @@ } &.avatar { + display: flex; flex-shrink: 0; } diff --git a/src/pages/settings/server/Members.tsx b/src/pages/settings/server/Members.tsx index b569e71af..e7d30a6f0 100644 --- a/src/pages/settings/server/Members.tsx +++ b/src/pages/settings/server/Members.tsx @@ -1,7 +1,7 @@ +import styles from './Panes.module.scss'; import { useEffect, useState } from "preact/hooks"; import { Servers } from "revolt.js/dist/api/objects"; -import Checkbox from "../../../components/ui/Checkbox"; -import Tip from "../../../components/ui/Tip"; +import UserIcon from "../../../components/common/user/UserIcon"; import { useForceUpdate, useUsers } from "../../../context/revoltjs/hooks"; interface Props { @@ -21,37 +21,15 @@ export function Members({ server }: Props) { }, [ ]); return ( -
- This section is under construction. - { members && members.length > 0 && users?.map(x => x &&
-
-
-
- - @{x.username} - { server.roles && Object.keys(server.roles).map(id => { - let role = server.roles?.[id]!; - let member = members.find(y => x._id === y._id.user)!; - - return ( - { - let roles = (member.roles ?? []).filter(z => z !== id); - if (selected) roles.push(id); - - ctx.client.servers.members.editMember(server._id, x._id, { roles }); - setMembers( - [ - ...members.filter(e => e._id.user !== x._id), - { - ...member, - roles - } - ] - ); - }}>{ role.name } - ) - }) } -
) } +
+
+ X Members +
+ { members && members.length > 0 && users?.map(x => x && +
+
@{x.username}
+
) + }
); } diff --git a/src/pages/settings/server/Panes.module.scss b/src/pages/settings/server/Panes.module.scss index ba25ba08e..91e4cb3b9 100644 --- a/src/pages/settings/server/Panes.module.scss +++ b/src/pages/settings/server/Panes.module.scss @@ -55,3 +55,24 @@ } } } + +.members { + + .subtitle { + display: flex; + justify-content: space-between; + font-size: 13px; + text-transform: uppercase; + color: var(--secondary-foreground); + font-weight: 700; + } + + .member { + gap: 8px; + padding: 10px; + display: flex; + align-items: center; + flex-direction: row; + background: var(--secondary-background); + } +} \ No newline at end of file From 0b1486ecda25f04f03ce8655c940a80faf9befbe Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Thu, 1 Jul 2021 19:27:38 +0200 Subject: [PATCH 0038/1462] Fix: changed icons to solid on sidebar for temp --- src/components/navigation/left/HomeSidebar.tsx | 4 ++-- src/components/ui/Category.tsx | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/navigation/left/HomeSidebar.tsx b/src/components/navigation/left/HomeSidebar.tsx index 98cbc6e92..6cfd9a429 100644 --- a/src/components/navigation/left/HomeSidebar.tsx +++ b/src/components/navigation/left/HomeSidebar.tsx @@ -1,6 +1,6 @@ import { Localizer, Text } from "preact-i18n"; import { useContext, useEffect } from "preact/hooks"; -import { Home, Group, Wrench, Save } from "@styled-icons/boxicons-regular"; +import { Home, UserDetail, Wrench, Save } from "@styled-icons/boxicons-solid"; import Category from '../../ui/Category'; import PaintCounter from "../../../lib/PaintCounter"; @@ -85,7 +85,7 @@ function HomeSidebar(props: Props) { ) !== "undefined" ? 'unread' : undefined } > - + diff --git a/src/components/ui/Category.tsx b/src/components/ui/Category.tsx index 7fae78e48..16c144440 100644 --- a/src/components/ui/Category.tsx +++ b/src/components/ui/Category.tsx @@ -18,7 +18,6 @@ const CategoryBase = styled.div>` justify-content: space-between; svg { - stroke: var(--foreground); cursor: pointer; } From 2c1421fd971f1eb1c6b0c297ada864506c8b4e2b Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 1 Jul 2021 19:37:36 +0100 Subject: [PATCH 0039/1462] Use UserIcon in server list header. Re-design status context menu. --- src/components/common/user/UserHeader.tsx | 12 +- .../navigation/left/ServerListSidebar.tsx | 27 ++-- src/lib/ContextMenus.tsx | 125 ++++++++++-------- src/styles/_context-menu.scss | 25 +++- 4 files changed, 111 insertions(+), 78 deletions(-) diff --git a/src/components/common/user/UserHeader.tsx b/src/components/common/user/UserHeader.tsx index e93f3fd2e..d234340e4 100644 --- a/src/components/common/user/UserHeader.tsx +++ b/src/components/common/user/UserHeader.tsx @@ -47,18 +47,8 @@ interface Props { export default function UserHeader({ user }: Props) { const { writeClipboard } = useIntermediate(); - function openPresenceSelector() { - openContextMenu("Status"); - } - return (
- }> @@ -69,7 +59,7 @@ export default function UserHeader({ user }: Props) { + onClick={() => openContextMenu("Status")}> diff --git a/src/components/navigation/left/ServerListSidebar.tsx b/src/components/navigation/left/ServerListSidebar.tsx index 5d94fbc51..cb1c7d122 100644 --- a/src/components/navigation/left/ServerListSidebar.tsx +++ b/src/components/navigation/left/ServerListSidebar.tsx @@ -6,7 +6,7 @@ import ServerIcon from "../../common/ServerIcon"; import { Children } from "../../../types/Preact"; import { Plus } from "@styled-icons/boxicons-regular"; import PaintCounter from "../../../lib/PaintCounter"; -import { attachContextMenu } from 'preact-context-menu'; +import { attachContextMenu, openContextMenu } from 'preact-context-menu'; import { connectState } from "../../../redux/connector"; import { useLocation, useParams } from "react-router-dom"; import { Unreads } from "../../../redux/reducers/unreads"; @@ -15,10 +15,11 @@ import { Channel, Servers } from "revolt.js/dist/api/objects"; import { LastOpened } from "../../../redux/reducers/last_opened"; import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice"; import { useIntermediate } from "../../../context/intermediate/Intermediate"; -import { useChannels, useForceUpdate, useServers } from "../../../context/revoltjs/hooks"; +import { useChannels, useForceUpdate, useSelf, useServers } from "../../../context/revoltjs/hooks"; import logoSVG from '../../../assets/logo.svg'; import Tooltip from "../../common/Tooltip"; +import UserIcon from "../../common/user/UserIcon"; function Icon({ children, unread, size }: { children: Children, unread?: 'mention' | 'unread', size: number }) { return ( @@ -81,7 +82,7 @@ const ServerList = styled.div` } `; -const ServerEntry = styled.div<{ active: boolean, invert?: boolean }>` +const ServerEntry = styled.div<{ active: boolean, home?: boolean }>` height: 58px; display: flex; align-items: center; @@ -91,7 +92,7 @@ const ServerEntry = styled.div<{ active: boolean, invert?: boolean }>` // outline: 1px solid red; } - > div, > svg { + > div { width: 46px; height: 46px; display: grid; @@ -139,10 +140,8 @@ const ServerEntry = styled.div<{ active: boolean, invert?: boolean }>` ` } } - ${ props => props.active && props.invert && css` - img { - filter: saturate(0) brightness(10); - } + ${ props => (!props.active || props.home) && css` + cursor: pointer; ` } `; @@ -153,6 +152,7 @@ interface Props { export function ServerListSidebar({ unreads, lastOpened }: Props) { const ctx = useForceUpdate(); + const self = useSelf(ctx); const activeServers = useServers(undefined, ctx) as Servers.Server[]; const channels = (useChannels(undefined, ctx) as Channel[]) .map(x => mapChannelWithUnread(x, unreads)); @@ -199,10 +199,13 @@ export function ServerListSidebar({ unreads, lastOpened }: Props) { - - - - + +
homeActive && openContextMenu("Status")}> + + + +
diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index c1844451d..265ca804c 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -19,8 +19,12 @@ import { Children } from "../types/Preact"; import LineDivider from "../components/ui/LineDivider"; import { connectState } from "../redux/connector"; import { internalEmit } from "./eventEmitter"; -import { At, Bell, BellOff, Check, CheckSquare, ChevronRight, Block, Square, LeftArrowAlt } from "@styled-icons/boxicons-regular"; +import { At, Bell, BellOff, Check, CheckSquare, ChevronRight, Block, Square, LeftArrowAlt, Trash } from "@styled-icons/boxicons-regular"; +import { Cog } from "@styled-icons/boxicons-solid"; import { getNotificationState, Notifications, NotificationState } from "../redux/reducers/notifications"; +import UserStatus from "../components/common/user/UserStatus"; +import { Link } from "react-router-dom"; +import IconButton from "../components/ui/IconButton"; interface ContextMenuData { user?: string; @@ -72,6 +76,7 @@ type Action = | { action: "leave_server"; target: Servers.Server } | { action: "delete_server"; target: Servers.Server } | { action: "open_notification_options", channel: Channels.Channel } + | { action: "open_settings" } | { action: "open_channel_settings", id: string } | { action: "open_server_settings", id: string } | { action: "open_server_channel_settings", server: string, id: string } @@ -315,6 +320,7 @@ function ContextMenus(props: Props) { break; } + case "open_settings": history.push('/settings'); break; case "open_channel_settings": history.push(`/channel/${data.id}/settings`); break; case "open_server_channel_settings": history.push(`/server/${data.server}/channel/${data.id}/settings`); break; case "open_server_settings": history.push(`/server/${data.id}/settings`); break; @@ -641,62 +647,75 @@ function ContextMenus(props: Props) { return elements; }} - - @{client.user?.username} - - -
- - - -
- - - -
- - - -
- - - - - - - {client.user?.status?.text && ( + + {() => <> +
+
+
@{client.user!.username}
+
+
+ + + + + +
+ + +
+ + + +
+ + + +
+ + - +
+ - )} - + +
+
+ + + +
+ { client.user!.status?.text && + + + + } +
+ } + {({ channel }: { channel: Channels.Channel }) => { const state = props.notifications[channel._id]; diff --git a/src/styles/_context-menu.scss b/src/styles/_context-menu.scss index 159efac95..a90e99e4b 100644 --- a/src/styles/_context-menu.scss +++ b/src/styles/_context-menu.scss @@ -4,17 +4,17 @@ padding: 6px 8px; user-select: none; border-radius: 4px; + font-size: .875rem; color: var(--secondary-foreground); background: var(--primary-background) !important; box-shadow: 0px 0px 8px 8px rgba(0, 0, 0, 0.05); - > span { + > span, .main > span { gap: 6px; margin: 2px 0; display: flex; padding: 6px 8px; border-radius: 3px; - font-size: .875rem; align-items: center; white-space: nowrap; @@ -33,6 +33,27 @@ color: var(--tertiary-foreground); } } +} + +.context-menu.Status { + .header { + gap: 8px; + display: flex; + padding: 6px 8px; + font-weight: 600; + align-items: center; + color: var(--foreground); + + .main { + flex-grow: 1; + display: flex; + flex-direction: column; + } + + .status { + font-size: .6rem; + } + } .indicator { width: 8px; From 4afdd1581341317cca3159438e62256cf76ac2f8 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 1 Jul 2021 21:23:54 +0100 Subject: [PATCH 0040/1462] Fix avatar direction. --- src/components/common/messaging/attachments/MessageReply.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/messaging/attachments/MessageReply.tsx b/src/components/common/messaging/attachments/MessageReply.tsx index 269cba4b4..95d931f01 100644 --- a/src/components/common/messaging/attachments/MessageReply.tsx +++ b/src/components/common/messaging/attachments/MessageReply.tsx @@ -26,7 +26,7 @@ export const ReplyBase = styled.div<{ head?: boolean, fail?: boolean, preview?: white-space: nowrap; text-overflow: ellipsis; - svg { + svg:first-child { flex-shrink: 0; transform: scaleX(-1); color: var(--tertiary-foreground); From 156aee4aba400bc39085ee69eb1688649c8ceaf6 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 1 Jul 2021 19:46:50 +0100 Subject: [PATCH 0041/1462] Filter theme keys. --- src/context/Theme.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/context/Theme.tsx b/src/context/Theme.tsx index bb496da0d..e37f0b654 100644 --- a/src/context/Theme.tsx +++ b/src/context/Theme.tsx @@ -101,10 +101,12 @@ export const PRESETS: { [key: string]: Theme } = { }, }; +const keys = Object.keys(PRESETS.dark); const GlobalTheme = createGlobalStyle<{ theme: Theme }>` :root { ${(props) => (Object.keys(props.theme) as Variables[]).map((key) => { + if (!keys.includes(key)) return; return `--${key}: ${props.theme[key]};`; })} } From a9d0f74f419c657360499f81adb6636b040f2ab2 Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Fri, 2 Jul 2021 10:38:43 +0200 Subject: [PATCH 0042/1462] Update: Work on new Friends tab + minor fixes --- .../navigation/BottomNavigation.tsx | 4 +- .../navigation/items/ButtonItem.tsx | 9 +- .../navigation/items/Item.module.scss | 4 +- .../navigation/left/ServerListSidebar.tsx | 4 +- src/components/ui/Header.tsx | 9 +- src/components/ui/Modal.tsx | 2 + src/pages/channels/ChannelHeader.tsx | 4 + src/pages/friends/Friend.module.scss | 29 ++++- src/pages/friends/Friend.tsx | 13 ++- src/pages/settings/server/Panes.module.scss | 14 +++ src/pages/settings/server/Roles.tsx | 101 ++++++++++-------- src/styles/_context-menu.scss | 2 +- 12 files changed, 128 insertions(+), 67 deletions(-) diff --git a/src/components/navigation/BottomNavigation.tsx b/src/components/navigation/BottomNavigation.tsx index c88fa2d31..7faa1a00a 100644 --- a/src/components/navigation/BottomNavigation.tsx +++ b/src/components/navigation/BottomNavigation.tsx @@ -4,7 +4,7 @@ import styled, { css } from "styled-components"; import { useSelf } from "../../context/revoltjs/hooks"; import { useHistory, useLocation } from "react-router"; import ConditionalLink from "../../lib/ConditionalLink"; -import { MessageRounded, Group } from "@styled-icons/boxicons-regular"; +import { Message, Group } from "@styled-icons/boxicons-regular"; const NavigationBase = styled.div` z-index: 10; @@ -50,7 +50,7 @@ export default function BottomNavigation() { } } }}> - +
- setName(e.currentTarget.value)} /> - -

serverm permmissions

- { Object.keys(ServerPermission) - .map(perm => { - let value = ServerPermission[perm as keyof typeof ServerPermission]; + return ( + selected && setSelected(id)}> + { role.name } + + ) + }) + } +
+ setName(e.currentTarget.value)} /> + +
+
+

serverm permmissions

+ { Object.keys(ServerPermission) + .map(perm => { + let value = ServerPermission[perm as keyof typeof ServerPermission]; - return ( - 0} onChange={c => setPerm([ c ? (p[0] | value) : (p[0] ^ value), p[1] ])}> - { perm } - - ) - }) - } -

channel permmissions

- { Object.keys(ChannelPermission) - .map(perm => { - let value = ChannelPermission[perm as keyof typeof ChannelPermission]; + return ( + 0} onChange={c => setPerm([ c ? (p[0] | value) : (p[0] ^ value), p[1] ])}> + { perm } + + ) + }) + } +

channel permmissions

+ { Object.keys(ChannelPermission) + .map(perm => { + let value = ChannelPermission[perm as keyof typeof ChannelPermission]; - return ( - >> 0) & value) > 0} onChange={c => setPerm([ p[0], c ? (p[1] | value) : (p[1] ^ value) ])}> - { perm } - - ) - }) - } - + return ( + >> 0) & value) > 0} onChange={c => setPerm([ p[0], c ? (p[1] | value) : (p[1] ^ value) ])}> + { perm } + + ) + }) + } + +
+
+
); } diff --git a/src/styles/_context-menu.scss b/src/styles/_context-menu.scss index a90e99e4b..66df13486 100644 --- a/src/styles/_context-menu.scss +++ b/src/styles/_context-menu.scss @@ -1,6 +1,6 @@ .preact-context-menu .context-menu { z-index: 100; - min-width: 180px; + min-width: 190px; padding: 6px 8px; user-select: none; border-radius: 4px; From 6abdb511b110894558c27a25383839d9752aa8e0 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 2 Jul 2021 09:41:37 +0100 Subject: [PATCH 0043/1462] All class name to be set on category / overline. --- src/components/ui/Category.tsx | 12 +++++++----- src/components/ui/Overline.tsx | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/ui/Category.tsx b/src/components/ui/Category.tsx index 16c144440..ccdd4e91c 100644 --- a/src/components/ui/Category.tsx +++ b/src/components/ui/Category.tsx @@ -31,18 +31,20 @@ const CategoryBase = styled.div>` ` } `; -interface Props { +type Props = Omit, 'children' | 'as'> & { text: Children; action?: () => void; variant?: 'default' | 'uniform'; } export default function Category(props: Props) { + let { text, action, ...otherProps } = props; + return ( - - {props.text} - {props.action && ( - + + {text} + {action && ( + )} ); diff --git a/src/components/ui/Overline.tsx b/src/components/ui/Overline.tsx index 86233697b..5a9f9d04c 100644 --- a/src/components/ui/Overline.tsx +++ b/src/components/ui/Overline.tsx @@ -2,7 +2,7 @@ import styled, { css } from "styled-components"; import { Children } from "../../types/Preact"; import { Text } from 'preact-i18n'; -interface Props { +type Props = Omit, 'children' | 'as'> & { error?: string; block?: boolean; children?: Children; From d84e76936adc074a9d526c0736ee5bcfe5ea2052 Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Fri, 2 Jul 2021 11:13:54 +0200 Subject: [PATCH 0044/1462] Fix: small fixes to friends menu --- src/pages/friends/Friend.module.scss | 9 +++++++-- src/pages/friends/Friend.tsx | 20 ++++++++++---------- src/pages/friends/Friends.tsx | 25 +++++++++++++------------ 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/pages/friends/Friend.module.scss b/src/pages/friends/Friend.module.scss index 5ac68fa01..1db3b2d71 100644 --- a/src/pages/friends/Friend.module.scss +++ b/src/pages/friends/Friend.module.scss @@ -1,10 +1,15 @@ .list { - padding: 16px; + padding: 0 20px 20px 20px; user-select: none; overflow-y: scroll; .overline { display: flex; + position: sticky; + top: 0; + background: var(--primary-background); + padding: 8px 0; + z-index: 10; } &[data-empty="true"] { @@ -67,7 +72,7 @@ display: flex; gap: 12px; - > div { + > a { height: 40px; width: 40px; diff --git a/src/pages/friends/Friend.tsx b/src/pages/friends/Friend.tsx index 6a6bbdc38..dd51b263f 100644 --- a/src/pages/friends/Friend.tsx +++ b/src/pages/friends/Friend.tsx @@ -29,18 +29,18 @@ export function Friend({ user }: Props) { subtext = actions.push( <> - - + + - - - - + + + + - - + + ); } diff --git a/src/pages/friends/Friends.tsx b/src/pages/friends/Friends.tsx index c331f34a6..c59bb9c89 100644 --- a/src/pages/friends/Friends.tsx +++ b/src/pages/friends/Friends.tsx @@ -1,5 +1,5 @@ import styles from "./Friend.module.scss"; -import { UserPlus } from "@styled-icons/boxicons-regular"; +import { Conversation, UserPlus } from "@styled-icons/boxicons-solid"; import { Friend } from "./Friend"; import { Text } from "preact-i18n"; @@ -34,11 +34,12 @@ export default function Friends() {
-
- openScreen({ id: 'special_input', type: 'add_friend' })}> - - -
+ openScreen({ id: 'special_input', type: 'add_friend' })}> {/* TOFIX: Make sure this opens the "Start Group DM" window on click */} + + + openScreen({ id: 'special_input', type: 'add_friend' })}> + +
)} {pending.length > 0 && ( - - –{" "} + + —{" "} {pending.length} )} @@ -62,8 +63,8 @@ export default function Friends() { ))} {friends.length > 0 && ( - - –{" "} + + —{" "} {friends.length} )} @@ -71,8 +72,8 @@ export default function Friends() { ))} {blocked.length > 0 && ( - - –{" "} + + —{" "} {blocked.length} )} From c8425d86c8efb64db1ac329ffd08148ba163d74f Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Fri, 2 Jul 2021 11:39:07 +0200 Subject: [PATCH 0045/1462] Fix: small fixes for mobile --- src/components/ui/Header.tsx | 5 +++++ src/pages/friends/Friend.module.scss | 7 +++++++ src/pages/friends/Friends.tsx | 4 +++- src/pages/settings/GenericSettings.tsx | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/components/ui/Header.tsx b/src/components/ui/Header.tsx index 05b941a6c..747a24faa 100644 --- a/src/components/ui/Header.tsx +++ b/src/components/ui/Header.tsx @@ -29,6 +29,11 @@ export default styled.div` flex-shrink: 0; } + @media only screen and (max-width: 768px) { + padding: 0 12px; + } + + ${ props => props.background && css` height: 120px; align-items: flex-end; diff --git a/src/pages/friends/Friend.module.scss b/src/pages/friends/Friend.module.scss index 1db3b2d71..ab28639b0 100644 --- a/src/pages/friends/Friend.module.scss +++ b/src/pages/friends/Friend.module.scss @@ -87,6 +87,13 @@ } } +@media only screen and (max-width: 768px) { + .list { + padding: 0 12px 12px 12px; + } +} + + //! FIXME: Move this to the Header component, do this: // 1. Check if header has topic, if yes, flex-grow: 0 on the title. // 2. If header has no topic (example: friends page), flex-grow 1 on the header title. diff --git a/src/pages/friends/Friends.tsx b/src/pages/friends/Friends.tsx index c59bb9c89..343a9fc07 100644 --- a/src/pages/friends/Friends.tsx +++ b/src/pages/friends/Friends.tsx @@ -1,5 +1,5 @@ import styles from "./Friend.module.scss"; -import { Conversation, UserPlus } from "@styled-icons/boxicons-solid"; +import { UserDetail, Conversation, UserPlus } from "@styled-icons/boxicons-solid"; import { Friend } from "./Friend"; import { Text } from "preact-i18n"; @@ -8,6 +8,7 @@ import Overline from "../../components/ui/Overline"; import IconButton from "../../components/ui/IconButton"; import { useUsers } from "../../context/revoltjs/hooks"; import { User, Users } from "revolt.js/dist/api/objects"; +import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice"; import { useIntermediate } from "../../context/intermediate/Intermediate"; export default function Friends() { @@ -31,6 +32,7 @@ export default function Friends() { return ( <>
+ { !isTouchscreenDevice && }
diff --git a/src/pages/settings/GenericSettings.tsx b/src/pages/settings/GenericSettings.tsx index e32c79397..151a6adae 100644 --- a/src/pages/settings/GenericSettings.tsx +++ b/src/pages/settings/GenericSettings.tsx @@ -65,7 +65,7 @@ export function GenericSettings({ pages, switchPage, category, custom, children, ) : ( <> switchPage()}> - + Date: Fri, 2 Jul 2021 11:13:14 +0100 Subject: [PATCH 0046/1462] Fix Friend button styling and actions. Can now call from friends list. --- src/components/ui/IconButton.tsx | 1 + src/context/revoltjs/RevoltClient.tsx | 12 ++++++++++-- src/pages/friends/Friend.module.scss | 12 ++++++------ src/pages/friends/Friend.tsx | 24 ++++++++++++++---------- src/pages/friends/Friends.tsx | 22 +++++++++++++++++----- 5 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/components/ui/IconButton.tsx b/src/components/ui/IconButton.tsx index a0c757840..bf946abc2 100644 --- a/src/components/ui/IconButton.tsx +++ b/src/components/ui/IconButton.tsx @@ -12,6 +12,7 @@ export default styled.div` display: grid; cursor: pointer; place-items: center; + transition: .1s ease background-color; fill: ${normal}; color: ${normal}; diff --git a/src/context/revoltjs/RevoltClient.tsx b/src/context/revoltjs/RevoltClient.tsx index 5ca77857a..086178274 100644 --- a/src/context/revoltjs/RevoltClient.tsx +++ b/src/context/revoltjs/RevoltClient.tsx @@ -3,12 +3,12 @@ import { Client } from "revolt.js"; import { takeError } from "./util"; import { createContext } from "preact"; import { Children } from "../../types/Preact"; +import { useHistory } from 'react-router-dom'; import { Route } from "revolt.js/dist/api/routes"; import { connectState } from "../../redux/connector"; import Preloader from "../../components/ui/Preloader"; import { WithDispatcher } from "../../redux/reducers"; import { AuthState } from "../../redux/reducers/auth"; -import { SyncOptions } from "../../redux/reducers/sync"; import { useEffect, useMemo, useState } from "preact/hooks"; import { useIntermediate } from '../intermediate/Intermediate'; import { registerEvents, setReconnectDisallowed } from "./events"; @@ -30,6 +30,8 @@ export interface ClientOperations { logout: (shouldRequest?: boolean) => Promise; loggedIn: () => boolean; ready: () => boolean; + + openDM: (user_id: string) => Promise; } export const AppContext = createContext(undefined as any); @@ -42,6 +44,7 @@ type Props = WithDispatcher & { }; function Context({ auth, children, dispatcher }: Props) { + const history = useHistory(); const { openScreen } = useIntermediate(); const [status, setStatus] = useState(ClientStatus.INIT); const [client, setClient] = useState(undefined as unknown as Client); @@ -132,7 +135,12 @@ function Context({ auth, children, dispatcher }: Props) { ready: () => ( operations.loggedIn() && typeof client.user !== "undefined" - ) + ), + openDM: async (user_id: string) => { + let channel = await client.users.openDM(user_id); + history.push(`/channel/${channel!._id}`); + return channel!._id; + } } }, [ client, auth.active ]); diff --git a/src/pages/friends/Friend.module.scss b/src/pages/friends/Friend.module.scss index ab28639b0..a8183e511 100644 --- a/src/pages/friends/Friend.module.scss +++ b/src/pages/friends/Friend.module.scss @@ -72,16 +72,16 @@ display: flex; gap: 12px; - > a { - height: 40px; + .button { width: 40px; + height: 40px; - &:nth-child(1):hover { - background: var(--status-online); //TOFIX: change to normal green color + &:hover.error { + background: var(--error); } - &:nth-child(3):hover { - background: var(--error); + &:hover.success { + background: var(--success); } } } diff --git a/src/pages/friends/Friend.tsx b/src/pages/friends/Friend.tsx index dd51b263f..2befba18a 100644 --- a/src/pages/friends/Friend.tsx +++ b/src/pages/friends/Friend.tsx @@ -1,18 +1,19 @@ import { Text } from "preact-i18n"; -import { Link } from "react-router-dom"; +import classNames from "classnames"; import styles from "./Friend.module.scss"; import { useContext } from "preact/hooks"; import { Children } from "../../types/Preact"; -import { X, Plus } from "@styled-icons/boxicons-regular"; -import { PhoneCall, Envelope } from "@styled-icons/boxicons-solid"; import IconButton from "../../components/ui/IconButton"; import { attachContextMenu } from "preact-context-menu"; +import { X, Plus } from "@styled-icons/boxicons-regular"; import { User, Users } from "revolt.js/dist/api/objects"; import { stopPropagation } from "../../lib/stopPropagation"; +import { VoiceOperationsContext } from "../../context/Voice"; import UserIcon from "../../components/common/user/UserIcon"; import UserStatus from '../../components/common/user/UserStatus'; -import { AppContext } from "../../context/revoltjs/RevoltClient"; +import { PhoneCall, Envelope } from "@styled-icons/boxicons-solid"; import { useIntermediate } from "../../context/intermediate/Intermediate"; +import { AppContext, OperationsContext } from "../../context/revoltjs/RevoltClient"; interface Props { user: User; @@ -21,6 +22,8 @@ interface Props { export function Friend({ user }: Props) { const client = useContext(AppContext); const { openScreen } = useIntermediate(); + const { openDM } = useContext(OperationsContext); + const { connect } = useContext(VoiceOperationsContext); const actions: Children[] = []; let subtext: Children = null; @@ -29,18 +32,16 @@ export function Friend({ user }: Props) { subtext = actions.push( <> - + className={classNames(styles.button, styles.success)} + onClick={ev => stopPropagation(ev, openDM(user._id).then(connect))}> - - + className={styles.button} + onClick={ev => stopPropagation(ev, openDM(user._id))}> - ); } @@ -48,6 +49,7 @@ export function Friend({ user }: Props) { if (user.relationship === Users.Relationship.Incoming) { actions.push( stopPropagation(ev, client.users.addFriend(user.username))}> @@ -67,6 +69,7 @@ export function Friend({ user }: Props) { ) { actions.push( stopPropagation(ev, client.users.removeFriend(user._id))}> @@ -76,6 +79,7 @@ export function Friend({ user }: Props) { if (user.relationship === Users.Relationship.Blocked) { actions.push( stopPropagation(ev, client.users.unblockUser(user._id))}> diff --git a/src/pages/friends/Friends.tsx b/src/pages/friends/Friends.tsx index 343a9fc07..b144030b8 100644 --- a/src/pages/friends/Friends.tsx +++ b/src/pages/friends/Friends.tsx @@ -29,6 +29,9 @@ export default function Friends() { x => x.relationship === Users.Relationship.Blocked ); + const online = friends.filter(x => x.online && x.status?.presence !== Users.Presence.Invisible); + const offline = friends.filter(x => !x.online || x.status?.presence === Users.Presence.Invisible); + return ( <>
@@ -36,7 +39,7 @@ export default function Friends() {
- openScreen({ id: 'special_input', type: 'add_friend' })}> {/* TOFIX: Make sure this opens the "Start Group DM" window on click */} + openScreen({ id: 'special_input', type: 'create_group' })}> openScreen({ id: 'special_input', type: 'add_friend' })}> @@ -64,13 +67,22 @@ export default function Friends() { {pending.map(y => ( ))} - {friends.length > 0 && ( + {online.length > 0 && ( + + —{" "} + {online.length} + + )} + {online.map(y => ( + + ))} + {offline.length > 0 && ( - —{" "} - {friends.length} + —{" "} + {offline.length} )} - {friends.map(y => ( + {offline.map(y => ( ))} {blocked.length > 0 && ( From 526aa72c0f5431da37e68f41408821126bfbbbad Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Fri, 2 Jul 2021 13:56:38 +0200 Subject: [PATCH 0047/1462] Update: Continued work on Friends tab + fixes --- src/components/navigation/BottomNavigation.tsx | 2 +- src/pages/channels/ChannelHeader.tsx | 11 ++++++----- src/pages/friends/Friend.module.scss | 17 ++++++++++++----- src/pages/friends/Friend.tsx | 2 +- src/pages/home/Home.tsx | 7 +++++-- src/pages/invite/Invite.tsx | 4 ++-- src/pages/settings/GenericSettings.tsx | 4 ++-- 7 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/components/navigation/BottomNavigation.tsx b/src/components/navigation/BottomNavigation.tsx index 7faa1a00a..675659c36 100644 --- a/src/components/navigation/BottomNavigation.tsx +++ b/src/components/navigation/BottomNavigation.tsx @@ -7,7 +7,7 @@ import ConditionalLink from "../../lib/ConditionalLink"; import { Message, Group } from "@styled-icons/boxicons-regular"; const NavigationBase = styled.div` - z-index: 10; + z-index: 100; height: 50px; display: flex; background: var(--secondary-background); diff --git a/src/pages/channels/ChannelHeader.tsx b/src/pages/channels/ChannelHeader.tsx index 6508cb6fc..d4a91217c 100644 --- a/src/pages/channels/ChannelHeader.tsx +++ b/src/pages/channels/ChannelHeader.tsx @@ -7,7 +7,8 @@ import Markdown from "../../components/markdown/Markdown"; import { getChannelName } from "../../context/revoltjs/util"; import UserStatus from "../../components/common/user/UserStatus"; import { AppContext } from "../../context/revoltjs/RevoltClient"; -import { Save, At, Group, Hash } from "@styled-icons/boxicons-regular"; +import { At, Hash } from "@styled-icons/boxicons-regular"; +import { Save, Group } from "@styled-icons/boxicons-solid"; import { useStatusColour } from "../../components/common/user/UserIcon"; import { useIntermediate } from "../../context/intermediate/Intermediate"; @@ -61,18 +62,18 @@ export default function ChannelHeader({ channel, toggleSidebar }: ChannelHeaderP let icon, recipient; switch (channel.channel_type) { case "SavedMessages": - icon = ; + icon = ; break; case "DirectMessage": - icon = ; + icon = ; const uid = client.channels.getRecipient(channel._id); recipient = client.users.get(uid); break; case "Group": - icon = ; + icon = ; break; case "TextChannel": - icon = ; + icon = ; break; } diff --git a/src/pages/friends/Friend.module.scss b/src/pages/friends/Friend.module.scss index a8183e511..3021e9afc 100644 --- a/src/pages/friends/Friend.module.scss +++ b/src/pages/friends/Friend.module.scss @@ -10,6 +10,8 @@ background: var(--primary-background); padding: 8px 0; z-index: 10; + + } &[data-empty="true"] { @@ -28,11 +30,11 @@ } .friend { - padding: 10px; + padding: 0 10px; + height: 60px; display: flex; border-radius: 5px; align-items: center; - flex-direction: row; cursor: pointer; &:hover { @@ -47,7 +49,7 @@ flex-grow: 1; margin: 0 12px; font-size: 16px; - + font-weight: 600; display: flex; flex-direction: column; text-overflow: ellipsis; @@ -61,6 +63,7 @@ .subtext { font-size: 12px; + font-weight: 400; color: var(--tertiary-foreground); white-space: nowrap; overflow: hidden; @@ -73,8 +76,8 @@ gap: 12px; .button { - width: 40px; - height: 40px; + width: 36px; + height: 36px; &:hover.error { background: var(--error); @@ -91,6 +94,10 @@ .list { padding: 0 12px 12px 12px; } + + .call { + display: none; + } } diff --git a/src/pages/friends/Friend.tsx b/src/pages/friends/Friend.tsx index 2befba18a..74b33a249 100644 --- a/src/pages/friends/Friend.tsx +++ b/src/pages/friends/Friend.tsx @@ -33,7 +33,7 @@ export function Friend({ user }: Props) { actions.push( <> stopPropagation(ev, openDM(user._id).then(connect))}> diff --git a/src/pages/home/Home.tsx b/src/pages/home/Home.tsx index eaa763de5..d45e15b57 100644 --- a/src/pages/home/Home.tsx +++ b/src/pages/home/Home.tsx @@ -3,13 +3,16 @@ import { Link } from "react-router-dom"; import { Text } from "preact-i18n"; import Header from "../../components/ui/Header"; - +import { Home as HomeIcon } from "@styled-icons/boxicons-solid"; import wideSVG from '../../assets/wide.svg'; export default function Home() { return (
-
+
+ + +

diff --git a/src/pages/invite/Invite.tsx b/src/pages/invite/Invite.tsx index 8fc2a1f3b..e05bcdf3f 100644 --- a/src/pages/invite/Invite.tsx +++ b/src/pages/invite/Invite.tsx @@ -1,6 +1,6 @@ import styles from './Invite.module.scss'; import Button from '../../components/ui/Button'; -import { LeftArrowAlt } from "@styled-icons/boxicons-regular"; +import { ArrowBack } from "@styled-icons/boxicons-regular"; import Overline from '../../components/ui/Overline'; import { Invites } from "revolt.js/dist/api/objects"; import Preloader from '../../components/ui/Preloader'; @@ -44,7 +44,7 @@ export default function Invite() { return (
- history.push('/')} /> + history.push('/')} />
{ !processing && diff --git a/src/pages/settings/GenericSettings.tsx b/src/pages/settings/GenericSettings.tsx index 151a6adae..a37006031 100644 --- a/src/pages/settings/GenericSettings.tsx +++ b/src/pages/settings/GenericSettings.tsx @@ -6,7 +6,7 @@ import Header from '../../components/ui/Header'; import Category from '../../components/ui/Category'; import IconButton from "../../components/ui/IconButton"; import LineDivider from "../../components/ui/LineDivider"; -import { LeftArrowAlt, X, XCircle } from "@styled-icons/boxicons-regular"; +import { ArrowBack, X, XCircle } from "@styled-icons/boxicons-regular"; import { Switch, useHistory, useParams } from "react-router-dom"; import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice"; import ButtonItem from "../../components/navigation/items/ButtonItem"; @@ -65,7 +65,7 @@ export function GenericSettings({ pages, switchPage, category, custom, children, ) : ( <> switchPage()}> - + Date: Fri, 2 Jul 2021 13:35:50 +0100 Subject: [PATCH 0048/1462] Link to profiles from message / member sidebar. --- src/components/common/messaging/Message.tsx | 8 +++++-- .../navigation/items/ButtonItem.tsx | 23 ++++++++++++------- .../navigation/right/MemberSidebar.tsx | 16 ++++++------- src/context/intermediate/Intermediate.tsx | 2 +- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/components/common/messaging/Message.tsx b/src/components/common/messaging/Message.tsx index 0c5369493..8c27c5130 100644 --- a/src/components/common/messaging/Message.tsx +++ b/src/components/common/messaging/Message.tsx @@ -14,6 +14,7 @@ import { useContext } from "preact/hooks"; import { AppContext } from "../../../context/revoltjs/RevoltClient"; import { memo } from "preact/compat"; import { MessageReply } from "./attachments/MessageReply"; +import { useIntermediate } from "../../../context/intermediate/Intermediate"; interface Props { attachContext?: boolean @@ -29,10 +30,13 @@ function Message({ attachContext, message, contrast, content: replacement, head: // TODO: of dependencies. We only need to update on u/avatar. const user = useUser(message.author); const client = useContext(AppContext); + const { openScreen } = useIntermediate(); const content = message.content as string; const head = preferHead || (message.replies && message.replies.length > 0); + const userContext = attachContext ? attachContextMenu('Menu', { user: message.author, contextualChannel: message.channel }) : undefined as any; // ! FIXME: tell fatal to make this type generic + const openProfile = () => openScreen({ id: 'profile', user_id: message.author }); return (
@@ -46,13 +50,13 @@ function Message({ attachContext, message, contrast, content: replacement, head: onContextMenu={attachContext ? attachContextMenu('Menu', { message, contextualChannel: message.channel, queued }) : undefined}> { head ? - : + : } { head && - + } diff --git a/src/components/navigation/items/ButtonItem.tsx b/src/components/navigation/items/ButtonItem.tsx index 139ec677b..176f5f809 100644 --- a/src/components/navigation/items/ButtonItem.tsx +++ b/src/components/navigation/items/ButtonItem.tsx @@ -14,7 +14,7 @@ import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice"; import { useIntermediate } from '../../../context/intermediate/Intermediate'; import { stopPropagation } from '../../../lib/stopPropagation'; -interface CommonProps { +type CommonProps = Omit, 'children' | 'as'> & { active?: boolean alert?: 'unread' | 'mention' alertCount?: number @@ -26,11 +26,12 @@ type UserProps = CommonProps & { channel?: Channels.DirectMessageChannel } -export function UserButton({ active, alert, alertCount, user, context, channel }: UserProps) { +export function UserButton(props: UserProps) { + const { active, alert, alertCount, user, context, channel, ...divProps } = props; const { openScreen } = useIntermediate(); return ( -
@@ -138,9 +142,12 @@ type ButtonProps = CommonProps & { compact?: boolean } -export default function ButtonItem({ active, alert, alertCount, onClick, className, children, compact }: ButtonProps) { +export default function ButtonItem(props: ButtonProps) { + const { active, alert, alertCount, onClick, className, children, compact, ...divProps } = props; + return ( -
diff --git a/src/components/navigation/right/MemberSidebar.tsx b/src/components/navigation/right/MemberSidebar.tsx index 973835490..96b3728ff 100644 --- a/src/components/navigation/right/MemberSidebar.tsx +++ b/src/components/navigation/right/MemberSidebar.tsx @@ -8,11 +8,12 @@ import { UserButton } from "../items/ButtonItem"; import { ChannelDebugInfo } from "./ChannelDebugInfo"; import { Channels, Servers, Users } from "revolt.js/dist/api/objects"; import { GenericSidebarBase, GenericSidebarList } from "../SidebarBase"; +import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { ClientboundNotification } from "revolt.js/dist/websocket/notifications"; +import { AppContext, ClientStatus, StatusContext } from "../../../context/revoltjs/RevoltClient"; import { HookContext, useChannel, useForceUpdate, useUsers } from "../../../context/revoltjs/hooks"; import placeholderSVG from "../items/placeholder.svg"; -import { AppContext, ClientStatus, StatusContext } from "../../../context/revoltjs/RevoltClient"; interface Props { ctx: HookContext @@ -31,6 +32,7 @@ export default function MemberSidebar(props: { channel?: Channels.Channel }) { } export function GroupMemberSidebar({ channel, ctx }: Props & { channel: Channels.GroupChannel }) { + const { openScreen } = useIntermediate(); const users = useUsers(undefined, ctx); let members = channel.recipients .map(x => users.find(y => y?._id === x)) @@ -112,13 +114,11 @@ export function GroupMemberSidebar({ channel, ctx }: Props & { channel: Channels {members.map( user => user && ( - // - - // + openScreen({ id: 'profile', user_id: user._id })} /> ) )} diff --git a/src/context/intermediate/Intermediate.tsx b/src/context/intermediate/Intermediate.tsx index ff723c0b9..3fb816742 100644 --- a/src/context/intermediate/Intermediate.tsx +++ b/src/context/intermediate/Intermediate.tsx @@ -98,7 +98,7 @@ export default function Intermediate(props: Props) { const navigate = (path: string) => history.push(path); const subs = [ - internalSubscribe("Intermediate", "open_profile", openProfile), + internalSubscribe("Intermediate", "openProfile", openProfile), internalSubscribe("Intermediate", "navigate", navigate) ] From f5c2838d3614d905e886ad7045b257ae49b47c55 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 2 Jul 2021 14:50:24 +0100 Subject: [PATCH 0049/1462] Add dayjs language defaults. Add remove / block user confirmation. --- external/lang | 2 +- src/context/Locale.tsx | 25 +++++++++++ src/context/intermediate/Intermediate.tsx | 4 +- src/context/intermediate/modals/Input.tsx | 1 + src/context/intermediate/modals/Prompt.tsx | 51 +++++++++++++++------- src/lib/ContextMenus.tsx | 25 +++++------ src/pages/friends/Friend.tsx | 2 +- 7 files changed, 79 insertions(+), 31 deletions(-) diff --git a/external/lang b/external/lang index 4ef733354..e200511dc 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit 4ef73335436f3118d660cec24ff7972d3ccd5984 +Subproject commit e200511dcb2c655e6ee89580fee9ef96c9f1f387 diff --git a/src/context/Locale.tsx b/src/context/Locale.tsx index 95fd9b79d..0385745c6 100644 --- a/src/context/Locale.tsx +++ b/src/context/Locale.tsx @@ -125,10 +125,34 @@ function Locale({ children, locale }: Props) { const [defns, setDefinition] = useState(definition); const lang = Languages[locale]; + function transformLanguage(obj: { [key: string]: any }) { + const dayjs = obj.dayjs; + const defaults = dayjs.defaults; + + const twelvehour = defaults?.twelvehour === 'yes' || true; + const separator: '/' | '-' | '.' = defaults?.date_separator ?? '/'; + const date: 'traditional' | 'simplified' | 'ISO8601' = defaults?.date_format ?? 'traditional'; + + const DATE_FORMATS = { + traditional: `DD${separator}MM${separator}YYYY`, + simplified: `MM${separator}DD${separator}YYYY`, + ISO8601: 'YYYY-MM-DD' + } + + dayjs['sameElse'] = DATE_FORMATS[date]; + Object.keys(dayjs) + .filter(k => k !== 'defaults') + .forEach(k => dayjs[k] = dayjs[k].replace(/{{time}}/g, twelvehour ? 'LT' : 'HH:mm')); + + return obj; + } + useEffect(() => { if (locale === "en") { + transformLanguage(definition); setDefinition(definition); dayjs.locale("en"); + dayjs.updateLocale('en', { calendar: definition.dayjs }); return; } @@ -141,6 +165,7 @@ function Locale({ children, locale }: Props) { import(`../../external/lang/${lang.i18n}.json`).then( async (lang_file) => { const defn = lang_file.default; + transformLanguage(defn); const target = lang.dayjs ?? lang.i18n; const dayjs_locale = await import(`../../node_modules/dayjs/esm/locale/${target}.js`); diff --git a/src/context/intermediate/Intermediate.tsx b/src/context/intermediate/Intermediate.tsx index 3fb816742..7cb972022 100644 --- a/src/context/intermediate/Intermediate.tsx +++ b/src/context/intermediate/Intermediate.tsx @@ -1,4 +1,4 @@ -import { Attachment, Channels, EmbedImage, Servers } from "revolt.js/dist/api/objects"; +import { Attachment, Channels, EmbedImage, Servers, Users } from "revolt.js/dist/api/objects"; import { useContext, useEffect, useMemo, useState } from "preact/hooks"; import { internalSubscribe } from "../../lib/eventEmitter"; import { Action } from "../../components/ui/Modal"; @@ -26,6 +26,8 @@ export type Screen = { type: "create_invite", target: Channels.TextChannel | Channels.GroupChannel } | { type: "kick_member", target: Servers.Server, user: string } | { type: "ban_member", target: Servers.Server, user: string } | + { type: "unfriend_user", target: Users.User } | + { type: "block_user", target: Users.User } | { type: "create_channel", target: Servers.Server } )) | ({ id: "special_input" } & ( diff --git a/src/context/intermediate/modals/Input.tsx b/src/context/intermediate/modals/Input.tsx index 68e009377..fd8d44eca 100644 --- a/src/context/intermediate/modals/Input.tsx +++ b/src/context/intermediate/modals/Input.tsx @@ -35,6 +35,7 @@ export function InputModal({ disabled={processing} actions={[ { + confirmation: true, text: , onClick: () => { setProcessing(true); diff --git a/src/context/intermediate/modals/Prompt.tsx b/src/context/intermediate/modals/Prompt.tsx index 78048d8f3..1af00210a 100644 --- a/src/context/intermediate/modals/Prompt.tsx +++ b/src/context/intermediate/modals/Prompt.tsx @@ -10,10 +10,11 @@ import Overline from "../../../components/ui/Overline"; import { AppContext } from "../../revoltjs/RevoltClient"; import { mapMessage, takeError } from "../../revoltjs/util"; import Modal, { Action } from "../../../components/ui/Modal"; -import { Channels, Servers } from "revolt.js/dist/api/objects"; +import { Channels, Servers, Users } from "revolt.js/dist/api/objects"; import { useContext, useEffect, useState } from "preact/hooks"; import UserIcon from "../../../components/common/user/UserIcon"; import Message from "../../../components/common/messaging/Message"; +import { TextReact } from "../../../lib/i18n"; interface Props { onClose: () => void; @@ -48,6 +49,8 @@ type SpecialProps = { onClose: () => void } & ( { type: "create_invite", target: Channels.TextChannel | Channels.GroupChannel } | { type: "kick_member", target: Servers.Server, user: string } | { type: "ban_member", target: Servers.Server, user: string } | + { type: "unfriend_user", target: Users.User } | + { type: "block_user", target: Users.User } | { type: "create_channel", target: Servers.Server } ) @@ -62,23 +65,33 @@ export function SpecialPromptModal(props: SpecialProps) { case 'close_dm': case 'leave_server': case 'delete_server': - case 'delete_channel': { + case 'delete_channel': + case 'unfriend_user': + case 'block_user': { const EVENTS = { - 'close_dm': 'confirm_close_dm', - 'delete_server': 'confirm_delete', - 'delete_channel': 'confirm_delete', - 'leave_group': 'confirm_leave', - 'leave_server': 'confirm_leave' + 'close_dm': ['confirm_close_dm', 'close'], + 'delete_server': ['confirm_delete', 'delete'], + 'delete_channel': ['confirm_delete', 'delete'], + 'leave_group': ['confirm_leave', 'leave'], + 'leave_server': ['confirm_leave', 'leave'], + 'unfriend_user': ['unfriend_user', 'remove'], + 'block_user': ['block_user', 'block'] }; let event = EVENTS[props.type]; - let name = props.type === 'close_dm' ? client.users.get(client.channels.getRecipient(props.target._id))?.username : props.target.name; + let name; + switch (props.type) { + case 'unfriend_user': + case 'block_user': name = props.target.username; break; + case 'close_dm': name = client.users.get(client.channels.getRecipient(props.target._id))?.username; break; + default: name = props.target.name; + } return ( } actions={[ @@ -86,15 +99,23 @@ export function SpecialPromptModal(props: SpecialProps) { confirmation: true, contrast: true, error: true, - text: , + text: , onClick: async () => { setProcessing(true); try { - if (props.type === 'leave_group' || props.type === 'close_dm' || props.type === 'delete_channel') { - await client.channels.delete(props.target._id); - } else { - await client.servers.delete(props.target._id); + switch (props.type) { + case 'unfriend_user': + await client.users.removeFriend(props.target._id); break; + case 'block_user': + await client.users.blockUser(props.target._id); break; + case 'leave_group': + case 'close_dm': + case 'delete_channel': + await client.channels.delete(props.target._id); break; + case 'leave_server': + case 'delete_server': + await client.servers.delete(props.target._id); break; } onClose(); @@ -106,7 +127,7 @@ export function SpecialPromptModal(props: SpecialProps) { }, { text: , onClick: onClose } ]} - content={} + content={{ name } }} />} disabled={processing} error={error} /> diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index 265ca804c..97e285293 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -60,11 +60,11 @@ type Action = | { action: "ban_member"; target: Servers.Server; user: string } | { action: "view_profile"; user: string } | { action: "message_user"; user: string } - | { action: "block_user"; user: string } - | { action: "unblock_user"; user: string } - | { action: "add_friend"; user: string } - | { action: "remove_friend"; user: string } - | { action: "cancel_friend"; user: string } + | { action: "block_user"; user: Users.User } + | { action: "unblock_user"; user: Users.User } + | { action: "add_friend"; user: Users.User } + | { action: "remove_friend"; user: Users.User } + | { action: "cancel_friend"; user: Users.User } | { action: "set_presence"; presence: Users.Presence } | { action: "set_status" } | { action: "clear_status" } @@ -264,22 +264,21 @@ function ContextMenus(props: Props) { case "add_friend": { - let user = client.users.get(data.user); - if (user) { - await client.users.addFriend(user.username); - } + await client.users.addFriend(data.user.username); } break; case "block_user": - await client.users.blockUser(data.user); + openScreen({ id: 'special_prompt', type: 'block_user', target: data.user }); break; case "unblock_user": - await client.users.unblockUser(data.user); + await client.users.unblockUser(data.user._id); break; case "remove_friend": + openScreen({ id: 'special_prompt', type: 'unfriend_user', target: data.user }); + break; case "cancel_friend": - await client.users.removeFriend(data.user); + await client.users.removeFriend(data.user._id); break; case "set_presence": @@ -466,7 +465,7 @@ function ContextMenus(props: Props) { for (const action of actions) { generateAction({ action: action as any, - user: user._id + user }); } } diff --git a/src/pages/friends/Friend.tsx b/src/pages/friends/Friend.tsx index 74b33a249..d50198cce 100644 --- a/src/pages/friends/Friend.tsx +++ b/src/pages/friends/Friend.tsx @@ -70,7 +70,7 @@ export function Friend({ user }: Props) { actions.push( stopPropagation(ev, client.users.removeFriend(user._id))}> + onClick={ev => stopPropagation(ev, openScreen({ id: 'special_prompt', type: 'unfriend_user', target: user }))}> ); From 8f047788c4f2d02b279b136a9b89edb33c0dd2a1 Mon Sep 17 00:00:00 2001 From: nizune <9-nizune@users.noreply.gitlab.insrt.uk> Date: Fri, 2 Jul 2021 16:51:06 +0200 Subject: [PATCH 0050/1462] Fix: Message copy brackets and icon changes --- external/lang | 2 +- src/components/common/messaging/Message.tsx | 4 +- .../common/messaging/MessageBase.tsx | 42 +++++++++++++------ .../common/messaging/MessageBox.tsx | 3 +- src/components/common/user/UserShort.tsx | 4 +- .../navigation/BottomNavigation.tsx | 6 +-- .../navigation/left/HomeSidebar.tsx | 4 +- src/components/ui/Modal.tsx | 2 - src/pages/channels/ChannelHeader.tsx | 4 +- src/pages/friends/Friend.module.scss | 20 ++++++--- src/pages/friends/Friends.tsx | 34 +++++++++++---- 11 files changed, 83 insertions(+), 42 deletions(-) diff --git a/external/lang b/external/lang index e200511dc..dad00381a 160000 --- a/external/lang +++ b/external/lang @@ -1 +1 @@ -Subproject commit e200511dcb2c655e6ee89580fee9ef96c9f1f387 +Subproject commit dad00381aaaafc1ab829816dffc31f0f37ee56a9 diff --git a/src/components/common/messaging/Message.tsx b/src/components/common/messaging/Message.tsx index 8c27c5130..46edea72c 100644 --- a/src/components/common/messaging/Message.tsx +++ b/src/components/common/messaging/Message.tsx @@ -55,9 +55,7 @@ function Message({ attachContext, message, contrast, content: replacement, head: { head && - - - + } { replacement ?? } diff --git a/src/components/common/messaging/MessageBase.tsx b/src/components/common/messaging/MessageBase.tsx index de70edcee..cd9d4b8c1 100644 --- a/src/components/common/messaging/MessageBase.tsx +++ b/src/components/common/messaging/MessageBase.tsx @@ -61,6 +61,7 @@ export default styled.div` .author { cursor: pointer; + font-weight: 600 !important; &:hover { text-decoration: underline; @@ -68,9 +69,6 @@ export default styled.div` } .copy { - width: 0; - height: 0; - opacity: 0; display: block; overflow: hidden; } @@ -92,13 +90,23 @@ export const MessageInfo = styled.div` flex-direction: row; justify-content: center; - ::selection { - background-color: transparent; - color: var(--tertiary-foreground); + .copyBracket { + opacity: 0; + position: absolute; + } + + .copyTime { + opacity: 0; + position: absolute; } svg { + user-select: none; cursor: pointer; + + &:active { + transform: translateY(1px); + } } time { @@ -106,11 +114,19 @@ export const MessageInfo = styled.div` } time, .edited { + margin-top: 1px; cursor: default; display: inline; font-size: 10px; color: var(--tertiary-foreground); } + + time, .edited > div { + &::selection { + background-color: transparent; + color: var(--tertiary-foreground); + } + } `; export const MessageContent = styled.div` @@ -118,7 +134,7 @@ export const MessageContent = styled.div` flex-grow: 1; display: flex; overflow: hidden; - font-size: 0.875rem; + font-size: .875rem; flex-direction: column; justify-content: center; `; @@ -135,9 +151,11 @@ export function MessageDetail({ message, position }: { message: MessageObject, p if (message.edited) { return ( <> - - [] - + @@ -149,9 +167,9 @@ export function MessageDetail({ message, position }: { message: MessageObject, p return ( <> ) diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx index 19ab5ce92..b035bfa62 100644 --- a/src/components/common/messaging/MessageBox.tsx +++ b/src/components/common/messaging/MessageBox.tsx @@ -5,7 +5,8 @@ import { Channel } from "revolt.js"; import styled from "styled-components"; import { defer } from "../../../lib/defer"; import IconButton from "../../ui/IconButton"; -import { Send, X } from '@styled-icons/boxicons-regular'; +import { X } from '@styled-icons/boxicons-regular'; +import { Send } from '@styled-icons/boxicons-solid'; import { debounce } from "../../../lib/debounce"; import Axios, { CancelTokenSource } from "axios"; import { useTranslation } from "../../../lib/i18n"; diff --git a/src/components/common/user/UserShort.tsx b/src/components/common/user/UserShort.tsx index 69a15fd39..f0cec4eda 100644 --- a/src/components/common/user/UserShort.tsx +++ b/src/components/common/user/UserShort.tsx @@ -3,7 +3,7 @@ import UserIcon from "./UserIcon"; import { Text } from "preact-i18n"; export function Username({ user, ...otherProps }: { user?: User } & JSX.HTMLAttributes) { - return { user?.username ?? }; + return { user?.username ?? }; } export default function UserShort({ user, size }: { user?: User, size?: number }) { @@ -11,4 +11,4 @@ export default function UserShort({ user, size }: { user?: User, size?: number } ; -} +} \ No newline at end of file diff --git a/src/components/navigation/BottomNavigation.tsx b/src/components/navigation/BottomNavigation.tsx index 675659c36..00bd0ab81 100644 --- a/src/components/navigation/BottomNavigation.tsx +++ b/src/components/navigation/BottomNavigation.tsx @@ -4,7 +4,7 @@ import styled, { css } from "styled-components"; import { useSelf } from "../../context/revoltjs/hooks"; import { useHistory, useLocation } from "react-router"; import ConditionalLink from "../../lib/ConditionalLink"; -import { Message, Group } from "@styled-icons/boxicons-regular"; +import { Message, Group } from "@styled-icons/boxicons-solid"; const NavigationBase = styled.div` z-index: 100; @@ -50,13 +50,13 @@ export default function BottomNavigation() { } } }}> - + diff --git a/src/components/navigation/left/HomeSidebar.tsx b/src/components/navigation/left/HomeSidebar.tsx index 6cfd9a429..edde0aaa3 100644 --- a/src/components/navigation/left/HomeSidebar.tsx +++ b/src/components/navigation/left/HomeSidebar.tsx @@ -1,6 +1,6 @@ import { Localizer, Text } from "preact-i18n"; import { useContext, useEffect } from "preact/hooks"; -import { Home, UserDetail, Wrench, Save } from "@styled-icons/boxicons-solid"; +import { Home, UserDetail, Wrench, Notepad } from "@styled-icons/boxicons-solid"; import Category from '../../ui/Category'; import PaintCounter from "../../../lib/PaintCounter"; @@ -93,7 +93,7 @@ function HomeSidebar(props: Props) { )} - + diff --git a/src/components/ui/Modal.tsx b/src/components/ui/Modal.tsx index 4fa3d7cd4..2faecdec3 100644 --- a/src/components/ui/Modal.tsx +++ b/src/components/ui/Modal.tsx @@ -42,8 +42,6 @@ const ModalContainer = styled.div` border-radius: 8px; max-width: calc(100vw - 20px); - inline-size: min(100%, 500px); - animation-name: ${zoomIn}; animation-duration: 0.25s; animation-timing-function: cubic-bezier(.3,.3,.18,1.1); diff --git a/src/pages/channels/ChannelHeader.tsx b/src/pages/channels/ChannelHeader.tsx index d4a91217c..a67204fe3 100644 --- a/src/pages/channels/ChannelHeader.tsx +++ b/src/pages/channels/ChannelHeader.tsx @@ -8,7 +8,7 @@ import { getChannelName } from "../../context/revoltjs/util"; import UserStatus from "../../components/common/user/UserStatus"; import { AppContext } from "../../context/revoltjs/RevoltClient"; import { At, Hash } from "@styled-icons/boxicons-regular"; -import { Save, Group } from "@styled-icons/boxicons-solid"; +import { Notepad, Group } from "@styled-icons/boxicons-solid"; import { useStatusColour } from "../../components/common/user/UserIcon"; import { useIntermediate } from "../../context/intermediate/Intermediate"; @@ -62,7 +62,7 @@ export default function ChannelHeader({ channel, toggleSidebar }: ChannelHeaderP let icon, recipient; switch (channel.channel_type) { case "SavedMessages": - icon = ; + icon = ; break; case "DirectMessage": icon = ; diff --git a/src/pages/friends/Friend.module.scss b/src/pages/friends/Friend.module.scss index 3021e9afc..de5fee43f 100644 --- a/src/pages/friends/Friend.module.scss +++ b/src/pages/friends/Friend.module.scss @@ -6,12 +6,16 @@ .overline { display: flex; position: sticky; + align-items: center; top: 0; background: var(--primary-background); - padding: 8px 0; + padding: 5px 0; z-index: 10; + cursor: pointer; - + svg { + margin-inline-end: 4px; + } } &[data-empty="true"] { @@ -90,9 +94,16 @@ } } +.divider { + width: 1px; + height: 24px; + margin: 0 8px; + background: var(--primary-background); +} + @media only screen and (max-width: 768px) { .list { - padding: 0 12px 12px 12px; + padding: 0 8px 8px 8px; } .call { @@ -100,10 +111,9 @@ } } - //! FIXME: Move this to the Header component, do this: // 1. Check if header has topic, if yes, flex-grow: 0 on the title. // 2. If header has no topic (example: friends page), flex-grow 1 on the header title. .title { flex-grow: 1; -} +} \ No newline at end of file diff --git a/src/pages/friends/Friends.tsx b/src/pages/friends/Friends.tsx index b144030b8..689419aeb 100644 --- a/src/pages/friends/Friends.tsx +++ b/src/pages/friends/Friends.tsx @@ -1,8 +1,7 @@ -import styles from "./Friend.module.scss"; -import { UserDetail, Conversation, UserPlus } from "@styled-icons/boxicons-solid"; - import { Friend } from "./Friend"; import { Text } from "preact-i18n"; +import styles from "./Friend.module.scss"; +import Tooltip from "../../components/common/Tooltip"; import Header from "../../components/ui/Header"; import Overline from "../../components/ui/Overline"; import IconButton from "../../components/ui/IconButton"; @@ -10,6 +9,8 @@ import { useUsers } from "../../context/revoltjs/hooks"; import { User, Users } from "revolt.js/dist/api/objects"; import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice"; import { useIntermediate } from "../../context/intermediate/Intermediate"; +import { ChevronDown, ChevronRight } from "@styled-icons/boxicons-regular"; +import { UserDetail, Conversation, UserPlus, TennisBall } from "@styled-icons/boxicons-solid"; export default function Friends() { const { openScreen } = useIntermediate(); @@ -39,12 +40,24 @@ export default function Friends() {
- openScreen({ id: 'special_input', type: 'create_group' })}> - - - openScreen({ id: 'special_input', type: 'add_friend' })}> - - + + openScreen({ id: 'special_input', type: 'create_group' })}> + + + + + openScreen({ id: 'special_input', type: 'add_friend' })}> + + + + {/* +
+ + + + + + */}
0 && ( + {/* TOFIX: Make each category collapsible */} —{" "} {pending.length} @@ -69,6 +83,7 @@ export default function Friends() { ))} {online.length > 0 && ( + {/* TOFIX: Make each category collapsible */} —{" "} {online.length} @@ -78,6 +93,7 @@ export default function Friends() { ))} {offline.length > 0 && ( + {/* TOFIX: Make each category collapsible */} —{" "} {offline.length} From e252c2ff2ee437fb628373dacea19a94cf1332ac Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 2 Jul 2021 16:24:36 +0100 Subject: [PATCH 0051/1462] Add SVG masks to server / user icons. --- src/components/common/user/UserIcon.tsx | 2 +- .../navigation/left/ServerListSidebar.tsx | 17 ++++++++--------- src/components/ui/Masks.tsx | 18 ++++++++++++++++++ src/pages/app.tsx | 2 ++ 4 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 src/components/ui/Masks.tsx diff --git a/src/components/common/user/UserIcon.tsx b/src/components/common/user/UserIcon.tsx index 85064c545..9d7bb8017 100644 --- a/src/components/common/user/UserIcon.tsx +++ b/src/components/common/user/UserIcon.tsx @@ -62,7 +62,7 @@ export default function UserIcon(props: Props & Omit