diff --git a/bfrontend/src/Components/Categories/CategoryButton.js b/bfrontend/src/Components/Categories/CategoryButton.js index e53fd5f..e1dd245 100644 --- a/bfrontend/src/Components/Categories/CategoryButton.js +++ b/bfrontend/src/Components/Categories/CategoryButton.js @@ -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 ( - ); diff --git a/bfrontend/src/Components/Categories/CategoryList.js b/bfrontend/src/Components/Categories/CategoryList.js index d480f58..9a20500 100644 --- a/bfrontend/src/Components/Categories/CategoryList.js +++ b/bfrontend/src/Components/Categories/CategoryList.js @@ -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 (
- {categoryList.map((category) => - - )} + { categoryList.map((category) => ( )) }
); } -} \ No newline at end of file +} + +const stateToProps = (state) => { + return { + selectedCategoryId: state?.selectedCategoryId + }; +}; + +export default connect(stateToProps)(CategoryList); \ No newline at end of file diff --git a/bfrontend/src/Components/Categories/CategoryProfileLink.js b/bfrontend/src/Components/Categories/CategoryProfileLink.js index df92aca..463347e 100644 --- a/bfrontend/src/Components/Categories/CategoryProfileLink.js +++ b/bfrontend/src/Components/Categories/CategoryProfileLink.js @@ -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 = Profile - } else { - picture = Profile - } - return ( -
- { picture } - { category.title } -
- ) + + ); } \ No newline at end of file diff --git a/bfrontend/src/Components/Categories/CategoryView.js b/bfrontend/src/Components/Categories/CategoryView.js index 01c192b..f499a5f 100644 --- a/bfrontend/src/Components/Categories/CategoryView.js +++ b/bfrontend/src/Components/Categories/CategoryView.js @@ -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 => ); if (messagesView === undefined || messagesView.length <= 0) { messagesView = ( -
+
A bit empty in here...
); @@ -98,8 +93,6 @@ const stateToProps = (state, ownProps) => { return { categories: state?.categories, messages: state?.messages[categoryId] || [], - subscribedToCategories: state?.subscribedToCategories || [], - gateway: state?.gateway }; }; diff --git a/bfrontend/src/Components/UI/ProfileLink.js b/bfrontend/src/Components/UI/ProfileLink.js new file mode 100644 index 0000000..7d9d529 --- /dev/null +++ b/bfrontend/src/Components/UI/ProfileLink.js @@ -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 = Profile + } else { + picture = Profile + } + } else { + picture = null; + } + + const classes = type === 'user' ? 'profile-link user-profile-link' : 'profile-link'; + const title = type === 'category' ? object.title : object.username; + + return ( +
+ { picture } + { title } +
+ ) +} \ No newline at end of file diff --git a/bfrontend/src/Components/Users/UserProfileLink.js b/bfrontend/src/Components/Users/UserProfileLink.js index 7b29322..be0f908 100644 --- a/bfrontend/src/Components/Users/UserProfileLink.js +++ b/bfrontend/src/Components/Users/UserProfileLink.js @@ -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 = Profile - } else { - picture = Profile - } - } else { - picture = null; - } +import ProfileLink from '../UI/ProfileLink' +export default function CategoryProfile({ user, size }) { return ( -
- { picture } - { user.username } -
- ) + + ); } \ No newline at end of file diff --git a/bfrontend/src/Gateway/GatewayConnection.js b/bfrontend/src/Gateway/GatewayConnection.js index 06b55db..4c6fe96 100644 --- a/bfrontend/src/Gateway/GatewayConnection.js +++ b/bfrontend/src/Gateway/GatewayConnection.js @@ -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; \ No newline at end of file diff --git a/bfrontend/src/Styles/App.scss b/bfrontend/src/Styles/App.scss index aef0763..c4d9c09 100644 --- a/bfrontend/src/Styles/App.scss +++ b/bfrontend/src/Styles/App.scss @@ -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; diff --git a/bfrontend/src/store.js b/bfrontend/src/store.js index 41c4f2e..9c596ea 100644 --- a/bfrontend/src/store.js +++ b/bfrontend/src/store.js @@ -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 }; }