ui overhaul + integrate gateway better

This commit is contained in:
hippoz 2021-03-28 21:05:52 +03:00
parent c5210b40c3
commit 118a55fed9
No known key found for this signature in database
GPG key ID: 7C52899193467641
23 changed files with 446 additions and 342 deletions

View file

@ -49,7 +49,7 @@ export default function Login() {
}
return (
<div id="login-container" className="card main-card">
<div id="login-container" className="main-card">
<label htmlFor="username">Username</label>
<br />
<input type="text" name="username" className="text-input" onChange={ ({ target }) => setUsernameInput(target.value) } />

View file

@ -6,8 +6,8 @@ import { useHistory } from 'react-router-dom';
export default function ChannelButton({ channel, selected }) {
const history = useHistory();
let buttonClasses = 'button channel-button';
if (selected) buttonClasses += ' pressed';
let buttonClasses = 'button button-channel';
if (selected) buttonClasses += ' button-pressed';
const handleClick = () => {
if (gatewayConnection.handshakeCompleted) {

View file

@ -6,9 +6,9 @@ import { connect } from 'react-redux'
function ChannelList({ selectedChannelId, channels }) {
if (!channels) {
return (
<div>
<>
<ChannelListLoader />
</div>
</>
);
} else {
return (

View file

@ -5,39 +5,39 @@ export default function ChannelListLoader(props) {
const lessThan600 = useMediaPredicate("(max-width: 600px)");
if (lessThan600) {
return (
<ContentLoader
speed={1.5}
width={62}
height={300}
viewBox="0 0 62 300"
backgroundColor="#434c5e"
foregroundColor="#4c566a"
{...props}
return (
<ContentLoader
speed={1.5}
width={100}
height={250}
viewBox="0 0 100 250"
backgroundColor="#423f3f"
foregroundColor="#4d4a4a"
{...props}
>
<rect x="6" y="5" rx="0" ry="0" width="50" height="25" />
<rect x="6" y="35" rx="0" ry="0" width="50" height="25" />
<rect x="6" y="65" rx="0" ry="0" width="50" height="25" />
<rect x="6" y="95" rx="0" ry="0" width="50" height="25" />
<rect x="6" y="125" rx="0" ry="0" width="50" height="25" />
<rect x="10" y="10" rx="0" ry="0" width="100" height="40" />
<rect x="10" y="55" rx="0" ry="0" width="100" height="40" />
<rect x="10" y="100" rx="0" ry="0" width="100" height="40" />
<rect x="10" y="145" rx="0" ry="0" width="100" height="40" />
<rect x="10" y="190" rx="0" ry="0" width="100" height="40" />
</ContentLoader>
);
} else {
return (
<ContentLoader
speed={1.5}
width={112}
height={300}
viewBox="0 0 112 300"
backgroundColor="#434c5e"
foregroundColor="#4c566a"
{...props}
return (
<ContentLoader
speed={1.5}
width={200}
height={250}
viewBox="0 0 200 250"
backgroundColor="#423f3f"
foregroundColor="#4d4a4a"
{...props}
>
<rect x="6" y="5" rx="0" ry="0" width="100" height="25" />
<rect x="6" y="35" rx="0" ry="0" width="100" height="25" />
<rect x="6" y="65" rx="0" ry="0" width="100" height="25" />
<rect x="6" y="95" rx="0" ry="0" width="100" height="25" />
<rect x="6" y="125" rx="0" ry="0" width="100" height="25" />
<rect x="10" y="10" rx="0" ry="0" width="180" height="40" />
<rect x="10" y="55" rx="0" ry="0" width="180" height="40" />
<rect x="10" y="145" rx="0" ry="0" width="180" height="40" />
<rect x="10" y="100" rx="0" ry="0" width="180" height="40" />
<rect x="10" y="190" rx="0" ry="0" width="180" height="40" />
</ContentLoader>
);
}

View file

@ -0,0 +1,25 @@
import UserProfileButton from '../Users/UserButton';
import { connect } from 'react-redux';
function Sidebar({ channelPresenceClientList }) {
const users = [
{ username: "thgitrhiorg" },
{ username: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" },
{ username: "FDGFEGSDFHRFGHNERTYBNRNBTYJMNUM" }
];
return (
<div className="main-card sidebar">
{ users.map((user) => <UserProfileButton user={ user }></UserProfileButton>) }
</div>
)
}
const stateToProps = (state) => {
return {
channelPresenceClientList: state?.channelPresenceClientList
};
};
export default connect(stateToProps)(Sidebar);

View file

@ -1,28 +1,28 @@
import ChannelViewLoader from './ChannelViewLoader';
import ChannelViewLoader from '../UI/ProfileLinkLoader';
import ChannelProfile from './ChannelProfileLink';
import Message from '../Messages/Message';
import gatewayConnection from '../../API/Gateway/globalGatewayConnection';
import ChannelUserList from "./ChannelUserList";
import { useParams } from 'react-router-dom';
import { connect, useDispatch } from 'react-redux';
import { useState, useRef, useEffect } from 'react';
function ChannelView({ channels, messages }) {
const ChannelView = ({ channels, messages, channel, selectedChannelId }) => {
const { id } = useParams();
const [ textInput, setTextInput ] = useState('');
const [ channel, setChannel ] = useState();
const textInputRef = useRef(null);
const invisibleBottomMessageRef = useRef(null);
const dispatch = useDispatch();
const scrollToBottom = () => {
useEffect(() => {
if (invisibleBottomMessageRef && invisibleBottomMessageRef.current) {
invisibleBottomMessageRef.current.scrollIntoView({ behaviour: 'smooth' });
}
}
useEffect(scrollToBottom, [messages]);
}, [messages]);
const handleTextboxKeydown = (e) => {
if (e.key === 'Enter') {
@ -34,15 +34,11 @@ function ChannelView({ channels, messages }) {
useEffect(() => {
if (!channels) return;
setChannel(channels.find(x => x._id === id));
}, [channels, id]);
useEffect(() => {
if (!channel) return;
if (channel._id === selectedChannelId) return;
dispatch({ type: 'channels/selectchannel', channelId: channel._id });
}, [channel, dispatch]);
}, [channels, id, dispatch, channel, selectedChannelId]);
if (channel) {
let messagesView = messages.map(m => <Message key={ m._id } message={ m } />);
@ -50,49 +46,57 @@ function ChannelView({ channels, messages }) {
if (messagesView === undefined || messagesView.length <= 0) {
messagesView = (
<div className='no-messages-warning'>
A bit empty in here...
Wow, such empty!
</div>
);
}
return (
<div className="card main-card main-content-card">
<div className="card bar-card">
<ChannelProfile channel={ channel } />
<div className="col-flex-card">
<div className="bar-card">
<ChannelProfile channel={ channel } size="24" />
</div>
<div className="card message-list-card">
{ messagesView }
<div ref={ invisibleBottomMessageRef }></div>
</div>
<div className="card bar-card-bottom">
<input className="text-input" type="text" placeholder="Go on, type something interesting!" ref={ textInputRef } onKeyDown={ handleTextboxKeydown } onChange={ ({ target }) => setTextInput(target.value) }></input>
<div className="main-card row-flex-card">
<div className="col-flex-card">
<div className="message-list-card">
{ messagesView }
<div ref={ invisibleBottomMessageRef }></div>
</div>
<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>
</div>
</div>
<ChannelUserList />
</div>
</div>
)
} else {
return (
<div className="card main-card main-content-card">
<div className="card bar-card">
<div className="main-card col-flex-card">
<div className="bar-card">
<ChannelViewLoader />
</div>
<div className="card message-list-card">
<div className="message-list-card">
</div>
<div className="card bar-card-bottom">
<div className="bar-card-bottom">
</div>
</div>
)
}
}
};
const stateToProps = (state, ownProps) => {
const channelId = ownProps.match.params.id; // NOTE(hippoz): kind of a hack, but it works and idk if theres any other solution
return {
channels: state?.channels,
channel: state?.channels?.find(x => x._id === channelId),
messages: state?.messages[channelId] || [],
selectedChannelId: state?.selectedChannelId,
};
};

View file

@ -33,12 +33,21 @@ function App({ user }) {
<div id="main-container">
<div id="root-container" className="main-display">
<BrowserRouter>
{ user && <Sidebar /> }
<Switch>
<Route path="/login" component={ Login } />
<Route path="/channels/:id" component={ ChannelView } />
<Route path="/channels/:id"
render={(props) => {
return (
<>
<Sidebar />
<ChannelView match={ props.match } />
</>
);
}}
/>
<Route path="/">
{ user && <Sidebar /> }
<Root user={user} />
</Route>
</Switch>

View file

@ -3,8 +3,8 @@ import UserProfileLink from '../Users/UserProfileLink';
export default function Message({ message }) {
return (
<div className="message">
<UserProfileLink size="40" user={ message.author } offset="true"><p>a</p></UserProfileLink>
<span>{ message.content }</span>
<UserProfileLink size="0" user={ message.author }></UserProfileLink>
<span style={ {"padding-left": "5px"} }>{ message.content }</span>
</div>
);
}

View file

@ -1,9 +1,9 @@
import defaultProfile from '../../Content/Images/defaultprofile_256px-256px.png'
export default function ProfileLink({ object, size=32, type, offset=true, children=null }) {
export default function ProfileLink({ object, size, type, offset=true, children=null }) {
let picture;
if (size !== 0) {
if (size !== "0") {
// TODO: Make a debug error message for then the size does not exist
const pictureClass = `profile-picture profile-picture-${size}`;
@ -28,4 +28,4 @@ export default function ProfileLink({ object, size=32, type, offset=true, childr
{ bottomInfo }
</div>
);
}
};

View file

@ -7,8 +7,8 @@ export default function ChannelViewLoader(props) {
width={100}
height={46}
viewBox="0 0 100 46"
backgroundColor="#434c5e"
foregroundColor="#4c566a"
backgroundColor="#423f3f"
foregroundColor="#4d4a4a"
{...props}
>
<rect x="50" y="14" rx="0" ry="0" width="50" height="15" />

View file

@ -1,13 +1,15 @@
import ChannelList from '../Channels/ChannelList';
import UserProfileLink from '../Users/UserProfileLink';
import ProfileLinkLoader from "../UI/ProfileLinkLoader";
import { connect } from 'react-redux';
function Sidebar({ user }) {
return (
<div className="card main-card channel-list-container">
<div className="card bar-card">
<UserProfileLink user={ user } />
<div className="main-card sidebar">
<div className="bar-card">
{ user && <UserProfileLink user={ user } /> }
{ !user && <ProfileLinkLoader></ProfileLinkLoader> }
</div>
<ChannelList />
</div>

View file

@ -0,0 +1,19 @@
import UserProfile from './UserProfileLink';
import { useHistory } from 'react-router-dom';
export default function ChannelUserButton({ user }) {
const history = useHistory();
let buttonClasses = 'button button-channel';
const handleClick = () => {
history.push(`/user/${user._id}`);
};
return (
<button className={ buttonClasses } onClick={ handleClick }>
<UserProfile user={ user } size="32" />
</button>
);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 645 B

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -1,57 +1,13 @@
$nord0darker: #22262e;
$nord1darker: #282b36;
$nord2darker: #333947;
$nord3darker: #40495a;
$nord4darker: #9da2ad;
@import "./colors.scss";
@import "./root.scss";
@import "./mixins.scss";
$nord0: #2E3440;
$nord1: #3B4252;
$nord2: #434C5E;
$nord3: #4C566A;
$nord4: #D8DEE9;
$nord5: #E5E9F0;
$nord6: #ECEFF4;
$nord7: #8FBCBB;
$nord8: #88C0D0;
$nord9: #81A1C1;
$nord10: #5E81AC;
$nord11: #BF616A;
$nord12: #D08770;
$nord13: #EBCB8B;
$nord14: #A3BE8C;
$nord15: #B48EAD;
:root {
--background-color: #{$nord0darker};
--default-main-card-color: var(--background-color);
--card-box-shadow-color:rgba(0, 0, 0, 0.27);
--default-text-color: #{$nord5};
--darker-text-color: #{$nord4darker};
--accent-color-dark: #{$nord1darker};
--accent-color-light: #{$nord2darker};
--accent-color-very-light: #{$nord3darker};
--channel-top-bar-color: var(--accent-color-light);
--channel-bottom-text-bar-color: var(--accent-color-light);
--channel-list-background-color: var(--background-color);
--channel-message-list-background-color: var(--background-color);
--channel-message-color: var(--accent-color-dark);
--button-color: var(--accent-color-dark);
--button-hover-color: var(--accent-color-light);
--default-transition-duration: 50ms;
--default-border-radius: 0px;
--default-button-border-radius: 0px;
--channel-message-border-radius: 0px;
--bar-cards-border-radius: 0px;
--channel-button-border-radius: 4px;
}
@import "./Components/Card.scss";
@import "./Components/Button.scss";
@import "./Components/Containers.scss";
@import "./Components/ProfileLink.scss";
@import "./Components/Message.scss";
@import "./Components/Textbox.scss";
::-webkit-scrollbar {
width: 0px;
@ -59,230 +15,15 @@ $nord15: #B48EAD;
::-webkit-scrollbar-track {
background: var(--accent-color-light);
}
::-webkit-scrollbar-thumb {
background: var(--default-main-card-color);
}
@mixin card {
padding: 0px;
margin: 0px;
background-color: var(--default-main-card-color);
border-radius: var(--default-border-radius);
box-shadow: 0px 3px 5px var(--card-box-shadow-color);
}
@mixin fancy-scrollbar-firefox {
scrollbar-width: none;
scrollbar-color: var(--default-main-card-color) var(--accent-color-light);
}
body {
margin: 0px;
padding: 0px;
color: var(--default-text-color);
background-color: var(--background-color);
font-family: Noto Sans,-apple-system,BlinkMacSystemFont,sans-serif;
}
.main-display {
padding: 0px;
margin: 0px;
display: flex;
background-color: var(--background-color);
min-height: 100vh;
max-height: 100vh;
flex-direction: row;
}
.card {
@include card;
&.bar-card {
background-color: var(--channel-top-bar-color);
min-height: 50px;
padding: 5px;
border-radius: var(--bar-cards-border-radius);
display: flex;
align-items: center;
justify-content: left;
font-size: large;
z-index: 99;
}
&.bar-card-bottom {
background-color: var(--channel-bottom-text-bar-color);
box-shadow: 0px -3px 5px var(--card-box-shadow-color);
min-height: 40px;
border-radius: var(--bar-cards-border-radius);
display: flex;
z-index: 100;
}
&.message-list-card {
@include fancy-scrollbar-firefox;
border-radius: 0px;
flex-grow: 1;
box-shadow: none;
overflow: auto;
background-color: var(--channel-message-list-background-color);
}
}
.main-card {
@include card;
box-shadow: none;
&.main-content-card {
flex-grow: 1;
display: flex;
flex-direction: column;
}
}
.button {
@include card;
padding: 5px;
margin: 5px;
border: 0px;
background-color: var(--button-color);
color: var(--default-text-color);
cursor: pointer;
// transition: background-color, var(--default-transition-duration);
border-radius: var(--default-button-border-radius);
min-height: 25px;
&.channel-button {
min-width: 200px;
max-width: 200px;
min-height: 40px;
max-height: 100px;
margin: 4px;
border-radius: var(--channel-button-border-radius);
}
&.pressed {
background-color: var(--accent-color-very-light);
}
}
.button:hover:not(.pressed) {
background-color: var(--accent-color-light);
}
.channel-list {
display: flex;
flex-direction: column;
word-wrap: break-word;
}
.channel-list-container {
@include fancy-scrollbar-firefox;
overflow: auto;
overflow-x: hidden;
background-color: var(--channel-list-background-color);
}
.profile-picture {
border-radius: 50%;
margin: 5px;
width: 32px;
height: 32px;
&.profile-picture-8 {
width: 8px;
height: 8px;
}
&.profile-picture-16 {
width: 16px;
height: 16px;
}
&.profile-picture-32 {
width: 32px;
height: 32px;
}
&.profile-picture-40 {
width: 40px;
height: 40px;
}
&.profile-picture-64 {
width: 64px;
height: 64px;
}
}
.profile-link {
display: flex;
flex-direction: row;
align-items: center;
justify-content: left;
&.profile-link-offset-text {
align-items: unset;
text-align: start;
}
}
.profile-username {
font-weight: bold;
}
.message {
@include card;
box-shadow: none;
display: flex;
flex-direction: column;
margin-top: 5px;
margin-bottom: 5px;
margin-left: 5px;
margin-right: 5px;
padding: 5px;
border-radius: var(--channel-message-border-radius);
background-color: var(--background-color);
}
.text-input {
@include card;
margin: 5px;
padding: 5px;
border: none;
color: var(--default-text-color);
flex-grow: 1;
}
.no-messages-warning {
text-align: center;
padding: 50px;
color: var(--darker-text-color);
}
.unread-indicator {
float: right;
}
@media only screen and (max-width: 600px) {
.button.channel-button {
min-width: 100px;
max-width: 100px;
}
padding: 0px;
}

View file

@ -0,0 +1,43 @@
.button {
@include card;
background-color: var(--button-color);
color: var(--default-text-color);
border-radius: var(--default-button-border-radius);
cursor: pointer;
padding: 5px;
margin: 5px;
border: 0px;
min-height: 25px;
&-channel {
@extend .button;
box-shadow: none;
border-radius: var(--channel-button-border-radius);
min-width: 200px;
max-width: 250px;
min-height: 40px;
margin: 4px;
padding: 2px;
}
&-pressed {
@extend .button;
background-color: var(--accent-color-very-light);
}
}
.button:hover:not(.button-pressed) {
background-color: var(--accent-color-light);
}
@media only screen and (max-width: 600px) {
.button.channel-button {
min-width: 100px;
max-width: 100px;
}
}

View file

@ -0,0 +1,67 @@
@mixin card {
padding: 0px;
margin: 0px;
background-color: var(--default-main-card-color);
border-radius: var(--default-border-radius);
box-shadow: 0px 1px 1px var(--card-box-shadow-color);
}
.card {
@include card;
}
.bar-card {
@include card;
background-color: var(--channel-top-bar-color);
box-shadow: 0 1px 1px var(--card-box-shadow-color);
height: 32px;
padding: 8px;
border-radius: var(--bar-cards-border-radius);
display: flex;
align-items: center;
justify-content: left;
font-size: medium;
z-index: 100;
}
.message-list-card {
@include card;
@include fancy-scrollbar-firefox;
background-color: var(--channel-message-list-background-color);
box-shadow: none;
border-radius: 0px;
flex-grow: 1;
overflow: auto;
}
.main-card {
@include card;
box-shadow: none;
}
.col-flex-card {
@include card;
box-shadow: none;
flex-grow: 1;
display: flex;
flex-direction: column;
}
.row-flex-card {
@include card;
box-shadow: none;
flex-grow: 10;
display: flex;
flex-direction: row;
}

View file

@ -0,0 +1,38 @@
.main-display {
padding: 0px;
margin: 0px;
display: flex;
background-color: var(--background-color);
min-height: 100vh;
max-height: 100vh;
flex-direction: row;
}
.sidebar {
@include fancy-scrollbar-firefox;
background-color: var(--channel-list-background-color);
display: flex;
flex-direction: column;
overflow: auto;
overflow-x: hidden;
}
.channel-list {
display: flex;
flex-direction: column;
text-overflow: ellipsis;
white-space: nowrap;
overflow-x: hidden;
flex-grow: 10;
margin: 5px;
}
.invis-bar {
display: flex;
flex-direction: column;
padding: 10px;
z-index: 100;
}

View file

@ -0,0 +1,23 @@
.message {
@include card;
box-shadow: none;
display: flex;
flex-direction: row;
margin: 3px;
margin-left: 10px;
padding: 1px;
border-radius: var(--channel-message-border-radius);
background-color: var(--background-color);
}
.no-messages-warning {
text-align: center;
padding: 50px;
color: var(--darker-text-color);
}
.unread-indicator {
float: right;
}

View file

@ -0,0 +1,48 @@
.profile-picture {
border-radius: 50%;
margin: 5px;
width: 32px;
height: 32px;
&.profile-picture-8 {
width: 8px;
height: 8px;
}
&.profile-picture-16 {
width: 16px;
height: 16px;
}
&.profile-picture-32 {
width: 32px;
height: 32px;
}
&.profile-picture-40 {
width: 40px;
height: 40px;
}
&.profile-picture-64 {
width: 64px;
height: 64px;
}
}
.profile-link {
display: flex;
align-items: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow-x: hidden;
&.profile-link-offset-text {
align-items: unset;
text-align: start;
}
}
.profile-username {
font-weight: 550;
}

View file

@ -0,0 +1,15 @@
.text-input {
@include card;
margin: 5px;
padding: 5px;
border: none;
color: var(--default-text-color);
flex-grow: 1;
&.message-input {
border-radius: var(--message-box-border-radius);
background-color: var(--accent-color-dark);
height: 24px;
}
}

View file

@ -0,0 +1,34 @@
$nord0darker: #22262e;
$nord1darker: #282b36;
$nord2darker: #333947;
$nord3darker: #40495a;
$nord4darker: #9da2ad;
$nord0: #2E3440;
$nord1: #3B4252;
$nord2: #434C5E;
$nord3: #4C566A;
$nord4: #D8DEE9;
$nord5: #E5E9F0;
$nord6: #ECEFF4;
$nord7: #8FBCBB;
$nord8: #88C0D0;
$nord9: #81A1C1;
$nord10: #5E81AC;
$nord11: #BF616A;
$nord12: #D08770;
$nord13: #EBCB8B;
$nord14: #A3BE8C;
$nord15: #B48EAD;
$dark1: #2d2929;
$dark2: #332f2f;
$dark3: #393636;
$dark4: #423f3f;
$dark5: #4d4a4a;
$light1: #999999;
$light2: #b0b0b0;
$light3: #c2c2c2;
$light4: #cfcfcf;
$light5: #d9d9d9;

View file

@ -0,0 +1,4 @@
@mixin fancy-scrollbar-firefox {
scrollbar-width: none;
scrollbar-color: var(--default-main-card-color) var(--accent-color-light);
}

View file

@ -0,0 +1,32 @@
:root {
--background-color: #{$dark1};
--default-main-card-color: var(--background-color);
--card-box-shadow-color:#1f1c1c;
--default-text-color: #{$light3};
--darker-text-color: #{$light1};
--accent-color-dark: #{$dark2};
--accent-color-light: #{$dark3};
--accent-color-very-light: #{$dark4};
--channel-top-bar-color: var(--accent-color-light);
--channel-bottom-text-bar-color: var(--accent-color-light);
--channel-list-background-color: var(--accent-color-dark);
--channel-message-list-background-color: var(--background-color);
--channel-message-color: var(--accent-color-dark);
--button-color: var(--accent-color-dark);
--button-hover-color: var(--accent-color-light);
--default-transition-duration: 50ms;
--default-border-radius: 0px;
--default-button-border-radius: 0px;
--channel-message-border-radius: 0px;
--bar-cards-border-radius: 0px;
--channel-button-border-radius: 4px;
--message-box-border-radius: 4px;
}