From 1cc9964b5f0ba102a56c387b8c4c88b3ced1b416 Mon Sep 17 00:00:00 2001 From: Cuter Date: Thu, 16 Mar 2023 15:30:28 +0100 Subject: [PATCH 1/3] dm --- front/volume/src/App.svelte | 42 ++++++++++++++++++--- front/volume/src/components/Channels.svelte | 3 +- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/front/volume/src/App.svelte b/front/volume/src/App.svelte index c0a742f..987aef8 100644 --- a/front/volume/src/App.svelte +++ b/front/volume/src/App.svelte @@ -26,9 +26,11 @@ import Pong from "./components/Pong/Pong.svelte"; import type { ChannelsType } from "./components/Channels.svelte"; + import { API_URL } from "./Auth"; import { store, getUser, login, verify } from "./Auth"; import FakeLogin from "./FakeLogin.svelte"; + // import { channel } from "diagnostics_channel"; // Single Page Application config let appState: string = APPSTATE.HOME; @@ -57,6 +59,15 @@ getUser(); }, 15000); + let DMChannel: Array = []; + onMount(async () => { + const res = await fetch(API_URL + "/channels/dms/" + DMUsername, { + credentials: "include", + mode: "cors", + }); + if (res.ok) DMChannel = await res.json(); + }); + function clickProfile() { setAppState(APPSTATE.PROFILE); } @@ -67,6 +78,18 @@ setAppState(APPSTATE.PROFILE_ID); } + let chan: Channels; + let DMUsername: string = ""; + async function openDirectChat(event: CustomEvent) { + // pass profile to backend + // backend looks for a chat and if it doesn't exist it creates it + // backend send chat id to front end + // front opens chat with selectChat() + DMUsername = event.detail; + console.log(chan); + chan.selectChat(DMChannel[0].id); + } + async function clickHistory() { setAppState(APPSTATE.HISTORY); } @@ -130,8 +153,9 @@ {clickLeaderboard} /> {#if appState.includes(APPSTATE.CHANNELS)} - {#if appState.replace(APPSTATE.CHANNELS, "") !== ""} +
setAppState(APPSTATE.CHANNELS)} on:keydown={() => setAppState(APPSTATE.CHANNELS)} > @@ -140,13 +164,17 @@ on:view-profile={openIdProfile} on:add-friend={addFriend} on:invite-to-game={pong.inviteToGame} + on:send-message={openDirectChat} />
- {:else} -
- + +
+
- {/if} + {/if} {#if appState === APPSTATE.LEADERBOARD}
@@ -244,4 +272,8 @@ outline: none; box-shadow: 0 0 0 2px rgba(25, 135, 84, 0.25); } + + .hidden { + display: none; + } diff --git a/front/volume/src/components/Channels.svelte b/front/volume/src/components/Channels.svelte index 1e47afd..a4b8eca 100644 --- a/front/volume/src/components/Channels.svelte +++ b/front/volume/src/components/Channels.svelte @@ -39,7 +39,8 @@ //--------------------------------------------------------------------------------/ export let onSelectChannel: (channel: ChannelsType) => void; - const selectChat = (id: number) => { + export const selectChat = (id: number) => { + console.log(id); const channel = channels.find((c) => c.id === id); if (channel) { joinChannel(id); From 7c72a8b0ec023d231451dac59f6e3c0815026f85 Mon Sep 17 00:00:00 2001 From: vvandenb Date: Thu, 16 Mar 2023 17:33:32 +0100 Subject: [PATCH 2/3] * DM front + back WIP --- back/volume/src/chat/chat.controller.ts | 14 ++-- back/volume/src/chat/chat.service.ts | 30 ++++---- front/volume/src/App.svelte | 76 ++++++++++++++------- front/volume/src/components/Channels.svelte | 19 +++--- front/volume/src/components/Chat.svelte | 8 +-- 5 files changed, 92 insertions(+), 55 deletions(-) diff --git a/back/volume/src/chat/chat.controller.ts b/back/volume/src/chat/chat.controller.ts index b8fc61f..e0773ff 100644 --- a/back/volume/src/chat/chat.controller.ts +++ b/back/volume/src/chat/chat.controller.ts @@ -214,22 +214,26 @@ export class ChatController { return await this.channelService.getChannelsForUser(+profile.id) } - @Get('dms/:otherId') + @Get('dms/:otherName') async getDMsForUser ( @Profile42() profile: Profile, @Param('otherName') otherName: string ): Promise { + const user = await this.usersService.findUser(profile.fdId) const other = await this.usersService.findUserByName(otherName) - const otherId = other.ftId const channels = await this.channelService.getChannelsForUser(+profile.id) - return channels.filter((channel: Channel) => { + if (user === null) { + throw new BadRequestException('User not found') + } + const dms = channels.filter((channel: Channel) => { return ( - channel.users?.some((ch) => ch.id === otherId) && + channel.name === (user.username + '&' + other.username) && channel.isPrivate && - channel.password === '' + (channel.password === undefined || channel.password === '') ) }) + return dms } @Post() diff --git a/back/volume/src/chat/chat.service.ts b/back/volume/src/chat/chat.service.ts index 69ea0df..ffd1cbf 100644 --- a/back/volume/src/chat/chat.service.ts +++ b/back/volume/src/chat/chat.service.ts @@ -1,4 +1,4 @@ -import { Injectable, NotFoundException } from '@nestjs/common' +import { BadRequestException, Injectable } from '@nestjs/common' import { InjectRepository } from '@nestjs/typeorm' import { Repository } from 'typeorm' @@ -20,7 +20,7 @@ export class ChatService { async createChannel (channel: CreateChannelDto): Promise { const user: User | null = await this.usersService.findUser(channel.owner) if (user == null) { - throw new NotFoundException(`User #${channel.owner} not found`) + throw new BadRequestException(`User #${channel.owner} not found`) } let newChannel: Channel @@ -29,10 +29,13 @@ export class ChatService { channel.otherDMedUsername ) if (otherUser == null) { - throw new NotFoundException( + throw new BadRequestException( `User #${channel.otherDMedUsername} not found` ) } + if (otherUser.id === user.id) { + throw new BadRequestException('Cannot DM yourself') + } newChannel = this.createDM(user, otherUser) } else { newChannel = new Channel() @@ -50,13 +53,10 @@ export class ChatService { const newDM = new Channel() newDM.isPrivate = true newDM.password = '' - newDM.owner = user newDM.users = [user, otherUser] newDM.admins = [] - newDM.name = user.username + ' & ' + otherUser.username - newDM.isPrivate = true - newDM.password = '' + newDM.name = user.username + '&' + otherUser.username return newDM } @@ -65,7 +65,7 @@ export class ChatService { id }) if (channel === null) { - throw new NotFoundException(`Channel #${id} not found`) + throw new BadRequestException(`Channel #${id} not found`) } channel.password = password await this.ChannelRepository.save(channel) @@ -109,7 +109,7 @@ export class ChatService { async getChannel (id: number): Promise { const channel = await this.ChannelRepository.findOneBy({ id }) if (channel == null) { - throw new NotFoundException(`Channel #${id} not found`) + throw new BadRequestException(`Channel #${id} not found`) } return channel } @@ -120,7 +120,7 @@ export class ChatService { relations: ['users', 'admins', 'banned', 'owner'] }) if (channel == null) { - throw new NotFoundException(`Channel #${id} not found`) + throw new BadRequestException(`Channel #${id} not found`) } return channel } @@ -143,7 +143,7 @@ export class ChatService { relations: { owner: true } }) if (channel === null) { - throw new NotFoundException(`Channel #${id} not found`) + throw new BadRequestException(`Channel #${id} not found`) } return channel.owner.ftId === userId } @@ -154,7 +154,7 @@ export class ChatService { relations: { admins: true } }) if (channel === null) { - throw new NotFoundException(`Channel #${id} not found`) + throw new BadRequestException(`Channel #${id} not found`) } return channel.admins.findIndex((user) => user.ftId === userId) !== -1 } @@ -165,7 +165,7 @@ export class ChatService { relations: { users: true } }) if (channel === null) { - throw new NotFoundException(`Channel #${id} not found`) + throw new BadRequestException(`Channel #${id} not found`) } return channel.users.findIndex((user) => user.ftId === userId) !== -1 } @@ -176,7 +176,7 @@ export class ChatService { relations: { banned: true } }) if (channel === null) { - throw new NotFoundException(`Channel #${id} not found`) + throw new BadRequestException(`Channel #${id} not found`) } return channel.banned.findIndex((user) => user.ftId === userId) !== -1 } @@ -186,7 +186,7 @@ export class ChatService { where: { id } }) if (channel === null) { - throw new NotFoundException(`Channel #${id} not found`) + throw new BadRequestException(`Channel #${id} not found`) } const mutation: number[] | undefined = channel.muted.find( diff --git a/front/volume/src/App.svelte b/front/volume/src/App.svelte index 987aef8..f79b317 100644 --- a/front/volume/src/App.svelte +++ b/front/volume/src/App.svelte @@ -30,7 +30,6 @@ import { store, getUser, login, verify } from "./Auth"; import FakeLogin from "./FakeLogin.svelte"; - // import { channel } from "diagnostics_channel"; // Single Page Application config let appState: string = APPSTATE.HOME; @@ -59,15 +58,6 @@ getUser(); }, 15000); - let DMChannel: Array = []; - onMount(async () => { - const res = await fetch(API_URL + "/channels/dms/" + DMUsername, { - credentials: "include", - mode: "cors", - }); - if (res.ok) DMChannel = await res.json(); - }); - function clickProfile() { setAppState(APPSTATE.PROFILE); } @@ -79,15 +69,54 @@ } let chan: Channels; - let DMUsername: string = ""; async function openDirectChat(event: CustomEvent) { - // pass profile to backend - // backend looks for a chat and if it doesn't exist it creates it - // backend send chat id to front end - // front opens chat with selectChat() - DMUsername = event.detail; - console.log(chan); - chan.selectChat(DMChannel[0].id); + const DMUsername = "test"; + let DMChannel: Array = []; + const res = await fetch(API_URL + "/channels/dms/" + DMUsername, { + credentials: "include", + mode: "cors", + }); + if (res.ok) { + DMChannel = await res.json(); + if (DMChannel.length != 0) { + chan.selectChat(DMChannel[0].id); + } else { + console.log("Creating DMChannel: " + $store.username + "&" + DMUsername) + const response = await fetch(API_URL + "/channels", { + credentials: "include", + method: "POST", + mode: "cors", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name: $store.username + "&" + DMUsername, + owner: $store.ftId, + password: "", + isPrivate: true, + isDM: true, + otherDMedUsername: DMUsername + }), + }); + if (response.ok) { + const res = await fetch(API_URL + "/channels/dms/" + DMUsername, { + credentials: "include", + mode: "cors", + }); + if (res.ok) { + DMChannel = await res.json(); + if (DMChannel.length != 0) { + console.log("Found DMChannel: ", DMChannel); + chan.selectChat(DMChannel[0].id); + } else { + alert("Error creating 1 DM"); + } + } else { + alert("Error creating 2 DM"); + } + } + } + } } async function clickHistory() { @@ -155,7 +184,7 @@ {#if appState.includes(APPSTATE.CHANNELS)}
setAppState(APPSTATE.CHANNELS)} on:keydown={() => setAppState(APPSTATE.CHANNELS)} > @@ -164,14 +193,15 @@ on:view-profile={openIdProfile} on:add-friend={addFriend} on:invite-to-game={pong.inviteToGame} - on:send-message={openDirectChat} + on:send-message={openDirectChat} />
+ class="{appState.replace(APPSTATE.CHANNELS, "") !== "" ? 'hidden' : ''}" + on:click={resetAppState} + on:keydown={resetAppState} + >
diff --git a/front/volume/src/components/Channels.svelte b/front/volume/src/components/Channels.svelte index a4b8eca..20d694a 100644 --- a/front/volume/src/components/Channels.svelte +++ b/front/volume/src/components/Channels.svelte @@ -32,20 +32,23 @@ }; let channels: Array = []; - onMount(async () => { + onMount(async () => { getChannels() - }); + }); //--------------------------------------------------------------------------------/ export let onSelectChannel: (channel: ChannelsType) => void; export const selectChat = (id: number) => { - console.log(id); - const channel = channels.find((c) => c.id === id); - if (channel) { - joinChannel(id); - onSelectChannel(channel); - } + getChannels().then(() => { + const channel = channels.find((c) => c.id === id); + if (channel) { + joinChannel(id); + onSelectChannel(channel); + } else { + alert("Did not find channel"); + } + }); }; //--------------------------------------------------------------------------------/ diff --git a/front/volume/src/components/Chat.svelte b/front/volume/src/components/Chat.svelte index 67fee85..f3fb19d 100644 --- a/front/volume/src/components/Chat.svelte +++ b/front/volume/src/components/Chat.svelte @@ -33,10 +33,10 @@ }); onDestroy(() => { - io.emit("LeaveChanel", async (response) => { + socket.emit("LeaveChanel", async (response) => { console.log(response.status); }); - io.disconnect(); + socket.disconnect(); }); //--------------------------------------------------------------------------------/ @@ -378,9 +378,9 @@ justify-content: center; align-items: center; } - + .chat { - background-color: #5f5e5e; + background-color: #343a40; border: 1px solid #dedede; border-radius: 5px; padding: 1rem; From e40a280d7c351256db5fbd54895386b478a2a463 Mon Sep 17 00:00:00 2001 From: vvandenb Date: Thu, 16 Mar 2023 20:52:26 +0100 Subject: [PATCH 3/3] * DMs done! --- back/volume/src/chat/chat.controller.ts | 3 +- back/volume/src/chat/chat.service.ts | 14 +++ front/volume/src/App.svelte | 110 +++++++++++++++--------- 3 files changed, 85 insertions(+), 42 deletions(-) diff --git a/back/volume/src/chat/chat.controller.ts b/back/volume/src/chat/chat.controller.ts index e0773ff..a452587 100644 --- a/back/volume/src/chat/chat.controller.ts +++ b/back/volume/src/chat/chat.controller.ts @@ -228,7 +228,8 @@ export class ChatController { } const dms = channels.filter((channel: Channel) => { return ( - channel.name === (user.username + '&' + other.username) && + (channel.name === (user.username + '&' + other.username) || + channel.name === (other.username + '&' + user.username)) && channel.isPrivate && (channel.password === undefined || channel.password === '') ) diff --git a/back/volume/src/chat/chat.service.ts b/back/volume/src/chat/chat.service.ts index ffd1cbf..af223a0 100644 --- a/back/volume/src/chat/chat.service.ts +++ b/back/volume/src/chat/chat.service.ts @@ -36,6 +36,20 @@ export class ChatService { if (otherUser.id === user.id) { throw new BadRequestException('Cannot DM yourself') } + + const channels = await this.getChannelsForUser(user.id) + const dmAlreadyExists = channels.find((channel: Channel) => { + return ( + (channel.name === (user.username + '&' + otherUser.username) || + channel.name === (otherUser.username + '&' + user.username)) && + channel.isPrivate && + (channel.password === undefined || channel.password === '') + ) + }) + if (dmAlreadyExists !== undefined) { + throw new BadRequestException('DM already exists') + } + newChannel = this.createDM(user, otherUser) } else { newChannel = new Channel() diff --git a/front/volume/src/App.svelte b/front/volume/src/App.svelte index f79b317..2f2ad41 100644 --- a/front/volume/src/App.svelte +++ b/front/volume/src/App.svelte @@ -34,10 +34,36 @@ // Single Page Application config let appState: string = APPSTATE.HOME; + function updateChat() { + const urlSplit = appState.split("#", 2) + if (urlSplit && urlSplit.length > 1) { + console.log(urlSplit[1]) + } + if (appState.includes(APPSTATE.CHANNELS) && urlSplit.length > 1) { + const currentChannelName = appState.split("#", 2)[1]; + fetch(API_URL + "/channels", { + credentials: "include", + mode: "cors", + }).then((res) => { + res.json().then((channels) => { + const channel = channels.find((c: ChannelsType) => c.name === currentChannelName); + if (channel) { + chan.selectChat(channel.id); + } else { + alert("Failed loading channel"); + } + }); + }).catch(() => { + alert("Failed loading channel"); + }); + } + } + history.replaceState({ appState: "" }, "", "/"); window.onpopstate = (e: PopStateEvent) => { if (e.state) { appState = e.state.appState; + updateChat(); } }; @@ -49,6 +75,7 @@ if (newState === appState) return; appState = newState; history.pushState({ appState }, "", appState); + updateChat(); } onMount(() => { @@ -68,21 +95,26 @@ setAppState(APPSTATE.PROFILE_ID); } - let chan: Channels; - async function openDirectChat(event: CustomEvent) { - const DMUsername = "test"; - let DMChannel: Array = []; - const res = await fetch(API_URL + "/channels/dms/" + DMUsername, { + async function getDMs(username: string): Promise { + const response = await fetch(API_URL + "/channels/dms/" + username, { credentials: "include", mode: "cors", }); + return response; + } + + let chan: Channels; + async function openDirectChat(event: CustomEvent) { + const DMUsername = event.detail; + let DMChannel: Array = []; + const res = await getDMs($store.username) if (res.ok) { DMChannel = await res.json(); if (DMChannel.length != 0) { chan.selectChat(DMChannel[0].id); } else { console.log("Creating DMChannel: " + $store.username + "&" + DMUsername) - const response = await fetch(API_URL + "/channels", { + fetch(API_URL + "/channels", { credentials: "include", method: "POST", mode: "cors", @@ -97,25 +129,24 @@ isDM: true, otherDMedUsername: DMUsername }), - }); - if (response.ok) { - const res = await fetch(API_URL + "/channels/dms/" + DMUsername, { - credentials: "include", - mode: "cors", - }); - if (res.ok) { - DMChannel = await res.json(); + }).then(async () => { + const response = await getDMs($store.username) + if (response.ok) { + DMChannel = await response.json(); if (DMChannel.length != 0) { - console.log("Found DMChannel: ", DMChannel); chan.selectChat(DMChannel[0].id); } else { - alert("Error creating 1 DM"); + alert("Error creating DM"); } } else { - alert("Error creating 2 DM"); + alert("Error creating DM"); } - } + }).catch((error) => { + alert(error.message); + }) } + } else { + alert("Error creating DM"); } } @@ -182,29 +213,26 @@ {clickLeaderboard} /> {#if appState.includes(APPSTATE.CHANNELS)} - -
setAppState(APPSTATE.CHANNELS)} - on:keydown={() => setAppState(APPSTATE.CHANNELS)} - > - -
- -
- -
- +
setAppState(APPSTATE.CHANNELS)} + on:keydown={() => setAppState(APPSTATE.CHANNELS)} + > + +
+
+ +
{/if} {#if appState === APPSTATE.LEADERBOARD}