feat(mobx): refactor and remove (react-)redux

This commit is contained in:
Paul
2021-12-23 21:43:11 +00:00
parent c5f9fc2873
commit 0591d44a31
55 changed files with 249 additions and 1522 deletions

View File

@@ -7,11 +7,12 @@ import { Channel as ChannelI } from "revolt.js/dist/maps/Channels";
import styled from "styled-components";
import { Text } from "preact-i18n";
import { useEffect, useState } from "preact/hooks";
import { useEffect } from "preact/hooks";
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
import { dispatch, getState } from "../../redux";
import { useApplicationState } from "../../mobx/State";
import { SIDEBAR_MEMBERS } from "../../mobx/stores/Layout";
import { useClient } from "../../context/revoltjs/RevoltClient";
@@ -83,15 +84,8 @@ export function Channel({ id }: { id: string }) {
return <TextChannel channel={channel} />;
}
const MEMBERS_SIDEBAR_KEY = "sidebar_members";
const CHANNELS_SIDEBAR_KEY = "sidebar_channels";
const TextChannel = observer(({ channel }: { channel: ChannelI }) => {
const [showMembers, setMembers] = useState(
getState().sectionToggle[MEMBERS_SIDEBAR_KEY] ?? true,
);
const [showChannels, setChannels] = useState(
getState().sectionToggle[CHANNELS_SIDEBAR_KEY] ?? true,
);
const layout = useApplicationState().layout;
// Mark channel as read.
useEffect(() => {
@@ -121,45 +115,7 @@ const TextChannel = observer(({ channel }: { channel: ChannelI }) => {
channel.nsfw
)
}>
<ChannelHeader
channel={channel}
toggleSidebar={() => {
setMembers(!showMembers);
if (showMembers) {
dispatch({
type: "SECTION_TOGGLE_SET",
id: MEMBERS_SIDEBAR_KEY,
state: false,
});
} else {
dispatch({
type: "SECTION_TOGGLE_UNSET",
id: MEMBERS_SIDEBAR_KEY,
});
}
}}
toggleChannelSidebar={() => {
if (isTouchscreenDevice) {
return;
}
setChannels(!showChannels);
if (showChannels) {
dispatch({
type: "SECTION_TOGGLE_SET",
id: CHANNELS_SIDEBAR_KEY,
state: false,
});
} else {
dispatch({
type: "SECTION_TOGGLE_UNSET",
id: CHANNELS_SIDEBAR_KEY,
});
}
}}
/>
<ChannelHeader channel={channel} />
<ChannelMain>
<ChannelContent>
<VoiceHeader id={channel._id} />
@@ -168,7 +124,10 @@ const TextChannel = observer(({ channel }: { channel: ChannelI }) => {
<JumpToBottom channel={channel} />
<MessageBox channel={channel} />
</ChannelContent>
{!isTouchscreenDevice && showMembers && <RightSidebar />}
{!isTouchscreenDevice &&
layout.getSectionState(SIDEBAR_MEMBERS, true) && (
<RightSidebar />
)}
</ChannelMain>
</AgeGate>
);

View File

@@ -1,4 +1,4 @@
import { At, Hash, Menu } from "@styled-icons/boxicons-regular";
import { At, Hash } from "@styled-icons/boxicons-regular";
import { Notepad, Group } from "@styled-icons/boxicons-solid";
import { observer } from "mobx-react-lite";
import { Channel } from "revolt.js/dist/maps/Channels";
@@ -7,6 +7,9 @@ import styled, { css } from "styled-components";
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
import { useApplicationState } from "../../mobx/State";
import { SIDEBAR_MEMBERS } from "../../mobx/stores/Layout";
import { useIntermediate } from "../../context/intermediate/Intermediate";
import { getChannelName } from "../../context/revoltjs/util";
@@ -69,14 +72,16 @@ const IconConainer = styled.div`
cursor: pointer;
color: var(--secondary-foreground);
${!isTouchscreenDevice && css`
${!isTouchscreenDevice &&
css`
&:hover {
color: var(--foreground);
}
`}
`
`;
export default observer(({ channel, toggleSidebar, toggleChannelSidebar }: ChannelHeaderProps) => {
export default observer(({ channel }: ChannelHeaderProps) => {
const layout = useApplicationState().layout;
const { openScreen } = useIntermediate();
const name = getChannelName(channel);
@@ -100,7 +105,12 @@ export default observer(({ channel, toggleSidebar, toggleChannelSidebar }: Chann
return (
<Header placement="primary">
<HamburgerAction />
<IconConainer onClick={toggleChannelSidebar}>{icon}</IconConainer>
<IconConainer
onClick={() =>
layout.toggleSectionState(SIDEBAR_MEMBERS, true)
}>
{icon}
</IconConainer>
<Info>
<span className="name">{name}</span>
{isTouchscreenDevice &&
@@ -143,7 +153,7 @@ export default observer(({ channel, toggleSidebar, toggleChannelSidebar }: Chann
</>
)}
</Info>
<HeaderActions channel={channel} toggleSidebar={toggleSidebar} />
<HeaderActions channel={channel} />
</Header>
);
});

View File

@@ -14,6 +14,9 @@ import { internalEmit } from "../../../lib/eventEmitter";
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
import { voiceState, VoiceStatus } from "../../../lib/vortex/VoiceState";
import { useApplicationState } from "../../../mobx/State";
import { SIDEBAR_MEMBERS } from "../../../mobx/stores/Layout";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
import UpdateIndicator from "../../../components/common/UpdateIndicator";
@@ -21,10 +24,8 @@ import IconButton from "../../../components/ui/IconButton";
import { ChannelHeaderProps } from "../ChannelHeader";
export default function HeaderActions({
channel,
toggleSidebar,
}: ChannelHeaderProps) {
export default function HeaderActions({ channel }: ChannelHeaderProps) {
const layout = useApplicationState().layout;
const { openScreen } = useIntermediate();
const history = useHistory();
@@ -40,7 +41,7 @@ export default function HeaderActions({
if (isTouchscreenDevice) {
openRightSidebar();
} else {
toggleSidebar?.();
layout.toggleSectionState(SIDEBAR_MEMBERS, true);
}
}

View File

@@ -10,15 +10,12 @@ import styled from "styled-components";
import { decodeTime } from "ulid";
import { Text } from "preact-i18n";
import { memo } from "preact/compat";
import { useEffect, useState } from "preact/hooks";
import { internalSubscribe, internalEmit } from "../../../lib/eventEmitter";
import { ChannelRenderer } from "../../../lib/renderer/Singleton";
import { useApplicationState } from "../../../mobx/State";
import { connectState } from "../../../redux/connector";
import { QueuedMessage } from "../../../redux/reducers/queue";
import RequiresOnline from "../../../context/revoltjs/RequiresOnline";
import { useClient } from "../../../context/revoltjs/RevoltClient";

View File

@@ -4,11 +4,12 @@ import styled, { css } from "styled-components";
import styles from "./Home.module.scss";
import { Text } from "preact-i18n";
import { useContext, useState } from "preact/hooks";
import { useContext } from "preact/hooks";
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
import { dispatch, getState } from "../../redux";
import { useApplicationState } from "../../mobx/State";
import { SIDEBAR_CHANNELS } from "../../mobx/stores/Layout";
import { AppContext } from "../../context/revoltjs/RevoltClient";
@@ -18,8 +19,6 @@ import Tooltip from "../../components/common/Tooltip";
import Header from "../../components/ui/Header";
import CategoryButton from "../../components/ui/fluent/CategoryButton";
const CHANNELS_SIDEBAR_KEY = "sidebar_channels";
const IconConainer = styled.div`
cursor: pointer;
color: var(--secondary-foreground);
@@ -34,29 +33,14 @@ const IconConainer = styled.div`
export default function Home() {
const client = useContext(AppContext);
const [showChannels, setChannels] = useState(
getState().sectionToggle[CHANNELS_SIDEBAR_KEY] ?? true,
);
const layout = useApplicationState().layout;
const toggleChannelSidebar = () => {
if (isTouchscreenDevice) {
return;
}
setChannels(!showChannels);
if (showChannels) {
dispatch({
type: "SECTION_TOGGLE_SET",
id: CHANNELS_SIDEBAR_KEY,
state: false,
});
} else {
dispatch({
type: "SECTION_TOGGLE_UNSET",
id: CHANNELS_SIDEBAR_KEY,
});
}
layout.toggleSectionState(SIDEBAR_CHANNELS, true);
};
return (

View File

@@ -10,8 +10,6 @@ import { useContext, useEffect, useState } from "preact/hooks";
import { defer } from "../../lib/defer";
import { TextReact } from "../../lib/i18n";
import { dispatch } from "../../redux";
import RequiresOnline from "../../context/revoltjs/RequiresOnline";
import {
AppContext,
@@ -168,11 +166,9 @@ export default function Invite() {
defer(() => {
if (server) {
dispatch({
type: "UNREADS_MARK_MULTIPLE_READ",
channels:
server.channel_ids,
});
client.unreads!.markMultipleRead(
server.channel_ids,
);
history.push(
`/server/${server._id}/channel/${invite.channel_id}`,

View File

@@ -6,8 +6,6 @@ import { TextReact } from "../../../lib/i18n";
import { stopPropagation } from "../../../lib/stopPropagation";
import { voiceState } from "../../../lib/vortex/VoiceState";
import { connectState } from "../../../redux/connector";
import Button from "../../../components/ui/Button";
import ComboBox from "../../../components/ui/ComboBox";
import Overline from "../../../components/ui/Overline";
@@ -17,7 +15,7 @@ const constraints = { audio: true };
// TODO: do not rewrite this code until voice is rewritten!
export function Component() {
export function Audio() {
const [mediaStream, setMediaStream] = useState<MediaStream | undefined>(
undefined,
);
@@ -163,7 +161,3 @@ function changeAudioDevice(deviceId: string, deviceType: string) {
window.localStorage.setItem("audioOutputDevice", deviceId);
}
}
export const Audio = connectState(Component, () => {
return;
});

View File

@@ -4,12 +4,7 @@ import styles from "./Panes.module.scss";
import { Text } from "preact-i18n";
import { useMemo } from "preact/hooks";
import PaintCounter from "../../../lib/PaintCounter";
import { useApplicationState } from "../../../mobx/State";
import LocaleOptions from "../../../mobx/stores/LocaleOptions";
import { dispatch } from "../../../redux";
import { connectState } from "../../../redux/connector";
import {
Language,

View File

@@ -5,23 +5,16 @@ import { useContext, useEffect, useState } from "preact/hooks";
import { urlBase64ToUint8Array } from "../../../lib/conversion";
import { useApplicationState } from "../../../mobx/State";
import { dispatch } from "../../../redux";
import { connectState } from "../../../redux/connector";
import { NotificationOptions } from "../../../redux/reducers/settings";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
import { AppContext } from "../../../context/revoltjs/RevoltClient";
import Checkbox from "../../../components/ui/Checkbox";
interface Props {
options?: NotificationOptions;
}
export function Component({ options }: Props) {
export function Notifications() {
const client = useContext(AppContext);
const { openScreen } = useIntermediate();
const sounds = useApplicationState().settings.sounds;
const settings = useApplicationState().settings;
const [pushEnabled, setPushEnabled] = useState<undefined | boolean>(
undefined,
);
@@ -43,7 +36,7 @@ export function Component({ options }: Props) {
</h3>
<Checkbox
disabled={!("Notification" in window)}
checked={options?.desktopEnabled ?? false}
checked={settings.get("notifications:desktop", false)!}
description={
<Text id="app.settings.pages.notifications.descriptions.enable_desktop" />
}
@@ -51,6 +44,7 @@ export function Component({ options }: Props) {
if (desktopEnabled) {
const permission =
await Notification.requestPermission();
if (permission !== "granted") {
return openScreen({
id: "error",
@@ -59,10 +53,7 @@ export function Component({ options }: Props) {
}
}
dispatch({
type: "SETTINGS_SET_NOTIFICATION_OPTIONS",
options: { desktopEnabled },
});
settings.set("notifications:desktop", desktopEnabled);
}}>
<Text id="app.settings.pages.notifications.enable_desktop" />
</Checkbox>
@@ -115,20 +106,16 @@ export function Component({ options }: Props) {
<h3>
<Text id="app.settings.pages.notifications.sounds" />
</h3>
{sounds.getState().map(({ id, enabled }) => (
{settings.sounds.getState().map(({ id, enabled }) => (
<Checkbox
key={id}
checked={enabled}
onChange={(enabled) => sounds.setEnabled(id, enabled)}>
onChange={(enabled) =>
settings.sounds.setEnabled(id, enabled)
}>
<Text id={`app.settings.pages.notifications.sound.${id}`} />
</Checkbox>
))}
</div>
);
}
export const Notifications = connectState(Component, (state) => {
return {
options: state.settings.notification,
};
});

View File

@@ -1,17 +1,16 @@
import { observer } from "mobx-react-lite";
import styles from "./Panes.module.scss";
import { Text } from "preact-i18n";
import { dispatch } from "../../../redux";
import { connectState } from "../../../redux/connector";
import { SyncKeys, SyncOptions } from "../../../redux/reducers/sync";
import { useApplicationState } from "../../../mobx/State";
import { SyncKeys } from "../../../mobx/stores/Sync";
import Checkbox from "../../../components/ui/Checkbox";
interface Props {
options?: SyncOptions;
}
export const Sync = observer(() => {
const sync = useApplicationState().sync;
export function Component(props: Props) {
return (
<div className={styles.notifications}>
<h3>
@@ -27,31 +26,16 @@ export function Component(props: Props) {
).map(([key, title]) => (
<Checkbox
key={key}
checked={
(props.options?.disabled ?? []).indexOf(key) === -1
}
checked={sync.isEnabled(key)}
description={
<Text
id={`app.settings.pages.sync.descriptions.${key}`}
/>
}
onChange={(enabled) =>
dispatch({
type: enabled
? "SYNC_ENABLE_KEY"
: "SYNC_DISABLE_KEY",
key,
})
}>
onChange={() => sync.toggle(key)}>
<Text id={`app.settings.pages.${title}`} />
</Checkbox>
))}
</div>
);
}
export const Sync = connectState(Component, (state) => {
return {
options: state.sync,
};
});

View File

@@ -3,9 +3,8 @@ import styled from "styled-components";
import { useEffect, useState } from "preact/hooks";
import { useApplicationState } from "../../../mobx/State";
import { dispatch } from "../../../redux";
import { Theme, generateVariables, ThemeOptions } from "../../../context/Theme";
import { Theme, generateVariables } from "../../../context/Theme";
import Tip from "../../../components/ui/Tip";
import previewPath from "../assets/preview.svg";