major code clean-up: the ChannelView component is now smaller, main-card css class has been removed, among other changes
This commit is contained in:
parent
eb89803398
commit
63fc9d7d50
18 changed files with 87 additions and 111 deletions
|
@ -66,7 +66,7 @@ export default function Create() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (specialCodePrompt) return (
|
if (specialCodePrompt) return (
|
||||||
<div id="login-container" className="main-card">
|
<div id="login-container" className="card">
|
||||||
<h1>One more thing!</h1>
|
<h1>One more thing!</h1>
|
||||||
<p>You need a special code to sign up here!</p>
|
<p>You need a special code to sign up here!</p>
|
||||||
<label htmlFor="specialcode">Special Code</label>
|
<label htmlFor="specialcode">Special Code</label>
|
||||||
|
@ -78,7 +78,7 @@ export default function Create() {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="login-container" className="main-card">
|
<div id="login-container" className="card">
|
||||||
<h1>Create an account</h1>
|
<h1>Create an account</h1>
|
||||||
<label htmlFor="username">Username</label>
|
<label htmlFor="username">Username</label>
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -49,7 +49,7 @@ export default function Login() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="login-container" className="main-card">
|
<div id="login-container" className="card">
|
||||||
<h1>Log in</h1>
|
<h1>Log in</h1>
|
||||||
<label htmlFor="username">Username</label>
|
<label htmlFor="username">Username</label>
|
||||||
<br />
|
<br />
|
||||||
|
|
29
bfrontend/src/Components/Channels/ChannelMessageView.js
Normal file
29
bfrontend/src/Components/Channels/ChannelMessageView.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import Message from "../Messages/Message";
|
||||||
|
import { useRef, useEffect } from 'react';
|
||||||
|
|
||||||
|
export default function ChannelMessageView({messages}) {
|
||||||
|
const invisibleBottomMessageRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (invisibleBottomMessageRef && invisibleBottomMessageRef.current) {
|
||||||
|
invisibleBottomMessageRef.current.scrollIntoView({ behaviour: 'smooth' });
|
||||||
|
}
|
||||||
|
}, [messages]);
|
||||||
|
|
||||||
|
let messagesView = messages.map((m, i) => {
|
||||||
|
return <Message key={ m._id } message={ m } />;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (messagesView === undefined || messagesView.length <= 0) {
|
||||||
|
messagesView = (
|
||||||
|
<div className='no-messages-warning'>
|
||||||
|
<span>No messages yet...</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="message-list-card">
|
||||||
|
{ messagesView }
|
||||||
|
<div ref={ invisibleBottomMessageRef }></div>
|
||||||
|
</div>;
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import UserProfileButton from '../Users/UserButton';
|
||||||
|
|
||||||
function ChannelUserList({ presence }) {
|
function ChannelUserList({ presence }) {
|
||||||
return (
|
return (
|
||||||
<div className="main-card sidebar">
|
<div className="card sidebar">
|
||||||
<div className="channel-list">
|
<div className="channel-list">
|
||||||
{ Object.keys(presence).map((userId) => <UserProfileButton key={ userId } user={ presence[userId] } />) }
|
{ Object.keys(presence).map((userId) => <UserProfileButton key={ userId } user={ presence[userId] } />) }
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,120 +1,64 @@
|
||||||
import ChannelViewLoader from '../UI/ProfileLinkLoader';
|
|
||||||
import ChannelProfile from './ChannelProfileLink';
|
import ChannelProfile from './ChannelProfileLink';
|
||||||
import Message from '../Messages/Message';
|
|
||||||
import gatewayConnection from '../../API/Gateway/globalGatewayConnection';
|
import gatewayConnection from '../../API/Gateway/globalGatewayConnection';
|
||||||
import ChannelUserList from "./ChannelUserList";
|
import ChannelUserList from "./ChannelUserList";
|
||||||
|
|
||||||
import { useParams } from 'react-router-dom';
|
|
||||||
import { connect, useDispatch } from 'react-redux';
|
import { connect, useDispatch } from 'react-redux';
|
||||||
import { useState, useRef, useEffect } from 'react';
|
import { useState, useRef, useEffect } from 'react';
|
||||||
|
import ChannelMessageView from './ChannelMessageView';
|
||||||
|
|
||||||
|
const ChannelView = ({ messages, channel, channelPresenceClientList }) => {
|
||||||
const ChannelView = ({ channels, messages, channel, selectedChannelId, experiments, channelPresenceClientList, gradientBannerNotificationText }) => {
|
|
||||||
const { id } = useParams();
|
|
||||||
const [ textInput, setTextInput ] = useState('');
|
const [ textInput, setTextInput ] = useState('');
|
||||||
|
|
||||||
const textInputRef = useRef(null);
|
const textInputRef = useRef(null);
|
||||||
const invisibleBottomMessageRef = useRef(null);
|
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (invisibleBottomMessageRef && invisibleBottomMessageRef.current) {
|
|
||||||
invisibleBottomMessageRef.current.scrollIntoView({ behaviour: 'smooth' });
|
|
||||||
}
|
|
||||||
}, [messages]);
|
|
||||||
|
|
||||||
const handleTextboxKeydown = (e) => {
|
const handleTextboxKeydown = (e) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
gatewayConnection.sendMessage(textInput, id);
|
gatewayConnection.sendMessage(textInput, channel._id);
|
||||||
textInputRef.current.value = '';
|
textInputRef.current.value = '';
|
||||||
setTextInput('');
|
setTextInput('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!channels) return;
|
|
||||||
if (!channel) return;
|
if (!channel) return;
|
||||||
if (channel._id === selectedChannelId) return;
|
|
||||||
|
|
||||||
dispatch({ type: 'channels/selectchannel', channelId: channel._id });
|
dispatch({ type: 'channels/selectchannel', channelId: channel._id });
|
||||||
}, [channels, id, dispatch, channel, selectedChannelId]);
|
}, [dispatch, channel]);
|
||||||
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
let messagesView = messages.map((m, i) => {
|
|
||||||
//if (messages[i-1] && messages[i-1].author.username === m.author.username) return <Message key={ m._id } message={ m } hideUsername={ true } />
|
|
||||||
return <Message key={ m._id } message={ m } />;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (messagesView === undefined || messagesView.length <= 0) {
|
|
||||||
messagesView = (
|
|
||||||
<div className='no-messages-warning'>
|
|
||||||
<div className="profile-picture default-user no-messages-icon">
|
|
||||||
<div className="default-channel-styled-text no-messages-text">
|
|
||||||
#?
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span style={ { marginTop: "1em" } }>No messages yet...</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-flex-card hidden-overflow">
|
<div className="col-flex-card hidden-overflow">
|
||||||
<div className="bar-card-accent">
|
<div className="bar-card-accent">
|
||||||
<ChannelProfile channel={ channel } size="24" />
|
<ChannelProfile channel={ channel } size="24" />
|
||||||
{ (experiments.voiceSFUTesting) && <button className="button" onClick={ () => gatewayConnection.beginVoiceSession(channel._id) }>
|
{/*
|
||||||
Join voice
|
{ (experiments.voiceSFUTesting) && <button className="button" onClick={ () => gatewayConnection.beginVoiceSession(channel._id) }>
|
||||||
</button>}
|
Join voice
|
||||||
|
</button>}
|
||||||
|
*/}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(gradientBannerNotificationText !== undefined) && <div className="gradient-banner-card" onClick={ () => dispatch({ type: "application/updatebannertext", text: undefined }) }>
|
<div className="row-flex-card hidden-overflow">
|
||||||
{ gradientBannerNotificationText }
|
|
||||||
</div>}
|
|
||||||
|
|
||||||
<div className="main-card row-flex-card hidden-overflow">
|
|
||||||
<div className="col-flex-card channel-message-panel hidden-overflow">
|
<div className="col-flex-card channel-message-panel hidden-overflow">
|
||||||
<div className="message-list-card">
|
<ChannelMessageView messages={messages}></ChannelMessageView>
|
||||||
{ messagesView }
|
|
||||||
<div ref={ invisibleBottomMessageRef }></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="invis-bar">
|
<div className="invis-bar">
|
||||||
<input className="text-input message-input" type="text" placeholder="Go on, type something interesting!" ref={ textInputRef } onKeyDown={ handleTextboxKeydown } onChange={ ({ target }) => setTextInput(target.value) }></input>
|
<input className="text-input message-input" type="text" placeholder="Go on, type something interesting!" ref={ textInputRef } onKeyDown={ handleTextboxKeydown } onChange={ ({ target }) => setTextInput(target.value) }></input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{ (experiments.userListTest) && <ChannelUserList presence={ channelPresenceClientList || [] } /> }
|
<ChannelUserList presence={ channelPresenceClientList || [] } />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<div className="main-card col-flex-card">
|
|
||||||
<div className="bar-card">
|
|
||||||
<ChannelViewLoader />
|
|
||||||
</div>
|
|
||||||
<div className="message-list-card">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div className="bar-card-bottom">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const stateToProps = (state, ownProps) => {
|
const stateToProps = (state, ownProps) => {
|
||||||
const channelId = ownProps.match.params.id; // NOTE: kind of a hack, but it works and idk if theres any other solution
|
const channelId = ownProps.channelId;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
channels: state?.channels,
|
|
||||||
channel: state?.channels?.find(x => x._id === channelId),
|
channel: state?.channels?.find(x => x._id === channelId),
|
||||||
messages: state?.messages[channelId] || [],
|
messages: state?.messages[channelId] || [],
|
||||||
selectedChannelId: state?.selectedChannelId,
|
|
||||||
experiments: state?.experiments || {},
|
|
||||||
channelPresenceClientList: state?.channelPresenceClientList,
|
channelPresenceClientList: state?.channelPresenceClientList,
|
||||||
gradientBannerNotificationText: state?.gradientBannerNotificationText
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,12 @@ import Root from '../Home/Root';
|
||||||
import Authenticator from '../../API/Authenticator';
|
import Authenticator from '../../API/Authenticator';
|
||||||
import Notification from '../UI/Notification';
|
import Notification from '../UI/Notification';
|
||||||
import './../../Styles/App.scss';
|
import './../../Styles/App.scss';
|
||||||
import ChannelView from '../Channels/ChannelView';
|
|
||||||
import Sidebar from '../UI/Sidebar';
|
import Sidebar from '../UI/Sidebar';
|
||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useDispatch, connect } from 'react-redux'
|
import { useDispatch, connect } from 'react-redux'
|
||||||
import { BrowserRouter, Switch, Route } from 'react-router-dom';
|
import { BrowserRouter, Switch, Route } from 'react-router-dom';
|
||||||
|
import LoggedInMount from './LoggedInMount';
|
||||||
|
|
||||||
function App({ user }) {
|
function App({ user }) {
|
||||||
const [ notificationText ] = useState('');
|
const [ notificationText ] = useState('');
|
||||||
|
@ -37,14 +37,7 @@ function App({ user }) {
|
||||||
<Route path="/login" component={ Login } />
|
<Route path="/login" component={ Login } />
|
||||||
<Route path="/create" component={ Create } />
|
<Route path="/create" component={ Create } />
|
||||||
<Route path="/channels/:id"
|
<Route path="/channels/:id"
|
||||||
render={(props) => {
|
render={() => <LoggedInMount />}
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Sidebar />
|
|
||||||
<ChannelView match={ props.match } />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route path="/">
|
<Route path="/">
|
||||||
|
|
11
bfrontend/src/Components/Main/LoggedInMount.js
Normal file
11
bfrontend/src/Components/Main/LoggedInMount.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import Sidebar from "../UI/Sidebar";
|
||||||
|
import ChannelView from "../Channels/ChannelView";
|
||||||
|
|
||||||
|
export default function LoggedInMount() {
|
||||||
|
const { id: channelId } = useParams();
|
||||||
|
return <>
|
||||||
|
<Sidebar />
|
||||||
|
<ChannelView channelId={ channelId } />
|
||||||
|
</>;
|
||||||
|
}
|
5
bfrontend/src/Components/UI/GradientBanner.js
Normal file
5
bfrontend/src/Components/UI/GradientBanner.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export default function GradientBanner() {
|
||||||
|
return (gradientBannerNotificationText !== undefined) && <div className="gradient-banner-card" onClick={ () => dispatch({ type: "application/updatebannertext", text: undefined }) }>
|
||||||
|
{ gradientBannerNotificationText }
|
||||||
|
</div>;
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import { connect } from 'react-redux';
|
||||||
|
|
||||||
function Sidebar({ user }) {
|
function Sidebar({ user }) {
|
||||||
return (
|
return (
|
||||||
<div className="main-card sidebar">
|
<div className="sidebar">
|
||||||
<div className="bar-card" style={{
|
<div className="bar-card" style={{
|
||||||
color: "var(--darker-text-color)"
|
color: "var(--darker-text-color)"
|
||||||
}}>
|
}}>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
background: var(--accent-color-light);
|
background: var(--accent-color-light);
|
||||||
}
|
}
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: var(--default-main-card-color);
|
background: var(--default-scrollbar-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -29,6 +29,15 @@ body {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
button,
|
||||||
font-size: 18px !important;
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
font-size: 18px;
|
||||||
}
|
}
|
|
@ -14,7 +14,6 @@
|
||||||
&-channel {
|
&-channel {
|
||||||
@extend .button;
|
@extend .button;
|
||||||
|
|
||||||
box-shadow: none;
|
|
||||||
border-radius: var(--channel-button-border-radius);
|
border-radius: var(--channel-button-border-radius);
|
||||||
width: 200px;
|
width: 200px;
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
@mixin card {
|
@mixin card {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
background-color: var(--default-main-card-color);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
border-radius: var(--default-border-radius);
|
border-radius: var(--default-border-radius);
|
||||||
box-shadow: 0px 1px 1px var(--card-box-shadow-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hh
|
// hh
|
||||||
|
@ -23,7 +22,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
font-size: medium;
|
font-size: medium;
|
||||||
z-index: 100;
|
z-index: 10;
|
||||||
|
|
||||||
&-accent {
|
&-accent {
|
||||||
@extend .bar-card;
|
@extend .bar-card;
|
||||||
|
@ -37,23 +36,14 @@
|
||||||
@include fancy-scrollbar-firefox;
|
@include fancy-scrollbar-firefox;
|
||||||
|
|
||||||
background-color: var(--channel-message-list-background-color);
|
background-color: var(--channel-message-list-background-color);
|
||||||
box-shadow: none;
|
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-card {
|
|
||||||
@include card;
|
|
||||||
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.col-flex-card {
|
.col-flex-card {
|
||||||
@include card;
|
@include card;
|
||||||
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -62,8 +52,6 @@
|
||||||
.row-flex-card {
|
.row-flex-card {
|
||||||
@include card;
|
@include card;
|
||||||
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
flex-grow: 10;
|
flex-grow: 10;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
@include fancy-scrollbar-firefox;
|
@include fancy-scrollbar-firefox;
|
||||||
|
@include card;
|
||||||
|
|
||||||
background-color: var(--channel-list-background-color);
|
background-color: var(--channel-list-background-color);
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
.message {
|
.message {
|
||||||
@include card;
|
@include card;
|
||||||
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
margin: 3px;
|
margin: 3px;
|
||||||
|
|
|
@ -79,17 +79,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.default-channel-styled-text {
|
.default-channel-styled-text {
|
||||||
font-size: 24px !important;
|
font-size: 24px;
|
||||||
filter: drop-shadow(2px 2px hsl(300, 60%, 25%));
|
filter: drop-shadow(2px 2px hsl(300, 60%, 25%));
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
&.no-messages-text {
|
&.no-messages-text {
|
||||||
filter: drop-shadow(45px 0 hsl(300, 60%, 40%));
|
filter: drop-shadow(45px 0 hsl(300, 60%, 40%));
|
||||||
font-size: 8em !important;
|
font-size: 8em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.default-user-styled-text {
|
.default-user-styled-text {
|
||||||
font-size: 24px !important;
|
font-size: 24px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
|
@ -13,6 +13,6 @@
|
||||||
height: 32px;
|
height: 32px;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
font-size: 16px !important;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
@mixin fancy-scrollbar-firefox {
|
@mixin fancy-scrollbar-firefox {
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
scrollbar-color: var(--default-main-card-color) var(--accent-color-light);
|
scrollbar-color: var(--default-scrollbar-color) var(--accent-color-light);
|
||||||
}
|
}
|
|
@ -5,8 +5,7 @@
|
||||||
--card-accent-color: hsl(0, 0%, 10%);
|
--card-accent-color: hsl(0, 0%, 10%);
|
||||||
--card-accent-color-dark: hsl(0, 0%, 5%);
|
--card-accent-color-dark: hsl(0, 0%, 5%);
|
||||||
|
|
||||||
--default-main-card-color: var(--background-color);
|
--default-scrollbar-color: var(--background-color);
|
||||||
--card-box-shadow-color: 0 1px 0 #1d1a1abe;
|
|
||||||
|
|
||||||
--focus-accent-background: var(--card-accent-color);
|
--focus-accent-background: var(--card-accent-color);
|
||||||
--focus-accent-background-deep: var(--card-accent-color-dark);
|
--focus-accent-background-deep: var(--card-accent-color-dark);
|
||||||
|
|
Loading…
Reference in a new issue