presence, experiment overrides, design improvements
This commit is contained in:
parent
2f220e511e
commit
033d0e4da1
15 changed files with 99 additions and 44 deletions
|
@ -10,6 +10,8 @@ const opcodes = {
|
||||||
2: { name: "YOO_ACK", data: "JSON" },
|
2: { name: "YOO_ACK", data: "JSON" },
|
||||||
3: { name: "ACTION_CREATE_MESSAGE", data: "JSON" },
|
3: { name: "ACTION_CREATE_MESSAGE", data: "JSON" },
|
||||||
4: { name: "EVENT_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" },
|
21: { name: "ACTION_VOICE_REQUEST_SESSION", data: "JSON" },
|
||||||
22: { name: "EVENT_VOICE_ASSIGN_SERVER", data: "JSON" },
|
22: { name: "EVENT_VOICE_ASSIGN_SERVER", data: "JSON" },
|
||||||
23: { name: "ACTION_VOICE_CONNECTION_REQUEST", 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 }));
|
this.ws.send(this.packet("YOO", { token }));
|
||||||
break;
|
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": {
|
case "YOO_ACK": {
|
||||||
// Server accepted connection
|
// Server accepted connection
|
||||||
logGateway("Got YOO_ACK", packet.data);
|
logGateway("Got YOO_ACK", packet.data);
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import GatewayConnection from './GatewayConnection';
|
import GatewayConnection from './GatewayConnection';
|
||||||
import config from '../../Config';
|
import config from '../../Config';
|
||||||
import store from '../../Global/store';
|
import store from '../../Global/store';
|
||||||
|
import logger from '../../Util/Logger';
|
||||||
|
|
||||||
|
const { warn } = logger(["Experiments"]);
|
||||||
|
|
||||||
const globalGatewayConnection = new GatewayConnection(config.gatewayUrl);
|
const globalGatewayConnection = new GatewayConnection(config.gatewayUrl);
|
||||||
|
|
||||||
|
@ -8,13 +11,29 @@ globalGatewayConnection.onopen = (sessionData) => {
|
||||||
store.dispatch({ type: 'gateway/connectionstatus', gateway: { isConnected: true } });
|
store.dispatch({ type: 'gateway/connectionstatus', gateway: { isConnected: true } });
|
||||||
store.dispatch({ type: 'authenticator/updatelocaluserobject', user: sessionData.user });
|
store.dispatch({ type: 'authenticator/updatelocaluserobject', user: sessionData.user });
|
||||||
store.dispatch({ type: 'channels/updatechannellist', channels: sessionData.channels });
|
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) => {
|
globalGatewayConnection.onmessage = (message) => {
|
||||||
store.dispatch({ type: 'messagestore/addmessage', message });
|
store.dispatch({ type: 'messagestore/addmessage', message });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
globalGatewayConnection.presenceUpdate = (presence) => {
|
||||||
|
store.dispatch({ type: 'channels/updatepresence', clientListEvent: presence });
|
||||||
|
};
|
||||||
|
|
||||||
globalGatewayConnection.onclose = function() {
|
globalGatewayConnection.onclose = function() {
|
||||||
store.dispatch({ type: 'authenticator/updatelocaluserobject', user: undefined });
|
store.dispatch({ type: 'authenticator/updatelocaluserobject', user: undefined });
|
||||||
store.dispatch({ type: 'gateway/connectionstatus', gateway: { isConnected: false } });
|
store.dispatch({ type: 'gateway/connectionstatus', gateway: { isConnected: false } });
|
||||||
|
|
|
@ -59,7 +59,7 @@ export default function Login() {
|
||||||
<br />
|
<br />
|
||||||
<input type="password" name="password" className="text-input" onChange={ ({ target }) => setPasswordInput(target.value) } />
|
<input type="password" name="password" className="text-input" onChange={ ({ target }) => setPasswordInput(target.value) } />
|
||||||
<br />
|
<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 } />
|
<Notification text={ info } />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,26 +1,14 @@
|
||||||
import UserProfileButton from '../Users/UserButton';
|
import UserProfileButton from '../Users/UserButton';
|
||||||
|
|
||||||
import { connect } from 'react-redux';
|
function ChannelUserList({ presence }) {
|
||||||
|
console.log(presence);
|
||||||
function ChannelUserList({ channelPresenceClientList }) {
|
|
||||||
const users = [
|
|
||||||
{ username: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", _id: "a" },
|
|
||||||
{ username: "FDGFEGSDFHRFGHNERTYBNRNBTYJMNUM", _id: "b" }
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="main-card sidebar">
|
<div className="main-card sidebar">
|
||||||
<div className="channel-list">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const stateToProps = (state) => {
|
export default ChannelUserList;
|
||||||
return {
|
|
||||||
channelPresenceClientList: state?.channelPresenceClientList
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(stateToProps)(ChannelUserList);
|
|
|
@ -9,7 +9,7 @@ import { connect, useDispatch } from 'react-redux';
|
||||||
import { useState, useRef, useEffect } from 'react';
|
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 { id } = useParams();
|
||||||
const [ textInput, setTextInput ] = useState('');
|
const [ textInput, setTextInput ] = useState('');
|
||||||
|
|
||||||
|
@ -60,6 +60,10 @@ const ChannelView = ({ channels, messages, channel, selectedChannelId, experimen
|
||||||
</button>}
|
</button>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{(gradientBannerNotificationText !== undefined) && <div className="gradient-banner-card">
|
||||||
|
{ gradientBannerNotificationText }
|
||||||
|
</div>}
|
||||||
|
|
||||||
<div className="main-card row-flex-card hidden-overflow">
|
<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">
|
<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>
|
<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 /> }
|
{ (experiments.userListTest) && <ChannelUserList presence={ channelPresenceClientList || [] } /> }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -100,7 +104,9 @@ const stateToProps = (state, ownProps) => {
|
||||||
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,
|
selectedChannelId: state?.selectedChannelId,
|
||||||
experiments: state?.experiments || {}
|
experiments: state?.experiments || {},
|
||||||
|
channelPresenceClientList: state?.channelPresenceClientList,
|
||||||
|
gradientBannerNotificationText: state?.gradientBannerNotificationText
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ export default function Root(props) {
|
||||||
return (
|
return (
|
||||||
<div id="login-message-container">
|
<div id="login-message-container">
|
||||||
<h1>Welcome back!</h1>
|
<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>
|
<button className="button" onClick={ () => { history.push('/create') } }>Create an account</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import defaultProfile from '../../Content/Images/defaultprofile_256px-256px.png'
|
|
||||||
|
|
||||||
// This is a mess pls fix later
|
// This is a mess pls fix later
|
||||||
export default function ProfileLink({ object, size, type, offset=true, children=null }) {
|
export default function ProfileLink({ object, size, type, offset=true, children=null }) {
|
||||||
let picture;
|
let picture;
|
||||||
|
|
|
@ -2,7 +2,7 @@ import UserProfile from './UserProfileLink';
|
||||||
|
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
export default function ChannelUserButton({ user }) {
|
export default function ChannelUserButton({ user, subtext }) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
let buttonClasses = 'button button-channel';
|
let buttonClasses = 'button button-channel';
|
||||||
|
@ -13,7 +13,7 @@ export default function ChannelUserButton({ user }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className={ buttonClasses } onClick={ handleClick }>
|
<button className={ buttonClasses } onClick={ handleClick }>
|
||||||
<UserProfile user={ user } size="32" />
|
<UserProfile subtext={ subtext } user={ user } size="32" />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
import ProfileLink from '../UI/ProfileLink'
|
import ProfileLink from '../UI/ProfileLink'
|
||||||
|
|
||||||
// TODO: Stop using this component and just use the ProfileLink component
|
// 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 (
|
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>) } />
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ const intitialState = {
|
||||||
gateway: { isConnected: false },
|
gateway: { isConnected: false },
|
||||||
messages: {},
|
messages: {},
|
||||||
channelPresenceClientList: {},
|
channelPresenceClientList: {},
|
||||||
|
gradientBannerNotificationText: undefined,
|
||||||
|
|
||||||
selectedChannelId: undefined
|
selectedChannelId: undefined
|
||||||
};
|
};
|
||||||
|
@ -57,13 +58,10 @@ const reducer = (state = intitialState, payload) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'presence/channel/clientlistupdate': {
|
case 'channels/updatepresence': {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
channelPresenceClientList: {
|
channelPresenceClientList: payload.clientListEvent
|
||||||
...state.channelPresenceClientList || [],
|
|
||||||
[payload.clientListEvent.channel._id]: payload.clientListEvent.clientList
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +72,13 @@ const reducer = (state = intitialState, payload) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'application/updatebannertext': {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
gradientBannerNotificationText: payload.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,13 @@
|
||||||
&-pressed {
|
&-pressed {
|
||||||
@extend .button;
|
@extend .button;
|
||||||
|
|
||||||
background-color: var(--button-selected-color);
|
background: var(--focus-accent-background);
|
||||||
color: var(--default-text-color);
|
color: var(--default-text-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:hover:not(.button-pressed) {
|
.button:hover:not(.button-pressed) {
|
||||||
background-color: var(--button-hover-color);
|
background: var(--focus-accent-background-deep);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 600px) {
|
@media only screen and (max-width: 600px) {
|
||||||
|
|
|
@ -67,4 +67,15 @@
|
||||||
flex-grow: 10;
|
flex-grow: 10;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
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;
|
||||||
}
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
min-width: 230px;
|
min-width: 235px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-list {
|
.channel-list {
|
||||||
|
|
|
@ -24,5 +24,5 @@
|
||||||
|
|
||||||
.message-content {
|
.message-content {
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
text-rendering: "optimizeLegibility";
|
text-rendering: optimizeLegibility;
|
||||||
}
|
}
|
|
@ -1,21 +1,33 @@
|
||||||
:root {
|
: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);
|
--default-main-card-color: var(--background-color);
|
||||||
--card-box-shadow-color: 0 1px 0 #1d1a1abe;
|
--card-box-shadow-color: 0 1px 0 #1d1a1abe;
|
||||||
|
|
||||||
--default-text-color: #cacaca;
|
--focus-accent-background: var(--card-accent-color);
|
||||||
--darker-text-color: #808080;
|
--focus-accent-background-deep: var(--card-accent-color-dark);
|
||||||
|
|
||||||
--card-accent-color: #212121;
|
--default-user-background: linear-gradient(
|
||||||
--focus-accent-color: hsl(246, 57%, 38%);
|
to bottom right,
|
||||||
--focus-accent-color-deep: hsl(255, 70%, 30%);
|
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-accent: var(--background-color);
|
||||||
--channel-top-bar-color: var(--background-color);
|
--channel-top-bar-color: var(--background-color);
|
||||||
--bar-card-border-bottom: solid 1px #1d1d1d;
|
--bar-card-border-bottom: solid 1px #1d1d1d;
|
||||||
--message-box-color: var(--card-accent-color);
|
--message-box-color: var(--card-accent-color);
|
||||||
--message-box-shadow: #22222273 6px 8px 12px;
|
|
||||||
--channel-top-bar-border-color: var(--accent-color-dark);
|
--channel-top-bar-border-color: var(--accent-color-dark);
|
||||||
|
|
||||||
--channel-list-background-color: var(--background-color);
|
--channel-list-background-color: var(--background-color);
|
||||||
|
|
Loading…
Reference in a new issue