Add no community chat (#209)
This commit is contained in:
parent
21e49cb7bf
commit
180b2be276
|
@ -103,11 +103,6 @@ export function ChatCreation({
|
|||
value={query}
|
||||
onInput={(e) => setQuery(e.currentTarget.value)}
|
||||
/>
|
||||
<SearchBlock
|
||||
query={query}
|
||||
discludeList={styledGroup}
|
||||
onClick={addMember}
|
||||
/>
|
||||
</SearchMembers>
|
||||
)}
|
||||
{!narrow && styledGroup.length === 5 && (
|
||||
|
@ -132,12 +127,18 @@ export function ChatCreation({
|
|||
Confirm
|
||||
</CreationBtn>
|
||||
{!narrow && <ActivityButton className="creation" />}
|
||||
<SearchBlock
|
||||
query={query}
|
||||
discludeList={styledGroup}
|
||||
onClick={addMember}
|
||||
/>
|
||||
</CreationBar>
|
||||
{!setEditGroup && !query && (
|
||||
{!setEditGroup && (
|
||||
<Contacts>
|
||||
<ContactsHeading>Contacts</ContactsHeading>
|
||||
<ContactsList>
|
||||
{identity &&
|
||||
!query &&
|
||||
Object.values(contacts)
|
||||
.filter(
|
||||
(e) =>
|
||||
|
@ -181,7 +182,7 @@ const CreationBar = styled.div`
|
|||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 32px;
|
||||
|
||||
position: relative;
|
||||
&.limit {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
import { ChatStateProvider } from "../contexts/chatStateProvider";
|
||||
import { IdentityProvider } from "../contexts/identityProvider";
|
||||
import { MessengerProvider } from "../contexts/messengerProvider";
|
||||
import {
|
||||
UserCreationState,
|
||||
useUserCreationState,
|
||||
} from "../contexts/userCreationStateProvider";
|
||||
|
||||
import { Chat } from "./Chat";
|
||||
import { IdentityLoader } from "./Form/IdentityLoader";
|
||||
|
||||
type ChatLoaderProps = {
|
||||
communityKey: string;
|
||||
};
|
||||
|
||||
export function ChatLoader({ communityKey }: ChatLoaderProps) {
|
||||
const [userCreationState] = useUserCreationState();
|
||||
|
||||
if (userCreationState === UserCreationState.NotCreating)
|
||||
return (
|
||||
<IdentityProvider>
|
||||
<MessengerProvider communityKey={communityKey}>
|
||||
<ChatStateProvider>
|
||||
<Chat />
|
||||
</ChatStateProvider>
|
||||
</MessengerProvider>
|
||||
</IdentityProvider>
|
||||
);
|
||||
if (userCreationState === UserCreationState.Creating) {
|
||||
return <IdentityLoader />;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
|
@ -4,17 +4,19 @@ import styled from "styled-components";
|
|||
|
||||
import { ConfigType } from "..";
|
||||
import { ActivityProvider } from "../contexts/activityProvider";
|
||||
import { ChatStateProvider } from "../contexts/chatStateProvider";
|
||||
import { ConfigProvider } from "../contexts/configProvider";
|
||||
import { FetchMetadataProvider } from "../contexts/fetchMetadataProvider";
|
||||
import { IdentityProvider } from "../contexts/identityProvider";
|
||||
import { MessengerProvider } from "../contexts/messengerProvider";
|
||||
import { ModalProvider } from "../contexts/modalProvider";
|
||||
import { NarrowProvider } from "../contexts/narrowProvider";
|
||||
import { ToastProvider } from "../contexts/toastProvider";
|
||||
import { UserCreationStateProvider } from "../contexts/userCreationStateProvider";
|
||||
import { Metadata } from "../models/Metadata";
|
||||
import { GlobalStyle } from "../styles/GlobalStyle";
|
||||
import { Theme } from "../styles/themes";
|
||||
|
||||
import { ChatLoader } from "./ChatLoader";
|
||||
import { Chat } from "./Chat";
|
||||
|
||||
interface DappConnectCommunityChatProps {
|
||||
theme: Theme;
|
||||
|
@ -37,15 +39,19 @@ export function DappConnectCommunityChat({
|
|||
<FetchMetadataProvider fetchMetadata={fetchMetadata}>
|
||||
<ModalProvider>
|
||||
<ActivityProvider>
|
||||
<UserCreationStateProvider>
|
||||
<ToastProvider>
|
||||
<Wrapper ref={ref}>
|
||||
<GlobalStyle />
|
||||
<ChatLoader communityKey={communityKey} />
|
||||
<IdentityProvider>
|
||||
<MessengerProvider communityKey={communityKey}>
|
||||
<ChatStateProvider>
|
||||
<Chat />
|
||||
<div id="modal-root" />
|
||||
</ChatStateProvider>
|
||||
</MessengerProvider>
|
||||
</IdentityProvider>
|
||||
</Wrapper>
|
||||
</ToastProvider>
|
||||
</UserCreationStateProvider>
|
||||
</ActivityProvider>
|
||||
</ModalProvider>
|
||||
</FetchMetadataProvider>
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
import { Identity } from "@waku/status-communities/dist/cjs";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { useSetIdentity } from "../../contexts/identityProvider";
|
||||
import {
|
||||
UserCreationState,
|
||||
useUserCreationState,
|
||||
} from "../../contexts/userCreationStateProvider";
|
||||
import {
|
||||
decryptIdentity,
|
||||
loadEncryptedIdentity,
|
||||
saveIdentity,
|
||||
} from "../../utils";
|
||||
|
||||
export function IdentityLoader() {
|
||||
const setIdentity = useSetIdentity();
|
||||
const [password, setPassword] = useState("");
|
||||
const state = useUserCreationState();
|
||||
|
||||
const [encryptedIdentity, setEncryptedIdentity] = useState(
|
||||
loadEncryptedIdentity() ?? ""
|
||||
);
|
||||
const [identityInMemory, setIdentityInMemory] = useState(false);
|
||||
const [wrongPassword, setWrongPassword] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (encryptedIdentity) {
|
||||
setIdentityInMemory(true);
|
||||
}
|
||||
setWrongPassword(false);
|
||||
}, [encryptedIdentity]);
|
||||
|
||||
const loadIdentity = useCallback(async () => {
|
||||
const identity = await decryptIdentity(encryptedIdentity, password);
|
||||
if (!identity) {
|
||||
setWrongPassword(true);
|
||||
} else {
|
||||
setIdentity(identity);
|
||||
state[1](UserCreationState.NotCreating);
|
||||
}
|
||||
}, [encryptedIdentity, password]);
|
||||
|
||||
const createIdentity = useCallback(async () => {
|
||||
const identity = Identity.generate();
|
||||
await saveIdentity(identity, password);
|
||||
setIdentity(identity);
|
||||
state[1](UserCreationState.NotCreating);
|
||||
}, [encryptedIdentity, password]);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
{encryptedIdentity ? (
|
||||
<FormWrappers>
|
||||
<InfoDiv>Please provide password for your identity</InfoDiv>
|
||||
{wrongPassword && <div>Wrong password</div>}
|
||||
<Input
|
||||
value={password}
|
||||
type={"password"}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
loadIdentity();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button onClick={loadIdentity}>LOAD</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setEncryptedIdentity("");
|
||||
}}
|
||||
>
|
||||
Create new identity
|
||||
</Button>
|
||||
</FormWrappers>
|
||||
) : (
|
||||
<FormWrappers>
|
||||
<InfoDiv>Please provide password for your identity</InfoDiv>
|
||||
<Input
|
||||
value={password}
|
||||
type={"password"}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
createIdentity();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button onClick={createIdentity}>Create</Button>
|
||||
{identityInMemory && (
|
||||
<Button
|
||||
onClick={() =>
|
||||
setEncryptedIdentity(loadEncryptedIdentity() ?? "")
|
||||
}
|
||||
>
|
||||
Go back
|
||||
</Button>
|
||||
)}
|
||||
</FormWrappers>
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
const Input = styled.input`
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
`;
|
||||
|
||||
const Button = styled.button`
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
box-shadow: 5px 5px 10px -4px rgba(197, 197, 255, 1);
|
||||
border-radius: 5px;
|
||||
background-color: ${({ theme }) => theme.buttonBg};
|
||||
`;
|
||||
|
||||
const Wrapper = styled.div`
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
const FormWrappers = styled.div`
|
||||
margin: auto;
|
||||
`;
|
||||
|
||||
const InfoDiv = styled.div`
|
||||
margin: 5px;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
`;
|
|
@ -1,4 +1,3 @@
|
|||
import { utils } from "@waku/status-communities/dist/cjs";
|
||||
import { bufToHex } from "@waku/status-communities/dist/cjs/utils";
|
||||
import React, { useMemo } from "react";
|
||||
import styled from "styled-components";
|
||||
|
@ -6,6 +5,7 @@ import styled from "styled-components";
|
|||
import { useIdentity } from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useModal } from "../../contexts/modalProvider";
|
||||
import { Contact } from "../../models/Contact";
|
||||
import { buttonStyles } from "../Buttons/buttonStyle";
|
||||
import { LogoutIcon } from "../Icons/LogoutIcon";
|
||||
import { LogoutModalName } from "../Modals/LogoutModal";
|
||||
|
@ -15,30 +15,32 @@ import { Member } from "./Member";
|
|||
export function MembersList() {
|
||||
const { contacts, nickname, activeChannel } = useMessengerContext();
|
||||
const identity = useIdentity();
|
||||
const userPK = useMemo(
|
||||
() => (identity ? bufToHex(identity?.publicKey) : undefined),
|
||||
[identity]
|
||||
);
|
||||
const { setModal } = useModal(LogoutModalName);
|
||||
|
||||
const userContacts = useMemo(() => {
|
||||
const members = useMemo(() => {
|
||||
const contactsArray = Object.values(contacts);
|
||||
if (identity) {
|
||||
return Object.values(contacts).filter(
|
||||
(e) => e.id != bufToHex(identity.publicKey)
|
||||
);
|
||||
} else {
|
||||
return Object.values(contacts);
|
||||
}
|
||||
}, [contacts, identity]);
|
||||
|
||||
const members = useMemo(
|
||||
() =>
|
||||
if (
|
||||
activeChannel &&
|
||||
activeChannel?.type === "group" &&
|
||||
activeChannel.members &&
|
||||
identity
|
||||
? activeChannel.members.filter(
|
||||
(e) => e.id !== utils.bufToHex(identity.publicKey)
|
||||
)
|
||||
: userContacts,
|
||||
[activeChannel]
|
||||
);
|
||||
activeChannel.type === "group" &&
|
||||
activeChannel.members
|
||||
) {
|
||||
const returnContacts: Contact[] = [];
|
||||
activeChannel.members.forEach((member) => {
|
||||
if (contacts[member.id] && member.id != userPK) {
|
||||
returnContacts.push(contacts[member.id]);
|
||||
}
|
||||
});
|
||||
return returnContacts;
|
||||
}
|
||||
return contactsArray.filter((e) => e.id !== userPK);
|
||||
}
|
||||
return contactsArray;
|
||||
}, [activeChannel, contacts, identity, userPK]);
|
||||
|
||||
const onlineContacts = useMemo(
|
||||
() => members.filter((e) => e.online),
|
||||
|
@ -57,9 +59,9 @@ export function MembersList() {
|
|||
<Row>
|
||||
<Member
|
||||
contact={{
|
||||
id: utils.bufToHex(identity.publicKey),
|
||||
id: userPK ?? "",
|
||||
customName: nickname,
|
||||
trueName: utils.bufToHex(identity.publicKey),
|
||||
trueName: userPK ?? "",
|
||||
}}
|
||||
isYou={true}
|
||||
/>
|
||||
|
|
|
@ -18,6 +18,7 @@ const MessengerContext = createContext<MessengerType>({
|
|||
communityData: undefined,
|
||||
contacts: {},
|
||||
contactsDispatch: () => undefined,
|
||||
addContact: () => undefined,
|
||||
activeChannel: undefined,
|
||||
channels: {},
|
||||
channelsDispatch: () => undefined,
|
||||
|
@ -33,7 +34,7 @@ export function useMessengerContext() {
|
|||
}
|
||||
|
||||
interface MessengerProviderProps {
|
||||
communityKey: string;
|
||||
communityKey: string | undefined;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
import React, { createContext, useContext, useState } from "react";
|
||||
|
||||
export enum UserCreationState {
|
||||
Creating,
|
||||
NotCreating,
|
||||
}
|
||||
|
||||
type UserCreationContextType = [
|
||||
UserCreationState,
|
||||
React.Dispatch<React.SetStateAction<UserCreationState>>
|
||||
];
|
||||
|
||||
const ChatStateContext = createContext<UserCreationContextType>([
|
||||
UserCreationState.NotCreating,
|
||||
() => undefined,
|
||||
]);
|
||||
|
||||
export function useUserCreationState() {
|
||||
return useContext(ChatStateContext);
|
||||
}
|
||||
|
||||
export function UserCreationStateProvider({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const state = useState(UserCreationState.NotCreating);
|
||||
return <ChatStateContext.Provider value={state} children={children} />;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
import React, { useRef } from "react";
|
||||
import { ThemeProvider } from "styled-components";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { ConfigType } from "..";
|
||||
import { ActivityProvider } from "../contexts/activityProvider";
|
||||
import { ChatStateProvider } from "../contexts/chatStateProvider";
|
||||
import { ConfigProvider } from "../contexts/configProvider";
|
||||
import { FetchMetadataProvider } from "../contexts/fetchMetadataProvider";
|
||||
import { IdentityProvider } from "../contexts/identityProvider";
|
||||
import { MessengerProvider } from "../contexts/messengerProvider";
|
||||
import { ModalProvider } from "../contexts/modalProvider";
|
||||
import { NarrowProvider } from "../contexts/narrowProvider";
|
||||
import { ToastProvider } from "../contexts/toastProvider";
|
||||
import { Metadata } from "../models/Metadata";
|
||||
import { GlobalStyle } from "../styles/GlobalStyle";
|
||||
import { Theme } from "../styles/themes";
|
||||
|
||||
import { GroupChat } from "./GroupChat";
|
||||
|
||||
interface DappConnectGroupChatProps {
|
||||
theme: Theme;
|
||||
config: ConfigType;
|
||||
fetchMetadata?: (url: string) => Promise<Metadata | undefined>;
|
||||
}
|
||||
|
||||
export function DappConnectGroupChat({
|
||||
theme,
|
||||
config,
|
||||
fetchMetadata,
|
||||
}: DappConnectGroupChatProps) {
|
||||
const ref = useRef<HTMLHeadingElement>(null);
|
||||
return (
|
||||
<ConfigProvider config={config}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<NarrowProvider myRef={ref}>
|
||||
<FetchMetadataProvider fetchMetadata={fetchMetadata}>
|
||||
<ModalProvider>
|
||||
<ActivityProvider>
|
||||
<ToastProvider>
|
||||
<Wrapper ref={ref}>
|
||||
<GlobalStyle />
|
||||
<IdentityProvider>
|
||||
<MessengerProvider communityKey={undefined}>
|
||||
<ChatStateProvider>
|
||||
<GroupChat />
|
||||
<div id="modal-root" />
|
||||
</ChatStateProvider>
|
||||
</MessengerProvider>
|
||||
</IdentityProvider>
|
||||
</Wrapper>
|
||||
</ToastProvider>
|
||||
</ActivityProvider>
|
||||
</ModalProvider>
|
||||
</FetchMetadataProvider>
|
||||
</NarrowProvider>
|
||||
</ThemeProvider>
|
||||
</ConfigProvider>
|
||||
);
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
`;
|
|
@ -0,0 +1,90 @@
|
|||
import React, { useState } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { Channels } from "../components/Channels/Channels";
|
||||
import { ChatCreation } from "../components/Chat/ChatCreation";
|
||||
import { AgreementModal } from "../components/Modals/AgreementModal";
|
||||
import { CoinbaseModal } from "../components/Modals/CoinbaseModal";
|
||||
import { EditModal } from "../components/Modals/EditModal";
|
||||
import { LeavingModal } from "../components/Modals/LeavingModal";
|
||||
import { LogoutModal } from "../components/Modals/LogoutModal";
|
||||
import { ProfileFoundModal } from "../components/Modals/ProfileFoundModal";
|
||||
import { ProfileModal } from "../components/Modals/ProfileModal";
|
||||
import { StatusModal } from "../components/Modals/StatusModal";
|
||||
import { UserCreationModal } from "../components/Modals/UserCreationModal";
|
||||
import { UserCreationStartModal } from "../components/Modals/UserCreationStartModal";
|
||||
import { WalletConnectModal } from "../components/Modals/WalletConnectModal";
|
||||
import { WalletModal } from "../components/Modals/WalletModal";
|
||||
import { ToastMessageList } from "../components/ToastMessages/ToastMessageList";
|
||||
import { ChatState, useChatState } from "../contexts/chatStateProvider";
|
||||
import { useNarrow } from "../contexts/narrowProvider";
|
||||
|
||||
import { GroupChatBody } from "./GroupChat/GroupChatBody";
|
||||
import { GroupMembers } from "./GroupMembers/GroupMembers";
|
||||
|
||||
function Modals() {
|
||||
return (
|
||||
<>
|
||||
<UserCreationModal />
|
||||
<EditModal />
|
||||
<ProfileModal />
|
||||
<StatusModal />
|
||||
<WalletModal />
|
||||
<WalletConnectModal />
|
||||
<CoinbaseModal />
|
||||
<LogoutModal />
|
||||
<AgreementModal />
|
||||
<ProfileFoundModal />
|
||||
<UserCreationStartModal />
|
||||
<LeavingModal />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function GroupChat() {
|
||||
const [state] = useChatState();
|
||||
const [showMembers, setShowMembers] = useState(false);
|
||||
const [editGroup, setEditGroup] = useState(false);
|
||||
const narrow = useNarrow();
|
||||
return (
|
||||
<ChatWrapper>
|
||||
{!narrow && (
|
||||
<ChannelsWrapper>
|
||||
<Channels setEditGroup={setEditGroup} />
|
||||
</ChannelsWrapper>
|
||||
)}
|
||||
{state === ChatState.ChatBody && (
|
||||
<GroupChatBody
|
||||
onClick={() => setShowMembers(!showMembers)}
|
||||
showMembers={showMembers}
|
||||
permission={true}
|
||||
editGroup={editGroup}
|
||||
setEditGroup={setEditGroup}
|
||||
/>
|
||||
)}
|
||||
{showMembers && !narrow && state === ChatState.ChatBody && (
|
||||
<GroupMembers />
|
||||
)}
|
||||
{state === ChatState.ChatCreation && <ChatCreation />}
|
||||
<Modals />
|
||||
<ToastMessageList />
|
||||
</ChatWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
const ChatWrapper = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const ChannelsWrapper = styled.div`
|
||||
width: 21%;
|
||||
height: 100%;
|
||||
min-width: 250px;
|
||||
background-color: ${({ theme }) => theme.sectionBackgroundColor};
|
||||
padding: 10px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
|
@ -0,0 +1,182 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { ChatCreation } from "../../components/Chat/ChatCreation";
|
||||
import { ChatInput } from "../../components/Chat/ChatInput";
|
||||
import {
|
||||
ChatTopbar,
|
||||
ChatTopbarLoading,
|
||||
} from "../../components/Chat/ChatTopbar";
|
||||
import { TokenRequirement } from "../../components/Form/TokenRequirement";
|
||||
import { MessagesList } from "../../components/Messages/MessagesList";
|
||||
import { NarrowChannels } from "../../components/NarrowMode/NarrowChannels";
|
||||
import { NarrowMembers } from "../../components/NarrowMode/NarrowMembers";
|
||||
import { LoadingSkeleton } from "../../components/Skeleton/LoadingSkeleton";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useNarrow } from "../../contexts/narrowProvider";
|
||||
import { Reply } from "../../hooks/useReply";
|
||||
import { ChannelData } from "../../models/ChannelData";
|
||||
|
||||
export enum ChatBodyState {
|
||||
Chat,
|
||||
Channels,
|
||||
Members,
|
||||
}
|
||||
|
||||
function ChatBodyLoading() {
|
||||
const narrow = useNarrow();
|
||||
return (
|
||||
<Wrapper>
|
||||
<ChatBodyWrapper className={narrow ? "narrow" : ""}>
|
||||
<ChatTopbarLoading />
|
||||
<LoadingSkeleton />
|
||||
<ChatInput reply={undefined} setReply={() => undefined} />
|
||||
</ChatBodyWrapper>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
type ChatBodyContentProps = {
|
||||
showState: ChatBodyState;
|
||||
switchShowState: (state: ChatBodyState) => void;
|
||||
channel: ChannelData;
|
||||
};
|
||||
|
||||
function ChatBodyContent({
|
||||
showState,
|
||||
switchShowState,
|
||||
channel,
|
||||
}: ChatBodyContentProps) {
|
||||
const [reply, setReply] = useState<Reply | undefined>(undefined);
|
||||
|
||||
switch (showState) {
|
||||
case ChatBodyState.Chat:
|
||||
return (
|
||||
<>
|
||||
<MessagesList setReply={setReply} channel={channel} />
|
||||
<ChatInput reply={reply} setReply={setReply} />
|
||||
</>
|
||||
);
|
||||
case ChatBodyState.Channels:
|
||||
return (
|
||||
<NarrowChannels
|
||||
setShowChannels={() => switchShowState(ChatBodyState.Channels)}
|
||||
/>
|
||||
);
|
||||
case ChatBodyState.Members:
|
||||
return (
|
||||
<NarrowMembers
|
||||
switchShowMembersList={() => switchShowState(ChatBodyState.Members)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
interface GroupChatBodyProps {
|
||||
onClick: () => void;
|
||||
showMembers: boolean;
|
||||
permission: boolean;
|
||||
editGroup: boolean;
|
||||
setEditGroup: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export function GroupChatBody({
|
||||
onClick,
|
||||
showMembers,
|
||||
permission,
|
||||
editGroup,
|
||||
setEditGroup,
|
||||
}: GroupChatBodyProps) {
|
||||
const { activeChannel, loadingMessenger } = useMessengerContext();
|
||||
|
||||
const narrow = useNarrow();
|
||||
const className = useMemo(() => (narrow ? "narrow" : ""), [narrow]);
|
||||
|
||||
const [showState, setShowState] = useState<ChatBodyState>(ChatBodyState.Chat);
|
||||
const switchShowState = useCallback(
|
||||
(state: ChatBodyState) => {
|
||||
if (narrow) {
|
||||
setShowState((prev) => (prev === state ? ChatBodyState.Chat : state));
|
||||
}
|
||||
},
|
||||
[narrow]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!narrow) {
|
||||
setShowState(ChatBodyState.Chat);
|
||||
}
|
||||
}, [narrow]);
|
||||
|
||||
if (!loadingMessenger && activeChannel) {
|
||||
return (
|
||||
<Wrapper>
|
||||
<ChatBodyWrapper className={className}>
|
||||
{editGroup ? (
|
||||
<ChatCreation
|
||||
setEditGroup={setEditGroup}
|
||||
activeChannel={activeChannel}
|
||||
/>
|
||||
) : (
|
||||
<ChatTopbar
|
||||
onClick={onClick}
|
||||
setEditGroup={setEditGroup}
|
||||
showMembers={showMembers}
|
||||
showState={showState}
|
||||
switchShowState={switchShowState}
|
||||
/>
|
||||
)}
|
||||
<ChatBodyContent
|
||||
showState={showState}
|
||||
switchShowState={switchShowState}
|
||||
channel={activeChannel}
|
||||
/>
|
||||
</ChatBodyWrapper>
|
||||
{!permission && (
|
||||
<BluredWrapper>
|
||||
<TokenRequirement />
|
||||
</BluredWrapper>
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return <ChatBodyLoading />;
|
||||
}
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
width: 61%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
background: ${({ theme }) => theme.bodyBackgroundColor};
|
||||
position: relative;
|
||||
|
||||
&.narrow {
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
const ChatBodyWrapper = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
background: ${({ theme }) => theme.bodyBackgroundColor};
|
||||
`;
|
||||
|
||||
const BluredWrapper = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: ${({ theme }) => theme.bodyBackgroundGradient};
|
||||
backdrop-filter: blur(4px);
|
||||
z-index: 2;
|
||||
`;
|
|
@ -0,0 +1,49 @@
|
|||
import React, { useMemo, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { MembersList } from "../../components/Members/MembersList";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
|
||||
export function GroupMembers() {
|
||||
const { addContact, activeChannel } = useMessengerContext();
|
||||
const heading = useMemo(
|
||||
() =>
|
||||
activeChannel && activeChannel?.type === "group"
|
||||
? "Group members"
|
||||
: "Members",
|
||||
[activeChannel]
|
||||
);
|
||||
const [newUserInput, setNewUserInput] = useState("");
|
||||
return (
|
||||
<>
|
||||
<MembersWrapper>
|
||||
<MemberHeading>{heading}</MemberHeading>
|
||||
<MembersList />
|
||||
<input
|
||||
value={newUserInput}
|
||||
onChange={(e) => setNewUserInput(e.target.value)}
|
||||
/>
|
||||
<button onClick={() => addContact(newUserInput)}>Add Contact</button>
|
||||
</MembersWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const MembersWrapper = styled.div`
|
||||
width: 18%;
|
||||
height: 100%;
|
||||
min-width: 164px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: ${({ theme }) => theme.sectionBackgroundColor};
|
||||
padding: 16px;
|
||||
overflow-y: scroll;
|
||||
`;
|
||||
|
||||
const MemberHeading = styled.h2`
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
color: ${({ theme }) => theme.primary};
|
||||
margin-bottom: 16px;
|
||||
`;
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
Contacts as ContactsClass,
|
||||
GroupChat,
|
||||
GroupChats,
|
||||
Identity,
|
||||
|
@ -28,10 +29,11 @@ export function useGroupChats(
|
|||
messenger: Messenger | undefined,
|
||||
identity: Identity | undefined,
|
||||
dispatch: (action: ChannelAction) => void,
|
||||
addChatMessage: (newMessage: ChatMessage | undefined, id: string) => void
|
||||
addChatMessage: (newMessage: ChatMessage | undefined, id: string) => void,
|
||||
contactsClass: ContactsClass | undefined
|
||||
) {
|
||||
const groupChat = useMemo(() => {
|
||||
if (messenger && identity) {
|
||||
if (messenger && identity && contactsClass) {
|
||||
const addChat = (chat: GroupChat) => {
|
||||
const members = chat.members
|
||||
.map((member) => member.id)
|
||||
|
@ -52,6 +54,7 @@ export function useGroupChats(
|
|||
description: `Chatkey: ${chat.members[0].id}`,
|
||||
members,
|
||||
};
|
||||
chat.members.forEach((member) => contactsClass.addContact(member.id));
|
||||
dispatch({ type: "AddChannel", payload: channel });
|
||||
};
|
||||
const removeChat = (chat: GroupChat) => {
|
||||
|
@ -81,7 +84,7 @@ export function useGroupChats(
|
|||
handleMessage
|
||||
);
|
||||
}
|
||||
}, [messenger, identity]);
|
||||
}, [messenger, identity, contactsClass]);
|
||||
|
||||
const createGroupChat = useCallback(
|
||||
(members: string[]) => {
|
||||
|
|
|
@ -17,12 +17,14 @@ export function useLoadPrevDay(
|
|||
const [loadingMessages, setLoadingMessages] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (chatId) {
|
||||
setLoadingMessages(loadingPreviousMessages.current[chatId]);
|
||||
}
|
||||
}, [chatId]);
|
||||
|
||||
const loadPrevDay = useCallback(
|
||||
async (id: string, groupChat?: boolean) => {
|
||||
if (messenger) {
|
||||
if (messenger && id) {
|
||||
const endTime = lastLoadTime.current[id] ?? new Date();
|
||||
const startTime = new Date(endTime.getTime() - _MS_PER_DAY * 5);
|
||||
const timeDiff = Math.floor(
|
||||
|
|
|
@ -41,6 +41,7 @@ export type MessengerType = {
|
|||
communityData: CommunityData | undefined;
|
||||
contacts: Contacts;
|
||||
contactsDispatch: (action: ContactsAction) => void;
|
||||
addContact: (publicKey: string) => void;
|
||||
channels: ChannelsData;
|
||||
channelsDispatch: (action: ChannelAction) => void;
|
||||
removeChannel: (channelId: string) => void;
|
||||
|
@ -105,7 +106,7 @@ function useCreateCommunity(
|
|||
}
|
||||
|
||||
export function useMessenger(
|
||||
communityKey: string,
|
||||
communityKey: string | undefined,
|
||||
identity: Identity | undefined,
|
||||
newNickname: string | undefined
|
||||
) {
|
||||
|
@ -117,6 +118,15 @@ export function useMessenger(
|
|||
newNickname
|
||||
);
|
||||
|
||||
const addContact = useCallback(
|
||||
(publicKey: string) => {
|
||||
if (contactsClass) {
|
||||
contactsClass.addContact(publicKey);
|
||||
}
|
||||
},
|
||||
[contactsClass]
|
||||
);
|
||||
|
||||
const {
|
||||
addChatMessage,
|
||||
addMessage,
|
||||
|
@ -176,7 +186,13 @@ export function useMessenger(
|
|||
createGroupChat,
|
||||
changeGroupChatName,
|
||||
addMembers,
|
||||
} = useGroupChats(messenger, identity, channelsDispatch, addChatMessage);
|
||||
} = useGroupChats(
|
||||
messenger,
|
||||
identity,
|
||||
channelsDispatch,
|
||||
addChatMessage,
|
||||
contactsClass
|
||||
);
|
||||
|
||||
const { loadPrevDay, loadingMessages } = useLoadPrevDay(
|
||||
channelsState.activeChannel.id,
|
||||
|
@ -237,9 +253,12 @@ export function useMessenger(
|
|||
}, [notifications, channelsState]);
|
||||
|
||||
const loadingMessenger = useMemo(() => {
|
||||
return !communityData || !messenger || !channelsState.activeChannel.id;
|
||||
return Boolean(
|
||||
(communityKey && !communityData) ||
|
||||
!messenger ||
|
||||
(communityKey && !channelsState.activeChannel.id)
|
||||
);
|
||||
}, [communityData, messenger, channelsState]);
|
||||
|
||||
return {
|
||||
messenger,
|
||||
messages,
|
||||
|
@ -252,6 +271,7 @@ export function useMessenger(
|
|||
communityData,
|
||||
contacts,
|
||||
contactsDispatch,
|
||||
addContact,
|
||||
channels: channelsState.channels,
|
||||
channelsDispatch,
|
||||
removeChannel,
|
||||
|
|
|
@ -22,16 +22,16 @@ export function useChatScrollHandle(
|
|||
(ref?.current?.clientHeight ?? 0) >= (ref?.current?.scrollHeight ?? 0)
|
||||
) {
|
||||
setScrollOnBot(true);
|
||||
loadPrevDay(activeChannel.id, activeChannel.type === "group");
|
||||
loadPrevDay(activeChannel.id, activeChannel.type !== "channel");
|
||||
}
|
||||
}
|
||||
}, [messages.length, loadingMessages, activeChannel]);
|
||||
}, [messages.length, activeChannel]);
|
||||
|
||||
useEffect(() => {
|
||||
const setScroll = () => {
|
||||
if (ref?.current && activeChannel) {
|
||||
if (ref.current.scrollTop <= 0) {
|
||||
loadPrevDay(activeChannel.id, activeChannel.type === "group");
|
||||
loadPrevDay(activeChannel.id, activeChannel.type !== "channel");
|
||||
}
|
||||
if (
|
||||
ref.current.scrollTop + ref.current.clientHeight ==
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
import { DappConnectCommunityChat } from "./components/DappConnectCommunityChat";
|
||||
import { ConfigType } from "./contexts/configProvider";
|
||||
import { DappConnectGroupChat } from "./groupChatComponents/DappConnectGroupChat";
|
||||
import { darkTheme, lightTheme } from "./styles/themes";
|
||||
export { DappConnectCommunityChat, lightTheme, darkTheme, ConfigType };
|
||||
|
||||
export {
|
||||
DappConnectCommunityChat,
|
||||
DappConnectGroupChat,
|
||||
lightTheme,
|
||||
darkTheme,
|
||||
ConfigType,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": { "project": "./tsconfig.json" },
|
||||
"env": { "es6": true },
|
||||
"ignorePatterns": ["node_modules", "dist", "coverage", "proto"],
|
||||
"plugins": ["import", "eslint-comments", "functional"],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:eslint-comments/recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/typescript",
|
||||
"prettier"
|
||||
],
|
||||
"globals": { "BigInt": true, "console": true, "WebAssembly": true },
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"eslint-comments/disable-enable-pair": [
|
||||
"error",
|
||||
{ "allowWholeFile": true }
|
||||
],
|
||||
"eslint-comments/no-unused-disable": "error",
|
||||
"import/order": [
|
||||
"error",
|
||||
{ "newlines-between": "always", "alphabetize": { "order": "asc" } }
|
||||
],
|
||||
"no-constant-condition": ["error", { "checkLoops": false }],
|
||||
"sort-imports": [
|
||||
"error",
|
||||
{ "ignoreDeclarationSort": true, "ignoreCase": true }
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.spec.ts", "**/test_utils/*.ts"],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-non-null-assertion": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extension": ["ts"],
|
||||
"spec": "src/**/*.spec.ts",
|
||||
"require": "ts-node/register",
|
||||
"exit": true
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
# package.json is formatted by package managers, so we ignore it here
|
||||
package.json
|
|
@ -0,0 +1 @@
|
|||
#React chat example
|
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"name": "@waku/react-group-chat-sdk-example",
|
||||
"main": "index.js",
|
||||
"version": "0.1.0",
|
||||
"repository": "https://github.com/status-im/dappconnect-chat-sdk/",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"packageManager": "yarn@3.0.1",
|
||||
"scripts": {
|
||||
"clean:all": "yarn clean && rimraf node_modules/",
|
||||
"clean": "rimraf dist/",
|
||||
"build": "rm -rf dist && webpack --mode=production --env ENV=production",
|
||||
"start": "webpack serve --mode=development --env ENV=$ENV COMMUNITY_KEY=$COMMUNITY_KEY --https",
|
||||
"fix": "run-s 'fix:*'",
|
||||
"fix:prettier": "prettier './{src,test}/**/*.{ts,tsx}' \"./*.json\" --write",
|
||||
"fix:lint": "eslint './{src,test}/**/*.{ts,tsx}' --fix",
|
||||
"test": "run-s 'test:*'",
|
||||
"test:lint": "eslint './{src,test}/**/*.{ts,tsx}'",
|
||||
"test:prettier": "prettier './{src,test}/**/*.{ts,tsx}' \"./*.json\" --list-different"
|
||||
},
|
||||
"dependencies": {
|
||||
"@waku/react-chat-sdk": "^0.1.0",
|
||||
"assert": "^2.0.0",
|
||||
"browserify-zlib": "^0.2.0",
|
||||
"buffer": "^6.0.3",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"https-browserify": "^1.0.0",
|
||||
"process": "^0.11.10",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"stream-http": "^3.2.0",
|
||||
"styled-components": "^5.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/react-hooks": "^7.0.1",
|
||||
"@types/chai": "^4.2.21",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"@types/node": "^16.4.12",
|
||||
"@types/react": "^17.0.15",
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"@types/react-router": "^5.1.16",
|
||||
"@types/react-router-dom": "^5.1.8",
|
||||
"@types/styled-components": "^5.1.12",
|
||||
"@typescript-eslint/eslint-plugin": "^4.29.0",
|
||||
"@typescript-eslint/parser": "^4.29.0",
|
||||
"chai": "^4.3.4",
|
||||
"css-loader": "^6.3.0",
|
||||
"esbuild-loader": "^2.15.1",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-hooks": "^0.2.0",
|
||||
"eslint-plugin-react": "^7.24.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"fork-ts-checker-webpack-plugin": "^6.3.1",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"jsdom": "^16.7.0",
|
||||
"jsdom-global": "^3.0.2",
|
||||
"mocha": "^9.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.3.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"source-map-loader": "^3.0.0",
|
||||
"style-loader": "^3.3.0",
|
||||
"ts-loader": "^9.2.5",
|
||||
"ts-node": "^10.1.0",
|
||||
"typescript": "^4.3.5",
|
||||
"webpack": "^5.48.0",
|
||||
"webpack-cli": "^4.7.2",
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
/* /index.html 200
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<title>DAppconnect group chat</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<script type="module" src="/index.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,139 @@
|
|||
import {
|
||||
DappConnectGroupChat,
|
||||
darkTheme,
|
||||
lightTheme,
|
||||
} from "@waku/react-chat-sdk";
|
||||
import React, { useRef, useState } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import styled from "styled-components";
|
||||
|
||||
const fetchMetadata = async (link: string) => {
|
||||
const response = await fetch("https://localhost:3000", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ site: link }),
|
||||
});
|
||||
const body = await response.text();
|
||||
const parsedBody = JSON.parse(body);
|
||||
if (
|
||||
"og:image" in parsedBody &&
|
||||
"og:site_name" in parsedBody &&
|
||||
"og:title" in parsedBody
|
||||
) {
|
||||
return JSON.parse(body);
|
||||
}
|
||||
};
|
||||
|
||||
function DragDiv() {
|
||||
const [x, setX] = useState(0);
|
||||
const [y, setY] = useState(0);
|
||||
const [width, setWidth] = useState(window.innerWidth - 50);
|
||||
const [height, setHeight] = useState(window.innerHeight - 50);
|
||||
const [showChat, setShowChat] = useState(true);
|
||||
const ref = useRef<HTMLHeadingElement>(null);
|
||||
const moved = useRef(false);
|
||||
const setting = useRef("");
|
||||
|
||||
const [theme, setTheme] = useState(true);
|
||||
|
||||
const onMouseMove = (e: MouseEvent) => {
|
||||
if (setting.current === "position") {
|
||||
e.preventDefault();
|
||||
setX(e.x - 20);
|
||||
setY(e.y - 20);
|
||||
}
|
||||
if (setting.current === "size") {
|
||||
setWidth(e.x - x);
|
||||
setHeight(e.y - y);
|
||||
e.preventDefault();
|
||||
}
|
||||
moved.current = true;
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
document.removeEventListener("mousemove", onMouseMove);
|
||||
document.removeEventListener("mouseup", onMouseUp);
|
||||
if (!moved.current) [setShowChat((prev) => !prev)];
|
||||
moved.current = false;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={() => {
|
||||
setTheme(!theme);
|
||||
}}
|
||||
>
|
||||
Change theme
|
||||
</button>
|
||||
<Drag style={{ left: x, top: y, width: width, height: height }} ref={ref}>
|
||||
<Bubble
|
||||
onMouseDown={() => {
|
||||
setting.current = "position";
|
||||
document.addEventListener("mousemove", onMouseMove);
|
||||
document.addEventListener("mouseup", onMouseUp);
|
||||
}}
|
||||
/>
|
||||
<FloatingDiv className={showChat ? "" : "hide"}>
|
||||
<DappConnectGroupChat
|
||||
theme={theme ? lightTheme : darkTheme}
|
||||
config={{
|
||||
environment: process.env.ENV ?? "",
|
||||
dappUrl: "https://0.0.0.0:8080",
|
||||
}}
|
||||
fetchMetadata={fetchMetadata}
|
||||
/>
|
||||
</FloatingDiv>
|
||||
{showChat && (
|
||||
<SizeSet
|
||||
onMouseDown={() => {
|
||||
setting.current = "size";
|
||||
document.addEventListener("mousemove", onMouseMove);
|
||||
document.addEventListener("mouseup", onMouseUp);
|
||||
}}
|
||||
></SizeSet>
|
||||
)}
|
||||
</Drag>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const FloatingDiv = styled.div`
|
||||
height: calc(100% - 50px);
|
||||
border: 1px solid black;
|
||||
|
||||
&.hide {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const SizeSet = styled.div`
|
||||
margin-left: auto;
|
||||
margin-right: 0px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: light-grey;
|
||||
border: 1px solid;
|
||||
`;
|
||||
|
||||
const Bubble = styled.div`
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
background-color: lightblue;
|
||||
border: 1px solid;
|
||||
`;
|
||||
|
||||
const Drag = styled.div`
|
||||
position: absolute;
|
||||
min-width: 375px;
|
||||
`;
|
||||
|
||||
ReactDOM.render(
|
||||
<div style={{ height: "100%" }}>
|
||||
<DragDiv />
|
||||
</div>,
|
||||
document.getElementById("root")
|
||||
);
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"outDir": "dist",
|
||||
"jsx": "react",
|
||||
"moduleResolution": "node",
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"composite": true,
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictPropertyInitialization": true,
|
||||
"noImplicitThis": true,
|
||||
"alwaysStrict": true,
|
||||
|
||||
/* Additional Checks */
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": false /* to set at a later stage */,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
|
||||
/* Debugging Options */
|
||||
"traceResolution": false,
|
||||
"listEmittedFiles": false,
|
||||
"listFiles": false,
|
||||
"pretty": true,
|
||||
|
||||
// Due to broken types in indirect dependencies
|
||||
"skipLibCheck": true,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./src/types",
|
||||
"../../node_modules/@types"
|
||||
]
|
||||
},
|
||||
"include": ["src"],
|
||||
"types": ["mocha"],
|
||||
"compileOnSave": false
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,88 @@
|
|||
const path = require('path');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
const { ESBuildMinifyPlugin } = require('esbuild-loader');
|
||||
|
||||
module.exports = env => {
|
||||
const environment = env.ENV || 'development';
|
||||
const communityKey = env.COMMUNITY_KEY || '';
|
||||
|
||||
return {
|
||||
entry: './src/index.tsx',
|
||||
output: {
|
||||
filename: 'index.[fullhash].js',
|
||||
path: path.join(__dirname, 'dist'),
|
||||
publicPath: '/',
|
||||
},
|
||||
devtool: 'source-map',
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js', '.json'],
|
||||
fallback: {
|
||||
buffer: require.resolve('buffer/'),
|
||||
crypto: require.resolve('crypto-browserify'),
|
||||
stream: require.resolve('stream-browserify'),
|
||||
assert: require.resolve('assert/'),
|
||||
http: require.resolve('stream-http'),
|
||||
https: require.resolve('https-browserify'),
|
||||
zlib: require.resolve('browserify-zlib')
|
||||
},
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
loader: 'esbuild-loader',
|
||||
exclude: /node_modules/,
|
||||
options: {
|
||||
loader: 'tsx',
|
||||
target: 'es2018',
|
||||
},
|
||||
},
|
||||
{
|
||||
enforce: 'pre',
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'source-map-loader',
|
||||
},
|
||||
{
|
||||
test: /\.(png|svg|jpg|gif|woff|woff2|eot|ttf|otf|ico)$/,
|
||||
use: ['file-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: ['style-loader', 'css-loader'],
|
||||
},
|
||||
],
|
||||
},
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new ESBuildMinifyPlugin({
|
||||
target: 'es2018',
|
||||
}),
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'src/index.html',
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.ENV': JSON.stringify(environment),
|
||||
'process.env.COMMUNITY_KEY': JSON.stringify(communityKey),
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
process: 'process/browser.js',
|
||||
Buffer: ['buffer', 'Buffer'],
|
||||
}),
|
||||
],
|
||||
devServer: {
|
||||
historyApiFallback: true,
|
||||
host: '0.0.0.0',
|
||||
stats: 'errors-only',
|
||||
overlay: true,
|
||||
hot: true,
|
||||
},
|
||||
stats: 'minimal',
|
||||
};
|
||||
};
|
54
yarn.lock
54
yarn.lock
|
@ -1343,6 +1343,60 @@ __metadata:
|
|||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@waku/react-group-chat-sdk-example@workspace:packages/react-group-chat-example":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@waku/react-group-chat-sdk-example@workspace:packages/react-group-chat-example"
|
||||
dependencies:
|
||||
"@testing-library/react-hooks": ^7.0.1
|
||||
"@types/chai": ^4.2.21
|
||||
"@types/mocha": ^9.0.0
|
||||
"@types/node": ^16.4.12
|
||||
"@types/react": ^17.0.15
|
||||
"@types/react-dom": ^17.0.9
|
||||
"@types/react-router": ^5.1.16
|
||||
"@types/react-router-dom": ^5.1.8
|
||||
"@types/styled-components": ^5.1.12
|
||||
"@typescript-eslint/eslint-plugin": ^4.29.0
|
||||
"@typescript-eslint/parser": ^4.29.0
|
||||
"@waku/react-chat-sdk": ^0.1.0
|
||||
assert: ^2.0.0
|
||||
browserify-zlib: ^0.2.0
|
||||
buffer: ^6.0.3
|
||||
chai: ^4.3.4
|
||||
crypto-browserify: ^3.12.0
|
||||
css-loader: ^6.3.0
|
||||
esbuild-loader: ^2.15.1
|
||||
eslint: ^7.32.0
|
||||
eslint-plugin-hooks: ^0.2.0
|
||||
eslint-plugin-react: ^7.24.0
|
||||
file-loader: ^6.2.0
|
||||
fork-ts-checker-webpack-plugin: ^6.3.1
|
||||
html-webpack-plugin: ^5.3.2
|
||||
https-browserify: ^1.0.0
|
||||
jsdom: ^16.7.0
|
||||
jsdom-global: ^3.0.2
|
||||
mocha: ^9.0.3
|
||||
npm-run-all: ^4.1.5
|
||||
prettier: ^2.3.2
|
||||
process: ^0.11.10
|
||||
react: ^17.0.2
|
||||
react-dom: ^17.0.2
|
||||
react-router-dom: ^5.2.0
|
||||
rimraf: ^3.0.2
|
||||
source-map-loader: ^3.0.0
|
||||
stream-browserify: ^3.0.0
|
||||
stream-http: ^3.2.0
|
||||
style-loader: ^3.3.0
|
||||
styled-components: ^5.3.1
|
||||
ts-loader: ^9.2.5
|
||||
ts-node: ^10.1.0
|
||||
typescript: ^4.3.5
|
||||
webpack: ^5.48.0
|
||||
webpack-cli: ^4.7.2
|
||||
webpack-dev-server: ^3.11.2
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@waku/status-communities@^0.1.0, @waku/status-communities@workspace:packages/status-communities":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@waku/status-communities@workspace:packages/status-communities"
|
||||
|
|
Loading…
Reference in New Issue