Add modal state provider (#125)
This commit is contained in:
parent
03ea71dca4
commit
3be3a7726f
|
@ -19,17 +19,11 @@ export function Chat() {
|
||||||
|
|
||||||
const narrow = useNarrow();
|
const narrow = useNarrow();
|
||||||
|
|
||||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
|
||||||
const showModal = () => setIsModalVisible(true);
|
|
||||||
|
|
||||||
const [isEditVisible, setIsEditVisible] = useState(false);
|
|
||||||
const showEditModal = () => setIsEditVisible(true);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatWrapper>
|
<ChatWrapper>
|
||||||
{!narrow && (
|
{!narrow && (
|
||||||
<ChannelsWrapper>
|
<ChannelsWrapper>
|
||||||
<StyledCommunity onClick={showModal} />
|
<StyledCommunity />
|
||||||
<Channels
|
<Channels
|
||||||
membersList={membersList}
|
membersList={membersList}
|
||||||
groupList={groupList}
|
groupList={groupList}
|
||||||
|
@ -42,8 +36,6 @@ export function Chat() {
|
||||||
<ChatBody
|
<ChatBody
|
||||||
onClick={() => setShowMembers(!showMembers)}
|
onClick={() => setShowMembers(!showMembers)}
|
||||||
showMembers={showMembers}
|
showMembers={showMembers}
|
||||||
onCommunityClick={showModal}
|
|
||||||
onEditClick={showEditModal}
|
|
||||||
membersList={membersList}
|
membersList={membersList}
|
||||||
groupList={groupList}
|
groupList={groupList}
|
||||||
setMembersList={setMembersList}
|
setMembersList={setMembersList}
|
||||||
|
@ -61,15 +53,8 @@ export function Chat() {
|
||||||
setCreateChat={setCreateChat}
|
setCreateChat={setCreateChat}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<CommunityModal
|
<CommunityModal subtitle="Public Community" />
|
||||||
isVisible={isModalVisible}
|
<EditModal />
|
||||||
onClose={() => setIsModalVisible(false)}
|
|
||||||
subtitle="Public Community"
|
|
||||||
/>
|
|
||||||
<EditModal
|
|
||||||
isVisible={isEditVisible}
|
|
||||||
onClose={() => setIsEditVisible(false)}
|
|
||||||
/>
|
|
||||||
</ChatWrapper>
|
</ChatWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,6 @@ enum ChatBodyState {
|
||||||
interface ChatBodyProps {
|
interface ChatBodyProps {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
showMembers: boolean;
|
showMembers: boolean;
|
||||||
onCommunityClick: () => void;
|
|
||||||
onEditClick: () => void;
|
|
||||||
membersList: string[];
|
membersList: string[];
|
||||||
groupList: [][];
|
groupList: [][];
|
||||||
setMembersList: any;
|
setMembersList: any;
|
||||||
|
@ -39,8 +37,6 @@ interface ChatBodyProps {
|
||||||
export function ChatBody({
|
export function ChatBody({
|
||||||
onClick,
|
onClick,
|
||||||
showMembers,
|
showMembers,
|
||||||
onCommunityClick,
|
|
||||||
onEditClick,
|
|
||||||
membersList,
|
membersList,
|
||||||
groupList,
|
groupList,
|
||||||
setMembersList,
|
setMembersList,
|
||||||
|
@ -88,7 +84,7 @@ export function ChatBody({
|
||||||
<>
|
<>
|
||||||
{narrow && (
|
{narrow && (
|
||||||
<CommunityWrap className={className}>
|
<CommunityWrap className={className}>
|
||||||
<Community onClick={onCommunityClick} />
|
<Community />
|
||||||
</CommunityWrap>
|
</CommunityWrap>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -113,7 +109,7 @@ export function ChatBody({
|
||||||
{!narrow && (
|
{!narrow && (
|
||||||
<MemberBtn
|
<MemberBtn
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className={showMembers && !narrow ? "active" : ""}
|
className={showMembers ? "active" : ""}
|
||||||
>
|
>
|
||||||
<MembersIcon />
|
<MembersIcon />
|
||||||
</MemberBtn>
|
</MemberBtn>
|
||||||
|
@ -129,7 +125,6 @@ export function ChatBody({
|
||||||
switchMemberList={() => switchShowState(ChatBodyState.Members)}
|
switchMemberList={() => switchShowState(ChatBodyState.Members)}
|
||||||
setShowChannelMenu={setShowChannelMenu}
|
setShowChannelMenu={setShowChannelMenu}
|
||||||
setEditGroup={setEditGroup}
|
setEditGroup={setEditGroup}
|
||||||
onEditClick={onEditClick}
|
|
||||||
setGroupList={setGroupList}
|
setGroupList={setGroupList}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import styled, { useTheme } from "styled-components";
|
import styled, { useTheme } from "styled-components";
|
||||||
|
|
||||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||||
|
import { useModal } from "../../contexts/modalProvider";
|
||||||
import { useLow } from "../../contexts/narrowProvider";
|
import { useLow } from "../../contexts/narrowProvider";
|
||||||
import { lightTheme, Theme } from "../../styles/themes";
|
import { lightTheme, Theme } from "../../styles/themes";
|
||||||
import { uintToImgUrl } from "../../utils/uintToImgUrl";
|
import { uintToImgUrl } from "../../utils/uintToImgUrl";
|
||||||
|
@ -11,7 +12,7 @@ import { GifIcon } from "../Icons/GifIcon";
|
||||||
import { PictureIcon } from "../Icons/PictureIcon";
|
import { PictureIcon } from "../Icons/PictureIcon";
|
||||||
import { StickerIcon } from "../Icons/StickerIcon";
|
import { StickerIcon } from "../Icons/StickerIcon";
|
||||||
import "emoji-mart/css/emoji-mart.css";
|
import "emoji-mart/css/emoji-mart.css";
|
||||||
import { Modal } from "../Modals/Modal";
|
import { SizeLimitModal, SizeLimitModalName } from "../Modals/SizeLimitModal";
|
||||||
|
|
||||||
export function ChatInput() {
|
export function ChatInput() {
|
||||||
const { sendMessage } = useMessengerContext();
|
const { sendMessage } = useMessengerContext();
|
||||||
|
@ -20,7 +21,6 @@ export function ChatInput() {
|
||||||
const [showEmoji, setShowEmoji] = useState(false);
|
const [showEmoji, setShowEmoji] = useState(false);
|
||||||
const [inputHeight, setInputHeight] = useState(40);
|
const [inputHeight, setInputHeight] = useState(40);
|
||||||
const [imageUint, setImageUint] = useState<undefined | Uint8Array>(undefined);
|
const [imageUint, setImageUint] = useState<undefined | Uint8Array>(undefined);
|
||||||
const [showSizeLimit, setShowSizeLimit] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener("click", () => setShowEmoji(false));
|
window.addEventListener("click", () => setShowEmoji(false));
|
||||||
|
@ -69,16 +69,11 @@ export function ChatInput() {
|
||||||
|
|
||||||
const low = useLow();
|
const low = useLow();
|
||||||
|
|
||||||
|
const { setModal } = useModal(SizeLimitModalName);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<Modal onClose={() => setShowSizeLimit(false)} isVisible={showSizeLimit}>
|
<SizeLimitModal />
|
||||||
<div
|
|
||||||
onClick={() => setShowSizeLimit(false)}
|
|
||||||
style={{ padding: "20px" }}
|
|
||||||
>
|
|
||||||
File size must be less than 1MB
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
{showEmoji && (
|
{showEmoji && (
|
||||||
<div>
|
<div>
|
||||||
<Picker
|
<Picker
|
||||||
|
@ -119,7 +114,7 @@ export function ChatInput() {
|
||||||
if (e.target.files[0].size < 1024 * 1024) {
|
if (e.target.files[0].size < 1024 * 1024) {
|
||||||
fileReader.readAsArrayBuffer(e.target.files[0]);
|
fileReader.readAsArrayBuffer(e.target.files[0]);
|
||||||
} else {
|
} else {
|
||||||
setShowSizeLimit(true);
|
setModal(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import React, { useMemo, useRef, useState } from "react";
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { useBlockedUsers } from "../../contexts/blockedUsersProvider";
|
import { useBlockedUsers } from "../../contexts/blockedUsersProvider";
|
||||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||||
|
import { useModal } from "../../contexts/modalProvider";
|
||||||
import { useChatScrollHandle } from "../../hooks/useChatScrollHandle";
|
import { useChatScrollHandle } from "../../hooks/useChatScrollHandle";
|
||||||
import { ChatMessage } from "../../models/ChatMessage";
|
import { ChatMessage } from "../../models/ChatMessage";
|
||||||
import { equalDate } from "../../utils";
|
import { equalDate } from "../../utils";
|
||||||
|
@ -10,8 +11,8 @@ import { EmptyChannel } from "../Channels/EmptyChannel";
|
||||||
import { ContactMenu } from "../Form/ContactMenu";
|
import { ContactMenu } from "../Form/ContactMenu";
|
||||||
import { LoadingIcon } from "../Icons/LoadingIcon";
|
import { LoadingIcon } from "../Icons/LoadingIcon";
|
||||||
import { UserIcon } from "../Icons/UserIcon";
|
import { UserIcon } from "../Icons/UserIcon";
|
||||||
import { LinkModal } from "../Modals/LinkModal";
|
import { LinkModal, LinkModalName } from "../Modals/LinkModal";
|
||||||
import { PictureModal } from "../Modals/PictureModal";
|
import { PictureModal, PictureModalName } from "../Modals/PictureModal";
|
||||||
import { textSmallStyles } from "../Text";
|
import { textSmallStyles } from "../Text";
|
||||||
|
|
||||||
import { ChatMessageContent } from "./ChatMessageContent";
|
import { ChatMessageContent } from "./ChatMessageContent";
|
||||||
|
@ -84,14 +85,17 @@ export function ChatMessages() {
|
||||||
|
|
||||||
const [image, setImage] = useState("");
|
const [image, setImage] = useState("");
|
||||||
const [link, setLink] = useState("");
|
const [link, setLink] = useState("");
|
||||||
|
|
||||||
|
const { setModal: setPictureModal } = useModal(PictureModalName);
|
||||||
|
const { setModal: setLinkModal } = useModal(LinkModalName);
|
||||||
|
|
||||||
|
useEffect(() => (!image ? undefined : setPictureModal(true)), [image]);
|
||||||
|
useEffect(() => (!link ? undefined : setLinkModal(true)), [link]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MessagesWrapper ref={ref}>
|
<MessagesWrapper ref={ref}>
|
||||||
<PictureModal
|
<PictureModal image={image} />
|
||||||
isVisible={!!image}
|
<LinkModal link={link} />
|
||||||
onClose={() => setImage("")}
|
|
||||||
image={image}
|
|
||||||
/>
|
|
||||||
<LinkModal isVisible={!!link} onClose={() => setLink("")} link={link} />
|
|
||||||
<EmptyChannel channel={activeChannel} />
|
<EmptyChannel channel={activeChannel} />
|
||||||
{loadingMessages && (
|
{loadingMessages && (
|
||||||
<LoadingWrapper>
|
<LoadingWrapper>
|
||||||
|
|
|
@ -2,17 +2,19 @@ import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { useMessengerContext } from "../contexts/messengerProvider";
|
import { useMessengerContext } from "../contexts/messengerProvider";
|
||||||
|
import { useModal } from "../contexts/modalProvider";
|
||||||
|
|
||||||
import { CommunityIdentity } from "./CommunityIdentity";
|
import { CommunityIdentity } from "./CommunityIdentity";
|
||||||
|
import { CommunityModalName } from "./Modals/CommunityModal";
|
||||||
import { CommunitySkeleton } from "./Skeleton/CommunitySkeleton";
|
import { CommunitySkeleton } from "./Skeleton/CommunitySkeleton";
|
||||||
|
|
||||||
interface CommunityProps {
|
interface CommunityProps {
|
||||||
onClick: () => void;
|
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Community({ onClick, className }: CommunityProps) {
|
export function Community({ className }: CommunityProps) {
|
||||||
const { communityData } = useMessengerContext();
|
const { communityData } = useMessengerContext();
|
||||||
|
const { setModal } = useModal(CommunityModalName);
|
||||||
|
|
||||||
if (!communityData) {
|
if (!communityData) {
|
||||||
return (
|
return (
|
||||||
|
@ -24,7 +26,7 @@ export function Community({ onClick, className }: CommunityProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button className={className} onClick={onClick}>
|
<button className={className} onClick={() => setModal(true)}>
|
||||||
<CommunityIdentity subtitle={`${communityData.members} members`} />
|
<CommunityIdentity subtitle={`${communityData.members} members`} />
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||||
|
import { useModal } from "../../contexts/modalProvider";
|
||||||
import { useNarrow } from "../../contexts/narrowProvider";
|
import { useNarrow } from "../../contexts/narrowProvider";
|
||||||
import { ChannelData } from "../../models/ChannelData";
|
import { ChannelData } from "../../models/ChannelData";
|
||||||
import { AddMemberIconSvg } from "../Icons/AddMemberIcon";
|
import { AddMemberIconSvg } from "../Icons/AddMemberIcon";
|
||||||
|
@ -10,6 +11,7 @@ import { EgitGroupSvg } from "../Icons/EditGroupIcon";
|
||||||
import { LeftIconSvg } from "../Icons/LeftIcon";
|
import { LeftIconSvg } from "../Icons/LeftIcon";
|
||||||
import { MembersSmallSvg } from "../Icons/MembersSmallIcon";
|
import { MembersSmallSvg } from "../Icons/MembersSmallIcon";
|
||||||
import { MuteSvg } from "../Icons/MuteIcon";
|
import { MuteSvg } from "../Icons/MuteIcon";
|
||||||
|
import { EditModalName } from "../Modals/EditModal";
|
||||||
|
|
||||||
import { DropdownMenu, MenuItem, MenuText } from "./DropdownMenu";
|
import { DropdownMenu, MenuItem, MenuText } from "./DropdownMenu";
|
||||||
|
|
||||||
|
@ -18,7 +20,6 @@ interface ChannelMenuProps {
|
||||||
switchMemberList: () => void;
|
switchMemberList: () => void;
|
||||||
setShowChannelMenu: (val: boolean) => void;
|
setShowChannelMenu: (val: boolean) => void;
|
||||||
setEditGroup: (val: boolean) => void;
|
setEditGroup: (val: boolean) => void;
|
||||||
onEditClick: () => void;
|
|
||||||
setGroupList: any;
|
setGroupList: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,13 +28,12 @@ export const ChannelMenu = ({
|
||||||
switchMemberList,
|
switchMemberList,
|
||||||
setShowChannelMenu,
|
setShowChannelMenu,
|
||||||
setEditGroup,
|
setEditGroup,
|
||||||
onEditClick,
|
|
||||||
setGroupList,
|
setGroupList,
|
||||||
}: ChannelMenuProps) => {
|
}: ChannelMenuProps) => {
|
||||||
const narrow = useNarrow();
|
const narrow = useNarrow();
|
||||||
const { clearNotifications, setActiveChannel, channels } =
|
const { clearNotifications, setActiveChannel, channels } =
|
||||||
useMessengerContext();
|
useMessengerContext();
|
||||||
|
const { setModal } = useModal(EditModalName);
|
||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
{narrow && (
|
{narrow && (
|
||||||
|
@ -58,7 +58,7 @@ export const ChannelMenu = ({
|
||||||
<AddMemberIconSvg width={16} height={16} />
|
<AddMemberIconSvg width={16} height={16} />
|
||||||
<MenuText>Add / remove from group</MenuText>
|
<MenuText>Add / remove from group</MenuText>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem onClick={onEditClick}>
|
<MenuItem onClick={() => setModal(true)}>
|
||||||
<EgitGroupSvg width={16} height={16} />
|
<EgitGroupSvg width={16} height={16} />
|
||||||
<MenuText>Edit name and image</MenuText>
|
<MenuText>Edit name and image</MenuText>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
|
@ -12,20 +12,18 @@ import { CopyInput } from "../Form/CopyInput";
|
||||||
import { StatusLogo } from "../Icons/StatusLogo";
|
import { StatusLogo } from "../Icons/StatusLogo";
|
||||||
import { textSmallStyles } from "../Text";
|
import { textSmallStyles } from "../Text";
|
||||||
|
|
||||||
import { BasicModalProps, Modal } from "./Modal";
|
import { Modal } from "./Modal";
|
||||||
import { Section, Text } from "./ModalStyle";
|
import { Section, Text } from "./ModalStyle";
|
||||||
|
|
||||||
interface CommunityModalProps extends BasicModalProps, CommunityIdentityProps {}
|
export const CommunityModalName = "CommunityModal";
|
||||||
|
|
||||||
export const CommunityModal = ({
|
type CommunityModalProps = CommunityIdentityProps;
|
||||||
isVisible,
|
|
||||||
onClose,
|
export const CommunityModal = ({ subtitle }: CommunityModalProps) => {
|
||||||
subtitle,
|
|
||||||
}: CommunityModalProps) => {
|
|
||||||
const narrow = useNarrow();
|
const narrow = useNarrow();
|
||||||
const { communityData } = useMessengerContext();
|
const { communityData } = useMessengerContext();
|
||||||
return (
|
return (
|
||||||
<Modal isVisible={isVisible} onClose={onClose}>
|
<Modal name={CommunityModalName}>
|
||||||
<Section>
|
<Section>
|
||||||
<CommunityIdentity subtitle={subtitle} />
|
<CommunityIdentity subtitle={subtitle} />
|
||||||
</Section>
|
</Section>
|
||||||
|
|
|
@ -2,15 +2,18 @@ import React, { useState } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||||
|
import { useModal } from "../../contexts/modalProvider";
|
||||||
import { buttonStyles } from "../Buttons/buttonStyle";
|
import { buttonStyles } from "../Buttons/buttonStyle";
|
||||||
import { ChannelLogo } from "../Channels/Channel";
|
import { ChannelLogo } from "../Channels/Channel";
|
||||||
import { AddIcon } from "../Icons/AddIcon";
|
import { AddIcon } from "../Icons/AddIcon";
|
||||||
import { textMediumStyles } from "../Text";
|
import { textMediumStyles } from "../Text";
|
||||||
|
|
||||||
import { BasicModalProps, Modal } from "./Modal";
|
import { Modal } from "./Modal";
|
||||||
import { Heading, Section } from "./ModalStyle";
|
import { Heading, Section } from "./ModalStyle";
|
||||||
|
|
||||||
export const EditModal = ({ isVisible, onClose }: BasicModalProps) => {
|
export const EditModalName = "editModal";
|
||||||
|
|
||||||
|
export const EditModal = () => {
|
||||||
const { activeChannel } = useMessengerContext();
|
const { activeChannel } = useMessengerContext();
|
||||||
const [groupName, setGroupName] = useState("");
|
const [groupName, setGroupName] = useState("");
|
||||||
const [image, setImage] = useState("");
|
const [image, setImage] = useState("");
|
||||||
|
@ -21,14 +24,16 @@ export const EditModal = ({ isVisible, onClose }: BasicModalProps) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { setModal } = useModal(EditModalName);
|
||||||
|
|
||||||
const handleUpload = () => {
|
const handleUpload = () => {
|
||||||
activeChannel.icon = image;
|
activeChannel.icon = image;
|
||||||
activeChannel.name = groupName;
|
activeChannel.name = groupName;
|
||||||
onClose();
|
setModal(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isVisible={isVisible} onClose={onClose}>
|
<Modal name={EditModalName}>
|
||||||
<Section>
|
<Section>
|
||||||
<Heading>Edit group name and image</Heading>
|
<Heading>Edit group name and image</Heading>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { useModal } from "../../contexts/modalProvider";
|
||||||
import { buttonStyles } from "../Buttons/buttonStyle";
|
import { buttonStyles } from "../Buttons/buttonStyle";
|
||||||
import { textMediumStyles } from "../Text";
|
import { textMediumStyles } from "../Text";
|
||||||
|
|
||||||
import { BasicModalProps, Modal } from "./Modal";
|
import { Modal } from "./Modal";
|
||||||
import { Heading, Section } from "./ModalStyle";
|
import { Heading, Section } from "./ModalStyle";
|
||||||
|
|
||||||
interface LinkModalProps extends BasicModalProps {
|
export const LinkModalName = "LinkModal";
|
||||||
|
|
||||||
|
interface LinkModalProps {
|
||||||
link: string;
|
link: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LinkModal = ({ isVisible, onClose, link }: LinkModalProps) => {
|
export const LinkModal = ({ link }: LinkModalProps) => {
|
||||||
|
const { setModal } = useModal(LinkModalName);
|
||||||
return (
|
return (
|
||||||
<Modal isVisible={isVisible} onClose={onClose}>
|
<Modal name={LinkModalName}>
|
||||||
<Section>
|
<Section>
|
||||||
<Heading>Are you sure you want to visit this website?</Heading>
|
<Heading>Are you sure you want to visit this website?</Heading>
|
||||||
</Section>
|
</Section>
|
||||||
|
@ -21,11 +25,11 @@ export const LinkModal = ({ isVisible, onClose, link }: LinkModalProps) => {
|
||||||
<Link>{link}</Link>
|
<Link>{link}</Link>
|
||||||
</Section>
|
</Section>
|
||||||
<ButtonSection>
|
<ButtonSection>
|
||||||
<ButtonNo onClick={onClose}>No</ButtonNo>
|
<ButtonNo onClick={() => setModal(false)}>No</ButtonNo>
|
||||||
<ButtonYes
|
<ButtonYes
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window?.open(link, "_blank", "noopener")?.focus();
|
window?.open(link, "_blank", "noopener")?.focus();
|
||||||
onClose();
|
setModal(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Yes, take me there
|
Yes, take me there
|
||||||
|
|
|
@ -2,11 +2,11 @@ import React, { ReactNode, useCallback, useEffect } from "react";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { useModal } from "../../contexts/modalProvider";
|
||||||
import { CrossIcon } from "../Icons/CrossIcon";
|
import { CrossIcon } from "../Icons/CrossIcon";
|
||||||
|
|
||||||
export interface BasicModalProps {
|
export interface BasicModalProps {
|
||||||
isVisible: boolean;
|
name: string;
|
||||||
onClose: () => void;
|
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,19 +14,16 @@ export interface ModalProps extends BasicModalProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Modal = ({
|
export const Modal = ({ name, children, className }: ModalProps) => {
|
||||||
isVisible,
|
const { isVisible, setModal } = useModal(name);
|
||||||
onClose,
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
}: ModalProps) => {
|
|
||||||
const listenKeyboard = useCallback(
|
const listenKeyboard = useCallback(
|
||||||
(event: KeyboardEvent) => {
|
(event: KeyboardEvent) => {
|
||||||
if (event.key === "Escape" || event.keyCode === 27) {
|
if (event.key === "Escape" || event.keyCode === 27) {
|
||||||
onClose();
|
setModal(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onClose]
|
[setModal]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -40,18 +37,23 @@ export const Modal = ({
|
||||||
|
|
||||||
if (!isVisible) return null;
|
if (!isVisible) return null;
|
||||||
|
|
||||||
return createPortal(
|
const element = document.getElementById("modal-root");
|
||||||
<ModalView>
|
|
||||||
<ModalOverlay onClick={onClose} />
|
if (element) {
|
||||||
<ModalBody className={className}>
|
return createPortal(
|
||||||
<CloseButton onClick={onClose} className={className}>
|
<ModalView>
|
||||||
<CrossIcon />
|
<ModalOverlay onClick={() => setModal(false)} />
|
||||||
</CloseButton>
|
<ModalBody className={className}>
|
||||||
{children}
|
<CloseButton onClick={() => setModal(false)} className={className}>
|
||||||
</ModalBody>
|
<CrossIcon />
|
||||||
</ModalView>,
|
</CloseButton>
|
||||||
document.body
|
{children}
|
||||||
);
|
</ModalBody>
|
||||||
|
</ModalView>,
|
||||||
|
element
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ModalView = styled.div`
|
const ModalView = styled.div`
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { BasicModalProps, Modal } from "./Modal";
|
import { Modal } from "./Modal";
|
||||||
|
|
||||||
interface PictureModalProps extends BasicModalProps {
|
export const PictureModalName = "PictureModal";
|
||||||
|
|
||||||
|
interface PictureModalProps {
|
||||||
image: string;
|
image: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PictureModal = ({
|
export const PictureModal = ({ image }: PictureModalProps) => {
|
||||||
isVisible,
|
|
||||||
onClose,
|
|
||||||
image,
|
|
||||||
}: PictureModalProps) => {
|
|
||||||
return (
|
return (
|
||||||
<Modal isVisible={isVisible} onClose={onClose} className="picture">
|
<Modal name={PictureModalName} className="picture">
|
||||||
<ModalImageWrapper>
|
<ModalImageWrapper>
|
||||||
<ModalImage src={image}></ModalImage>
|
<ModalImage src={image}></ModalImage>
|
||||||
</ModalImageWrapper>
|
</ModalImageWrapper>
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { useModal } from "../../contexts/modalProvider";
|
||||||
|
|
||||||
|
import { Modal } from "./Modal";
|
||||||
|
|
||||||
|
export const SizeLimitModalName = "SizeLimitModal";
|
||||||
|
|
||||||
|
export function SizeLimitModal() {
|
||||||
|
const { setModal } = useModal(SizeLimitModalName);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal name={SizeLimitModalName}>
|
||||||
|
<div onClick={() => setModal(false)} style={{ padding: "20px" }}>
|
||||||
|
File size must be less than 1MB
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import styled from "styled-components";
|
||||||
|
|
||||||
import { BlockedUsersProvider } from "../contexts/blockedUsersProvider";
|
import { BlockedUsersProvider } from "../contexts/blockedUsersProvider";
|
||||||
import { FetchMetadataProvider } from "../contexts/fetchMetadataProvider";
|
import { FetchMetadataProvider } from "../contexts/fetchMetadataProvider";
|
||||||
|
import { ModalProvider } from "../contexts/modalProvider";
|
||||||
import { NarrowProvider } from "../contexts/narrowProvider";
|
import { NarrowProvider } from "../contexts/narrowProvider";
|
||||||
import { Metadata } from "../models/Metadata";
|
import { Metadata } from "../models/Metadata";
|
||||||
import { GlobalStyle } from "../styles/GlobalStyle";
|
import { GlobalStyle } from "../styles/GlobalStyle";
|
||||||
|
@ -28,10 +29,13 @@ export function ReactChat({
|
||||||
<NarrowProvider myRef={ref}>
|
<NarrowProvider myRef={ref}>
|
||||||
<FetchMetadataProvider fetchMetadata={fetchMetadata}>
|
<FetchMetadataProvider fetchMetadata={fetchMetadata}>
|
||||||
<BlockedUsersProvider>
|
<BlockedUsersProvider>
|
||||||
<Wrapper ref={ref}>
|
<ModalProvider>
|
||||||
<GlobalStyle />
|
<Wrapper ref={ref}>
|
||||||
<ChatLoader communityKey={communityKey} />
|
<GlobalStyle />
|
||||||
</Wrapper>
|
<ChatLoader communityKey={communityKey} />
|
||||||
|
<div id="modal-root" />
|
||||||
|
</Wrapper>
|
||||||
|
</ModalProvider>
|
||||||
</BlockedUsersProvider>
|
</BlockedUsersProvider>
|
||||||
</FetchMetadataProvider>
|
</FetchMetadataProvider>
|
||||||
</NarrowProvider>
|
</NarrowProvider>
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import React, {
|
||||||
|
createContext,
|
||||||
|
useCallback,
|
||||||
|
useContext,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
|
type ModalsState = {
|
||||||
|
[name: string]: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ModalContextType = [
|
||||||
|
state: ModalsState,
|
||||||
|
setState: React.Dispatch<React.SetStateAction<ModalsState>>
|
||||||
|
];
|
||||||
|
|
||||||
|
const ModalContext = createContext<ModalContextType>([{}, () => undefined]);
|
||||||
|
|
||||||
|
export function useModal(name: string) {
|
||||||
|
const [modals, setModals] = useContext(ModalContext);
|
||||||
|
const setModal = useCallback(
|
||||||
|
(state: boolean) => {
|
||||||
|
setModals((prev) => {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[name]: state,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[name, modals]
|
||||||
|
);
|
||||||
|
const isVisible = useMemo(() => modals?.[name] ?? false, [modals, name]);
|
||||||
|
return { isVisible, setModal };
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IdentityProviderProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ModalProvider({ children }: IdentityProviderProps) {
|
||||||
|
const modalState = useState<ModalsState>({});
|
||||||
|
return <ModalContext.Provider value={modalState} children={children} />;
|
||||||
|
}
|
Loading…
Reference in New Issue