Commit 86c23aa9 authored by insert's avatar insert

Work on main chat.

Co-authored-by: default avatarnizune <[email protected]>
parent d9e53a1a
Pipeline #274 passed with stage
in 2 minutes and 7 seconds
import { FunctionComponent, createElement, CSSProperties, SVGProps } from 'react';
import styles from './Icon.module.scss';
import classNames from 'classnames';
import { remove } from 'flatbase/dist/util/props';
/* === SOLID ICONS === */
import { ReactComponent as cogSolid } from 'boxicons/svg/solid/bxs-cog.svg';
......@@ -19,6 +20,8 @@ import { ReactComponent as wrenchSolid } from 'boxicons/svg/solid/bxs-wrench.svg
import { ReactComponent as infoCircleSolid } from 'boxicons/svg/solid/bxs-info-circle.svg';
import { ReactComponent as helpCircleSolid } from 'boxicons/svg/solid/bxs-help-circle.svg';
import { ReactComponent as megaphoneSolid } from 'boxicons/svg/solid/bxs-megaphone.svg';
import { ReactComponent as chatSolid } from 'boxicons/svg/solid/bxs-chat.svg';
import { ReactComponent as groupSolid } from 'boxicons/svg/solid/bxs-group.svg';
/* === REGULAR ICONS === */
import { ReactComponent as plusRegular } from 'boxicons/svg/regular/bx-plus.svg';
......@@ -31,7 +34,9 @@ import { ReactComponent as logoutRegular } from 'boxicons/svg/regular/bx-log-out
import { ReactComponent as leftArrowAltRegular } from 'boxicons/svg/regular/bx-left-arrow-alt.svg';
import { ReactComponent as xRegular } from 'boxicons/svg/regular/bx-x.svg';
import { ReactComponent as checkRegular } from 'boxicons/svg/regular/bx-check.svg';
import { ReactComponent as atRegular } from 'boxicons/svg/regular/bx-at.svg';
import { ReactComponent as menuRegular } from 'boxicons/svg/regular/bx-menu.svg';
import { ClassValue } from 'classnames/types';
export type Icons = 'cogSolid' | 'plusRegular' | 'homeSolid' | 'newsSolid' | 'userDetailSolid'
......@@ -39,7 +44,7 @@ export type Icons = 'cogSolid' | 'plusRegular' | 'homeSolid' | 'newsSolid' | 'us
| 'idCardSolid' | 'extensionSolid' | 'microphoneSolid' | 'cardSolid' | 'brushSolid'
| 'bodyRegular' | 'slideshowSolid' | 'globeRegular' | 'wrenchSolid' | 'infoCircleSolid'
| 'fileRegular' | 'helpCircleSolid' | 'megaphoneSolid' | 'logoutRegular' | 'leftArrowAltRegular'
| 'xRegular' | 'checkRegular';
| 'xRegular' | 'checkRegular' | 'atRegular' | 'chatSolid' | 'groupSolid' | 'menuRegular';
const INDEX: { [key in Icons]: FunctionComponent } = { cogSolid, plusRegular, homeSolid, newsSolid,
userDetailSolid, userPlusSolid, mobileRegular,
chevronDownRegular, shieldSolid, idCardSolid,
......@@ -48,16 +53,19 @@ const INDEX: { [key in Icons]: FunctionComponent } = { cogSolid, plusRegular, h
globeRegular, wrenchSolid, infoCircleSolid,
fileRegular, helpCircleSolid, megaphoneSolid,
logoutRegular, leftArrowAltRegular, xRegular,
checkRegular };
interface IconProps extends SVGProps<SVGElement> {
checkRegular, atRegular, chatSolid, groupSolid,
menuRegular };
interface IconProps extends Omit<SVGProps<SVGElement>, 'className'> {
icon: Icons,
color?: string,
className?: string
className?: ClassValue[] | ClassValue
}
export function Icon(props: IconProps) {
const style: CSSProperties = {
fill: props.color
};
return createElement(INDEX[props.icon], { className: classNames(styles.icon, props.className), style, ...props } as any);
return createElement(INDEX[props.icon], {
className: classNames(styles.icon, props.className), style, ...remove(props, ['className']) } as any);
}
\ No newline at end of file
......@@ -22,6 +22,10 @@
.messages {
flex-grow: 1;
.pending {
opacity: .45;
}
}
.messageBox {
......
import React, { useContext, useState, useEffect, FormEvent } from 'react';
import React, { useContext, useState, useEffect, FormEvent, createContext } from 'react';
import styles from './Channel.module.scss';
import classNames from 'classnames';
import { ChatContext, Page } from '../Chat';
import { Channel as RChannel, Collection } from 'riotchat.js';
import { Instance } from '../../internal/Client';
import { Message } from 'riotchat.js/dist/internal/Message';
import { Message as RMessage } from 'riotchat.js/dist/internal/Message';
import { scrollable, hiddenScrollbar } from '../../components/util/Scrollbar';
import { Input } from '../../components/ui/elements/Input';
import Header from './channel/Header';
import Message from './channel/Message';
export const ChannelContext = createContext<RChannel | undefined>(undefined);
export default function Channel(props: { id: string }) {
let chat = useContext(ChatContext);
......@@ -50,29 +54,31 @@ export default function Channel(props: { id: string }) {
[styles.visible]: !!((Page.GROUP | Page.GUILD) & chat.page)
});
let messages = (channel.messages as Collection<string, Message>).array();
let messages = (channel.messages as Collection<string, RMessage>).array();
return (
<div className={styles.root}>
<div className={styles.header}>
channel id = {channel.id}
</div>
<div className={styles.body}>
<div className={styles.chat}>
<div className={classNames(styles.messages, scrollable)}>
{ messages.map(m => <p>{m.author.username}: {m.content}</p>) }
<div style={{ float: 'left', clear: 'both' }}
ref={e => e && e.scrollIntoView()}></div>
<ChannelContext.Provider value={channel}>
<div className={styles.root}>
<div className={styles.header}>
<Header />
</div>
<div className={styles.body}>
<div className={styles.chat}>
<div className={classNames(styles.messages, scrollable)}>
{ messages.map(m => <Message message={m} />) }
<div style={{ float: 'left', clear: 'both' }}
ref={e => e && e.scrollIntoView()}></div>
</div>
<div className={styles.messageBox}>
<form onSubmit={sendMessage}>
<Input type='text' value={message} onChange={e => setMessage(e.target.value)} />
</form>
</div>
</div>
<div className={styles.messageBox}>
<form onSubmit={sendMessage}>
<Input type='text' value={message} onChange={e => setMessage(e.target.value)} />
</form>
<div className={classNames(sidebar, hiddenScrollbar)}>
sidebar time
</div>
</div>
<div className={classNames(sidebar, hiddenScrollbar)}>
sidebar time
</div>
</div>
</div>
</ChannelContext.Provider>
);
}
\ No newline at end of file
.header {
height: 58px;
display: flex;
align-items: center;
padding: 0 20px;
.info {
display: flex;
align-items: center;
flex: 1 1 auto;
.hamburger {
display: none;
align-items: center;
margin-right: 10px;
flex-shrink: 1;
cursor: pointer;
@media only screen and (max-width: 900px) {display: flex;}
svg {
width: 28px;
height: 28px;
}
}
.channel {
margin-right: 5px;
}
.title {
font-weight: 600;
}
.dropdown {
cursor: pointer;
}
.divider {
width: 1px;
height: 20px;
margin: 0 12px;
//flex: 0 0 auto;
border-radius: 60px;
//box-sizing: border-box;
background: var(--divider);
}
.description {
font-size: 14px;
}
.indicator {
display: none;
width: 10px;
height: 10px;
margin-left: 8px;
border-radius: 50%;
background-color: gray;
flex: 0 0 auto;
&.online { background-color: var(--green); }
&.streaming { background-color: var(--streaming); }
&.away { background-color: var(--yellow); }
&.busy { background-color: var(--red); }
@media only screen and (max-width: 900px) {
display: flex;
}
}
}
}
\ No newline at end of file
import React, { useContext } from 'react';
import styles from './Header.module.scss';
import { ChannelContext } from '../Channel';
import { Channel } from 'riotchat.js';
import { Icon, Icons } from '../../../components/ui/elements/Icon';
import { DMChannel, GroupChannel } from 'riotchat.js/dist/internal/Channel';
export default function Header() {
let channel = useContext(ChannelContext) as Channel;
let title, icon: Icons;
if (channel instanceof DMChannel) {
title = channel.recipient.username;
icon = 'atRegular';
} else if (channel instanceof GroupChannel) {
title = channel.group.displayTitle;
icon = 'groupSolid';
} else {
title = 'TODO';
icon = 'chatSolid';
}
return (
<div className={styles.header}>
<div className={styles.info}>
<div className={styles.hamburger}><Icon icon="menuRegular"/></div>
<Icon className={styles.channel} icon={icon} />
<div className={styles.title}>{title}</div>
<div className={styles.dropdown}><Icon icon="chevronDownRegular"/></div>
<div className={styles.divider}/>
<div className={styles.description}>Hello this is a test description</div>
<div className={styles.indicator}/>
</div>
<div className={styles.menu}>
</div>
</div>
);
}
\ No newline at end of file
.message {
display: flex;
.author {
flex-shrink: 1;
img {
width: 40px;
height: 40px;
border-radius: 50%;
}
}
.content {
flex-grow: 1;
}
}
\ No newline at end of file
import React from 'react';
import styles from './Message.module.scss';
import { Message as RMessage } from 'riotchat.js/dist/internal/Message';
export default function Message(props: { message: RMessage }) {
let msg = props.message;
return (
<div className={styles.message}>
<div className={styles.author}>
<img alt={msg.author.username} src={msg.author.avatarURL} />
</div>
<div className={styles.content}>
<b>{msg.author.username}</b>
<p>{msg.content}</p>
</div>
</div>
);
}
\ No newline at end of file
......@@ -56,13 +56,14 @@
.add {
width: 80px;
z-index: 1;
position: fixed;
position: absolute;
//position: sticky; //FIXED ON CHROME, NEED TO CHECK OTHER DEVICES
display: flex;
align-items: center;
justify-content: center;
bottom: 0;
left: 0;
background: linear-gradient(transparent, var(--primary));
background: linear-gradient(rgba(0, 0, 0, 0), var(--primary));
svg { cursor: pointer; }
......
......@@ -1780,6 +1780,15 @@ [email protected]^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
[email protected]^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/aphrodite/-/aphrodite-2.3.1.tgz#376b9964c8742218fd10b8b82786f9d22e650e41"
integrity sha512-hwRxpYarrHLRti62RlWplK3A1bDkh4dw5jjDh4Xvra6z45B5yx9Rqsiaw3duELCI/FLOYxlxVe1bysRpIw5X1Q==
dependencies:
asap "^2.0.3"
inline-style-prefixer "^5.0.4"
string-hash "^1.1.3"
[email protected]^1.0.3, [email protected]^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
......@@ -1888,7 +1897,7 @@ [email protected]^1.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
[email protected]~2.0.6:
[email protected]^2.0.3, [email protected]~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
......@@ -3138,6 +3147,14 @@ [email protected]^0.10.0:
postcss "^7.0.6"
postcss-selector-parser "^5.0.0-rc.4"
[email protected]^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz#3b472b398787291b47cfe3e44fecfdd9e914ba99"
integrity sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==
dependencies:
hyphenate-style-name "^1.0.2"
isobject "^3.0.1"
[email protected]:
version "2.1.1"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.1.tgz#d8254f72e412bb2238bb44dd674ffbef497333ea"
......@@ -4403,6 +4420,15 @@ [email protected]^2.0.1:
rimraf "2.6.3"
write "1.0.3"
[email protected]^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/flatbase/-/flatbase-0.1.2.tgz#ee54921498c721887934a0adbd42bc46f7d65009"
integrity sha512-JyamlDg+g42oy/j2DsrPKgN84OZNn2XYCe+yzJy0Q6iwEkfAvHAmt4x4Cc/njyoL1O+0Z9HlvFQHI0/XfVxAmw==
dependencies:
aphrodite "^2.3.1"
react-input-autosize "^2.2.1"
react-textarea-autosize "^7.1.0"
[email protected]^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916"
......@@ -5077,6 +5103,11 @@ [email protected]^1.0.0:
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
[email protected]^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48"
integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==
[email protected]:
version "0.4.23"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
......@@ -5250,6 +5281,13 @@ [email protected]^1.3.5, [email protected]~1.3.0:
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
[email protected]^5.0.4:
version "5.1.0"
resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-5.1.0.tgz#cb63195f9456dcda25cf59743e45c4d9815b0811"
integrity sha512-giteQHPMrApQOSjNSjteO5ZGSGMRf9gas14fRy2lg2buSc1nRnj6o6xuNds5cMTKrkncyrTu3gJn/yflFMVdmg==
dependencies:
css-in-js-utils "^2.0.0"
[email protected]:
version "6.2.2"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406"
......@@ -8621,7 +8659,7 @@ [email protected]^2.0.1:
kleur "^3.0.2"
sisteransi "^1.0.0"
[email protected]^15.5.4, [email protected]^15.6.0, [email protected]^15.6.1, [email protected]^15.6.2:
[email protected]^15.5.4, [email protected]^15.5.8, [email protected]^15.6.0, [email protected]^15.6.1, [email protected]^15.6.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
......@@ -8862,6 +8900,13 @@ [email protected]^5.2.1:
react-fast-compare "^2.0.2"
react-side-effect "^1.1.0"
[email protected]^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8"
integrity sha512-3+K4CD13iE4lQQ2WlF8PuV5htfmTRLH6MDnfndHM6LuBRszuXnuyIfE7nhSKt8AzRBZ50bu0sAhkNMeS5pxQQA==
dependencies:
prop-types "^15.5.8"
[email protected]^0.8.1:
version "0.8.3"
resolved "https://registry.yarnpkg.com/react-interactive/-/react-interactive-0.8.3.tgz#c3c6c3f99b2e5efc20a9ccc54504cf2c03984d5b"
......@@ -8969,6 +9014,14 @@ [email protected]^1.1.0:
exenv "^1.2.1"
shallowequal "^1.0.1"
[email protected]^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-7.1.0.tgz#3132cb77e65d94417558d37c0bfe415a5afd3445"
integrity sha512-c2FlR/fP0qbxmlrW96SdrbgP/v0XZMTupqB90zybvmDVDutytUgPl7beU35klwcTeMepUIQEpQUn3P3bdshGPg==
dependencies:
"@babel/runtime" "^7.1.2"
prop-types "^15.6.0"
[email protected]^16.0.0, [email protected]^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
......@@ -10040,6 +10093,11 @@ [email protected]^1.0.0:
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
[email protected]^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=
[email protected]^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment