subscribe to all available categories, instead of subscribing to them when you click on them if that makes sense

This commit is contained in:
hippoz 2021-02-09 20:09:36 +02:00
parent 57e72d24c7
commit d35198e88e
No known key found for this signature in database
GPG key ID: 7C52899193467641
9 changed files with 83 additions and 81 deletions

View file

@ -3,9 +3,12 @@ import gatewayConnection from '../../Gateway/globalGatewayConnection';
import { useHistory } from 'react-router-dom';
export default function CategoryButton({ category }) {
export default function CategoryButton({ category, selected }) {
const history = useHistory();
let buttonClasses = 'button category-button';
if (selected) buttonClasses += ' pressed';
const handleClick = () => {
if (gatewayConnection.isConnected) {
history.push(`/categories/${category._id}`);
@ -13,7 +16,7 @@ export default function CategoryButton({ category }) {
};
return (
<button className="button category-button" onClick={ handleClick }>
<button className={ buttonClasses } onClick={ handleClick }>
<CategoryProfile category={ category } size="32" />
</button>
);

View file

@ -3,13 +3,14 @@ import CategoryButton from './CategoryButton';
import APIRequest from '../../APIRequest';
import { couldNotReach } from '../../Errors';
import { useDispatch } from 'react-redux'
import { connect, useDispatch } from 'react-redux'
import { useState, useEffect } from 'react';
import Logger from '../../Logger';
import gatewayConnection from '../../Gateway/globalGatewayConnection';
const { log: loaderLog } = Logger([ 'CategoryList', 'Loader' ]);
export default function CategoryList() {
function CategoryList({ selectedCategoryId }) {
const [ categoryList, setCategoryList ] = useState();
const [ error, setError ] = useState();
@ -24,6 +25,9 @@ export default function CategoryList() {
loaderLog('Got category list from server, dispatching...');
setCategoryList(json.categories || []);
dispatch({ type: 'categories/updatecategorylist', categories: json.categories });
loaderLog('Subscribing to all categories...');
// TODO: IMPORTANT: Subscribing to a lot of channels puts strain on the server
gatewayConnection.subscribeToCategoryChats(json.categories.map(category => category._id));
})
.catch(() => {
setError(true);
@ -49,10 +53,16 @@ export default function CategoryList() {
} else {
return (
<div className="category-list">
{categoryList.map((category) =>
<CategoryButton key={ category._id } category={ category } />
)}
{ categoryList.map((category) => ( <CategoryButton key={ category._id } category={ category } selected={ (category._id === selectedCategoryId) } /> )) }
</div>
);
}
}
}
const stateToProps = (state) => {
return {
selectedCategoryId: state?.selectedCategoryId
};
};
export default connect(stateToProps)(CategoryList);

View file

@ -1,24 +1,7 @@
import defaultProfile from '../../Images/defaultprofile_256px-256px.png'
import ProfileLink from '../UI/ProfileLink'
export default function CategoryProfile({ category, size }) {
let picture;
if (!size) size = 32;
// TODO: Make a debug error message for then the size does not exist
const pictureClass = `profile-picture profile-picture-${size}`;
if (category.picture) {
// Not actually implemented on the server and can be unsafe, this is just futureproofing
picture = <img className={ pictureClass } src={ category.picture } alt="Profile"></img>
} else {
picture = <img className={ pictureClass } src={ defaultProfile } alt="Profile"></img>
}
return (
<div className="profile-link">
{ picture }
<span className="profile-username">{ category.title }</span>
</div>
)
<ProfileLink object={ category } size={ size } type="category" />
);
}

View file

@ -7,7 +7,7 @@ import { useParams } from 'react-router-dom';
import { connect, useDispatch } from 'react-redux';
import { useState, useRef, useEffect } from 'react';
function CategoryView({ categories, messages, isHandlingRoute=true, subscribedToCategories, gateway: { isConnected: isGatewayConnected } }) {
function CategoryView({ categories, messages }) {
const { id } = useParams();
const [ textInput, setTextInput ] = useState('');
const [ category, setCategory ] = useState();
@ -32,29 +32,24 @@ function CategoryView({ categories, messages, isHandlingRoute=true, subscribedTo
}
}
useEffect(() => {
if (isHandlingRoute) {
if (!id || id === '') return;
if (!isGatewayConnected ) return;
if (subscribedToCategories.includes(id)) return;
dispatch({ type: 'categories/selectcategory', categoryId: id });
gatewayConnection.subscribeToCategoryChat(id);
}
}, [dispatch, id, isHandlingRoute, subscribedToCategories, isGatewayConnected]);
useEffect(() => {
if (!categories) return;
setCategory(categories.find(x => x._id === id));
}, [ categories, id ]);
useEffect(() => {
if (!category) return;
dispatch({ type: 'categories/selectcategory', categoryId: category._id });
}, [ category, dispatch ]);
if (category) {
let messagesView = messages.map(m => <Message key={ m._id } message={ m } />);
if (messagesView === undefined || messagesView.length <= 0) {
messagesView = (
<div class='no-messages-warning'>
<div className='no-messages-warning'>
A bit empty in here...
</div>
);
@ -98,8 +93,6 @@ const stateToProps = (state, ownProps) => {
return {
categories: state?.categories,
messages: state?.messages[categoryId] || [],
subscribedToCategories: state?.subscribedToCategories || [],
gateway: state?.gateway
};
};

View file

@ -0,0 +1,30 @@
import defaultProfile from '../../Images/defaultprofile_256px-256px.png'
export default function ProfileLink({ object, size, type }) {
let picture;
if (!size) size = 32;
if (size !== 0) {
// TODO: Make a debug error message for then the size does not exist
const pictureClass = `profile-picture profile-picture-${size}`;
if (object.picture) {
// Not actually implemented on the server and can be unsafe, this is just futureproofing
picture = <img className={ pictureClass } src={ object.picture } alt="Profile"></img>
} else {
picture = <img className={ pictureClass } src={ defaultProfile } alt="Profile"></img>
}
} else {
picture = null;
}
const classes = type === 'user' ? 'profile-link user-profile-link' : 'profile-link';
const title = type === 'category' ? object.title : object.username;
return (
<div className={ classes }>
{ picture }
<span className="profile-username">{ title }</span>
</div>
)
}

View file

@ -1,27 +1,7 @@
import defaultProfile from '../../Images/defaultprofile_256px-256px.png'
export default function UserProfileLink({ user, size }) {
let picture;
if (!size) size = 32;
if (size !== 0) {
// TODO: Make a debug error message for then the size does not exist
const pictureClass = `profile-picture profile-picture-${size}`;
if (user.picture) {
// Not actually implemented on the server and can be unsafe, this is just futureproofing
picture = <img className={ pictureClass } src={ user.picture } alt="Profile"></img>
} else {
picture = <img className={ pictureClass } src={ defaultProfile } alt="Profile"></img>
}
} else {
picture = null;
}
import ProfileLink from '../UI/ProfileLink'
export default function CategoryProfile({ user, size }) {
return (
<div className="profile-link user-profile-link">
{ picture }
<span className="profile-username">{ user.username }</span>
</div>
)
<ProfileLink object={ user } size={ size } type="user" />
);
}

View file

@ -74,14 +74,12 @@ GatewayConnection.prototype.sendMessage = function(categoryId, content) {
});
};
GatewayConnection.prototype.subscribeToCategoryChat = function(categoryId) {
GatewayConnection.prototype.subscribeToCategoryChats = function(categoryIds) {
if (!this.isConnected) return;
const request = [categoryId];
gatewayLog('Subscribing to channel(s)', categoryIds);
gatewayLog('Subscribing to channel(s)', request);
this.socket.emit('subscribe', request);
this.socket.emit('subscribe', categoryIds);
};
export default GatewayConnection;

View file

@ -1,7 +1,7 @@
$nord0darker: #22262e;
$nord1darker: #282b36;
$nord2darker: #333947;
$nord3darker: #40495a;
$nord4darker: #9da2ad;
$nord0: #2E3440;
@ -32,6 +32,7 @@ $nord15: #B48EAD;
--accent-color-dark: #{$nord1darker};
--accent-color-light: #{$nord2darker};
--accent-color-very-light: #{$nord3darker};
--category-top-bar-color: var(--accent-color-light);
--category-bottom-text-bar-color: var(--accent-color-light);
@ -171,11 +172,11 @@ body {
}
&.pressed {
background-color: var(--accent-color-light);
background-color: var(--accent-color-very-light);
}
}
.button:hover {
.button:hover:not(.pressed) {
background-color: var(--accent-color-light);
}
@ -274,6 +275,10 @@ body {
color: var(--darker-text-color);
}
.unread-indicator {
float: right;
}
@media only screen and (max-width: 600px) {
.button.category-button {
min-width: 100px;

View file

@ -2,11 +2,14 @@ import { createStore } from 'redux';
const intitialState = {
user: null,
categories: null,
gateway: { isConnected: false },
messages: {},
subscribedToCategories: [],
categoryPresenceClientList: {}
categoryPresenceClientList: {},
selectedCategoryId: undefined
};
const reducer = (state = intitialState, payload) => {
@ -50,10 +53,7 @@ const reducer = (state = intitialState, payload) => {
case 'categories/selectcategory': {
return {
...state,
subscribedToCategories: [
...state.subscribedToCategories || [],
payload.categoryId
]
selectedCategoryId: payload.categoryId
};
}