Extract channel component (#27)
This commit is contained in:
parent
f0dec3d5af
commit
e4710c3445
|
@ -2,26 +2,25 @@ import React, { useEffect } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { ChannelData, channels } from "../helpers/channelsMock";
|
import { ChannelData, channels } from "../helpers/channelsMock";
|
||||||
|
import { CommunityData } from "../helpers/communityMock";
|
||||||
import { Theme } from "../styles/themes";
|
import { Theme } from "../styles/themes";
|
||||||
|
|
||||||
|
import { Community, MembersAmount } from "./Community";
|
||||||
import { MutedIcon } from "./Icons/MutedIcon";
|
import { MutedIcon } from "./Icons/MutedIcon";
|
||||||
|
|
||||||
interface ChannelsProps {
|
interface ChannelsProps {
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
icon: string;
|
community: CommunityData;
|
||||||
name: string;
|
|
||||||
notifications: { [id: string]: number };
|
notifications: { [id: string]: number };
|
||||||
clearNotifications: (id: string) => void;
|
clearNotifications: (id: string) => void;
|
||||||
members: number;
|
|
||||||
setActiveChannel: (val: ChannelData) => void;
|
setActiveChannel: (val: ChannelData) => void;
|
||||||
activeChannelId: number;
|
activeChannelId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Channels({
|
export function Channels({
|
||||||
theme,
|
theme,
|
||||||
icon,
|
community,
|
||||||
name,
|
|
||||||
members,
|
|
||||||
notifications,
|
notifications,
|
||||||
setActiveChannel,
|
setActiveChannel,
|
||||||
clearNotifications,
|
clearNotifications,
|
||||||
|
@ -38,13 +37,7 @@ export function Channels({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChannelsWrapper theme={theme}>
|
<ChannelsWrapper theme={theme}>
|
||||||
<Community>
|
<Community community={community} theme={theme} />
|
||||||
<CommunityLogo src={icon} alt={`${name} logo`} />
|
|
||||||
<CommunityInfo>
|
|
||||||
<CommunityName theme={theme}>{name}</CommunityName>
|
|
||||||
<MembersAmount theme={theme}>{members} members</MembersAmount>
|
|
||||||
</CommunityInfo>
|
|
||||||
</Community>
|
|
||||||
<ChannelList>
|
<ChannelList>
|
||||||
{channels.map((channel) => (
|
{channels.map((channel) => (
|
||||||
<Channel
|
<Channel
|
||||||
|
@ -146,41 +139,10 @@ const ChannelsWrapper = styled.div<ThemeProps>`
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Community = styled.div`
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const CommunityLogo = styled.img`
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-left: 10px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const CommunityInfo = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-left: 8px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const CommunityName = styled.h1<ThemeProps>`
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 22px;
|
|
||||||
color: ${({ theme }) => theme.textPrimaryColor};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const MembersAmount = styled.p<ThemeProps>`
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 16px;
|
|
||||||
letter-spacing: 0.1px;
|
|
||||||
color: ${({ theme }) => theme.textSecondaryColor};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const ChannelList = styled.div`
|
const ChannelList = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
margin-top: 16px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ChannelWrapper = styled.div<ThemeProps>`
|
const ChannelWrapper = styled.div<ThemeProps>`
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, { useState } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { ChannelData, channels } from "../helpers/channelsMock";
|
import { ChannelData, channels } from "../helpers/channelsMock";
|
||||||
|
import { CommunityData } from "../helpers/communityMock";
|
||||||
import { useMessenger } from "../hooks/useMessenger";
|
import { useMessenger } from "../hooks/useMessenger";
|
||||||
import { Theme } from "../styles/themes";
|
import { Theme } from "../styles/themes";
|
||||||
|
|
||||||
|
@ -11,12 +12,13 @@ import { Members } from "./Members";
|
||||||
|
|
||||||
interface ChatProps {
|
interface ChatProps {
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
channelsON?: boolean;
|
community: CommunityData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Chat({ theme, channelsON }: ChatProps) {
|
export function Chat({ theme, community }: ChatProps) {
|
||||||
const [activeChannel, setActiveChannel] = useState<ChannelData>(channels[0]);
|
const [activeChannel, setActiveChannel] = useState<ChannelData>(channels[0]);
|
||||||
const [showMembers, setShowMembers] = useState(true);
|
const [showMembers, setShowMembers] = useState(true);
|
||||||
|
const [showChannels, setShowChannels] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
messenger,
|
messenger,
|
||||||
|
@ -31,14 +33,12 @@ export function Chat({ theme, channelsON }: ChatProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatWrapper>
|
<ChatWrapper>
|
||||||
{channelsON && (
|
{showChannels && (
|
||||||
<Channels
|
<Channels
|
||||||
notifications={notifications}
|
notifications={notifications}
|
||||||
clearNotifications={clearNotifications}
|
clearNotifications={clearNotifications}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
icon={"https://www.cryptokitties.co/icons/logo.svg"}
|
community={community}
|
||||||
name={"CryptoKitties"}
|
|
||||||
members={186}
|
|
||||||
setActiveChannel={setActiveChannel}
|
setActiveChannel={setActiveChannel}
|
||||||
activeChannelId={activeChannel.id}
|
activeChannelId={activeChannel.id}
|
||||||
/>
|
/>
|
||||||
|
@ -51,11 +51,19 @@ export function Chat({ theme, channelsON }: ChatProps) {
|
||||||
sendMessage={sendMessage}
|
sendMessage={sendMessage}
|
||||||
onClick={() => setShowMembers(!showMembers)}
|
onClick={() => setShowMembers(!showMembers)}
|
||||||
showMembers={showMembers}
|
showMembers={showMembers}
|
||||||
|
community={community}
|
||||||
|
showCommunity={!showChannels}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Loading>Connecting to waku</Loading>
|
<Loading>Connecting to waku</Loading>
|
||||||
)}
|
)}
|
||||||
{showMembers && <Members theme={theme} channel={activeChannel} />}
|
{showMembers && (
|
||||||
|
<Members
|
||||||
|
theme={theme}
|
||||||
|
channel={activeChannel}
|
||||||
|
setShowChannels={setShowChannels}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</ChatWrapper>
|
</ChatWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,11 @@ import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { ChannelData } from "../../helpers/channelsMock";
|
import { ChannelData } from "../../helpers/channelsMock";
|
||||||
|
import { CommunityData } from "../../helpers/communityMock";
|
||||||
import { ChatMessage } from "../../models/ChatMessage";
|
import { ChatMessage } from "../../models/ChatMessage";
|
||||||
import { Theme } from "../../styles/themes";
|
import { Theme } from "../../styles/themes";
|
||||||
import { Channel } from "../Channels";
|
import { Channel } from "../Channels";
|
||||||
|
import { Community } from "../Community";
|
||||||
import { MembersIcon } from "../Icons/MembersIcon";
|
import { MembersIcon } from "../Icons/MembersIcon";
|
||||||
|
|
||||||
import { ChatInput } from "./ChatInput";
|
import { ChatInput } from "./ChatInput";
|
||||||
|
@ -13,23 +15,33 @@ import { ChatMessages } from "./ChatMessages";
|
||||||
interface ChatBodyProps {
|
interface ChatBodyProps {
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
channel: ChannelData;
|
channel: ChannelData;
|
||||||
|
community: CommunityData;
|
||||||
messages: ChatMessage[];
|
messages: ChatMessage[];
|
||||||
sendMessage: (text: string) => void;
|
sendMessage: (text: string) => void;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
showMembers: boolean;
|
showMembers: boolean;
|
||||||
|
showCommunity: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ChatBody({
|
export function ChatBody({
|
||||||
theme,
|
theme,
|
||||||
channel,
|
channel,
|
||||||
|
community,
|
||||||
messages,
|
messages,
|
||||||
sendMessage,
|
sendMessage,
|
||||||
onClick,
|
onClick,
|
||||||
showMembers,
|
showMembers,
|
||||||
|
showCommunity,
|
||||||
}: ChatBodyProps) {
|
}: ChatBodyProps) {
|
||||||
return (
|
return (
|
||||||
<ChatBodyWrapper theme={theme}>
|
<ChatBodyWrapper theme={theme}>
|
||||||
|
<ChatTopbar>
|
||||||
<ChannelWrapper>
|
<ChannelWrapper>
|
||||||
|
{showCommunity && (
|
||||||
|
<CommunityWrap theme={theme}>
|
||||||
|
<Community community={community} theme={theme} />
|
||||||
|
</CommunityWrap>
|
||||||
|
)}
|
||||||
<Channel
|
<Channel
|
||||||
channel={channel}
|
channel={channel}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
|
@ -37,6 +49,7 @@ export function ChatBody({
|
||||||
activeView={true}
|
activeView={true}
|
||||||
isMuted={false}
|
isMuted={false}
|
||||||
/>
|
/>
|
||||||
|
</ChannelWrapper>
|
||||||
<MemberBtn
|
<MemberBtn
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className={showMembers ? "active" : ""}
|
className={showMembers ? "active" : ""}
|
||||||
|
@ -44,7 +57,7 @@ export function ChatBody({
|
||||||
>
|
>
|
||||||
<MembersIcon theme={theme} />
|
<MembersIcon theme={theme} />
|
||||||
</MemberBtn>
|
</MemberBtn>
|
||||||
</ChannelWrapper>
|
</ChatTopbar>
|
||||||
<ChatMessages messages={messages} theme={theme} />
|
<ChatMessages messages={messages} theme={theme} />
|
||||||
<ChatInput theme={theme} addMessage={sendMessage} />
|
<ChatInput theme={theme} addMessage={sendMessage} />
|
||||||
</ChatBodyWrapper>
|
</ChatBodyWrapper>
|
||||||
|
@ -59,15 +72,39 @@ const ChatBodyWrapper = styled.div<ThemeProps>`
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: ${({ theme }) => theme.bodyBackgroundColor};
|
background: ${({ theme }) => theme.textPrimaryColor};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ChannelWrapper = styled.div`
|
const ChannelWrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ChatTopbar = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const CommunityWrap = styled.div<ThemeProps>`
|
||||||
|
padding-right: 16px;
|
||||||
|
margin-right: 16px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 50%;
|
||||||
|
width: 2px;
|
||||||
|
height: 24px;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
border-radius: 1px;
|
||||||
|
background: ${({ theme }) => theme.bodyBackgroundColor};
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const MemberBtn = styled.button<ThemeProps>`
|
const MemberBtn = styled.button<ThemeProps>`
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { CommunityData } from "../helpers/communityMock";
|
||||||
|
import { Theme } from "../styles/themes";
|
||||||
|
|
||||||
|
interface CommunityProps {
|
||||||
|
theme: Theme;
|
||||||
|
community: CommunityData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Community({ theme, community }: CommunityProps) {
|
||||||
|
return (
|
||||||
|
<CommunityWrap>
|
||||||
|
<CommunityLogo src={community.icon} alt={`${community.name} logo`} />
|
||||||
|
<CommunityInfo>
|
||||||
|
<CommunityName theme={theme}>{community.name}</CommunityName>
|
||||||
|
<MembersAmount theme={theme}>{community.members} members</MembersAmount>
|
||||||
|
</CommunityInfo>
|
||||||
|
</CommunityWrap>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ThemeProps {
|
||||||
|
theme: Theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommunityWrap = styled.div`
|
||||||
|
display: flex;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CommunityLogo = styled.img`
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-left: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CommunityInfo = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CommunityName = styled.h1<ThemeProps>`
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 22px;
|
||||||
|
color: ${({ theme }) => theme.textPrimaryColor};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const MembersAmount = styled.p<ThemeProps>`
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
letter-spacing: 0.1px;
|
||||||
|
color: ${({ theme }) => theme.textSecondaryColor};
|
||||||
|
`;
|
|
@ -10,9 +10,10 @@ import { UserIcon } from "./Icons/UserIcon";
|
||||||
interface MembersProps {
|
interface MembersProps {
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
channel: ChannelData;
|
channel: ChannelData;
|
||||||
|
setShowChannels: (val: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Members({ theme, channel }: MembersProps) {
|
export function Members({ theme, channel, setShowChannels }: MembersProps) {
|
||||||
return (
|
return (
|
||||||
<MembersWrapper theme={theme}>
|
<MembersWrapper theme={theme}>
|
||||||
<MemberHeading theme={theme}>Members</MemberHeading>
|
<MemberHeading theme={theme}>Members</MemberHeading>
|
||||||
|
@ -36,6 +37,7 @@ export function Members({ theme, channel }: MembersProps) {
|
||||||
theme={theme}
|
theme={theme}
|
||||||
member={member}
|
member={member}
|
||||||
isOnline={member.isOnline}
|
isOnline={member.isOnline}
|
||||||
|
setShowChannels={setShowChannels}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</MemberCategory>
|
</MemberCategory>
|
||||||
|
@ -49,6 +51,7 @@ export function Members({ theme, channel }: MembersProps) {
|
||||||
theme={theme}
|
theme={theme}
|
||||||
member={member}
|
member={member}
|
||||||
isOnline={member.isOnline}
|
isOnline={member.isOnline}
|
||||||
|
setShowChannels={setShowChannels}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</MemberCategory>
|
</MemberCategory>
|
||||||
|
@ -61,11 +64,17 @@ interface MemberProps {
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
member: any;
|
member: any;
|
||||||
isOnline: boolean;
|
isOnline: boolean;
|
||||||
|
setShowChannels: (val: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Member({ theme, member, isOnline }: MemberProps) {
|
export function Member({
|
||||||
|
theme,
|
||||||
|
member,
|
||||||
|
isOnline,
|
||||||
|
setShowChannels,
|
||||||
|
}: MemberProps) {
|
||||||
return (
|
return (
|
||||||
<MemberData>
|
<MemberData onClick={() => setShowChannels(true)}>
|
||||||
<MemberIcon
|
<MemberIcon
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: member.avatar ? `url(${member.avatar})` : "unset",
|
backgroundImage: member.avatar ? `url(${member.avatar})` : "unset",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
import { community } from "../helpers/communityMock";
|
||||||
import { GlobalStyle } from "../styles/GlobalStyle";
|
import { GlobalStyle } from "../styles/GlobalStyle";
|
||||||
import { lightTheme } from "../styles/themes";
|
import { lightTheme } from "../styles/themes";
|
||||||
|
|
||||||
|
@ -9,7 +10,7 @@ export function ReactChat() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<GlobalStyle />
|
<GlobalStyle />
|
||||||
<Chat channelsON={true} theme={lightTheme} />
|
<Chat theme={lightTheme} community={community} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
export type CommunityData = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
icon: string;
|
||||||
|
members: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const community = {
|
||||||
|
id: 1,
|
||||||
|
name: "CryptoKitties",
|
||||||
|
icon: "https://www.cryptokitties.co/icons/logo.svg",
|
||||||
|
members: 186,
|
||||||
|
};
|
Loading…
Reference in New Issue