Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update client design #42

Merged
merged 31 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1c3a2a9
refactor: started redesign of client
ZickZenni Sep 11, 2024
9ff6357
chore(webpack): add path to src/discord
ZickZenni Sep 12, 2024
d4f7977
feat: add guild icon url
ZickZenni Sep 12, 2024
6395652
feat(serverbar): add server icon
ZickZenni Sep 12, 2024
e9a15f1
chore: remove unused log saving
ZickZenni Sep 12, 2024
79b8026
feat: add page layout
ZickZenni Sep 13, 2024
4590e1b
chore: fix lint error
ZickZenni Sep 13, 2024
ccfef90
feat: add useGuilds hook
ZickZenni Sep 13, 2024
e68bfcc
feat: add servers to serverbar
ZickZenni Sep 13, 2024
0fa3063
chore: add pagelayout to homepage
ZickZenni Sep 13, 2024
8b86fd2
chore: rename src/renderer/old to src/renderer/_old
Sep 13, 2024
eff1fe1
feat: add discord logo
Sep 13, 2024
e377d2e
feat: add user avatar animated option
Sep 13, 2024
5b5be15
chore: default client window size
Sep 13, 2024
cd3f8fe
feat: add hooks for renderer
Sep 13, 2024
82fccc0
refactor(renderer): components, pages, styles and App.tsx
Sep 13, 2024
6fc0d39
chore: change titlebar icons
ZickZenni Sep 14, 2024
73df82a
feat: add WaveCord title onto titlebar
ZickZenni Sep 14, 2024
2b52f77
feat(guild): add banner url
ZickZenni Sep 17, 2024
0fdfabc
feat: add channel and messages hook
ZickZenni Sep 17, 2024
7e033b0
refactor(unfinished): updated client design
ZickZenni Sep 17, 2024
ed653f0
fix: warning about server key
Sep 18, 2024
0ae5470
chore: remove homepage sidebar dummy items
Sep 18, 2024
f7c7102
fix(BaseUser): bool -> boolean
Sep 18, 2024
1d4f8a8
feat(BaseUser): add `getAvatarDecorationUrl`
Sep 18, 2024
4a7d173
feat: add message attachments
Sep 18, 2024
897f75f
feat: add tenor gif fetching
Sep 18, 2024
3d0d55b
feat: add channel messages
Sep 18, 2024
1539f0f
fix: lint import/order error
Sep 18, 2024
836a056
chore: remove old renderer code
Sep 18, 2024
273003e
fix: incomplete url substring sanitization
Sep 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .erb/configs/webpack.config.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import webpack from 'webpack';
import TsconfigPathsPlugins from 'tsconfig-paths-webpack-plugin';
import path from 'path';
import webpackPaths from './webpack.paths';
import { dependencies as externals } from '../../release/app/package.json';

Expand Down Expand Up @@ -47,6 +48,10 @@ const configuration: webpack.Configuration = {
modules: [webpackPaths.srcPath, 'node_modules'],
// There is no need to add aliases here, the paths in tsconfig get mirrored
plugins: [new TsconfigPathsPlugins()],
alias: {
'@': path.join(__dirname, '../../src/renderer'),
'@/discord': path.join(__dirname, '../../src/discord'),
},
},

plugins: [
Expand Down
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
"editor.formatOnPaste": true
},

"[typescriptreact]": {
"editor.formatOnSave": true,
"editor.formatOnPaste": true
},

"javascript.validate.enable": false,
"javascript.format.enable": false,
"typescript.format.enable": false,
Expand Down
1 change: 1 addition & 0 deletions assets/app/icons/discord.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion assets/app/icons/titlebar/maximize.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion assets/app/icons/titlebar/minimize.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion assets/app/icons/titlebar/x.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions src/discord/structures/Attachment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Snowflake } from './Snowflake';

export interface Attachment {
content_type: string;
filename: string;
height: number;
id: Snowflake;
placeholder: string;
proxy_url: string;
size: number;
url: string;
width: number;
}
2 changes: 2 additions & 0 deletions src/discord/structures/Message.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Attachment } from './Attachment';
import { Snowflake } from './Snowflake';
import { IUserData } from './user/BaseUser';

