presence, experiment overrides, design improvements

This commit is contained in:
hippoz 2021-06-10 18:42:53 +03:00
parent 2f220e511e
commit 033d0e4da1
Signed by: hippoz
GPG key ID: 7C52899193467641
15 changed files with 99 additions and 44 deletions

View file

@ -10,6 +10,8 @@ const opcodes = {
2: { name: "YOO_ACK", data: "JSON" },
3: { name: "ACTION_CREATE_MESSAGE", data: "JSON" },
4: { name: "EVENT_CREATE_MESSAGE", data: "JSON" },
5: { name: "ACTION_UPDATE_STATUS", data: "JSON" },
6: { name: "EVENT_CHANNEL_MEMBERS", data: "JSON" },
21: { name: "ACTION_VOICE_REQUEST_SESSION", data: "JSON" },
22: { name: "EVENT_VOICE_ASSIGN_SERVER", data: "JSON" },
23: { name: "ACTION_VOICE_CONNECTION_REQUEST", data: "JSON" },
@ -84,6 +86,20 @@ GatewayConnection.prototype.connect = function(token) {
this.ws.send(this.packet("YOO", { token }));
break;
}
case "EVENT_CHANNEL_MEMBERS": {
this.presence = {
...this.presence,
...packet.data
}
for (const [userId, user] of Object.entries(this.presence)) {
if (user.status <= 0)
delete this.presence[userId];
}
this.fire("presenceUpdate", this.presence);
break;
}
case "YOO_ACK": {
// Server accepted connection
logGateway("Got YOO_ACK", packet.data);

View file

@ -1,6 +1,9 @@
import GatewayConnection from './GatewayConnection';
import config from '../../Config';
import store from '../../Global/store';
import logger from '../../Util/Logger';
const { warn } = logger(["Experiments"]);
const globalGatewayConnection = new GatewayConnection(config.gatewayUrl);
@ -8,13 +11,29 @@ globalGatewayConnection.onopen = (sessionData) => {
store.dispatch({ type: 'gateway/connectionstatus', gateway: { isConnected: true } });
store.dispatch({ type: 'authenticator/updatelocaluserobject', user: sessionData.user });
store.dispatch({ type: 'channels/updatechannellist', channels: sessionData.channels });
store.dispatch({ type: 'application/updateexperiments', experiments: sessionData.__global_experiments || [] });
if (localStorage.getItem("enableExperimentOverrides")) {
warn("Experiment overrides are enabled");
const experimentModifiers = JSON.parse(localStorage.getItem("experimentOverrides"));
const experiments = {
...sessionData.__global_experiments || {},
...experimentModifiers || {}
};
store.dispatch({ type: 'application/updateexperiments', experiments });
store.dispatch({ type: 'application/updatebannertext', text: "Experiment overrides are enabled! Things could go haywire!" });
} else {
store.dispatch({ type: 'application/updateexperiments', experiments: sessionData.__global_experiments || {} });
}
};
globalGatewayConnection.onmessage = (message) => {
store.dispatch({ type: 'messagestore/addmessage', message });
};
globalGatewayConnection.presenceUpdate = (presence) => {
store.dispatch({ type: 'channels/updatepresence', clientListEvent: presence });
};
globalGatewayConnection.onclose = function() {
store.dispatch({ type: 'authenticator/updatelocaluserobject', user: undefined });
store.dispatch({ type: 'gateway/connectionstatus', gateway: { isConnected: false } });

View file

@ -59,7 +59,7 @@ export default function Login() {
<br />
<input type="password" name="password" className="text-input" onChange={ ({ target }) => setPasswordInput(target.value) } />
<br />
<button id="login-submit" className="button" onClick={ handleLoginContinueButton }>Continue</button>
<button id="login-submit" className="button-pressed" onClick={ handleLoginContinueButton }>Continue</button>
<Notification text={ info } />
</div>
);

View file

@ -1,26 +1,14 @@
import UserProfileButton from '../Users/UserButton';
import { connect } from 'react-redux';
function ChannelUserList({ channelPresenceClientList }) {
const users = [
{ username: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", _id: "a" },
{ username: "FDGFEGSDFHRFGHNERTYBNRNBTYJMNUM", _id: "b" }
];
function ChannelUserList({ presence }) {
console.log(presence);
return (
<div className="main-card sidebar">
<div className="channel-list">
{ users.map((user) => <UserProfileButton key={ user._id } user={ user } />) }
{ Object.keys(presence).map((userId) => <UserProfileButton key={ userId } user={ presence[userId] } />) }
</div>
</div>
)
}
const stateToProps = (state) => {
return {
channelPresenceClientList: state?.channelPresenceClientList
};
};
export default connect(stateToProps)(ChannelUserList);
export default ChannelUserList;

View file

@ -9,7 +9,7 @@ import { connect, useDispatch } from 'react-redux';
import { useState, useRef, useEffect } from 'react';
const ChannelView = ({ channels, messages, channel, selectedChannelId, experiments }) => {
const ChannelView = ({ channels, messages, channel, selectedChannelId, experiments, channelPresenceClientList, gradientBannerNotificationText }) => {
const { id } = useParams();
const [ textInput, setTextInput ] = useState('');
@ -60,6 +60,10 @@ const ChannelView = ({ channels, messages, channel, selectedChannelId, experimen
</button>}
</div>
{(gradientBannerNotificationText !== undefined) && <div className="gradient-banner-card">
{ gradientBannerNotificationText }
</div>}
<div className="main-card row-flex-card hidden-overflow">
<div className="col-flex-card channel-message-panel hidden-overflow">
<div className="message-list-card">
@ -71,7 +75,7 @@ const ChannelView = ({ channels, messages, channel, selectedChannelId, experimen
<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>
{ (experiments.userListTest) && <ChannelUserList /> }
{ (experiments.userListTest) && <ChannelUserList presence={ channelPresenceClientList || [] } /> }
</div>
</div>
)
@ -100,7 +104,9 @@ const stateToProps = (state, ownProps) => {
channel: state?.channels?.find(x => x._id === channelId),
messages: state?.messages[channelId] || [],
selectedChannelId: state?.selectedChannelId,
experiments: state?.experiments || {}
experiments: state?.experiments || {},
channelPresenceClientList: state?.channelPresenceClientList,
gradientBannerNotificationText: state?.gradientBannerNotificationText
};
};

View file

@ -9,7 +9,7 @@ export default function Root(props) {
return (
<div id="login-message-container">
<h1>Welcome back!</h1>
<button className="button" onClick={ () => { history.push('/login') } }>Log in</button>
<button className="button-pressed" onClick={ () => { history.push('/login') } }>Log in</button>
<button className="button" onClick={ () => { history.push('/create') } }>Create an account</button>
</div>
);

View file

@ -1,5 +1,3 @@
import defaultProfile from '../../Content/Images/defaultprofile_256px-256px.png'
// This is a mess pls fix later
export default function ProfileLink({ object, size, type, offset=true, children=null }) {
let picture;

View file

@ -2,7 +2,7 @@ import UserProfile from './UserProfileLink';
import { useHistory } from 'react-router-dom';
export default function ChannelUserButton({ user }) {
export default function ChannelUserButton({ user, subtext }) {
const history = useHistory();
let buttonClasses = 'button button-channel';
@ -13,7 +13,7 @@ export default function ChannelUserButton({ user }) {
return (
<button className={ buttonClasses } onClick={ handleClick }>
<UserProfile user={ user } size="32" />
<UserProfile subtext={ subtext } user={ user } size="32" />
</button>
);
}

View file

@ -1,8 +1,8 @@
import ProfileLink from '../UI/ProfileLink'
// TODO: Stop using this component and just use the ProfileLink component
export default function ChannelProfile({ user, size, offset=false }) {
export default function UserProfile({ user, size, subtext }) {
return (
<ProfileLink object={ user } size={ size } type="user" offset={ offset } />
<ProfileLink object={ user } size={ size } type="user" offset={ subtext !== undefined } children={ (subtext) && (<span>{ subtext }</span>) } />
);
}

View file

@ -8,6 +8,7 @@ const intitialState = {
gateway: { isConnected: false },
messages: {},
channelPresenceClientList: {},
gradientBannerNotificationText: undefined,
selectedChannelId: undefined
};
@ -57,13 +58,10 @@ const reducer = (state = intitialState, payload) => {
};
}
case 'presence/channel/clientlistupdate': {
case 'channels/updatepresence': {
return {
...state,
channelPresenceClientList: {
...state.channelPresenceClientList || [],
[payload.clientListEvent.channel._id]: payload.clientListEvent.clientList
}
channelPresenceClientList: payload.clientListEvent
};
}
@ -74,6 +72,13 @@ const reducer = (state = intitialState, payload) => {
}
}
case 'application/updatebannertext': {
return {
...state,
gradientBannerNotificationText: payload.text
}
}
default: {
return state;
}

View file

@ -26,13 +26,13 @@
&-pressed {
@extend .button;
background-color: var(--button-selected-color);
background: var(--focus-accent-background);
color: var(--default-text-color);
}
}
.button:hover:not(.button-pressed) {
background-color: var(--button-hover-color);
background: var(--focus-accent-background-deep);
}
@media only screen and (max-width: 600px) {

View file

@ -67,4 +67,15 @@
flex-grow: 10;
display: flex;
flex-direction: row;
}
.gradient-banner-card {
background: var(--default-user-background);
height: 1.5rem;
padding: 10px;
margin: 10px;
border-radius: 0.3243rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

View file

@ -17,7 +17,7 @@
flex-direction: column;
overflow: auto;
overflow-x: hidden;
min-width: 230px;
min-width: 235px;
}
.channel-list {

View file

@ -24,5 +24,5 @@
.message-content {
padding-left: 6px;
text-rendering: "optimizeLegibility";
text-rendering: optimizeLegibility;
}

View file

@ -1,21 +1,33 @@
:root {
--background-color: #030303;
--background-color: hsl(0, 0%, 1%);
--default-text-color: hsl(0, 0%, 79%);
--darker-text-color: hsl(0, 0%, 53%);
--card-accent-color: hsl(0, 0%, 10%);
--card-accent-color-dark: hsl(0, 0%, 5%);
--default-main-card-color: var(--background-color);
--card-box-shadow-color: 0 1px 0 #1d1a1abe;
--default-text-color: #cacaca;
--darker-text-color: #808080;
--focus-accent-background: var(--card-accent-color);
--focus-accent-background-deep: var(--card-accent-color-dark);
--card-accent-color: #212121;
--focus-accent-color: hsl(246, 57%, 38%);
--focus-accent-color-deep: hsl(255, 70%, 30%);
--default-user-background: linear-gradient(
to bottom right,
hsl(275, 55%, 40%),
hsl(300, 55%, 40%),
hsl(325, 55%, 40%)
);
--default-channel-background: linear-gradient(
to bottom right,
hsl(150, 55%, 40%),
hsl(175, 55%, 40%),
hsl(200, 55%, 40%)
);
--channel-top-bar-color-accent: var(--background-color);
--channel-top-bar-color: var(--background-color);
--bar-card-border-bottom: solid 1px #1d1d1d;
--message-box-color: var(--card-accent-color);
--message-box-shadow: #22222273 6px 8px 12px;
--channel-top-bar-border-color: var(--accent-color-dark);
--channel-list-background-color: var(--background-color);