Skip to content

Commit

Permalink
feat: add direct messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Calvin Rohloff committed Sep 19, 2024
1 parent d04a081 commit 8fa442b
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 26 deletions.
8 changes: 7 additions & 1 deletion src/renderer/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import '@/styles/channel/ChannelList.css';
import '@/styles/channel/Message.css';
import '@/styles/channel/MessageAttachment.css';

import '@/styles/directmessage/DirectMessageButton.css';
import '@/styles/directmessage/DirectMessageList.css';

import '@/styles/page/GuildChannelPage.css';
import '@/styles/page/GuildPage.css';
import '@/styles/page/HomePage.css';
Expand All @@ -34,6 +37,7 @@ import SideBar from '@/components/app/SideBar';
import HomePage from '@/pages/HomePage/HomePage';
import GuildPage from '@/pages/GuildPage/GuildPage';
import GuildChannelPage from './pages/GuildPage/GuildChannelPage';
import HomeChannelPage from './pages/HomePage/HomeChannelPage';

export default function App() {
return (
Expand All @@ -43,7 +47,9 @@ export default function App() {
<SideBar />
<UserPanel />
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/" element={<HomePage />}>
<Route path="channel/:channelId" element={<HomeChannelPage />} />
</Route>
<Route path="/guild/:guildId" element={<GuildPage />}>
<Route path="channel/:channelId" element={<GuildChannelPage />} />
</Route>
Expand Down
71 changes: 71 additions & 0 deletions src/renderer/components/directmessage/DirectMessageButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { ChannelType } from '@/discord/structures/channel/BaseChannel';
import RendererChannel from '@/discord/structures/channel/RendererChannel';
import useUser from '@/hooks/useUser';
import useUsers from '@/hooks/useUsers';
import { useLocation, useNavigate } from 'react-router-dom';

type DirectMessageButtonProps = {
channel: RendererChannel;
};

export default function DirectMessageButton({
channel,
}: DirectMessageButtonProps) {
const location = useLocation();
const navigate = useNavigate();

const user = useUser(undefined);
const members = useUsers(channel.recipientIds ?? []);

if (user === null) return null;

const onClick = () => {
navigate(`/channel/${channel.id}`);
};

const getName = () => {
if (channel.type === ChannelType.GroupDM) {
if (channel.name.length > 0) return channel.name;

const membs = [user, ...members];
return membs
.map((v) => (v.globalName ? v.globalName : v.username))
.join(', ');
}

if (members.length === 0) return '';

const member = members[0];

if (member.globalName === null || member.globalName.length === 0)
return member.username;

return member.globalName;
};

const getIcon = () => {
if (members.length === 0) return '';

if (channel.type === ChannelType.GroupDM)
return channel.getChannelIcon() ?? members[0].getAvatarUrl();

return members[0].getAvatarUrl();
};

const isSelected = location.pathname.includes(`/channel/${channel.id}`);

return (
<div
className={`DirectMessage ${isSelected && 'DirectMessage--selected'}`}
role="presentation"
onClick={() => onClick()}
>
<img
className="DirectMessage--icon-img"
src={getIcon()}
alt="Direct Message Icon"
/>
<p className="DirectMessage--name">{getName()}</p>
</div>
);
}
31 changes: 31 additions & 0 deletions src/renderer/components/directmessage/DirectMessageList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import usePrivateChannels from '@/hooks/usePrivateChannels';
import DirectMessageButton from './DirectMessageButton';

export default function DirectMessageList() {
const channels = usePrivateChannels();

return (
<div className="DirectMessageList hidden-scrollbar">
{
/* Sort private channels by their last message id */
channels
.sort((a, b) => {
if (a.lastMessageId === null) return -1;

if (b.lastMessageId === null) return 1;

return Number(a.lastMessageId) - Number(b.lastMessageId);
})
.reverse()
.map((channel) => {
return (
<DirectMessageButton
key={`Channel:home:${channel.id}`}
channel={channel}
/>
);
})
}
</div>
);
}
38 changes: 38 additions & 0 deletions src/renderer/pages/HomePage/HomeChannelPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Message from '@/components/channel/Message';
import { ChannelType } from '@/discord/structures/channel/BaseChannel';
import useChannel from '@/hooks/useChannel';
import useMessages from '@/hooks/useMessages';
import useUsers from '@/hooks/useUsers';
import { useParams } from 'react-router-dom';

export default function HomeChannelPage() {
const params = useParams();
const channelId = params.channelId ?? '';

const channel = useChannel(channelId);
const messages = useMessages(channel);
const members = useUsers(channel?.recipientIds ?? []);

if (channel === null) return null;

const getName = () => {
if (channel.type === ChannelType.GroupDM) return channel.name;

if (members.length === 0) return '';

return members[0].globalName;
};

return (
<div className="GuildChannelPage">
<div className="GuildChannelPage--header">
<p className="GuildChannelPage--header-title">{getName()}</p>
</div>
<div className="GuildChannelPage--messages-container hidden-scrollbar">
{messages.map((msg) => {
return <Message message={msg} />;
})}
</div>
</div>
);
}
26 changes: 2 additions & 24 deletions src/renderer/pages/HomePage/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,14 @@
import DirectMessageButton from '@/components/directmessage/DirectMessageButton';
import DirectMessageList from '@/components/directmessage/DirectMessageList';
import PageLayout from '@/components/page/PageLayout';
import PageSideBar from '@/components/page/PageSideBar';
import usePrivateChannels from '@/hooks/usePrivateChannels';
import { Outlet } from 'react-router-dom';

export default function HomePage() {
const channels = usePrivateChannels();

return (
<PageLayout>
<div className="HomePage">
<PageSideBar>
{
/* Sort private channels by their last message id */
channels
.sort((a, b) => {
if (a.lastMessageId === null) return -1;

if (b.lastMessageId === null) return 1;

return Number(a.lastMessageId) - Number(b.lastMessageId);
})
.reverse()
.map((channel) => {
return (
<DirectMessageButton
key={`Channel:home:${channel.id}`}
channel={channel}
/>
);
})
}
<DirectMessageList />
</PageSideBar>
<div className="HomePage--content">
<Outlet />
Expand Down
33 changes: 33 additions & 0 deletions src/renderer/styles/directmessage/DirectMessageButton.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.DirectMessage {
display: flex;
align-items: center;
width: calc(var(--channel-item-width) - var(--channel-item-padding) * 2);
height: calc(var(--channel-item-height) - var(--channel-item-padding) * 2);
padding: 10px;
border-radius: 12px;
color: #73747a;
font-weight: 600;
transition: all 0.34s cubic-bezier(0.075, 0.82, 0.165, 1);
cursor: pointer;
flex-shrink: 0;
flex-grow: 0;
gap: 6px;
}

.DirectMessage:hover,
.DirectMessage--selected {
background: #1f1e25;
color: #fff;
}

.DirectMessage--icon-img {
width: 32px;
border-radius: 50%;
}

.DirectMessage--name {
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
9 changes: 9 additions & 0 deletions src/renderer/styles/directmessage/DirectMessageList.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.DirectMessageList {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
overflow: hidden;
overflow-y: auto;
align-items: center;
}
25 changes: 24 additions & 1 deletion src/renderer/styles/page/GuildChannelPage.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
:root {
--guild-channel-header-height: 50px;
}

.GuildChannelPage {
position: relative;
width: calc(100% - 40px);
height: calc(100% - 40px);
padding: 20px;
}

.GuildChannelPage--header {
padding: 20px;
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: calc(100% - 40px);
height: calc(2px + var(--guild-channel-header-height) - 20px);
background: #1b1d21;
filter: drop-shadow(0px 5px 8px #0000005c);
}

.GuildChannelPage--messages-container {
padding-top: calc(var(--guild-channel-header-height) + 10px);
display: flex;
flex-direction: column-reverse;
height: calc(100% - 20px);
height: calc(100% - 20px - var(--guild-channel-header-height));
overflow-y: auto;
gap: 6px;
}

.GuildChannelPage--header-title {
font-size: 20px;
font-weight: 500;
}

0 comments on commit 8fa442b

Please sign in to comment.