LTS Code. Tried to add DMs *I failed
This commit is contained in:
parent
e6e063366d
commit
77f611886b
@ -6,7 +6,22 @@ import { WSEvent } from './ws-event';
|
|||||||
export default class implements WSEvent<'CHANNEL_CREATE'> {
|
export default class implements WSEvent<'CHANNEL_CREATE'> {
|
||||||
public on = 'CHANNEL_CREATE' as const;
|
public on = 'CHANNEL_CREATE' as const;
|
||||||
|
|
||||||
public async invoke(ws: WebSocket, client: Socket, { name, guildId, type }: WS.Params.ChannelCreate) {
|
public async invoke(ws: WebSocket, client: Socket, params: WS.Params.ChannelCreate) {
|
||||||
|
const { name, guildId, type, userIds } = params;
|
||||||
|
|
||||||
|
if (type === 'DM') {
|
||||||
|
if (!userIds) throw new TypeError('userIds required for DM creation');
|
||||||
|
const channel = await deps.channels.createDM(userIds);
|
||||||
|
return [{
|
||||||
|
emit: this.on,
|
||||||
|
to: userIds,
|
||||||
|
send: {
|
||||||
|
channel,
|
||||||
|
creatorId: ws.sessions.get(client.id),
|
||||||
|
},
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
if (!name || !guildId || !type)
|
if (!name || !guildId || !type)
|
||||||
throw new TypeError('Not enough options were provided');
|
throw new TypeError('Not enough options were provided');
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import OverviewPage from './pages/overview-page';
|
|||||||
import LogoutPage from './pages/auth/logout-page';
|
import LogoutPage from './pages/auth/logout-page';
|
||||||
import PrivateRoute from './routing/private-route';
|
import PrivateRoute from './routing/private-route';
|
||||||
import NotFoundPage from './pages/not-found-page';
|
import NotFoundPage from './pages/not-found-page';
|
||||||
|
import DMPage from './pages/dm-page';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { ready } from '../store/auth';
|
import { ready } from '../store/auth';
|
||||||
@ -38,6 +39,7 @@ export default function App() {
|
|||||||
{/* Users must be logged in to use private routes. */}
|
{/* Users must be logged in to use private routes. */}
|
||||||
<PrivateRoute exact path="/themes/:themeCode" component={ThemePage} />
|
<PrivateRoute exact path="/themes/:themeCode" component={ThemePage} />
|
||||||
<PrivateRoute exact path="/channels/@me" component={OverviewPage} />
|
<PrivateRoute exact path="/channels/@me" component={OverviewPage} />
|
||||||
|
<PrivateRoute exact path="/channels/@me/:channelId?" component={DMPage} />
|
||||||
<PrivateRoute exact path="/channels/:guildId/:channelId?" component={GuildPage} />
|
<PrivateRoute exact path="/channels/:guildId/:channelId?" component={GuildPage} />
|
||||||
|
|
||||||
{/* This route is a catch-all for any other routes that don't exist. */}
|
{/* This route is a catch-all for any other routes that don't exist. */}
|
||||||
|
@ -11,7 +11,7 @@ import { Util } from '@acrd/types';
|
|||||||
const TextBasedChannel: React.FunctionComponent = () => {
|
const TextBasedChannel: React.FunctionComponent = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const channel = useSelector((s: Store.AppState) => s.ui.activeChannel)!;
|
const channel = useSelector((s: Store.AppState) => s.ui.activeChannel)!;
|
||||||
const guild = useSelector((s: Store.AppState) => s.ui.activeGuild)!;
|
const guild = useSelector((s: Store.AppState) => s.ui.activeGuild);
|
||||||
const messages = useSelector(getChannelMessages(channel.id));
|
const messages = useSelector(getChannelMessages(channel.id));
|
||||||
const perms = usePerms();
|
const perms = usePerms();
|
||||||
const [cachedContent, setCachedContent] = useState<Util.Dictionary>({});
|
const [cachedContent, setCachedContent] = useState<Util.Dictionary>({});
|
||||||
@ -41,7 +41,11 @@ const TextBasedChannel: React.FunctionComponent = () => {
|
|||||||
dispatch(fetchMessages(channel.id, back));
|
dispatch(fetchMessages(channel.id, back));
|
||||||
}
|
}
|
||||||
|
|
||||||
const canRead = perms.canInChannel('READ_MESSAGES', guild.id, channel.id);
|
const canRead = channel.type === 'DM'
|
||||||
|
? true
|
||||||
|
: guild
|
||||||
|
? perms.canInChannel('READ_MESSAGES', guild.id, channel.id)
|
||||||
|
: false;
|
||||||
|
|
||||||
const LoadingIndicator: React.FunctionComponent = () => (
|
const LoadingIndicator: React.FunctionComponent = () => (
|
||||||
<>
|
<>
|
||||||
|
36
frontend/src/components/navigation/sidebar/dm-list.tsx
Normal file
36
frontend/src/components/navigation/sidebar/dm-list.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { getDMChannels } from '../../../store/channels';
|
||||||
|
import FoundUsername from '../../user/username';
|
||||||
|
import { ChannelTypes } from '@acrd/types';
|
||||||
|
|
||||||
|
const DMList: React.FunctionComponent = () => {
|
||||||
|
const channels = useSelector(getDMChannels());
|
||||||
|
const selfUser = useSelector((s: Store.AppState) => s.auth.user)!;
|
||||||
|
const users = useSelector((s: Store.AppState) => s.entities.users);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="channels px-2 w-60 bg-bg-secondary">
|
||||||
|
<div className="mt-2">
|
||||||
|
{channels.map(c => {
|
||||||
|
const otherUserId = (c as ChannelTypes.DM).userIds
|
||||||
|
.find(id => id !== selfUser.id);
|
||||||
|
const otherUser = users.find(u => u.id === otherUserId);
|
||||||
|
if (!otherUser) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={c.id}
|
||||||
|
to={`/channels/@me/${c.id}`}
|
||||||
|
className="flex items-center rounded p-2 mb-2 hover:bg-bg-modifier-hover">
|
||||||
|
<FoundUsername user={otherUser} size="sm" />
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DMList;
|
58
frontend/src/components/pages/dm-page.tsx
Normal file
58
frontend/src/components/pages/dm-page.tsx
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import AppNavbar from '../navigation/app-navbar';
|
||||||
|
import Sidebar from '../navigation/sidebar/sidebar';
|
||||||
|
import { Redirect, useParams } from 'react-router-dom';
|
||||||
|
import { actions as uiActions } from '../../store/ui';
|
||||||
|
import TextBasedChannel from '../channel/text-based-channel';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import PageWrapper from './page-wrapper';
|
||||||
|
import { getDMChannel, createDM } from '../../store/channels';
|
||||||
|
import WSListener from '../ws-listener';
|
||||||
|
import DMList from '../navigation/sidebar/dm-list';
|
||||||
|
|
||||||
|
const DMPage: React.FunctionComponent = () => {
|
||||||
|
const { channelId }: any = useParams();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const channel = useSelector(getDMChannel(channelId));
|
||||||
|
const users = useSelector((s: Store.AppState) => s.entities.users);
|
||||||
|
const selfUser = useSelector((s: Store.AppState) => s.auth.user)!;
|
||||||
|
const ui = useSelector((s: Store.AppState) => s.ui);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!channel && channelId) {
|
||||||
|
const otherUser = users.find(u => u.id === channelId);
|
||||||
|
if (otherUser) {
|
||||||
|
dispatch(createDM(otherUser.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dispatch(uiActions.pageSwitched({ channel }));
|
||||||
|
}, [channel, channelId]);
|
||||||
|
|
||||||
|
if (!channel && !channelId)
|
||||||
|
return <Redirect to="/channels/@me" />;
|
||||||
|
|
||||||
|
const otherUser = users.find(u =>
|
||||||
|
channel?.type === 'DM' && channel.userIds.includes(u.id) && u.id !== selfUser.id);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageWrapper pageTitle={otherUser?.username ?? 'Direct Messages'}>
|
||||||
|
<WSListener />
|
||||||
|
<div className="flex">
|
||||||
|
<Sidebar />
|
||||||
|
<div className="bg-bg-primary flex-1">
|
||||||
|
<AppNavbar />
|
||||||
|
<div
|
||||||
|
style={{ height: 'calc(100vh - 48px)' }}
|
||||||
|
className="flex">
|
||||||
|
{channel && ui.activeChannel && {
|
||||||
|
'DM': <TextBasedChannel />,
|
||||||
|
}[channel.type]}
|
||||||
|
<DMList />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PageWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DMPage;
|
@ -40,6 +40,7 @@ const GuildPage: React.FunctionComponent = () => {
|
|||||||
className="flex">
|
className="flex">
|
||||||
{ui.activeChannel && {
|
{ui.activeChannel && {
|
||||||
'TEXT': <TextBasedChannel />,
|
'TEXT': <TextBasedChannel />,
|
||||||
|
'DM': <TextBasedChannel />,
|
||||||
'VOICE': <div className="w-full p-2">Add something cool here for voice channels?</div>,
|
'VOICE': <div className="w-full p-2">Add something cool here for voice channels?</div>,
|
||||||
}[channel.type]}
|
}[channel.type]}
|
||||||
<MemberList />
|
<MemberList />
|
||||||
|
@ -67,6 +67,11 @@ export const getChannel = (id: string) => createSelector(
|
|||||||
channels => channels.find(c => c.id === id),
|
channels => channels.find(c => c.id === id),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const getDMChannel = (id: string) => createSelector(
|
||||||
|
state => state.entities.channels,
|
||||||
|
channels => channels.find(c => c.id === id && c.type === 'DM')
|
||||||
|
);
|
||||||
|
|
||||||
export const getChannelByName = (guildId: string, name: string) => createSelector(
|
export const getChannelByName = (guildId: string, name: string) => createSelector(
|
||||||
state => state.entities.channels,
|
state => state.entities.channels,
|
||||||
channels => {
|
channels => {
|
||||||
@ -81,3 +86,28 @@ export const getChannelUsers = (channelId: string) => createSelector(
|
|||||||
return vc.userIds.map(id => users.find(u => u.id === id))
|
return vc.userIds.map(id => users.find(u => u.id === id))
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const getDMChannels = () => createSelector(
|
||||||
|
state => state.entities.channels,
|
||||||
|
channels => channels.filter(c => c.type === 'DM')
|
||||||
|
);
|
||||||
|
|
||||||
|
export const createDM = (userId: string) => (dispatch, getState: () => Store.AppState) => {
|
||||||
|
const selfUser = getState().auth.user!;
|
||||||
|
const existingDM = getState().entities.channels
|
||||||
|
.find(c => c.type === 'DM' &&
|
||||||
|
c.userIds.includes(selfUser.id) &&
|
||||||
|
c.userIds.includes(userId));
|
||||||
|
|
||||||
|
if (existingDM) return;
|
||||||
|
|
||||||
|
dispatch(api.wsCallBegan({
|
||||||
|
event: 'CHANNEL_CREATE',
|
||||||
|
data: {
|
||||||
|
type: 'DM',
|
||||||
|
userIds: [selfUser.id, userId],
|
||||||
|
name: 'DM',
|
||||||
|
guildId: '0'
|
||||||
|
} as unknown as WS.Params.ChannelCreate,
|
||||||
|
}));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user