export interface Message {
attachments: Attachment[];
content: string;
timestamp: string;
id: Snowflake;
Expand Down
6 changes: 5 additions & 1 deletion src/discord/structures/guild/BaseGuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,11 @@ export abstract class BaseGuild {
}

public getIconUrl(): string {
return '';
return `https://cdn.discordapp.com/icons/${this.id}/${this.icon}.png`;
}

public getBannerUrl(): string {
return `https://cdn.discordapp.com/banners/${this.id}/${this.banner}.webp?size=300`;
}

public toRaw(): IGuildData {
Expand Down
13 changes: 12 additions & 1 deletion src/discord/structures/user/BaseUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,28 @@ export default class BaseUser {
data.avatar_decoration_data ?? this.avatarDecorationData;
}

public getAvatarUrl(): string {
public getAvatarUrl(animated: boolean = false): string {
if (this.avatar === null) {
const id = BigInt(this.id);
// eslint-disable-next-line no-bitwise
const index = (id >> 22n) % 6n;
return `https://cdn.discordapp.com/embed/avatars/${index < 0 ? 0 : index}.png`;
}

if (this.avatar.startsWith('a_') && animated)
return `https://cdn.discordapp.com/avatars/${this.id}/${this.avatar}.gif`;

return `https://cdn.discordapp.com/avatars/${this.id}/${this.avatar}.png`;
}

public getAvatarDecorationUrl(): string | null {
if (this.avatarDecorationData === null) return null;

return `https://cdn.discordapp.com/avatar-decoration-presets/${
this.avatarDecorationData.asset
}.png`;
}

public toRaw(): IUserData {
return {
id: this.id,
Expand Down
19 changes: 11 additions & 8 deletions src/main/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { GatewayDispatchEvents, GatewaySocketEvent } from '../discord/ws/types';
import { registerHandler, registerListener, sendToRenderer } from './ipc';
import { CreateMessageOptions } from '../discord/structures/channel/BaseChannel';
import { Message } from '../discord/structures/Message';
import Tenor from './utils/tenor';

export default class WaveCordApp {
public readonly resourcesPath: string;
Expand All @@ -25,6 +26,8 @@ export default class WaveCordApp {

public discord: Client;

public tenor: Tenor;

public ready: boolean = false;

public quitting: boolean = false;
Expand All @@ -33,6 +36,7 @@ export default class WaveCordApp {

public constructor() {
this.discord = new Client({ debug: true });
this.tenor = new Tenor();

app.setPath('userData', path.join(app.getPath('appData'), 'WaveCord'));

Expand All @@ -59,12 +63,6 @@ export default class WaveCordApp {
this.discord.on('dispatch', (event: GatewaySocketEvent) => {
logger.info('Received event: ', event.event);

if (event.event === GatewayDispatchEvents.Ready)
fs.writeFileSync(
'/home/rohloff/Documents/discord_ready_output.txt',
JSON.stringify(event.data ?? {}),
);

if (event.event === GatewayDispatchEvents.MessageCreate) {
const message = event.data as Message;
sendToRenderer(this.window!, 'discord:gateway:message-create', message);
Expand Down Expand Up @@ -111,8 +109,8 @@ export default class WaveCordApp {
logger.info('Creating new window.');
this.window = new BrowserWindow({
show: false,
width: 1250,
height: 697,
width: 1320,
height: 763,
minWidth: 450,
minHeight: 250,
icon: path.join(this.resourcesPath, 'icon.png'),
Expand Down Expand Up @@ -245,6 +243,11 @@ export default class WaveCordApp {
return channel.createMessage(options);
},
);

registerHandler('tenor:fetch-gif', async (url: string) => {
const result = await this.tenor.fetchGif(url);
return result;
});
}

private initTray() {
Expand Down
3 changes: 2 additions & 1 deletion src/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export type IpcChannels =
| 'discord:set-last-visited-channel'
| 'discord:create-message'
| 'discord:gateway:message-create'
| 'discord:relationships';
| 'discord:relationships'
| 'tenor:fetch-gif';

export function registerHandler(
channel: IpcChannels,
Expand Down
81 changes: 81 additions & 0 deletions src/main/utils/tenor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
export interface TenorGifFormat {
type: string;
url: string;
duration: number;
preview: string;
width: number;
height: number;
size: number;
}

export interface TenorGif {
id: string;
title: string;
media_formats: TenorGifFormat[];
created: number;
content_description: string;
h1_title: string;
tags: string[];
flags: string[];
hasaudio: boolean;
}

export interface TenorFetchResult {
gif: TenorGif | null;
}

export default class Tenor {
public async fetchGif(url: string): Promise<TenorFetchResult> {
const result: TenorFetchResult = {
gif: null,
};

const uri = new URL(url);

if (uri.hostname.toLowerCase() !== 'tenor.com') return result;
if (!uri.pathname.toLowerCase().startsWith('/view/')) return result;

const response = await fetch(url);
const text = await response.text();

const raw = `{"appConfig${text.split('appConfig')[1].split('</script>')[0]}`;
const json = JSON.parse(raw);

// eslint-disable-next-line no-restricted-syntax
for (const id of Object.keys(json.gifs.byId)) {
const data = json.gifs.byId[id];

if (!data.loaded) continue;

const dataRes = data.results[0];

result.gif = {
id: dataRes.id,
title: dataRes.title,
created: dataRes.created,
content_description: dataRes.content_description,
flags: dataRes.flags,
h1_title: dataRes.h1_title,
hasaudio: dataRes.hasaudio,
media_formats: [],
tags: dataRes.tags,
};

// eslint-disable-next-line no-restricted-syntax
for (const formatType of Object.keys(dataRes.media_formats)) {
const formatData = dataRes.media_formats[formatType];
result.gif.media_formats.push({
type: formatType,
url: formatData.url,
duration: formatData.duration,
preview: formatData.preview,
size: formatData.size,
width: formatData.dims[0],
height: formatData.dims[1],
});
}
}

return result;
}
}
55 changes: 36 additions & 19 deletions src/renderer/App.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,53 @@
/* eslint-disable import/order */
import { MemoryRouter as Router, Routes, Route } from 'react-router-dom';

// Styles
import './styles/global.css';
import './styles/vars.css';
import '@/styles/app/App.css';
import '@/styles/app/TitleBar.css';
import '@/styles/app/SideBar.css';
import '@/styles/app/UserBar.css';

import '@/styles/channel/ChannelButton.css';
import '@/styles/channel/ChannelList.css';
import '@/styles/channel/Message.css';
import '@/styles/channel/MessageAttachment.css';

import '@/styles/page/GuildChannelPage.css';
import '@/styles/page/GuildPage.css';
import '@/styles/page/PageLayout.css';
import '@/styles/page/PageSideBar.css';

import '@/styles/server/ServerBar.css';
import '@/styles/server/Server.css';
import '@/styles/server/ServerInfo.css';

import '@/styles/user/UserPanel.css';

// Components
import Titlebar from './components/Titlebar';
import Serverbar from './components/Serverbar';
import Loading from './components/Loading';
import AppContent from '@/components/app/AppContent';
import TitleBar from '@/components/app/TitleBar';
import UserPanel from '@/components/user/UserPanel';
import SideBar from '@/components/app/SideBar';

// Pages
import HomePage from './pages/Home';
import GuildPage from './pages/Guild';
import ChannelPage from './pages/Guild/Channel';
import DirectMessagePage from './pages/Home/DirectMessage';
import HomePage from '@/pages/HomePage/HomePage';
import GuildPage from '@/pages/GuildPage/GuildPage';
import GuildChannelPage from './pages/GuildPage/GuildChannelPage';

export default function App() {
return (
<Router>
<Titlebar />
<Loading />
<Serverbar />
<div className="app__content">
<TitleBar />
<AppContent>
<SideBar />
<UserPanel />
<Routes>
<Route path="/" element={<HomePage />}>
<Route path="dm/:dmId" element={<DirectMessagePage />} />
</Route>
<Route path="/guild/:id" element={<GuildPage />}>
<Route path="channel/:channelId" element={<ChannelPage />} />
<Route path="/" element={<HomePage />} />
<Route path="/guild/:guildId" element={<GuildPage />}>
<Route path="channel/:channelId" element={<GuildChannelPage />} />
</Route>
</Routes>
</div>
</AppContent>
</Router>
);
}
50 changes: 0 additions & 50 deletions src/renderer/components/Loading/Loading.css

This file was deleted.

Loading
Loading