subscribe to all available categories, instead of subscribing to them when you click on them if that makes sense
This commit is contained in:
parent
57e72d24c7
commit
d35198e88e
9 changed files with 83 additions and 81 deletions
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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);
|
|
@ -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" />
|
||||
);
|
||||
}
|
|
@ -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
|
||||
};
|
||||
};
|
||||
|
||||
|
|
30
bfrontend/src/Components/UI/ProfileLink.js
Normal file
30
bfrontend/src/Components/UI/ProfileLink.js
Normal 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>
|
||||
)
|
||||
}
|
|
@ -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" />
|
||||
);
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue