Add community dialog (#30)
This commit is contained in:
parent
654c0c29d7
commit
a4e2aee6f2
|
@ -0,0 +1,62 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { Theme } from "../../styles/themes";
|
||||||
|
|
||||||
|
const userAgent = window.navigator.userAgent;
|
||||||
|
const platform = window.navigator.platform;
|
||||||
|
const macosPlatforms = ["Macintosh", "MacIntel", "MacPPC", "Mac68K"];
|
||||||
|
const windowsPlatforms = ["Win32", "Win64", "Windows", "WinCE"];
|
||||||
|
const iosPlatforms = ["iPhone", "iPad", "iPod"];
|
||||||
|
|
||||||
|
export const DownloadButton = ({ theme }: { theme: Theme }) => {
|
||||||
|
const [link, setlink] = useState("https://status.im/get/");
|
||||||
|
const [os, setOs] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (macosPlatforms.includes(platform)) {
|
||||||
|
setlink(
|
||||||
|
"https://status-im-files.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-v0.3.0-beta-a8c37d.dmg"
|
||||||
|
);
|
||||||
|
setOs("Mac");
|
||||||
|
} else if (iosPlatforms.includes(platform)) {
|
||||||
|
setlink(
|
||||||
|
"https://apps.apple.com/us/app/status-private-communication/id1178893006"
|
||||||
|
);
|
||||||
|
setOs("iOS");
|
||||||
|
} else if (windowsPlatforms.includes(platform)) {
|
||||||
|
setlink(
|
||||||
|
"https://status-im-files.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-v0.3.0-beta-a8c37d.exe"
|
||||||
|
);
|
||||||
|
setOs("Windows");
|
||||||
|
} else if (/Android/.test(userAgent)) {
|
||||||
|
setlink(
|
||||||
|
"https://play.google.com/store/apps/details?id=im.status.ethereum"
|
||||||
|
);
|
||||||
|
setOs("Android");
|
||||||
|
} else if (/Linux/.test(platform)) {
|
||||||
|
setlink(
|
||||||
|
"https://status-im-files.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-v0.3.0-beta-a8c37d.tar.gz"
|
||||||
|
);
|
||||||
|
setOs("Linux");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link href={link} theme={theme} target="_blank" rel="noopener noreferrer">
|
||||||
|
{os ? `Download Status for ${os}` : "Download Status"}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Link = styled.a`
|
||||||
|
margin-top: 24px;
|
||||||
|
padding: 11px 32px;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 22px;
|
||||||
|
text-align: center;
|
||||||
|
color: ${({ theme }) => theme.tertiary};
|
||||||
|
background: ${({ theme }) => theme.buttonBg};
|
||||||
|
border-radius: 8px;
|
||||||
|
`;
|
|
@ -5,8 +5,9 @@ import { ChannelData, channels } from "../helpers/channelsMock";
|
||||||
import { CommunityData } from "../helpers/communityMock";
|
import { CommunityData } from "../helpers/communityMock";
|
||||||
import { Theme } from "../styles/themes";
|
import { Theme } from "../styles/themes";
|
||||||
|
|
||||||
import { Community, MembersAmount } from "./Community";
|
import { Community } from "./Community";
|
||||||
import { MutedIcon } from "./Icons/MutedIcon";
|
import { MutedIcon } from "./Icons/MutedIcon";
|
||||||
|
import { textMediumStyles } from "./Text";
|
||||||
|
|
||||||
interface ChannelsProps {
|
interface ChannelsProps {
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
|
@ -37,7 +38,7 @@ export function Channels({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChannelsWrapper theme={theme}>
|
<ChannelsWrapper theme={theme}>
|
||||||
<Community community={community} theme={theme} />
|
<StyledCommunity theme={theme} community={community} />
|
||||||
<ChannelList>
|
<ChannelList>
|
||||||
{channels.map((channel) => (
|
{channels.map((channel) => (
|
||||||
<Channel
|
<Channel
|
||||||
|
@ -139,6 +140,18 @@ const ChannelsWrapper = styled.div<ThemeProps>`
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledCommunity = styled(Community)`
|
||||||
|
padding-left: 0 0 0 10px;
|
||||||
|
margin: 0 0 16px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const MembersAmount = styled.p<ThemeProps>`
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
letter-spacing: 0.1px;
|
||||||
|
color: ${({ theme }) => theme.secondary};
|
||||||
|
`;
|
||||||
|
|
||||||
const ChannelList = styled.div`
|
const ChannelList = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -193,11 +206,10 @@ const ChannelLogo = styled.div<ThemeProps>`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ChannelName = styled.p<ThemeProps>`
|
const ChannelName = styled.p<ThemeProps>`
|
||||||
color: ${({ theme }) => theme.textPrimaryColor};
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 15px;
|
|
||||||
line-height: 22px;
|
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
color: ${({ theme }) => theme.primary};
|
||||||
|
${textMediumStyles}
|
||||||
|
|
||||||
&.active,
|
&.active,
|
||||||
&.notified {
|
&.notified {
|
||||||
|
|
|
@ -34,13 +34,13 @@ export function ChatInput({ theme, addMessage }: ChatInputProps) {
|
||||||
onSelect={addEmoji}
|
onSelect={addEmoji}
|
||||||
theme={theme === lightTheme ? "light" : "dark"}
|
theme={theme === lightTheme ? "light" : "dark"}
|
||||||
set="apple"
|
set="apple"
|
||||||
color={theme.memberNameColor}
|
color={theme.tertiary}
|
||||||
emojiSize={26}
|
emojiSize={26}
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
bottom: "100%",
|
bottom: "100%",
|
||||||
right: "0",
|
right: "0",
|
||||||
color: theme.textSecondaryColor,
|
color: theme.secondary,
|
||||||
}}
|
}}
|
||||||
showPreview={false}
|
showPreview={false}
|
||||||
showSkinTones={false}
|
showSkinTones={false}
|
||||||
|
@ -106,7 +106,7 @@ const Input = styled.textarea<ThemeProps>`
|
||||||
background: ${({ theme }) => theme.inputColor};
|
background: ${({ theme }) => theme.inputColor};
|
||||||
border-radius: 36px 16px 4px 36px;
|
border-radius: 36px 16px 4px 36px;
|
||||||
border: 1px solid ${({ theme }) => theme.inputColor};
|
border: 1px solid ${({ theme }) => theme.inputColor};
|
||||||
color: ${({ theme }) => theme.textPrimaryColor};
|
color: ${({ theme }) => theme.primary};
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
padding-top: 9px;
|
padding-top: 9px;
|
||||||
padding-bottom: 9px;
|
padding-bottom: 9px;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import styled from "styled-components";
|
||||||
import { ChatMessage } from "../../models/ChatMessage";
|
import { ChatMessage } from "../../models/ChatMessage";
|
||||||
import { Theme } from "../../styles/themes";
|
import { Theme } from "../../styles/themes";
|
||||||
import { UserIcon } from "../Icons/UserIcon";
|
import { UserIcon } from "../Icons/UserIcon";
|
||||||
|
import { textSmallStyles } from "../Text";
|
||||||
|
|
||||||
import { ChatMessageContent } from "./ChatMessageContent";
|
import { ChatMessageContent } from "./ChatMessageContent";
|
||||||
|
|
||||||
|
@ -94,11 +95,11 @@ const DateSeparator = styled.div`
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 13px;
|
|
||||||
line-height: 18px;
|
|
||||||
color: #939ba1;
|
color: #939ba1;
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
${textSmallStyles}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ContentWrapper = styled.div`
|
const ContentWrapper = styled.div`
|
||||||
|
@ -126,7 +127,7 @@ export const Icon = styled.div`
|
||||||
const UserNameWrapper = styled.div<ThemeProps>`
|
const UserNameWrapper = styled.div<ThemeProps>`
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
color: ${({ theme }) => theme.memberNameColor};
|
color: ${({ theme }) => theme.tertiary};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const TimeWrapper = styled.div<ThemeProps>`
|
const TimeWrapper = styled.div<ThemeProps>`
|
||||||
|
@ -134,7 +135,7 @@ const TimeWrapper = styled.div<ThemeProps>`
|
||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
letter-spacing: 0.2px;
|
letter-spacing: 0.2px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: ${({ theme }) => theme.textSecondaryColor};
|
color: ${({ theme }) => theme.secondary};
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -142,5 +143,5 @@ const MessageText = styled.div<ThemeProps>`
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
color: ${({ theme }) => theme.textPrimaryColor};
|
color: ${({ theme }) => theme.primary};
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -1,57 +1,42 @@
|
||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import styled from "styled-components";
|
|
||||||
|
|
||||||
import { CommunityData } from "../helpers/communityMock";
|
import { CommunityData } from "../helpers/communityMock";
|
||||||
import { Theme } from "../styles/themes";
|
import { Theme } from "../styles/themes";
|
||||||
|
|
||||||
|
import { CommunityIdentity } from "./CommunityIdentity";
|
||||||
|
import { CommunityModal } from "./Modals/CommunityModal";
|
||||||
|
|
||||||
interface CommunityProps {
|
interface CommunityProps {
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
community: CommunityData;
|
community: CommunityData;
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Community({ theme, community }: CommunityProps) {
|
export function Community({ theme, community, className }: CommunityProps) {
|
||||||
|
const { name, icon, members, description } = community;
|
||||||
|
|
||||||
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommunityWrap>
|
<>
|
||||||
<CommunityLogo src={community.icon} alt={`${community.name} logo`} />
|
<button className={className} onClick={() => setIsModalVisible(true)}>
|
||||||
<CommunityInfo>
|
<CommunityIdentity
|
||||||
<CommunityName theme={theme}>{community.name}</CommunityName>
|
name={name}
|
||||||
<MembersAmount theme={theme}>{community.members} members</MembersAmount>
|
icon={icon}
|
||||||
</CommunityInfo>
|
subtitle={`${members} members`}
|
||||||
</CommunityWrap>
|
theme={theme}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<CommunityModal
|
||||||
|
isVisible={isModalVisible}
|
||||||
|
onClose={() => setIsModalVisible(false)}
|
||||||
|
icon={icon}
|
||||||
|
name={name}
|
||||||
|
theme={theme}
|
||||||
|
subtitle="Public Community"
|
||||||
|
description={description}
|
||||||
|
publicKey="0xD95DBdaB08A9FED2D71ac9C3028AAc40905d8CF3"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
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};
|
|
||||||
`;
|
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { Theme } from "../styles/themes";
|
||||||
|
|
||||||
|
import { textMediumStyles } from "./Text";
|
||||||
|
|
||||||
|
export interface CommunityIdentityProps {
|
||||||
|
icon: string;
|
||||||
|
name: string;
|
||||||
|
subtitle: string;
|
||||||
|
theme: Theme;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CommunityIdentity = ({
|
||||||
|
icon,
|
||||||
|
name,
|
||||||
|
subtitle,
|
||||||
|
className,
|
||||||
|
theme,
|
||||||
|
}: CommunityIdentityProps) => {
|
||||||
|
return (
|
||||||
|
<Row className={className}>
|
||||||
|
<Logo src={icon} alt={`${name} logo`} />
|
||||||
|
<div>
|
||||||
|
<Name theme={theme}>{name}</Name>
|
||||||
|
<Subtitle theme={theme}>{subtitle}</Subtitle>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Row = styled.div`
|
||||||
|
display: flex;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Logo = styled.img`
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Name = styled.p`
|
||||||
|
font-weight: 500;
|
||||||
|
color: ${({ theme }) => theme.primary};
|
||||||
|
|
||||||
|
${textMediumStyles}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Subtitle = styled.p`
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
letter-spacing: 0.1px;
|
||||||
|
color: ${({ theme }) => theme.secondary};
|
||||||
|
`;
|
|
@ -0,0 +1,75 @@
|
||||||
|
import React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { Theme } from "../../styles/themes";
|
||||||
|
import { copy } from "../../utils/copy";
|
||||||
|
import { reduceString } from "../../utils/reduceString";
|
||||||
|
import { textMediumStyles, textSmallStyles } from "../Text";
|
||||||
|
|
||||||
|
interface CopyInputProps {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
theme: Theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CopyInput = ({ label, value, theme }: CopyInputProps) => (
|
||||||
|
<div>
|
||||||
|
<Label theme={theme}>{label}</Label>
|
||||||
|
<Wrapper theme={theme}>
|
||||||
|
<Text theme={theme}>{reduceString(value, 15, 15)}</Text>
|
||||||
|
<CopyButtonWrapper>
|
||||||
|
<CopyButton theme={theme} onClick={() => copy(value)}>
|
||||||
|
Copy
|
||||||
|
</CopyButton>
|
||||||
|
</CopyButtonWrapper>
|
||||||
|
</Wrapper>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Label = styled.p`
|
||||||
|
margin-bottom: 7px;
|
||||||
|
font-weight: 500;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: ${({ theme }) => theme.primary};
|
||||||
|
|
||||||
|
${textSmallStyles}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
position: relative;
|
||||||
|
padding: 14px 70px 14px 8px;
|
||||||
|
background: ${({ theme }) => theme.inputColor};
|
||||||
|
border-radius: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Text = styled.p`
|
||||||
|
color: ${({ theme }) => theme.primary};
|
||||||
|
|
||||||
|
${textMediumStyles}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CopyButtonWrapper = styled.div`
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 70px;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
background: ${({ theme }) => theme.inputColor};
|
||||||
|
border-radius: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CopyButton = styled.button`
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
letter-spacing: 0.1px;
|
||||||
|
color: ${({ theme }) => theme.tertiary};
|
||||||
|
background: ${({ theme }) => theme.buttonBg};
|
||||||
|
border: 1px solid ${({ theme }) => theme.tertiary};
|
||||||
|
border-radius: 6px;
|
||||||
|
`;
|
|
@ -0,0 +1,28 @@
|
||||||
|
import React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { Theme } from "../../styles/themes";
|
||||||
|
|
||||||
|
export const CrossIcon = ({ theme }: { theme: Theme }) => (
|
||||||
|
<Icon
|
||||||
|
theme={theme}
|
||||||
|
width="12"
|
||||||
|
height="12"
|
||||||
|
viewBox="0 0 12 12"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M6 4.57404L1.72275 0.296796C1.32616 -0.0997918 0.689941 -0.0975927 0.296174 0.296174C-0.100338 0.692686 -0.0973145 1.32864 0.296796 1.72275L4.57404 6L0.296796 10.2772C-0.0997918 10.6738 -0.0975927 11.3101 0.296174 11.7038C0.692686 12.1003 1.32864 12.0973 1.72275 11.7032L6 7.42596L10.2772 11.7032C10.6738 12.0998 11.3101 12.0976 11.7038 11.7038C12.1003 11.3073 12.0973 10.6714 11.7032 10.2772L7.42596 6L11.7032 1.72275C12.0998 1.32616 12.0976 0.689941 11.7038 0.296174C11.3073 -0.100338 10.6714 -0.0973145 10.2772 0.296796L6 4.57404Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
</Icon>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Icon = styled.svg`
|
||||||
|
& > path {
|
||||||
|
fill: ${({ theme }) => theme.primary};
|
||||||
|
}
|
||||||
|
`;
|
|
@ -41,10 +41,10 @@ export const EmojiIcon = ({ theme, isActive }: ThemeProps) => {
|
||||||
|
|
||||||
const Icon = styled.svg<ThemeProps>`
|
const Icon = styled.svg<ThemeProps>`
|
||||||
& > path {
|
& > path {
|
||||||
fill: ${({ theme }) => theme.textSecondaryColor};
|
fill: ${({ theme }) => theme.secondary};
|
||||||
}
|
}
|
||||||
|
|
||||||
& > path.active {
|
& > path.active {
|
||||||
fill: ${({ theme }) => theme.memberNameColor};
|
fill: ${({ theme }) => theme.tertiary};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -41,10 +41,10 @@ export const GifIcon = ({ theme, isActive }: ThemeProps) => {
|
||||||
|
|
||||||
const Icon = styled.svg<ThemeProps>`
|
const Icon = styled.svg<ThemeProps>`
|
||||||
& > path {
|
& > path {
|
||||||
fill: ${({ theme }) => theme.textSecondaryColor};
|
fill: ${({ theme }) => theme.secondary};
|
||||||
}
|
}
|
||||||
|
|
||||||
& > path.active {
|
& > path.active {
|
||||||
fill: ${({ theme }) => theme.memberNameColor};
|
fill: ${({ theme }) => theme.tertiary};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -28,6 +28,6 @@ export const MembersIcon = ({ theme }: ThemeProps) => {
|
||||||
|
|
||||||
const Icon = styled.svg<ThemeProps>`
|
const Icon = styled.svg<ThemeProps>`
|
||||||
& > path {
|
& > path {
|
||||||
fill: ${({ theme }) => theme.textPrimaryColor};
|
fill: ${({ theme }) => theme.primary};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -30,6 +30,6 @@ export const MutedIcon = ({ theme }: ThemeProps) => {
|
||||||
|
|
||||||
const Icon = styled.svg<ThemeProps>`
|
const Icon = styled.svg<ThemeProps>`
|
||||||
& > path {
|
& > path {
|
||||||
fill: ${({ theme }) => theme.textPrimaryColor};
|
fill: ${({ theme }) => theme.primary};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -32,6 +32,6 @@ export const PictureIcon = ({ theme }: ThemeProps) => {
|
||||||
|
|
||||||
const Icon = styled.svg<ThemeProps>`
|
const Icon = styled.svg<ThemeProps>`
|
||||||
& > path {
|
& > path {
|
||||||
fill: ${({ theme }) => theme.textSecondaryColor};
|
fill: ${({ theme }) => theme.secondary};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -33,10 +33,10 @@ export const StickerIcon = ({ theme, isActive }: ThemeProps) => {
|
||||||
|
|
||||||
const Icon = styled.svg<ThemeProps>`
|
const Icon = styled.svg<ThemeProps>`
|
||||||
& > path {
|
& > path {
|
||||||
fill: ${({ theme }) => theme.textSecondaryColor};
|
fill: ${({ theme }) => theme.secondary};
|
||||||
}
|
}
|
||||||
|
|
||||||
& > path.active {
|
& > path.active {
|
||||||
fill: ${({ theme }) => theme.memberNameColor};
|
fill: ${({ theme }) => theme.tertiary};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
import React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { DownloadButton } from "../Buttons/DownloadButton";
|
||||||
|
import {
|
||||||
|
CommunityIdentity,
|
||||||
|
CommunityIdentityProps,
|
||||||
|
} from "../CommunityIdentity";
|
||||||
|
import { CopyInput } from "../Form/CopyInput";
|
||||||
|
import { StatusLogo } from "../Icons/StatusLogo";
|
||||||
|
import { textMediumStyles, textSmallStyles } from "../Text";
|
||||||
|
|
||||||
|
import { BasicModalProps, Modal } from "./Modal";
|
||||||
|
|
||||||
|
interface CommunityModalProps extends BasicModalProps, CommunityIdentityProps {
|
||||||
|
description: string;
|
||||||
|
publicKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CommunityModal = ({
|
||||||
|
isVisible,
|
||||||
|
onClose,
|
||||||
|
icon,
|
||||||
|
name,
|
||||||
|
subtitle,
|
||||||
|
description,
|
||||||
|
publicKey,
|
||||||
|
theme,
|
||||||
|
}: CommunityModalProps) => {
|
||||||
|
return (
|
||||||
|
<Modal theme={theme} isVisible={isVisible} onClose={onClose}>
|
||||||
|
<Section theme={theme}>
|
||||||
|
<CommunityIdentity
|
||||||
|
theme={theme}
|
||||||
|
icon={icon}
|
||||||
|
name={name}
|
||||||
|
subtitle={subtitle}
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
|
<Section theme={theme}>
|
||||||
|
<Text theme={theme}>{description}</Text>
|
||||||
|
</Section>
|
||||||
|
<Section theme={theme}>
|
||||||
|
<CopyInput
|
||||||
|
theme={theme}
|
||||||
|
value={publicKey}
|
||||||
|
label="Community public key"
|
||||||
|
/>
|
||||||
|
<Hint theme={theme}>
|
||||||
|
To access this community, paste community public key in Status desktop
|
||||||
|
or mobile app
|
||||||
|
</Hint>
|
||||||
|
</Section>
|
||||||
|
<BottomSection theme={theme}>
|
||||||
|
<StatusLogo theme={theme} />
|
||||||
|
<DownloadButton theme={theme} />
|
||||||
|
</BottomSection>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Section = styled.div`
|
||||||
|
padding: 20px 16px;
|
||||||
|
|
||||||
|
& + & {
|
||||||
|
border-top: 1px solid ${({ theme }) => theme.border};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Text = styled.p`
|
||||||
|
color: ${({ theme }) => theme.primary};
|
||||||
|
|
||||||
|
${textMediumStyles}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Hint = styled.p`
|
||||||
|
margin-top: 16px;
|
||||||
|
color: ${({ theme }) => theme.secondary};
|
||||||
|
|
||||||
|
${textSmallStyles}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const BottomSection = styled(Section)`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
|
@ -0,0 +1,100 @@
|
||||||
|
import React, { ReactNode, useCallback, useEffect } from "react";
|
||||||
|
import { createPortal } from "react-dom";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { Theme } from "../../styles/themes";
|
||||||
|
import { CrossIcon } from "../Icons/CrossIcon";
|
||||||
|
|
||||||
|
export interface BasicModalProps {
|
||||||
|
isVisible: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
className?: string;
|
||||||
|
theme: Theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModalProps extends BasicModalProps {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Modal = ({
|
||||||
|
isVisible,
|
||||||
|
onClose,
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
theme,
|
||||||
|
}: ModalProps) => {
|
||||||
|
const listenKeyboard = useCallback(
|
||||||
|
(event: KeyboardEvent) => {
|
||||||
|
if (event.key === "Escape" || event.keyCode === 27) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onClose]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isVisible) {
|
||||||
|
window.addEventListener("keydown", listenKeyboard, true);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("keydown", listenKeyboard, true);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, [isVisible, listenKeyboard]);
|
||||||
|
|
||||||
|
if (!isVisible) return null;
|
||||||
|
|
||||||
|
return createPortal(
|
||||||
|
<ModalView>
|
||||||
|
<ModalOverlay onClick={onClose} theme={theme} />
|
||||||
|
<ModalBody theme={theme} className={className}>
|
||||||
|
<CloseButton onClick={onClose}>
|
||||||
|
<CrossIcon theme={theme} />
|
||||||
|
</CloseButton>
|
||||||
|
{children}
|
||||||
|
</ModalBody>
|
||||||
|
</ModalView>,
|
||||||
|
document.body
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ModalView = styled.div`
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 9999;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ModalBody = styled.div`
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
max-width: 480px;
|
||||||
|
width: 100%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background: ${({ theme }) => theme.bodyBackgroundColor};
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow-y: auto;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ModalOverlay = styled.div`
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: ${({ theme }) => theme.primary};
|
||||||
|
opacity: 0.4;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CloseButton = styled.button`
|
||||||
|
position: absolute;
|
||||||
|
top: 12px;
|
||||||
|
right: 12px;
|
||||||
|
padding: 10px;
|
||||||
|
`;
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { css } from "styled-components";
|
||||||
|
|
||||||
|
export const textSmallStyles = css`
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 18px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const textMediumStyles = css`
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 22px;
|
||||||
|
`;
|
|
@ -3,6 +3,7 @@ export type CommunityData = {
|
||||||
name: string;
|
name: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
members: number;
|
members: number;
|
||||||
|
description: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const community = {
|
export const community = {
|
||||||
|
@ -10,4 +11,5 @@ export const community = {
|
||||||
name: "CryptoKitties",
|
name: "CryptoKitties",
|
||||||
icon: "https://www.cryptokitties.co/icons/logo.svg",
|
icon: "https://www.cryptokitties.co/icons/logo.svg",
|
||||||
members: 186,
|
members: 186,
|
||||||
|
description: "A community of cat lovers, meow!",
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
export type Theme = {
|
export type Theme = {
|
||||||
textPrimaryColor: string;
|
primary: string;
|
||||||
textSecondaryColor: string;
|
secondary: string;
|
||||||
bodyBackgroundColor: string;
|
bodyBackgroundColor: string;
|
||||||
sectionBackgroundColor: string;
|
sectionBackgroundColor: string;
|
||||||
memberNameColor: string;
|
tertiary: string;
|
||||||
guestNameColor: string;
|
guestNameColor: string;
|
||||||
iconColor: string;
|
iconColor: string;
|
||||||
iconUserColor: string;
|
iconUserColor: string;
|
||||||
|
@ -11,14 +11,16 @@ export type Theme = {
|
||||||
activeChannelBackground: string;
|
activeChannelBackground: string;
|
||||||
notificationColor: string;
|
notificationColor: string;
|
||||||
inputColor: string;
|
inputColor: string;
|
||||||
|
border: string;
|
||||||
|
buttonBg: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const lightTheme: Theme = {
|
export const lightTheme: Theme = {
|
||||||
textPrimaryColor: "#000",
|
primary: "#000",
|
||||||
textSecondaryColor: "#939BA1",
|
secondary: "#939BA1",
|
||||||
|
tertiary: "#4360DF",
|
||||||
bodyBackgroundColor: "#fff",
|
bodyBackgroundColor: "#fff",
|
||||||
sectionBackgroundColor: "#F6F8FA",
|
sectionBackgroundColor: "#F6F8FA",
|
||||||
memberNameColor: "#4360DF",
|
|
||||||
guestNameColor: "#887AF9",
|
guestNameColor: "#887AF9",
|
||||||
iconColor: "#D37EF4",
|
iconColor: "#D37EF4",
|
||||||
iconUserColor: "#717199",
|
iconUserColor: "#717199",
|
||||||
|
@ -26,14 +28,16 @@ export const lightTheme: Theme = {
|
||||||
activeChannelBackground: "#E9EDF1",
|
activeChannelBackground: "#E9EDF1",
|
||||||
notificationColor: "#4360DF",
|
notificationColor: "#4360DF",
|
||||||
inputColor: "#EEF2F5",
|
inputColor: "#EEF2F5",
|
||||||
|
border: "#EEF2F5",
|
||||||
|
buttonBg: "rgba(67, 96, 223, 0.2)",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const darkTheme: Theme = {
|
export const darkTheme: Theme = {
|
||||||
textPrimaryColor: "#fff",
|
primary: "#fff",
|
||||||
textSecondaryColor: "#909090",
|
secondary: "#909090",
|
||||||
|
tertiary: "#88B0FF",
|
||||||
bodyBackgroundColor: "#000",
|
bodyBackgroundColor: "#000",
|
||||||
sectionBackgroundColor: "#252525",
|
sectionBackgroundColor: "#252525",
|
||||||
memberNameColor: "#88B0FF",
|
|
||||||
guestNameColor: "#887AF9",
|
guestNameColor: "#887AF9",
|
||||||
iconColor: "#D37EF4",
|
iconColor: "#D37EF4",
|
||||||
iconUserColor: "#717199",
|
iconUserColor: "#717199",
|
||||||
|
@ -41,6 +45,8 @@ export const darkTheme: Theme = {
|
||||||
activeChannelBackground: "#2C2C2C",
|
activeChannelBackground: "#2C2C2C",
|
||||||
notificationColor: "#887AF9",
|
notificationColor: "#887AF9",
|
||||||
inputColor: "#373737",
|
inputColor: "#373737",
|
||||||
|
border: "#373737",
|
||||||
|
buttonBg: "rgba(134, 158, 255, 0.3)",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default { lightTheme, darkTheme };
|
export default { lightTheme, darkTheme };
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export const copy = (text: string) => {
|
||||||
|
navigator.clipboard.writeText(text).catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
};
|
|
@ -0,0 +1,9 @@
|
||||||
|
export const reduceString = (
|
||||||
|
string: string,
|
||||||
|
limitBefore: number,
|
||||||
|
limitAfter: number
|
||||||
|
) => {
|
||||||
|
return `${string.substring(0, limitBefore)}...${string.substring(
|
||||||
|
string.length - limitAfter
|
||||||
|
)}`;
|
||||||
|
};
|
Loading…
Reference in New Issue