beginnings of react-recoil
Starting off with Recoilizing setOverlay Also set up the atom structure
This commit is contained in:
parent
a0f25158d3
commit
4f2d272d00
38
package-lock.json
generated
38
package-lock.json
generated
@ -18,6 +18,7 @@
|
||||
"moment": "^2.29.1",
|
||||
"pg": "^8.7.1",
|
||||
"react-contenteditable": "^3.3.6",
|
||||
"recoil": "^0.5.2",
|
||||
"sass": "^1.43.4",
|
||||
"sharp": "^0.29.2",
|
||||
"socket.io": "^4.3.1",
|
||||
@ -3770,6 +3771,11 @@
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
|
||||
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
|
||||
},
|
||||
"node_modules/hamt_plus": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz",
|
||||
"integrity": "sha1-4hwlKWjH4zsg9qGwlM2FeHomVgE="
|
||||
},
|
||||
"node_modules/har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
@ -6289,6 +6295,25 @@
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/recoil": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.5.2.tgz",
|
||||
"integrity": "sha512-Edibzpu3dbUMLy6QRg73WL8dvMl9Xqhp+kU+f2sJtXxsaXvAlxU/GcnDE8HXPkprXrhHF2e6SZozptNvjNF5fw==",
|
||||
"dependencies": {
|
||||
"hamt_plus": "1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.13.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
},
|
||||
"react-native": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/regexpp": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
|
||||
@ -10679,6 +10704,11 @@
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
|
||||
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
|
||||
},
|
||||
"hamt_plus": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz",
|
||||
"integrity": "sha1-4hwlKWjH4zsg9qGwlM2FeHomVgE="
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
@ -12613,6 +12643,14 @@
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"recoil": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.5.2.tgz",
|
||||
"integrity": "sha512-Edibzpu3dbUMLy6QRg73WL8dvMl9Xqhp+kU+f2sJtXxsaXvAlxU/GcnDE8HXPkprXrhHF2e6SZozptNvjNF5fw==",
|
||||
"requires": {
|
||||
"hamt_plus": "1.0.2"
|
||||
}
|
||||
},
|
||||
"regexpp": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
|
||||
|
@ -16,6 +16,7 @@
|
||||
"moment": "^2.29.1",
|
||||
"pg": "^8.7.1",
|
||||
"react-contenteditable": "^3.3.6",
|
||||
"recoil": "^0.5.2",
|
||||
"sass": "^1.43.4",
|
||||
"sharp": "^0.29.2",
|
||||
"socket.io": "^4.3.1",
|
||||
|
91
src/client/webapp/elements/atoms.ts
Normal file
91
src/client/webapp/elements/atoms.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { atom, selector } from 'recoil';
|
||||
import { Channel, GuildMetadata, Member, Message } from '../data-types';
|
||||
import CombinedGuild from '../guild-combined';
|
||||
|
||||
export interface GuildWithValue<T> {
|
||||
guild: CombinedGuild;
|
||||
value: T;
|
||||
}
|
||||
|
||||
export interface GuildWithErrorableValue<T> {
|
||||
guild: CombinedGuild;
|
||||
value: T | null;
|
||||
valueError: unknown | null;
|
||||
}
|
||||
|
||||
export interface ChannelWithErrorableValue<T> {
|
||||
channel: Channel;
|
||||
value: T | null;
|
||||
valueError: unknown | null;
|
||||
}
|
||||
|
||||
export const overlayState = atom<ReactNode>({
|
||||
key: 'overlayState',
|
||||
default: null
|
||||
});
|
||||
|
||||
export const guildsState = atom<GuildWithErrorableValue<GuildMetadata>[] | null>({
|
||||
key: 'guildsState',
|
||||
default: null
|
||||
});
|
||||
|
||||
export const selectedGuildIdState = atom<number | null>({
|
||||
key: 'selectedGuildIdState',
|
||||
default: null
|
||||
});
|
||||
|
||||
export const selectedGuildWithMetaState = selector<GuildWithErrorableValue<GuildMetadata> | null>({
|
||||
key: 'selectedGuildWithMetaState',
|
||||
get: ({ get }) => {
|
||||
const guildsWithMeta = get(guildsState);
|
||||
if (guildsWithMeta === null) return null;
|
||||
|
||||
const guildId = get(selectedGuildIdState);
|
||||
if (guildId === null) return null;
|
||||
|
||||
return guildsWithMeta.find(guildWithMeta => guildWithMeta.guild.id === guildId) ?? null;
|
||||
}
|
||||
});
|
||||
|
||||
export const selectedGuildState = selector<CombinedGuild | null>({
|
||||
key: 'selectedGuildState',
|
||||
get: ({ get }) => {
|
||||
const guildWithMeta = get(selectedGuildWithMetaState);
|
||||
if (guildWithMeta === null) return null;
|
||||
|
||||
return guildWithMeta.guild;
|
||||
}
|
||||
});
|
||||
|
||||
export const selectedGuildMembersState = atom<GuildWithErrorableValue<Member[]> | null>({
|
||||
key: 'selectedGuildMembersState',
|
||||
default: null
|
||||
});
|
||||
|
||||
export const selectedGuildWithChannelsState = atom<GuildWithErrorableValue<Channel[]> | null>({
|
||||
key: 'selectedGuildChannelsState',
|
||||
default: null
|
||||
});
|
||||
|
||||
export const selectedGuildWithActiveChannelIdState = atom<GuildWithValue<string | null> | null>({
|
||||
key: 'selectedGuildWithActiveChannelIdState',
|
||||
default: null
|
||||
});
|
||||
|
||||
|
||||
export const selectedGuildWithActiveChannelMessagesState = atom<GuildWithValue<ChannelWithErrorableValue<Message[]> | null> | null>({
|
||||
key: 'selectedGuildWithActiveChannelMessagesState',
|
||||
default: null
|
||||
});
|
||||
|
||||
export const selectedGuildWithActiveChannelState = selector<GuildWithValue<Channel> | null>({
|
||||
key: 'selectedGuildActiveChannelState',
|
||||
get: ({ get }) => {
|
||||
const guildWithChannelMessages = get(selectedGuildWithActiveChannelMessagesState);
|
||||
if (guildWithChannelMessages === null || guildWithChannelMessages.value === null) return null;
|
||||
|
||||
return { guild: guildWithChannelMessages.guild, value: guildWithChannelMessages.value.channel };
|
||||
}
|
||||
});
|
||||
|
@ -3,33 +3,36 @@ const electronConsole = electronRemote.getGlobal('console') as Console;
|
||||
import Logger from '../../../../logger/logger';
|
||||
const LOG = Logger.create(__filename, electronConsole);
|
||||
|
||||
import React, { FC, RefObject, useCallback, useEffect } from "react";
|
||||
import { useCloseWhenEscapeOrClickedOrContextOutsideEffect } from '../require/react-helper';
|
||||
import React, { FC, ReactNode, RefObject, useCallback, useEffect } from "react";
|
||||
import { useActionWhenEscapeOrClickedOrContextOutsideEffect } from '../require/react-helper';
|
||||
import { overlayState } from '../atoms';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
interface OverlayProps {
|
||||
childRootRef?: RefObject<HTMLElement>; // clicks outside this ref will close the overlay
|
||||
close: () => void;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
const Overlay: FC<OverlayProps> = (props: OverlayProps) => {
|
||||
const { childRootRef, close, children } = props;
|
||||
const { childRootRef, children } = props;
|
||||
|
||||
const setOverlay = useSetRecoilState<ReactNode>(overlayState);
|
||||
|
||||
if (childRootRef) {
|
||||
useCloseWhenEscapeOrClickedOrContextOutsideEffect(childRootRef, close);
|
||||
useActionWhenEscapeOrClickedOrContextOutsideEffect(childRootRef, () => setOverlay(null));
|
||||
}
|
||||
|
||||
const keyDownHandler = useCallback((e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
close()
|
||||
setOverlay(null)
|
||||
}
|
||||
}, [ close ]);
|
||||
}, [ setOverlay ]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('keydown', keyDownHandler);
|
||||
return () => {
|
||||
window.removeEventListener('keydown', keyDownHandler);
|
||||
}
|
||||
}, []);
|
||||
}, [ keyDownHandler ]);
|
||||
|
||||
return <div className="overlay">{children}</div>
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { DependencyList, FC, ReactNode, RefObject, useRef } from 'react'
|
||||
import { IAlignment } from '../../require/elements-util';
|
||||
import { useCloseWhenEscapeOrClickedOrContextOutsideEffect } from '../../require/react-helper';
|
||||
import { useActionWhenEscapeOrClickedOrContextOutsideEffect } from '../../require/react-helper';
|
||||
import Context from './context';
|
||||
|
||||
export interface ContextMenuProps {
|
||||
@ -18,7 +18,7 @@ const ContextMenu: FC<ContextMenuProps> = (props: ContextMenuProps) => {
|
||||
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useCloseWhenEscapeOrClickedOrContextOutsideEffect(rootRef, close);
|
||||
useActionWhenEscapeOrClickedOrContextOutsideEffect(rootRef, close);
|
||||
|
||||
return (
|
||||
<Context
|
||||
|
@ -1,6 +1,8 @@
|
||||
import React, { Dispatch, FC, ReactNode, RefObject, SetStateAction, useCallback, useMemo } from 'react';
|
||||
import React, { FC, ReactNode, RefObject, useCallback, useMemo } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { Member } from '../../data-types';
|
||||
import CombinedGuild from '../../guild-combined';
|
||||
import { overlayState } from '../atoms';
|
||||
import PersonalizeOverlay from '../overlays/overlay-personalize';
|
||||
import { SubscriptionResult } from '../require/guild-subscriptions';
|
||||
import ContextMenu from './components/context-menu';
|
||||
@ -10,11 +12,12 @@ export interface ConnectionInfoContextMenuProps {
|
||||
selfMemberResult: SubscriptionResult<Member>;
|
||||
relativeToRef: RefObject<HTMLElement>;
|
||||
close: () => void;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const ConnectionInfoContextMenu: FC<ConnectionInfoContextMenuProps> = (props: ConnectionInfoContextMenuProps) => {
|
||||
const { guild, selfMemberResult, relativeToRef, close, setOverlay } = props;
|
||||
const { guild, selfMemberResult, relativeToRef, close } = props;
|
||||
|
||||
const setOverlay = useSetRecoilState<ReactNode>(overlayState)
|
||||
|
||||
const setSelfStatus = useCallback(async (status: string) => {
|
||||
if (selfMemberResult.value.status !== status) {
|
||||
@ -36,7 +39,7 @@ const ConnectionInfoContextMenu: FC<ConnectionInfoContextMenuProps> = (props: Co
|
||||
|
||||
const openPersonalize = useCallback(() => {
|
||||
close();
|
||||
setOverlay(<PersonalizeOverlay guild={guild} selfMemberResult={selfMemberResult} close={() => setOverlay(null)} />);
|
||||
setOverlay(<PersonalizeOverlay guild={guild} selfMemberResult={selfMemberResult} />);
|
||||
}, [ guild, selfMemberResult, close ]);
|
||||
|
||||
const alignment = useMemo(() => {
|
||||
|
@ -1,6 +1,8 @@
|
||||
import React, { Dispatch, FC, ReactNode, RefObject, SetStateAction, useCallback, useMemo } from 'react';
|
||||
import React, { FC, ReactNode, RefObject, useCallback, useMemo } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { GuildMetadata, Member } from '../../data-types';
|
||||
import CombinedGuild from '../../guild-combined';
|
||||
import { overlayState } from '../atoms';
|
||||
import ChannelOverlay from '../overlays/overlay-channel';
|
||||
import GuildSettingsOverlay from '../overlays/overlay-guild-settings';
|
||||
import BaseElements from '../require/base-elements';
|
||||
@ -13,20 +15,21 @@ export interface GuildTitleContextMenuProps {
|
||||
guild: CombinedGuild;
|
||||
guildMetaResult: SubscriptionResult<GuildMetadata>;
|
||||
selfMember: Member;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const GuildTitleContextMenu: FC<GuildTitleContextMenuProps> = (props: GuildTitleContextMenuProps) => {
|
||||
const { close, relativeToRef, guild, guildMetaResult, selfMember, setOverlay } = props;
|
||||
const { close, relativeToRef, guild, guildMetaResult, selfMember } = props;
|
||||
|
||||
const setOverlay = useSetRecoilState<ReactNode>(overlayState);
|
||||
|
||||
const openGuildSettings = useCallback(() => {
|
||||
close();
|
||||
setOverlay(<GuildSettingsOverlay guild={guild} guildMetaResult={guildMetaResult} close={() => setOverlay(null)} />);
|
||||
setOverlay(<GuildSettingsOverlay guild={guild} guildMetaResult={guildMetaResult} />);
|
||||
}, [ guild, guildMetaResult, close ]);
|
||||
|
||||
const openCreateChannel = useCallback(() => {
|
||||
close();
|
||||
setOverlay(<ChannelOverlay guild={guild} close={() => setOverlay(null)} />);
|
||||
setOverlay(<ChannelOverlay guild={guild} />);
|
||||
}, [ guild, close ]);
|
||||
|
||||
const guildSettingsElement = useMemo(() => {
|
||||
|
@ -10,11 +10,10 @@ export interface ChannelListProps {
|
||||
channelsFetchError: unknown | null;
|
||||
activeChannel: Channel | null;
|
||||
setActiveChannel: Dispatch<SetStateAction<Channel | null>>;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const ChannelList: FC<ChannelListProps> = (props: ChannelListProps) => {
|
||||
const { guild, selfMember, channels, channelsFetchError, activeChannel, setActiveChannel, setOverlay } = props;
|
||||
const { guild, selfMember, channels, channelsFetchError, activeChannel, setActiveChannel } = props;
|
||||
|
||||
const hasModifyPrivilege = selfMember && selfMember.privileges.includes('modify_channels');
|
||||
|
||||
@ -35,7 +34,6 @@ const ChannelList: FC<ChannelListProps> = (props: ChannelListProps) => {
|
||||
selfMember={selfMember}
|
||||
channel={channel} activeChannel={activeChannel}
|
||||
setActiveChannel={() => { setActiveChannel(channel); }}
|
||||
setOverlay={setOverlay}
|
||||
/>
|
||||
));
|
||||
}, [ selfMember, channelsFetchError, channels, guild, selfMember, activeChannel ]);
|
||||
|
@ -10,6 +10,8 @@ import ChannelOverlay from '../../overlays/overlay-channel';
|
||||
import BaseElements from '../../require/base-elements';
|
||||
import { useContextHover } from '../../require/react-helper';
|
||||
import BasicHover, { BasicHoverSide } from '../../contexts/context-hover-basic';
|
||||
import { overlayState } from '../../atoms';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
export interface ChannelElementProps {
|
||||
guild: CombinedGuild;
|
||||
@ -17,14 +19,15 @@ export interface ChannelElementProps {
|
||||
selfMember: Member; // Note: Expected to use this later since it may not be best to have css-based hiding
|
||||
activeChannel: Channel | null;
|
||||
setActiveChannel: Dispatch<SetStateAction<Channel | null>>;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const ChannelElement: FC<ChannelElementProps> = (props: ChannelElementProps) => {
|
||||
const { guild, channel, selfMember, activeChannel, setActiveChannel, setOverlay } = props;
|
||||
const { guild, channel, selfMember, activeChannel, setActiveChannel } = props;
|
||||
|
||||
const modifyRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const setOverlay = useSetRecoilState<ReactNode>(overlayState);
|
||||
|
||||
const baseClassName = activeChannel?.id === channel.id ? 'channel text active' : 'channel text';
|
||||
|
||||
const [ modifyContextHover, modifyMouseEnterCallable, modifyMouseLeaveCallable ] = useContextHover(
|
||||
@ -46,7 +49,7 @@ const ChannelElement: FC<ChannelElementProps> = (props: ChannelElementProps) =>
|
||||
}, [ modifyRef, channel ]);
|
||||
|
||||
const launchModify = useCallback(() => {
|
||||
setOverlay(<ChannelOverlay guild={guild} channel={channel} close={() => { setOverlay(null); }} />);
|
||||
setOverlay(<ChannelOverlay guild={guild} channel={channel} />);
|
||||
}, [ guild, channel ]);
|
||||
|
||||
return (
|
||||
|
@ -1,7 +1,9 @@
|
||||
import moment from 'moment';
|
||||
import React, { Dispatch, FC, ReactNode, SetStateAction, useCallback, useMemo } from 'react';
|
||||
import React, { FC, ReactNode, useCallback, useMemo } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { Member, Message } from '../../../data-types';
|
||||
import CombinedGuild from '../../../guild-combined';
|
||||
import { overlayState } from '../../atoms';
|
||||
import ImageContextMenu from '../../contexts/context-menu-image';
|
||||
import ImageOverlay from '../../overlays/overlay-image';
|
||||
import ElementsUtil, { IAlignment } from '../../require/elements-util';
|
||||
@ -47,11 +49,12 @@ interface PreviewImageElementProps {
|
||||
resourceId: string;
|
||||
resourceName: string;
|
||||
resourceIdGuild: CombinedGuild;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const PreviewImageElement: FC<PreviewImageElementProps> = (props: PreviewImageElementProps) => {
|
||||
const { guild, previewWidth, previewHeight, resourcePreviewId, resourceId, resourceName, resourceIdGuild, setOverlay } = props;
|
||||
const { guild, previewWidth, previewHeight, resourcePreviewId, resourceId, resourceName, resourceIdGuild } = props;
|
||||
|
||||
const setOverlay = useSetRecoilState<ReactNode>(overlayState);
|
||||
|
||||
// TODO: Handle resourceError
|
||||
const [ previewImgSrc, previewResourceResult, previewResourceError ] = useSoftImageSrcResourceSubscription(guild, resourcePreviewId, resourceIdGuild);
|
||||
@ -67,7 +70,7 @@ const PreviewImageElement: FC<PreviewImageElementProps> = (props: PreviewImageEl
|
||||
}, [ previewResourceResult, resourceName ]);
|
||||
|
||||
const openImageOverlay = useCallback(() => {
|
||||
setOverlay(<ImageOverlay guild={guild} resourceId={resourceId} resourceName={resourceName} resourceIdGuild={resourceIdGuild} close={() => setOverlay(null)} />);
|
||||
setOverlay(<ImageOverlay guild={guild} resourceId={resourceId} resourceName={resourceName} resourceIdGuild={resourceIdGuild} />);
|
||||
}, [ guild, resourceId, resourceName ]);
|
||||
|
||||
return (
|
||||
@ -86,11 +89,10 @@ export interface MessageElementProps {
|
||||
message: Message;
|
||||
prevMessage: Message | null;
|
||||
messageGuild: CombinedGuild;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const MessageElement: FC<MessageElementProps> = (props: MessageElementProps) => {
|
||||
const { guild, message, prevMessage, messageGuild, setOverlay } = props;
|
||||
const { guild, message, prevMessage, messageGuild } = props;
|
||||
|
||||
const className = useMemo(() => {
|
||||
return message.isContinued(prevMessage) ? 'message-react continued' : 'message-react';
|
||||
@ -146,7 +148,6 @@ const MessageElement: FC<MessageElementProps> = (props: MessageElementProps) =>
|
||||
resourceId={message.resourceId}
|
||||
resourceIdGuild={messageGuild}
|
||||
resourceName={message.resourceName ?? 'unknown.unk'}
|
||||
setOverlay={setOverlay}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
@ -10,11 +10,10 @@ interface MessageListProps {
|
||||
channel: Channel;
|
||||
channelGuild: CombinedGuild;
|
||||
setFetchRetryCallable: Dispatch<SetStateAction<(() => Promise<void>) | null>>;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const MessageList: FC<MessageListProps> = (props: MessageListProps) => {
|
||||
const { guild, channel, channelGuild, setFetchRetryCallable, setOverlay } = props;
|
||||
const { guild, channel, channelGuild, setFetchRetryCallable } = props;
|
||||
|
||||
const infiniteScrollElementRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@ -46,7 +45,7 @@ const MessageList: FC<MessageListProps> = (props: MessageListProps) => {
|
||||
for (let i = 0; i < messagesResult.value.elements.length; ++i) {
|
||||
const prevMessage = messagesResult.value.elements[i - 1] ?? null;
|
||||
const message = messagesResult.value.elements[i] as Message;
|
||||
result.push(<MessageElement key={guild.id + message.id} guild={guild} message={message} prevMessage={prevMessage} messageGuild={messagesResult.guild} setOverlay={setOverlay} />);
|
||||
result.push(<MessageElement key={guild.id + message.id} guild={guild} message={message} prevMessage={prevMessage} messageGuild={messagesResult.guild} />);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -3,7 +3,7 @@ const electronConsole = electronRemote.getGlobal('console') as Console;
|
||||
import Logger from '../../../../logger/logger';
|
||||
const LOG = Logger.create(__filename, electronConsole);
|
||||
|
||||
import React, { Dispatch, FC, SetStateAction, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import React, { Dispatch, FC, ReactNode, SetStateAction, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import GuildsManager from '../../guilds-manager';
|
||||
import moment from 'moment';
|
||||
import TextInput from '../components/input-text';
|
||||
@ -17,6 +17,8 @@ import { useAsyncSubmitButton, useOneTimeAsyncAction } from '../require/react-he
|
||||
import * as fs from 'fs/promises';
|
||||
import Button from '../components/button';
|
||||
import Overlay from '../components/overlay';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { overlayState } from '../atoms';
|
||||
|
||||
export interface IAddGuildData {
|
||||
name: string,
|
||||
@ -53,13 +55,13 @@ export interface AddGuildOverlayProps {
|
||||
guildsManager: GuildsManager;
|
||||
addGuildData: IAddGuildData;
|
||||
setActiveGuild: Dispatch<SetStateAction<CombinedGuild | null>>;
|
||||
close: () => void;
|
||||
}
|
||||
|
||||
const AddGuildOverlay: FC<AddGuildOverlayProps> = (props: AddGuildOverlayProps) => {
|
||||
const { guildsManager, addGuildData, setActiveGuild, close } = props;
|
||||
const { guildsManager, addGuildData, setActiveGuild } = props;
|
||||
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
const setOverlay = useSetRecoilState<ReactNode>(overlayState);
|
||||
|
||||
const expired = addGuildData.expires && addGuildData.expires < new Date().getTime();
|
||||
const exampleDisplayName = useMemo(() => getExampleDisplayName(), []);
|
||||
@ -108,10 +110,10 @@ const AddGuildOverlay: FC<AddGuildOverlayProps> = (props: AddGuildOverlayProps)
|
||||
|
||||
setActiveGuild(newGuild);
|
||||
|
||||
close();
|
||||
setOverlay(null);
|
||||
return { result: newGuild, errorMessage: null };
|
||||
},
|
||||
[ displayName, avatarBuff, displayNameInputValid, avatarInputValid, close ]
|
||||
[ displayName, avatarBuff, displayNameInputValid, avatarInputValid, setOverlay ]
|
||||
);
|
||||
|
||||
const errorMessage = useMemo(() => {
|
||||
@ -121,7 +123,7 @@ const AddGuildOverlay: FC<AddGuildOverlayProps> = (props: AddGuildOverlayProps)
|
||||
}, [ validationErrorMessage, submitFailMessage ]);
|
||||
|
||||
return (
|
||||
<Overlay childRootRef={rootRef} close={close} >
|
||||
<Overlay childRootRef={rootRef}>
|
||||
<div ref={rootRef} className="content add-guild">
|
||||
<InvitePreview
|
||||
name={addGuildData.name} iconSrc={addGuildData.iconSrc}
|
||||
|
@ -3,7 +3,7 @@ const electronConsole = electronRemote.getGlobal('console') as Console;
|
||||
import Logger from '../../../../logger/logger';
|
||||
const LOG = Logger.create(__filename, electronConsole);
|
||||
|
||||
import React, { FC, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import React, { FC, ReactNode, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import CombinedGuild from '../../guild-combined';
|
||||
import BaseElements from '../require/base-elements';
|
||||
import TextInput from '../components/input-text';
|
||||
@ -13,18 +13,21 @@ import { Channel } from '../../data-types';
|
||||
import { useAsyncSubmitButton } from '../require/react-helper';
|
||||
import Button from '../components/button';
|
||||
import Overlay from '../components/overlay';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { overlayState } from '../atoms';
|
||||
|
||||
export interface ChannelOverlayProps {
|
||||
guild: CombinedGuild;
|
||||
channel?: Channel;
|
||||
close: () => void;
|
||||
}
|
||||
const ChannelOverlay: FC<ChannelOverlayProps> = (props: ChannelOverlayProps) => {
|
||||
const { guild, channel, close } = props;
|
||||
const { guild, channel } = props;
|
||||
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
const nameInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const setOverlay = useSetRecoilState<ReactNode>(overlayState);
|
||||
|
||||
const [ edited, setEdited ] = useState<boolean>(false);
|
||||
|
||||
const [ name, setName ] = useState<string>(channel?.name ?? '');
|
||||
@ -66,7 +69,7 @@ const ChannelOverlay: FC<ChannelOverlayProps> = (props: ChannelOverlayProps) =>
|
||||
if (validationErrorMessage) return { result: null, errorMessage: 'Invalid input' };
|
||||
|
||||
if (!edited) {
|
||||
close();
|
||||
setOverlay(null);
|
||||
return { result: null, errorMessage: null };
|
||||
}
|
||||
|
||||
@ -82,10 +85,10 @@ const ChannelOverlay: FC<ChannelOverlayProps> = (props: ChannelOverlayProps) =>
|
||||
return { result: null, errorMessage: `Error ${channel ? 'updating' : 'creating'} channel`}
|
||||
}
|
||||
|
||||
close();
|
||||
setOverlay(null);
|
||||
return { result: null, errorMessage: null };
|
||||
},
|
||||
[ edited, validationErrorMessage, name, flavorText, close ],
|
||||
[ edited, validationErrorMessage, name, flavorText, setOverlay ],
|
||||
{ start: channel ? 'Modify Channel' : 'Create Channel' }
|
||||
);
|
||||
|
||||
@ -96,7 +99,7 @@ const ChannelOverlay: FC<ChannelOverlayProps> = (props: ChannelOverlayProps) =>
|
||||
}, [ validationErrorMessage, submitFailMessage ]);
|
||||
|
||||
return (
|
||||
<Overlay childRootRef={rootRef} close={close} >
|
||||
<Overlay childRootRef={rootRef}>
|
||||
<div ref={rootRef} className="content submit-dialog modify-channel">
|
||||
<div className="preview channel-title">
|
||||
<div className="channel-icon">{BaseElements.TEXT_CHANNEL_ICON}</div>
|
||||
|
@ -4,15 +4,14 @@ import Overlay from '../components/overlay';
|
||||
export interface ErrorMessageOverlayProps {
|
||||
title: string;
|
||||
message: string;
|
||||
close: () => void;
|
||||
}
|
||||
const ErrorMessageOverlay: FC<ErrorMessageOverlayProps> = (props: ErrorMessageOverlayProps) => {
|
||||
const { title, message, close } = props;
|
||||
const { title, message } = props;
|
||||
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
return (
|
||||
<Overlay childRootRef={rootRef} close={close}>
|
||||
<Overlay childRootRef={rootRef}>
|
||||
<div ref={rootRef} className="content error-message">
|
||||
<div className="icon">
|
||||
<img src="./img/error.png" alt="error" />
|
||||
|
@ -10,10 +10,9 @@ import { SubscriptionResult } from '../require/guild-subscriptions';
|
||||
export interface GuildSettingsOverlayProps {
|
||||
guild: CombinedGuild;
|
||||
guildMetaResult: SubscriptionResult<GuildMetadata>;
|
||||
close: () => void;
|
||||
}
|
||||
const GuildSettingsOverlay: FC<GuildSettingsOverlayProps> = (props: GuildSettingsOverlayProps) => {
|
||||
const { guild, guildMetaResult, close } = props;
|
||||
const { guild, guildMetaResult } = props;
|
||||
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@ -27,7 +26,7 @@ const GuildSettingsOverlay: FC<GuildSettingsOverlayProps> = (props: GuildSetting
|
||||
}, [ selectedId ]);
|
||||
|
||||
return (
|
||||
<Overlay childRootRef={rootRef} close={close}>
|
||||
<Overlay childRootRef={rootRef}>
|
||||
<div ref={rootRef} className="content display-swapper guild-settings">
|
||||
<ChoicesControl title={guildMetaResult.value.name} selectedId={selectedId} setSelectedId={setSelectedId} choices={[
|
||||
{ id: 'overview', display: 'Overview' },
|
||||
|
@ -17,11 +17,10 @@ export interface ImageOverlayProps {
|
||||
resourceId: string;
|
||||
resourceName: string;
|
||||
resourceIdGuild: CombinedGuild;
|
||||
close: () => void;
|
||||
}
|
||||
|
||||
const ImageOverlay: FC<ImageOverlayProps> = (props: ImageOverlayProps) => {
|
||||
const { guild, resourceId, resourceName, resourceIdGuild, close } = props;
|
||||
const { guild, resourceId, resourceName, resourceIdGuild } = props;
|
||||
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@ -43,7 +42,7 @@ const ImageOverlay: FC<ImageOverlayProps> = (props: ImageOverlayProps) => {
|
||||
);
|
||||
|
||||
return (
|
||||
<Overlay childRootRef={rootRef} close={close}>
|
||||
<Overlay childRootRef={rootRef}>
|
||||
<div ref={rootRef} className="content popup-image">
|
||||
<img src={imgSrc} alt={resourceName} title={resourceName} onContextMenu={onContextMenu}></img>
|
||||
<div className="download">
|
||||
|
@ -3,7 +3,7 @@ const electronConsole = electronRemote.getGlobal('console') as Console;
|
||||
import Logger from '../../../../logger/logger';
|
||||
const LOG = Logger.create(__filename, electronConsole);
|
||||
|
||||
import React, { createRef, FC, MutableRefObject, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import React, { createRef, FC, MutableRefObject, ReactNode, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Member } from '../../data-types';
|
||||
import Globals from '../../globals';
|
||||
import CombinedGuild from '../../guild-combined';
|
||||
@ -14,14 +14,17 @@ import { useAsyncSubmitButton } from '../require/react-helper';
|
||||
import Button from '../components/button';
|
||||
import Overlay from '../components/overlay';
|
||||
import { SubscriptionResult, useResourceSubscription } from '../require/guild-subscriptions';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { overlayState } from '../atoms';
|
||||
|
||||
export interface PersonalizeOverlayProps {
|
||||
guild: CombinedGuild;
|
||||
selfMemberResult: SubscriptionResult<Member>;
|
||||
close: () => void;
|
||||
}
|
||||
const PersonalizeOverlay: FC<PersonalizeOverlayProps> = (props: PersonalizeOverlayProps) => {
|
||||
const { guild, selfMemberResult, close } = props;
|
||||
const { guild, selfMemberResult } = props;
|
||||
|
||||
const setOverlay = useSetRecoilState<ReactNode>(overlayState);
|
||||
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@ -93,10 +96,11 @@ const PersonalizeOverlay: FC<PersonalizeOverlayProps> = (props: PersonalizeOverl
|
||||
}
|
||||
}
|
||||
|
||||
close();
|
||||
// Close the overlay
|
||||
setOverlay(null);
|
||||
return { result: null, errorMessage: null };
|
||||
},
|
||||
[ validationErrorMessage, displayName, savedDisplayName, avatarBuff, savedAvatarBuff, close ]
|
||||
[ validationErrorMessage, displayName, savedDisplayName, avatarBuff, savedAvatarBuff, setOverlay ]
|
||||
);
|
||||
|
||||
//if (saveFailed) return 'Unable to save personalization';
|
||||
@ -107,7 +111,7 @@ const PersonalizeOverlay: FC<PersonalizeOverlayProps> = (props: PersonalizeOverl
|
||||
}, [ validationErrorMessage, submitFailMessage ]);
|
||||
|
||||
return (
|
||||
<Overlay childRootRef={rootRef} close={close}>
|
||||
<Overlay childRootRef={rootRef}>
|
||||
<div ref={rootRef} className="content personalize">
|
||||
<div className="personalization">
|
||||
<div className="avatar">
|
||||
|
@ -323,7 +323,7 @@ export function useColumnReverseInfiniteScroll(
|
||||
|
||||
// Makes sure to also allow you to fly-out a click starting inside of the ref'd element but was dragged outside
|
||||
/** Calls the close action when you hit escape or click outside of the ref element */
|
||||
export function useCloseWhenEscapeOrClickedOrContextOutsideEffect(ref: RefObject<HTMLElement>, close: () => void) {
|
||||
export function useActionWhenEscapeOrClickedOrContextOutsideEffect(ref: RefObject<HTMLElement>, actionFunc: () => void) {
|
||||
// Have to use a ref here and not states since we can't re-assign state between mouseup and click
|
||||
const mouseRef = useRef<{ mouseDownTarget: Node | null, mouseUpTarget: Node | null}>({ mouseDownTarget: null, mouseUpTarget: null });
|
||||
|
||||
@ -337,8 +337,8 @@ export function useCloseWhenEscapeOrClickedOrContextOutsideEffect(ref: RefObject
|
||||
|
||||
if (mouseRef.current.mouseDownTarget !== null || mouseRef.current.mouseUpTarget !== null) return;
|
||||
|
||||
close();
|
||||
}, [ ref, mouseRef, close ]);
|
||||
actionFunc();
|
||||
}, [ ref, mouseRef, actionFunc ]);
|
||||
|
||||
const handleMouseDown = useCallback((event: MouseEvent) => {
|
||||
if (!ref.current) return;
|
||||
@ -364,14 +364,14 @@ export function useCloseWhenEscapeOrClickedOrContextOutsideEffect(ref: RefObject
|
||||
if (!ref.current) return;
|
||||
if (ref.current.contains(event.target as Node)) return;
|
||||
// Context menu is fired on mouse-down so no need to do special checks.
|
||||
close();
|
||||
actionFunc();
|
||||
}, [ ref ]);
|
||||
|
||||
const handleKeyDown = useCallback((event: KeyboardEvent) => {
|
||||
if (!ref.current) return;
|
||||
if (event.key !== 'Escape') return;
|
||||
|
||||
close();
|
||||
actionFunc();
|
||||
}, [ ref ]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -1,5 +1,7 @@
|
||||
import React, { FC, ReactNode, useState } from 'react';
|
||||
import React, { FC, ReactNode } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import GuildsManager from '../guilds-manager';
|
||||
import { overlayState } from './atoms';
|
||||
import GuildsManagerElement from './sections/guilds-manager';
|
||||
import TitleBar from './sections/title-bar';
|
||||
|
||||
@ -10,15 +12,16 @@ export interface RootElementProps {
|
||||
const RootElement: FC<RootElementProps> = (props: RootElementProps) => {
|
||||
const { guildsManager } = props;
|
||||
|
||||
const [ overlay, setOverlay ] = useState<ReactNode>(null);
|
||||
const [ overlay, setOverlay ] = useRecoilState<ReactNode>(overlayState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<TitleBar />
|
||||
<GuildsManagerElement guildsManager={guildsManager} setOverlay={setOverlay} />
|
||||
<GuildsManagerElement guildsManager={guildsManager} />
|
||||
<div className="react-overlays">{overlay}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default RootElement;
|
||||
|
||||
|
@ -9,11 +9,10 @@ import { isNonNullAndHasValue, SubscriptionResult } from '../require/guild-subsc
|
||||
export interface ConnectionInfoProps {
|
||||
guild: CombinedGuild;
|
||||
selfMemberResult: SubscriptionResult<Member | null> | null;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const ConnectionInfo: FC<ConnectionInfoProps> = (props: ConnectionInfoProps) => {
|
||||
const { guild, selfMemberResult, setOverlay } = props;
|
||||
const { guild, selfMemberResult } = props;
|
||||
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@ -35,7 +34,7 @@ const ConnectionInfo: FC<ConnectionInfoProps> = (props: ConnectionInfoProps) =>
|
||||
return (
|
||||
<ConnectionInfoContextMenu
|
||||
guild={guild} selfMemberResult={selfMemberResult} relativeToRef={rootRef}
|
||||
close={close} setOverlay={setOverlay}
|
||||
close={close}
|
||||
/>
|
||||
);
|
||||
}, [ guild, selfMemberResult, rootRef ]);
|
||||
|
@ -13,20 +13,23 @@ import AddGuildOverlay from '../overlays/overlay-add-guild';
|
||||
import ErrorMessageOverlay from '../overlays/overlay-error-message';
|
||||
import BasicHover, { BasicHoverSide } from '../contexts/context-hover-basic';
|
||||
import BaseElements from '../require/base-elements';
|
||||
import { overlayState } from '../atoms';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
export interface GuildListContainerProps {
|
||||
guildsManager: GuildsManager;
|
||||
guilds: CombinedGuild[];
|
||||
activeGuild: CombinedGuild | null;
|
||||
setActiveGuild: Dispatch<SetStateAction<CombinedGuild | null>>;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const GuildListContainer: FC<GuildListContainerProps> = (props: GuildListContainerProps) => {
|
||||
const { guildsManager, guilds, activeGuild, setActiveGuild, setOverlay } = props;
|
||||
const { guildsManager, guilds, activeGuild, setActiveGuild } = props;
|
||||
|
||||
const addGuildRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const setOverlay = useSetRecoilState<ReactNode>(overlayState);
|
||||
|
||||
const [ contextHover, onMouseEnter, onMouseLeave ] = useContextHover(() => {
|
||||
return (
|
||||
<BasicHover relativeToRef={addGuildRef} realignDeps={[]} side={BasicHoverSide.RIGHT}>
|
||||
@ -66,9 +69,9 @@ const GuildListContainer: FC<GuildListContainerProps> = (props: GuildListContain
|
||||
typeof addGuildData?.iconSrc !== 'string'
|
||||
) {
|
||||
LOG.debug('bad guild data:', { addGuildData, fileText });
|
||||
setOverlay(<ErrorMessageOverlay title="Unable to parse guild file" message="Bad guild data" close={() => setOverlay(null)} />);
|
||||
setOverlay(<ErrorMessageOverlay title="Unable to parse guild file" message="Bad guild data" />);
|
||||
} else {
|
||||
setOverlay(<AddGuildOverlay guildsManager={guildsManager} addGuildData={addGuildData} setActiveGuild={setActiveGuild} close={() => setOverlay(null)} />);
|
||||
setOverlay(<AddGuildOverlay guildsManager={guildsManager} addGuildData={addGuildData} setActiveGuild={setActiveGuild} />);
|
||||
}
|
||||
}, [ guildsManager ]);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { Dispatch, FC, ReactNode, SetStateAction, useMemo, useRef } from 'react';
|
||||
import React, { FC, useMemo, useRef } from 'react';
|
||||
import { GuildMetadata, Member } from '../../data-types';
|
||||
import CombinedGuild from '../../guild-combined';
|
||||
import GuildTitleContextMenu from '../contexts/context-menu-guild-title';
|
||||
@ -9,11 +9,10 @@ export interface GuildTitleProps {
|
||||
guild: CombinedGuild;
|
||||
guildMetaResult: SubscriptionResult<GuildMetadata | null> | null;
|
||||
selfMemberResult: SubscriptionResult<Member | null> | null;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const GuildTitle: FC<GuildTitleProps> = (props: GuildTitleProps) => {
|
||||
const { guild, guildMetaResult, selfMemberResult, setOverlay } = props;
|
||||
const { guild, guildMetaResult, selfMemberResult } = props;
|
||||
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@ -33,7 +32,6 @@ const GuildTitle: FC<GuildTitleProps> = (props: GuildTitleProps) => {
|
||||
<GuildTitleContextMenu
|
||||
relativeToRef={rootRef} close={close}
|
||||
guild={guild} guildMetaResult={guildMetaResult} selfMember={selfMemberResult.value}
|
||||
setOverlay={setOverlay}
|
||||
/>
|
||||
);
|
||||
}, [ guild, guildMetaResult, selfMemberResult, rootRef ]);
|
||||
|
@ -3,7 +3,7 @@ const electronConsole = electronRemote.getGlobal('console') as Console;
|
||||
import Logger from '../../../../logger/logger';
|
||||
const LOG = Logger.create(__filename, electronConsole);
|
||||
|
||||
import React, { Dispatch, FC, ReactNode, SetStateAction, useCallback, useEffect, useState } from 'react';
|
||||
import React, { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { Channel, Message } from '../../data-types';
|
||||
import CombinedGuild from '../../guild-combined';
|
||||
import ChannelList from '../lists/channel-list';
|
||||
@ -17,11 +17,10 @@ import SendMessage from './send-message';
|
||||
|
||||
export interface GuildElementProps {
|
||||
guild: CombinedGuild;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const GuildElement: FC<GuildElementProps> = (props: GuildElementProps) => {
|
||||
const { guild, setOverlay } = props;
|
||||
const { guild } = props;
|
||||
|
||||
// TODO: Handle fetch errors by allowing for retry
|
||||
// TODO: Handle fetch errors in message list
|
||||
@ -84,20 +83,19 @@ const GuildElement: FC<GuildElementProps> = (props: GuildElementProps) => {
|
||||
return (
|
||||
<div className="guild-react">
|
||||
<div className="guild-sidebar">
|
||||
<GuildTitle guild={guild} selfMemberResult={selfMemberResult} guildMetaResult={guildMetaResult} setOverlay={setOverlay} />
|
||||
<GuildTitle guild={guild} selfMemberResult={selfMemberResult} guildMetaResult={guildMetaResult} />
|
||||
<ChannelList
|
||||
guild={guild} selfMember={selfMemberResult?.value ?? null}
|
||||
channels={channelsResult?.value ?? null} channelsFetchError={channelsFetchError}
|
||||
activeChannel={activeChannel} setActiveChannel={setActiveChannel}
|
||||
setOverlay={setOverlay}
|
||||
/>
|
||||
<ConnectionInfo guild={guild} selfMemberResult={selfMemberResult} setOverlay={setOverlay} />
|
||||
<ConnectionInfo guild={guild} selfMemberResult={selfMemberResult} />
|
||||
</div>
|
||||
<div className="guild-channel">
|
||||
<ChannelTitle channel={activeChannel} />
|
||||
<div className="guild-channel-content">
|
||||
<div className="guild-channel-feed-wrapper">
|
||||
{activeChannel && activeChannelGuild && <MessageList guild={guild} channel={activeChannel} channelGuild={activeChannelGuild} setFetchRetryCallable={setFetchMessagesRetryCallable} setOverlay={setOverlay} />}
|
||||
{activeChannel && activeChannelGuild && <MessageList guild={guild} channel={activeChannel} channelGuild={activeChannelGuild} setFetchRetryCallable={setFetchMessagesRetryCallable} />}
|
||||
{activeChannel && activeChannelGuild && <SendMessage guild={guild} channel={activeChannel} />}
|
||||
</div>
|
||||
<div className="member-list-wrapper">
|
||||
|
@ -7,11 +7,10 @@ import GuildListContainer from './guild-list-container';
|
||||
|
||||
export interface GuildsManagerElementProps {
|
||||
guildsManager: GuildsManager;
|
||||
setOverlay: Dispatch<SetStateAction<ReactNode>>;
|
||||
}
|
||||
|
||||
const GuildsManagerElement: FC<GuildsManagerElementProps> = (props: GuildsManagerElementProps) => {
|
||||
const { guildsManager, setOverlay } = props;
|
||||
const { guildsManager } = props;
|
||||
|
||||
const [ guilds ] = useGuildListSubscription(guildsManager);
|
||||
const [ activeGuild, setActiveGuild ] = useState<CombinedGuild | null>(null);
|
||||
@ -30,9 +29,8 @@ const GuildsManagerElement: FC<GuildsManagerElementProps> = (props: GuildsManage
|
||||
<GuildListContainer
|
||||
guildsManager={guildsManager} guilds={guilds}
|
||||
activeGuild={activeGuild} setActiveGuild={setActiveGuild}
|
||||
setOverlay={setOverlay}
|
||||
/>
|
||||
{activeGuild && <GuildElement guild={activeGuild} setOverlay={setOverlay} />}
|
||||
{activeGuild && <GuildElement guild={activeGuild} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import ResourceRAMCache from './resource-ram-cache';
|
||||
import ReactDOM from 'react-dom';
|
||||
import React from 'react';
|
||||
import RootElement from './elements/root';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
LOG.silly('modules loaded');
|
||||
|
||||
@ -58,7 +59,7 @@ window.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
LOG.silly('guildsManager initialized');
|
||||
|
||||
ReactDOM.render(<RootElement guildsManager={guildsManager} />, document.getElementById('react-root'));
|
||||
ReactDOM.render(<RecoilRoot><RootElement guildsManager={guildsManager} /></RecoilRoot>, document.getElementById('react-root'));
|
||||
})();
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user