mirror of
https://github.com/stoatchat/for-legacy-web.git
synced 2026-03-06 17:11:55 +00:00
feat(mobx): refactor and remove (react-)redux
This commit is contained in:
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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}`,
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user