chore: more back
This commit is contained in:
parent
9ffb5da0b5
commit
316b16670c
|
@ -33,6 +33,7 @@
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
"dotenv": "8.2.0",
|
"dotenv": "8.2.0",
|
||||||
"history": "^4.7.2",
|
"history": "^4.7.2",
|
||||||
|
"lodash.throttle": "^4.1.1",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-hot-loader": "4.13.0",
|
"react-hot-loader": "4.13.0",
|
||||||
"react-redux": "^7.2.2",
|
"react-redux": "^7.2.2",
|
||||||
|
|
|
@ -37,7 +37,7 @@ const App = () => {
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Router>
|
</Router>
|
||||||
{!isAnonymous && <Right />}
|
{<Right />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import './index.scss';
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import FriendsActive from './active';
|
|
||||||
import FriendsAdd from './add';
|
|
||||||
import FriendsFavorites from './favorites';
|
|
||||||
import FriendsPendingIncoming from './pending/incoming';
|
|
||||||
import FriendsPendingOutgoing from './pending/outgoing';
|
|
||||||
|
|
||||||
export default function ChatLeftFriends() {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="friends"
|
|
||||||
>
|
|
||||||
<FriendsAdd />
|
|
||||||
<FriendsActive />
|
|
||||||
<FriendsFavorites />
|
|
||||||
<FriendsPendingIncoming />
|
|
||||||
<FriendsPendingOutgoing />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatLeftFriends.propTypes = {};
|
|
25
app/src/react/components/left/friends/index.jsx
Normal file
25
app/src/react/components/left/friends/index.jsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Active from './active';
|
||||||
|
import Add from './add';
|
||||||
|
import Favorites from './favorites';
|
||||||
|
import PendingIncoming from './pending/incoming';
|
||||||
|
import PendingOutgoing from './pending/outgoing';
|
||||||
|
|
||||||
|
export default function ChatLeftFriends() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="friends"
|
||||||
|
>
|
||||||
|
<Add />
|
||||||
|
<Active />
|
||||||
|
<Favorites />
|
||||||
|
<PendingIncoming />
|
||||||
|
<PendingOutgoing />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatLeftFriends.propTypes = {};
|
|
@ -19,8 +19,9 @@ import {
|
||||||
|
|
||||||
import Bar from 'components/bar';
|
import Bar from 'components/bar';
|
||||||
import Branding from 'components/branding';
|
import Branding from 'components/branding';
|
||||||
import Friends from 'components/friends';
|
|
||||||
// import ChatLeftRooms from './chat--leftRooms';
|
import Friends from './friends';
|
||||||
|
import Rooms from './rooms';
|
||||||
|
|
||||||
export default function ChatLeft() {
|
export default function ChatLeft() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
@ -57,7 +58,7 @@ export default function ChatLeft() {
|
||||||
isHorizontal
|
isHorizontal
|
||||||
onActive={(active) => dispatch(setLeftActiveIndex(active))}
|
onActive={(active) => dispatch(setLeftActiveIndex(active))}
|
||||||
/>
|
/>
|
||||||
{/* {0 === active && <ChatLeftRooms />} */}
|
{0 === active && <Rooms />}
|
||||||
{1 === active && <Friends />}
|
{1 === active && <Friends />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
54
app/src/react/components/left/rooms/add/index.jsx
Normal file
54
app/src/react/components/left/rooms/add/index.jsx
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
import {push} from 'connected-react-router';
|
||||||
|
import React, {useRef, useState} from 'react';
|
||||||
|
import {useDispatch} from 'react-redux';
|
||||||
|
|
||||||
|
import {validateChannel} from '@reddichat/core/client';
|
||||||
|
|
||||||
|
export default function ChatLeftRoomsAdd() {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [text, setText] = useState('');
|
||||||
|
const $form = useRef(null);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="chat--leftRoomsAdd"
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
onSubmit={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
if (validateChannel({type: 'r', name: text})) {
|
||||||
|
dispatch(push(`/chat/r/${text}`));
|
||||||
|
}
|
||||||
|
setText('');
|
||||||
|
}}
|
||||||
|
ref={$form}
|
||||||
|
>
|
||||||
|
<label className="channels__join">
|
||||||
|
Start chatting at
|
||||||
|
<span className="channels__joinTextWrapper">
|
||||||
|
<input
|
||||||
|
className="channels__joinText"
|
||||||
|
onChange={(event) => {
|
||||||
|
setText(event.target.value);
|
||||||
|
}}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if ('Enter' === event.key && !event.shiftKey) {
|
||||||
|
if ($form.current) {
|
||||||
|
$form.current.dispatchEvent(new Event('submit', {cancelable: true}));
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
placeholder="reddichat"
|
||||||
|
type="text"
|
||||||
|
value={text}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatLeftRoomsAdd.propTypes = {};
|
30
app/src/react/components/left/rooms/add/index.scss
Normal file
30
app/src/react/components/left/rooms/add/index.scss
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
@import 'scss/colors.scss';
|
||||||
|
|
||||||
|
.channels__join[class] {
|
||||||
|
align-items: center;
|
||||||
|
background-color: #272727;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channels__joinTextWrapper {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channels__joinTextWrapper::before {
|
||||||
|
content: '/r/';
|
||||||
|
font-size: 0.8em;
|
||||||
|
padding: 0 0.25em 0 0.5em;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channels__joinText {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding-left: 0.25em;
|
||||||
|
text-transform: lowercase;
|
||||||
|
width: 0%;
|
||||||
|
}
|
37
app/src/react/components/left/rooms/favorites/index.jsx
Normal file
37
app/src/react/components/left/rooms/favorites/index.jsx
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {useDispatch, useSelector} from 'react-redux';
|
||||||
|
|
||||||
|
import {
|
||||||
|
favoriteChannelsSelector,
|
||||||
|
submitRemoveFavorite,
|
||||||
|
} from '@reddichat/user/client';
|
||||||
|
|
||||||
|
import Channels from 'components/channels';
|
||||||
|
|
||||||
|
export default function ChatLeftRoomsFavorites() {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const favorites = useSelector(favoriteChannelsSelector);
|
||||||
|
|
||||||
|
const channels = favorites
|
||||||
|
.map((channel) => ({
|
||||||
|
name: channel,
|
||||||
|
actions: [
|
||||||
|
['💔', 'Unfavorite', () => dispatch(submitRemoveFavorite(`/r/${channel}`))],
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="chat--leftRoomsFavorites"
|
||||||
|
>
|
||||||
|
<Channels
|
||||||
|
channels={channels}
|
||||||
|
type="/r/"
|
||||||
|
title="Favorites"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatLeftRoomsFavorites.propTypes = {};
|
21
app/src/react/components/left/rooms/index.jsx
Normal file
21
app/src/react/components/left/rooms/index.jsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Add from './add';
|
||||||
|
import Favorites from './favorites';
|
||||||
|
import Recent from './recent';
|
||||||
|
|
||||||
|
export default function ChatLeftRooms() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="chat--leftRooms"
|
||||||
|
>
|
||||||
|
<Add />
|
||||||
|
<Favorites />
|
||||||
|
<Recent />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatLeftRooms.propTypes = {};
|
0
app/src/react/components/left/rooms/index.scss
Normal file
0
app/src/react/components/left/rooms/index.scss
Normal file
41
app/src/react/components/left/rooms/recent/index.jsx
Normal file
41
app/src/react/components/left/rooms/recent/index.jsx
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {useDispatch, useSelector} from 'react-redux';
|
||||||
|
|
||||||
|
import {
|
||||||
|
favoriteChannelsSelector,
|
||||||
|
recentSelector,
|
||||||
|
removeRecent,
|
||||||
|
submitAddFavorite,
|
||||||
|
} from '@reddichat/user/client';
|
||||||
|
|
||||||
|
import Channels from 'components/channels';
|
||||||
|
|
||||||
|
export default function ChatLeftRoomsRecent() {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const favorites = useSelector(favoriteChannelsSelector);
|
||||||
|
const recent = useSelector(recentSelector)
|
||||||
|
.filter((channel) => -1 === favorites.indexOf(channel));
|
||||||
|
const channels = recent
|
||||||
|
.map((channel) => ({
|
||||||
|
name: channel,
|
||||||
|
actions: [
|
||||||
|
['❤️', 'Favorite', () => dispatch(submitAddFavorite(`/r/${channel}`))],
|
||||||
|
['×', 'Close', () => dispatch(removeRecent(channel))],
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="chat--leftRoomsRecent"
|
||||||
|
>
|
||||||
|
<Channels
|
||||||
|
channels={channels}
|
||||||
|
type="/r/"
|
||||||
|
title="Recent"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatLeftRoomsRecent.propTypes = {};
|
44
app/src/react/components/right/blocked/index.jsx
Normal file
44
app/src/react/components/right/blocked/index.jsx
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import {useDispatch, useSelector} from 'react-redux';
|
||||||
|
|
||||||
|
import {
|
||||||
|
submitUnblock,
|
||||||
|
usernamesSelector,
|
||||||
|
} from '@reddichat/user/client';
|
||||||
|
|
||||||
|
import Channel from 'components/channel';
|
||||||
|
|
||||||
|
export default function ChatRightBlocked(props) {
|
||||||
|
const {ids} = props;
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const usernames = useSelector(usernamesSelector);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="chat--rightBlocked"
|
||||||
|
>
|
||||||
|
<h2 className="blocked__chatsTitle">Blocked</h2>
|
||||||
|
<ul className="blocked__chatsList">
|
||||||
|
{ids.map((id) => {
|
||||||
|
const blockedActions = [
|
||||||
|
['😶', 'Unblock', () => dispatch(submitUnblock(id))],
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<Channel
|
||||||
|
key={id}
|
||||||
|
actions={blockedActions}
|
||||||
|
name={usernames[id] || '?'}
|
||||||
|
type="/u/"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatRightBlocked.propTypes = {
|
||||||
|
ids: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||||
|
};
|
10
app/src/react/components/right/blocked/index.scss
Normal file
10
app/src/react/components/right/blocked/index.scss
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
@import 'scss/colors.scss';
|
||||||
|
|
||||||
|
.blocked__chatsTitle {
|
||||||
|
color: $color-muted;
|
||||||
|
font-family: var(--thick-title-font-family);
|
||||||
|
font-size: 0.7em;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 2.5em 1em 0.625em 1.375em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
|
@ -2,41 +2,42 @@ import './index.scss';
|
||||||
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
// import {useDispatch, useSelector} from 'react-redux';
|
import {useDispatch, useSelector} from 'react-redux';
|
||||||
import {Link} from 'react-router-dom';
|
import {Link} from 'react-router-dom';
|
||||||
|
|
||||||
// import {
|
import {
|
||||||
// rightActiveIndexSelector,
|
rightActiveIndexSelector,
|
||||||
// rightIsOpenSelector,
|
rightIsOpenSelector,
|
||||||
// setRightActiveIndex,
|
setRightActiveIndex,
|
||||||
// } from '~/common/state/app';
|
} from '@reddichat/app/client';
|
||||||
// import {channelUsersSelector} from '~/common/state/chat';
|
import {channelUsersSelector} from '@reddichat/chat/client';
|
||||||
// import {
|
import {
|
||||||
// blockedSelector,
|
blockedSelector,
|
||||||
// } from '~/common/state/user';
|
} from '@reddichat/user/client';
|
||||||
|
|
||||||
// import useChannel from '~/client/hooks/useChannel';
|
import useChannel from 'hooks/useChannel';
|
||||||
|
|
||||||
// import Bar from './bar';
|
import Bar from 'components/bar';
|
||||||
// import ChatRightBlocked from './chat--rightBlocked';
|
|
||||||
// import ChatRightUsers from './chat--rightUsers';
|
import Blocked from './blocked';
|
||||||
|
import Users from './users';
|
||||||
|
|
||||||
export default function ChatRight() {
|
export default function ChatRight() {
|
||||||
// const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
// const activeIndex = useSelector(rightActiveIndexSelector);
|
const activeIndex = useSelector(rightActiveIndexSelector);
|
||||||
// const channel = useChannel();
|
const channel = useChannel();
|
||||||
// const blockedIds = useSelector(blockedSelector);
|
const blockedIds = useSelector(blockedSelector);
|
||||||
// const channelUsers = useSelector((state) => channelUsersSelector(state, channel));
|
const channelUsers = useSelector((state) => channelUsersSelector(state, channel));
|
||||||
// const isOpen = useSelector(rightIsOpenSelector);
|
const isOpen = useSelector(rightIsOpenSelector);
|
||||||
const showsAsOpen = true;
|
const showsAsOpen = isOpen;
|
||||||
// const rightButtons = []
|
const rightButtons = []
|
||||||
// .concat(channelUsers.length > 0 ? [{icon: '🙃', label: 'Present'}] : [])
|
.concat(channelUsers.length > 0 ? [{icon: '🙃', label: 'Present'}] : [])
|
||||||
// .concat(blockedIds.length > 0 ? [{icon: '☢️', label: 'Blocked'}] : []);
|
.concat(blockedIds.length > 0 ? [{icon: '☢️', label: 'Blocked'}] : []);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classnames('right', 'flexed', showsAsOpen ? 'open' : 'closed')}
|
className={classnames('right', 'flexed', showsAsOpen ? 'open' : 'closed')}
|
||||||
>
|
>
|
||||||
{/* <Bar
|
<Bar
|
||||||
active={activeIndex}
|
active={activeIndex}
|
||||||
buttons={rightButtons}
|
buttons={rightButtons}
|
||||||
className="bar--right"
|
className="bar--right"
|
||||||
|
@ -46,10 +47,10 @@ export default function ChatRight() {
|
||||||
<div className="right__links">
|
<div className="right__links">
|
||||||
<Link className="right__link" to="/about">About</Link>
|
<Link className="right__link" to="/about">About</Link>
|
||||||
<span className="right__linksBullet">•</span>
|
<span className="right__linksBullet">•</span>
|
||||||
<Link className="right__link" to="/logout">Log out</Link>
|
<Link className="right__link" to="/auth/logout">Log out</Link>
|
||||||
</div>
|
</div>
|
||||||
{0 === activeIndex && channelUsers.length > 0 && <ChatRightUsers />}
|
{0 === activeIndex && channelUsers.length > 0 && <Users />}
|
||||||
{1 === activeIndex && blockedIds.length > 0 && <ChatRightBlocked ids={blockedIds} />} */}
|
{1 === activeIndex && blockedIds.length > 0 && <Blocked ids={blockedIds} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
121
app/src/react/components/right/users/index.jsx
Normal file
121
app/src/react/components/right/users/index.jsx
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {useDispatch, useSelector} from 'react-redux';
|
||||||
|
|
||||||
|
import {channelIsAnonymous} from '@reddichat/core/client';
|
||||||
|
import {channelUsersSelector} from '@reddichat/chat/client';
|
||||||
|
import {
|
||||||
|
blockedSelector,
|
||||||
|
favoriteUsersSelector,
|
||||||
|
friendshipIdIndex,
|
||||||
|
friendshipSelector,
|
||||||
|
idSelector,
|
||||||
|
redditUsernameSelector,
|
||||||
|
submitAddFavorite,
|
||||||
|
submitAddFriend,
|
||||||
|
submitBlock,
|
||||||
|
submitConfirmFriend,
|
||||||
|
submitRemoveFavorite,
|
||||||
|
submitRemoveFriend,
|
||||||
|
submitUnblock,
|
||||||
|
usernamesSelector,
|
||||||
|
} from '@reddichat/user/client';
|
||||||
|
|
||||||
|
import useChannel from 'hooks/useChannel';
|
||||||
|
|
||||||
|
import Channel from 'components/channel';
|
||||||
|
|
||||||
|
export default function ChatRightUsers() {
|
||||||
|
const channel = useChannel();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const blocked = useSelector(blockedSelector);
|
||||||
|
const favoriteUsers = useSelector(favoriteUsersSelector);
|
||||||
|
const friendship = useSelector(friendshipSelector);
|
||||||
|
const userId = useSelector(idSelector);
|
||||||
|
const ids = useSelector((state) => channelUsersSelector(state, channel));
|
||||||
|
const redditUsername = useSelector(redditUsernameSelector);
|
||||||
|
const usernames = useSelector(usernamesSelector);
|
||||||
|
const list = ids
|
||||||
|
.map((id) => [id, usernames[id]])
|
||||||
|
.sort((l, r) => (l[1] < r[1] ? -1 : 1));
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="chat--rightUsers"
|
||||||
|
>
|
||||||
|
<h2 className="users__chatsTitle">Who's here</h2>
|
||||||
|
<ul className="users__chatsList">
|
||||||
|
{list.map(([id, username]) => {
|
||||||
|
const hasBlocked = -1 !== blocked.indexOf(id);
|
||||||
|
const isAnonymous = channelIsAnonymous(channel);
|
||||||
|
const isSelf = redditUsername === username;
|
||||||
|
const index = friendshipIdIndex(friendship, id);
|
||||||
|
const hasFriendship = -1 !== index;
|
||||||
|
const userActions = [];
|
||||||
|
if (!isAnonymous && !isSelf) {
|
||||||
|
if (hasFriendship) {
|
||||||
|
if ('active' === friendship[index].status) {
|
||||||
|
if (-1 === favoriteUsers.indexOf(username)) {
|
||||||
|
userActions.push([
|
||||||
|
'🚫',
|
||||||
|
'Unfriend',
|
||||||
|
() => dispatch(submitRemoveFriend(id)),
|
||||||
|
]);
|
||||||
|
userActions.push([
|
||||||
|
'❤️',
|
||||||
|
'Favorite',
|
||||||
|
() => dispatch(submitAddFavorite(`/u/${username}`)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
userActions.push([
|
||||||
|
'💔',
|
||||||
|
'Unfavorite',
|
||||||
|
() => dispatch(submitRemoveFavorite(`/u/${username}`)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (friendship[index].adderId !== userId) {
|
||||||
|
userActions.push([
|
||||||
|
'👎',
|
||||||
|
'Deny friend request',
|
||||||
|
() => dispatch(submitRemoveFriend(id)),
|
||||||
|
]);
|
||||||
|
const {adderId} = friendship[index];
|
||||||
|
userActions.push([
|
||||||
|
'👍',
|
||||||
|
'Confirm friend request',
|
||||||
|
() => dispatch(submitConfirmFriend(adderId)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!hasBlocked) {
|
||||||
|
userActions.push(['➕', 'Add friend', () => dispatch(submitAddFriend(username))]);
|
||||||
|
}
|
||||||
|
if (hasBlocked) {
|
||||||
|
userActions.push(['😶', 'Unblock', () => dispatch(submitUnblock(id))]);
|
||||||
|
}
|
||||||
|
else if (-1 === favoriteUsers.indexOf(username)) {
|
||||||
|
userActions.push(['☢️', 'Block', () => dispatch(submitBlock(id))]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Channel
|
||||||
|
key={id}
|
||||||
|
actions={userActions}
|
||||||
|
href={(
|
||||||
|
(hasFriendship && userId !== id)
|
||||||
|
? `/chat/u/${username}`
|
||||||
|
: null
|
||||||
|
)}
|
||||||
|
name={username || '?'}
|
||||||
|
type="/u/"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatRightUsers.propTypes = {};
|
11
app/src/react/components/right/users/index.scss
Normal file
11
app/src/react/components/right/users/index.scss
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
@import 'scss/colors.scss';
|
||||||
|
|
||||||
|
.users__chatsTitle {
|
||||||
|
color: $color-muted;
|
||||||
|
font-family: var(--thick-title-font-family);
|
||||||
|
font-size: 0.7em;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 2.5em 1em 0.625em 1.375em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
32
app/src/react/hooks/useBreakpoints.js
Normal file
32
app/src/react/hooks/useBreakpoints.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import {useState, useEffect} from 'react';
|
||||||
|
import throttle from 'lodash.throttle';
|
||||||
|
|
||||||
|
const points = {
|
||||||
|
nano: 0,
|
||||||
|
tiny: 320,
|
||||||
|
tablet: 720,
|
||||||
|
desktop: 1280,
|
||||||
|
hd: 1920,
|
||||||
|
uhd: 3840,
|
||||||
|
};
|
||||||
|
|
||||||
|
const satisfiedPoints = (width) => {
|
||||||
|
const keys = Object.keys(points);
|
||||||
|
const satisfied = {};
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
const key = keys[i];
|
||||||
|
satisfied[key] = width >= points[key];
|
||||||
|
}
|
||||||
|
return satisfied;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useBreakpoints = () => {
|
||||||
|
const [satisfied, setSatisfied] = useState(() => satisfiedPoints(window.innerWidth));
|
||||||
|
useEffect(() => {
|
||||||
|
const onResize = throttle(() => setSatisfied(satisfiedPoints(window.innerWidth)), 100);
|
||||||
|
window.addEventListener('resize', onResize);
|
||||||
|
return () => window.removeEventListener('resize', onResize);
|
||||||
|
}, []);
|
||||||
|
return satisfied;
|
||||||
|
};
|
||||||
|
export default useBreakpoints;
|
8
app/src/react/hooks/useChannel.js
Normal file
8
app/src/react/hooks/useChannel.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import {useLocation} from 'react-router-dom';
|
||||||
|
|
||||||
|
import {parseChatChannel} from '@reddichat/core/client';
|
||||||
|
|
||||||
|
export default function useChannel() {
|
||||||
|
const {pathname} = useLocation();
|
||||||
|
return parseChatChannel(pathname);
|
||||||
|
}
|
|
@ -968,8 +968,8 @@
|
||||||
|
|
||||||
"@latus/react@^1.0.0":
|
"@latus/react@^1.0.0":
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://npm.i12e.cha0s.io/@latus%2freact/-/react-1.0.0.tgz#e68c8cd7015725c17a2aa18aebff52b39bbecca5"
|
resolved "https://npm.i12e.cha0s.io/@latus%2freact/-/react-1.0.0.tgz#965c0ca868f4fd83195e26f99bfd82d03ec8f361"
|
||||||
integrity sha512-ywXWx21xcJvVfp67Mj6rIaw4p9wepDDmRF0zzhyaJbhAu3weJ5oK9yd3IwWEYONtc/lzblak+3/fEaK+GFM01Q==
|
integrity sha512-ffWESmTinN2vxfxkpznysF+uU1rWSbB3AtvS2XWLzPg/X3A5yRql4J2602SHIy/xXhLWzHueDZ5pzxDiGe0S8g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@neutrinojs/react" "^9.4.0"
|
"@neutrinojs/react" "^9.4.0"
|
||||||
debug "4.3.1"
|
debug "4.3.1"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user