Merge branch 'master' into luke

This commit is contained in:
LuckyLaszlo
2023-01-11 13:14:25 +01:00
48 changed files with 25430 additions and 435 deletions

2
.gitignore vendored
View File

@@ -18,7 +18,7 @@ Thumbs.db
node_modules node_modules
./srcs/requirement/nestjs/api_back/dist ./srcs/requirement/nestjs/api_back/dist
./srcs/requirements/svelte/api_front/public/build/ ./srcs/requirements/svelte/api_front/public/build/*
# Logs # Logs
logs logs

106
README.md
View File

@@ -1,5 +1,4 @@
- CONFLICT srcs/requirements/svelte/api_front/public/build/bundle.js CONFLICT srcs/requirements/nestjs/api_back/src/friendship/friendship.service.ts
- CONFLICT srcs/requirements/svelte/api_front/public/build/bundle.js.map
### Pour lancer le docker : ### Pour lancer le docker :
@@ -132,3 +131,106 @@
- [docker](https://github.com/docker/docker-install) - [docker](https://github.com/docker/docker-install)
---
## http status :
```
- '100': 'CONTINUE',
- '101': 'SWITCHING_PROTOCOLS',
- '102': 'PROCESSING',
- '103': 'EARLYHINTS',
- '200': 'OK',
- '201': 'CREATED',
- '202': 'ACCEPTED',
- '203': 'NON_AUTHORITATIVE_INFORMATION',
- '204': 'NO_CONTENT',
- '205': 'RESET_CONTENT',
- '206': 'PARTIAL_CONTENT',
- '300': 'AMBIGUOUS',
- '301': 'MOVED_PERMANENTLY',
- '302': 'FOUND',
- '303': 'SEE_OTHER',
- '304': 'NOT_MODIFIED',
- '307': 'TEMPORARY_REDIRECT',
- '308': 'PERMANENT_REDIRECT',
- '400': 'BAD_REQUEST',
- '401': 'UNAUTHORIZED',
- '402': 'PAYMENT_REQUIRED',
- '403': 'FORBIDDEN',
- '404': 'NOT_FOUND',
- '405': 'METHOD_NOT_ALLOWED',
- '406': 'NOT_ACCEPTABLE',
- '407': 'PROXY_AUTHENTICATION_REQUIRED',
- '408': 'REQUEST_TIMEOUT',
- '409': 'CONFLICT',
- '410': 'GONE',
- '411': 'LENGTH_REQUIRED',
- '412': 'PRECONDITION_FAILED',
- '413': 'PAYLOAD_TOO_LARGE',
- '414': 'URI_TOO_LONG',
- '415': 'UNSUPPORTED_MEDIA_TYPE',
- '416': 'REQUESTED_RANGE_NOT_SATISFIABLE',
- '417': 'EXPECTATION_FAILED',
- '418': 'I_AM_A_TEAPOT',
- '421': 'MISDIRECTED',
- '422': 'UNPROCESSABLE_ENTITY',
- '424': 'FAILED_DEPENDENCY',
- '428': 'PRECONDITION_REQUIRED',
- '429': 'TOO_MANY_REQUESTS',
- '500': 'INTERNAL_SERVER_ERROR',
- '501': 'NOT_IMPLEMENTED',
- '502': 'BAD_GATEWAY',
- '503': 'SERVICE_UNAVAILABLE',
- '504': 'GATEWAY_TIMEOUT',
- '505': 'HTTP_VERSION_NOT_SUPPORTED',
- CONTINUE: 100,
- SWITCHING_PROTOCOLS: 101,
- PROCESSING: 102,
- EARLYHINTS: 103,
- OK: 200,
- CREATED: 201,
- ACCEPTED: 202,
- NON_AUTHORITATIVE_INFORMATION: 203,
- NO_CONTENT: 204,
- RESET_CONTENT: 205,
- PARTIAL_CONTENT: 206,
- AMBIGUOUS: 300,
- MOVED_PERMANENTLY: 301,
- FOUND: 302,
- SEE_OTHER: 303,
- NOT_MODIFIED: 304,
- TEMPORARY_REDIRECT: 307,
- PERMANENT_REDIRECT: 308,
- BAD_REQUEST: 400,
- UNAUTHORIZED: 401,
- PAYMENT_REQUIRED: 402,
- FORBIDDEN: 403,
- NOT_FOUND: 404,
- METHOD_NOT_ALLOWED: 405,
- NOT_ACCEPTABLE: 406,
- PROXY_AUTHENTICATION_REQUIRED: 407,
- REQUEST_TIMEOUT: 408,
- CONFLICT: 409,
- GONE: 410,
- LENGTH_REQUIRED: 411,
- PRECONDITION_FAILED: 412,
- PAYLOAD_TOO_LARGE: 413,
- URI_TOO_LONG: 414,
- UNSUPPORTED_MEDIA_TYPE: 415,
- REQUESTED_RANGE_NOT_SATISFIABLE: 416,
- EXPECTATION_FAILED: 417,
- I_AM_A_TEAPOT: 418,
- MISDIRECTED: 421,
- UNPROCESSABLE_ENTITY: 422,
- FAILED_DEPENDENCY: 424,
- PRECONDITION_REQUIRED: 428,
- TOO_MANY_REQUESTS: 429,
- INTERNAL_SERVER_ERROR: 500,
- NOT_IMPLEMENTED: 501,
- BAD_GATEWAY: 502,
- SERVICE_UNAVAILABLE: 503,
- GATEWAY_TIMEOUT: 504,
- HTTP_VERSION_NOT_SUPPORTED: 505
```

View File

@@ -9,6 +9,7 @@ import { AuthenticationModule } from './auth/42/authentication.module';
import { PassportModule } from '@nestjs/passport'; import { PassportModule } from '@nestjs/passport';
import { GameModule } from './game/game.module'; import { GameModule } from './game/game.module';
import { ChatGateway } from './chat/chat.gateway'; import { ChatGateway } from './chat/chat.gateway';
import { ChatModule } from './chat/chat.module';
@Module({ @Module({
imports: [ imports: [
@@ -30,12 +31,10 @@ import { ChatGateway } from './chat/chat.gateway';
//avec une classe pour le module //avec une classe pour le module
synchronize: true, synchronize: true,
}), }),
ChatModule,
// GameModule, // GameModule,
], ],
controllers: [AppController], controllers: [AppController],
providers: [ providers: [AppService],
AppService,
ChatGateway,
],
}) })
export class AppModule {} export class AppModule {}

View File

@@ -0,0 +1,105 @@
import { Controller, UseGuards, HttpException, HttpStatus, Get, Post, Body, Req, Res } from '@nestjs/common';
import { AuthenticateGuard, TwoFactorGuard } from 'src/auth/42/guards/42guards';
import { ConnectedSocket } from '@nestjs/websockets';
import { ChatService } from './chat.service';
import { User } from 'src/users/entities/user.entity';
import { PartialUsersDto } from 'src/users/dto/partial-users.dto';
import { createRoomDto } from './dto/createRoom.dto';
import { joinRoomDto } from './dto/joinRoom.dto';
import { setCurrentRoomDto } from './dto/setCurrentRoom.dto';
@Controller('chat')
export class ChatController {
constructor(
private chatService: ChatService,
) {}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Get('myrooms')
async getMyRooms(@Req() req, @Res() res): Promise<object>
{
console.log("- in getMyRooms controller");
const rooms = await this.chatService.getMyRooms(req.user);
console.log("- out getMyRooms controller");
return res.status(HttpStatus.OK).json({ rooms: rooms });
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Get('allrooms')
async getAllRooms(@Req() req, @Res() res): Promise<object>
{
console.log("- in getAllRooms controller");
const rooms = await this.chatService.getAllNotMyRooms(req.user);
console.log("- out getAllRooms controller");
return res.status(HttpStatus.OK).json({ rooms: rooms });
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Get('current')
async setCurrentRoom(@Body() setCurrentRoomDto: setCurrentRoomDto, @Req() req, @Res() res): Promise<object>
{
console.log("- in setCurrentRoom controller");
const response = await this.chatService.setCurrentRoom(req.user, setCurrentRoomDto.name);
console.log("- out setCurrentRoom controller");
return res.status(HttpStatus.OK).json({ message: response });
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Post('create')
async createRoom(@Body() createRoomDto: createRoomDto, @Req() req, @Res() res): Promise<object>
{
console.log("- in createRoom controller");
const response = await this.chatService.addUserToNewRoom(req.user, createRoomDto);
console.log("- out createRoom controller");
return res.status(HttpStatus.OK).json({ room_name: createRoomDto.room_name, message: response });
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Post('join')
async joinRoom(@Body() joinRoomDto: joinRoomDto, @Req() req, @Res() res): Promise<object>
{
console.log("- in joinRoom controller");
const response = await this.chatService.addUserToRoom(req.user, joinRoomDto);
console.log("- out joinRoom controller");
return res.status(HttpStatus.OK).json({ room_name: joinRoomDto.room_name, message: response });
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Post('change')
async changeRoom(@Body() joinRoomDto: joinRoomDto, @Req() req, @Res() res): Promise<object>
{
console.log("- in changeRoom controller");
const response = await this.chatService.setCurrentRoom(req.user, joinRoomDto.room_name);
console.log("- out changeRoom controller");
return res.status(HttpStatus.OK).json({ room_name: joinRoomDto.room_name, message: response });
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Post('leave')
async leaveRoom(@Body() body)
{
console.log("- in leaveRoom controller");
console.log("- out leaveRoom controller");
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Get('messages')
async getMessages(@Req() req, @Res() res): Promise<object>
{
console.log("- in getMessages controller");
const messages = await this.chatService.getMessagesFromCurrentRoom(req.user);
console.log("- out getMessages controller");
return res.status(HttpStatus.OK).json({ messages: messages });
}
}

View File

@@ -1,13 +1,7 @@
import { import { WebSocketGateway, SubscribeMessage, WebSocketServer, MessageBody, ConnectedSocket, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';
WebSocketGateway,
SubscribeMessage,
WebSocketServer,
MessageBody,
OnGatewayConnection,
OnGatewayDisconnect,
} from '@nestjs/websockets';
import { UsersService } from 'src/users/users.service'; import { UsersService } from 'src/users/users.service';
import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto'; import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto';
import { ChatService } from './chat.service';
@WebSocketGateway(5000, { @WebSocketGateway(5000, {
path: '/chat', path: '/chat',
@@ -19,26 +13,43 @@ export class ChatGateway
constructor constructor
( (
private usersService: UsersService, private usersService: UsersService,
private chatService: ChatService,
) {} ) {}
@WebSocketServer() @WebSocketServer()
server; server;
// how to guard the handleConnection ? // how to guard the handleConnection ?
// https://github.com/nestjs/nest/issues/882 // https://github.com/nestjs/nest/issues/882
async handleConnection(client) { async handleConnection(client) {
// const paginationQuery = new PaginationQueryDto(); console.log('- Client connected :', client.id, client.handshake.query.username);
// const users = await this.usersService.findAll(paginationQuery); client.username = client.handshake.query.username;
}
async handleDisconnect(client) {
console.log('- Client disconnected :', client.id, client.username);
}
// const users = await this.usersService.findAll(client); @SubscribeMessage('join')
// const users = await this.usersService.findAll(client); async joinRoom(@ConnectedSocket() socket, @MessageBody() room_name: string): Promise<void>
console.log('---- Client connected :', client.id); {
// console.log('users :', users); console.log('- in joinRoom gateway');
socket.leave(socket.room);
socket.join(room_name);
socket.room = room_name;
console.log('- out joinRoom gateway');
} }
handleDisconnect(client) {
console.log('---- client disconnected :', client.id); @SubscribeMessage('message')
async handleMessage(@ConnectedSocket() socket, @MessageBody() message: string): Promise<void>
{
console.log('- in handleMessage gateway');
//let room_name = await this.chatService.getCurrentRoom(socket.username);
socket.to(socket.room).emit('message', socket.username, message);
this.chatService.addMessageToCurrentRoom(socket.username, message);
console.log('- out handleMessage gateway');
} }
/*
*/
} }

View File

@@ -0,0 +1,28 @@
import { Module } from '@nestjs/common';
import { ChatController } from './chat.controller';
import { ChatService } from './chat.service';
import { ChatGateway } from './chat.gateway';
import { UsersModule } from 'src/users/users.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Chatroom } from './entities/chatroom.entity';
import { User } from 'src/users/entities/user.entity';
@Module({
imports: [
TypeOrmModule.forFeature([Chatroom, User]),
UsersModule,
],
controllers: [
ChatController,
],
exports: [
],
providers: [
ChatService,
ChatGateway,
],
})
export class ChatModule {}

View File

@@ -0,0 +1,219 @@
import { HttpException, HttpStatus, Injectable, Res } from '@nestjs/common';
import { User } from 'src/users/entities/user.entity';
import { UsersService } from 'src/users/users.service';
import { Chatroom } from './entities/chatroom.entity';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { createRoomDto } from './dto/createRoom.dto';
import { joinRoomDto } from './dto/joinRoom.dto';
import { messagesDto } from './dto/messages.dto';
@Injectable()
export class ChatService {
constructor(
private usersService: UsersService,
@InjectRepository(User)
private readonly userRepository: Repository<User>,
@InjectRepository(Chatroom)
private readonly chatroomRepository: Repository<Chatroom>,
) { }
// temp for test
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/* GETTERS ************************************************
*/
async getMyRooms(user: User)
{
console.log("-- in getMyRooms service");
const rooms = await this.chatroomRepository
.createQueryBuilder('chatroom')
.where('chatroom.users LIKE :user_name', { user_name: `%${user.username}%` })
.getMany();
console.log("-- out getMyRooms service");
return rooms;
}
async getAllRooms()
{
console.log("-- in getAllRooms service");
const rooms = await this.chatroomRepository
.createQueryBuilder('chatroom')
.getMany();
console.log("-- out getAllRooms service");
return rooms;
}
async getAllNotMyRooms(user: User)
{
console.log("-- in getAllNotMyRooms service");
const user_db = await this.getUserByName(user.username);
//const user_db = await this.usersService.findOne(user.username);
const rooms = await this.chatroomRepository
.createQueryBuilder('chatroom')
.where('chatroom.type != :type', { type: 'private' })
.andWhere('chatroom.users NOT LIKE :user_name', { user_name: `%${user.username}%` })
.getMany();
//const users = await this.getAllUsers();
//let allRooms = [...rooms, ...users];
console.log("-- out getAllNotMyRooms service");
return rooms;
}
async getMessagesFromCurrentRoom(user: User)
{
console.log("-- in getMessagesFromCurrentRoom service");
const user_db = await this.getUserByName(user.username);
//const user_db = await this.usersService.findOne(user.username);
const currentRoom = await this.getRoomByName(user_db.currentRoom);
console.log("-- out getMessagesFromCurrentRoom service");
return currentRoom.messages;
}
async getCurrentRoom(username: string)
{
console.log("-- in getCurrentRoom service");
const user_db = await this.getUserByName(username);
//const user_db = await this.usersService.findOne(username);
console.log("-- out getCurrentRoom service");
return user_db.currentRoom;
}
async getRoomByName(name: string)
{
console.log("-- in getRoomByName service");
const room = await this.chatroomRepository
.createQueryBuilder('chatroom')
.where('chatroom.name = :name', { name: name })
.getOne();
console.log("-- out getRoomByName service");
return room;
}
async getRoomById(id: number)
{
console.log("-- in getRoomById service");
const room = await this.chatroomRepository
.createQueryBuilder('chatroom')
.where('chatroom.id = :id', { id: id })
.getOne();
console.log("-- out getRoomById service");
return room;
}
/* SETTERS ************************************************
*/
async setCurrentRoom(user: User, name: string)
{
console.log("-- in setCurrentRoom service");
const user_db = await this.getUserByName(user.username);
//const user_db = await this.usersService.findOne(user.username);
user_db.currentRoom = name;
this.userRepository.save(user_db);
console.log("-- out setCurrentRoom service");
return `room "${name}" is now current room`;
}
/* ADDERS *************************************************
*/
async addUserToNewRoom(user: User, createRoomDto: createRoomDto)
{
console.log("-- in addUserToRoom service");
const room = await this.getRoomByName(createRoomDto.room_name);
if (room)
throw new HttpException(`This room already exist`, HttpStatus.CONFLICT);
// create chatroom
const newChatroom = new Chatroom();
newChatroom.name = createRoomDto.room_name;
newChatroom.type = createRoomDto.room_type;
newChatroom.owner = user.username;
newChatroom.users = [user.username];
newChatroom.messages = [{ name: "SERVER", message: `creation of room ${createRoomDto.room_name}` }];
this.chatroomRepository.save(newChatroom);
console.log("-- out addUserToRoom service");
return "successfull room creation";
}
async addUserToRoom(user: User, joinRoomDto: joinRoomDto)
{
console.log("-- in addUserToRoom service");
const room = await this.getRoomByName(joinRoomDto.room_name);
if (room.users.includes(user.username))
throw new HttpException(`your have already join this room`, HttpStatus.CONFLICT);
// update room with new user
room.users.push(user.username);
this.chatroomRepository.save(room);
const rooms = await this.getMyRooms(user);
const allRooms = await this.getAllRooms();
console.log("-- out addUserToRoom service");
return "successfull joining room";
}
async addMessageToCurrentRoom(username: string, message: string)
{
console.log("-- in addMessageToCurrentRoom service");
const user_db = await this.getUserByName(username);
//const user_db = await this.usersService.findOne(username);
const currentRoom = await this.getRoomByName(user_db.currentRoom);
let chat_message = {
name: username,
message: message,
};
currentRoom.messages.push(chat_message);
this.chatroomRepository.save(currentRoom);
console.log("-- out addMessageToCurrentRoom service");
}
/* REMOVERS ***********************************************
*/
async removeUserFromRoom(user: User, room_name: string)
{
console.log("-- in removeUserFromRoom service");
// get room
// remove user
}
/* SEARCH IN USER *****************************************
*/
async getUserByName(name: string)
{
console.log("-- in getUserByName service");
const user = await this.userRepository
.createQueryBuilder('user')
.where('user.username = :name', { name: name })
.getOne();
console.log("-- out getUserByName service");
return user;
}
}

View File

@@ -0,0 +1,18 @@
import { IsBoolean, IsEmpty, IsInt, IsNotEmpty, IsNumber, IsString, IsOptional } from "class-validator";
import { IsNull } from "typeorm";
export class createRoomDto
{
@IsString()
@IsNotEmpty()
room_name: string;
@IsString()
@IsNotEmpty()
room_type: 'public' | 'private' | 'direct';
@IsString()
@IsOptional()
room_password: string;
}

View File

@@ -0,0 +1,10 @@
import { IsBoolean, IsEmpty, IsInt, IsNotEmpty, IsNumber, IsString, IsOptional } from "class-validator";
import { IsNull } from "typeorm";
export class joinRoomDto
{
@IsString()
@IsNotEmpty()
room_name: string;
}

View File

@@ -0,0 +1,9 @@
import { IsBoolean, IsEmpty, IsInt, IsNotEmpty, IsNumber, IsString, IsOptional, IsArray } from "class-validator";
import { IsNull } from "typeorm";
export class messagesDto
{
@IsArray()
messages: { name: string; message: string }[];
}

View File

@@ -0,0 +1,10 @@
import { IsBoolean, IsEmpty, IsInt, IsNotEmpty, IsNumber, IsString, IsOptional } from "class-validator";
import { IsNull } from "typeorm";
export class setCurrentRoomDto
{
@IsString()
@IsNotEmpty()
name: string;
}

View File

@@ -0,0 +1,38 @@
import {
Entity,
Column,
ManyToOne,
ManyToMany,
JoinTable,
PrimaryGeneratedColumn
} from "typeorm";
import { User } from 'src/users/entities/user.entity';
@Entity('chatroom')
export class Chatroom {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
type: string;
// @ManyToOne(type => User, user => user.ownedRooms)
// owner: User;
//
// @ManyToMany(type => User)
// @JoinTable()
// users: User[];
@Column()
owner: string; // name
@Column("simple-array")
users: string[]; // names
@Column("json")
messages: { name: string, message: string }[];
}

View File

@@ -254,7 +254,6 @@ export class FriendshipService {
// const friendship = await this.friendshipRepository.findOneBy({ sender: creator, receiver: receiver }); // const friendship = await this.friendshipRepository.findOneBy({ sender: creator, receiver: receiver });
const friendship = await this.friendshipRepository const friendship = await this.friendshipRepository
.createQueryBuilder('friendship') .createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender') .leftJoinAndSelect('friendship.sender', 'sender')
@@ -459,4 +458,4 @@ export class FriendshipService {
console.log('we are not blocked in friendship service') console.log('we are not blocked in friendship service')
return false; return false;
} }
} }

View File

@@ -52,4 +52,9 @@ export class User {
@JoinColumn() @JoinColumn()
@OneToOne(() => UserStats, { cascade: true }) @OneToOne(() => UserStats, { cascade: true })
stats: UserStats; stats: UserStats;
// ROOMS :
@Column({ nullable: true })
currentRoom: string; // chatroom name
} }

View File

@@ -45,6 +45,7 @@ export class UsersService {
isEnabledTwoFactorAuth: user.isEnabledTwoFactorAuth, isEnabledTwoFactorAuth: user.isEnabledTwoFactorAuth,
status: user.status, status: user.status,
stats: user.stats, stats: user.stats,
currentRoom: user.currentRoom,
}; };
console.log(`Returned Partial User.` + partialUser.username + user.username); console.log(`Returned Partial User.` + partialUser.username + user.username);
return partialUser; return partialUser;

View File

@@ -0,0 +1,55 @@
server {
listen 8080;
listen [::]:8080;
server_name localhost;
location /api/v2 {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://backend_dev:3000;
}
location /chat {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://backend_dev:5000/chat;
}
location /api/v2/game/gameserver {
deny all;
}
location /pong {
proxy_pass http://game_server:8042/pong;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://frontend_dev:8080;
}
}
server {
listen 35729 default_server;
listen [::]:35729 default_server;
server_name localhost;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://frontend_dev:35729;
}
}

View File

@@ -0,0 +1,2 @@
WEBSITE_HOST=localhost
WEBSITE_PORT=8080

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,6 @@
<script lang="ts"> <script lang="ts">
// routing import Router, { replace } from "svelte-spa-router";
// may not need {link} here
import Router, { link, replace } from "svelte-spa-router";
import { primaryRoutes } from "./routes/primaryRoutes.js"; import { primaryRoutes } from "./routes/primaryRoutes.js";
// import primaryRoutes from "./routes/primaryRoutes.svelte";
const conditionsFailed = (event) => { const conditionsFailed = (event) => {
console.error('conditionsFailed event', event.detail); console.error('conditionsFailed event', event.detail);
@@ -15,6 +12,5 @@
</script> </script>
<!-- <h1>Testing</h1> -->
<Router routes={primaryRoutes} on:conditionsFailed={conditionsFailed}/> <Router routes={primaryRoutes} on:conditionsFailed={conditionsFailed}/>

View File

@@ -4,14 +4,7 @@
<h1>We are sorry!</h1> <h1>We are sorry!</h1>
<p>This isn't a url that we use.</p> <p>This isn't a url that we use.</p>
<!-- <img src="https://picsum.photos/id/685/800/400" alt="img"> -->
<p>Go home you're drunk.</p> <p>Go home you're drunk.</p>
<a href="/" use:link> <a href="/" use:link>
<h2>Take me home →</h2> <h2>Take me home →</h2>
</a> </a>
<style>
/* img {
width: 100%;
} */
</style>

View File

@@ -74,7 +74,6 @@
overflow-y: hidden; overflow-y: hidden;
} */ } */
header { header {
/* didn't work... */ /* didn't work... */
overflow-y: hidden; overflow-y: hidden;

View File

@@ -2,7 +2,7 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte'; import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte';
import { push } from 'svelte-spa-router';
import Chat from '../../pieces/chat/Chat.svelte'; import Chat from '../../pieces/chat/Chat.svelte';
@@ -19,13 +19,11 @@
<Chat color="bisque"/> <Chat color="bisque"/>
<!-- is this if excessive? -->
<div class="outer"> <div class="outer">
<!-- OHHHH i could use #await instead of if and have an nice loading page! -->
{#if user !== undefined} {#if user !== undefined}
<GenerateUserDisplay user={user} primary={true}/> <GenerateUserDisplay user={user} primary={true}/>
<button on:click={() => (push('/profile/settings'))}>Profile Settings</button>
{:else} {:else}
<!-- might be unnecessary since you can't access the page without fetching the user -->
<h2>Sorry</h2> <h2>Sorry</h2>
<div>Failed to load current</div> <div>Failed to load current</div>
{/if} {/if}
@@ -36,140 +34,7 @@
div.outer{ div.outer{
max-width: 960px; max-width: 960px;
margin: 40px auto; margin: 40px auto;
}
/* The main part */
main{
max-width: 960px;
margin: 40px auto;
text-align: center; text-align: center;
} }
/* Normal CSS stuff */
.avatar{
max-width: 150px;
/* padding: 5px; */
}
/* The variable rich section */
section.main-stats{
max-width: 600px;
margin: 40px auto;
text-align: center;
/* i think i want to use a grid? */
display: grid;
grid-template-columns: repeat(3, 1fr);
/* not sure about this, maybe top should be larger? */
grid-template-rows: repeat(3, 1fr);
}
/* the stuff in the grid*/
section.main-stats h4{
grid-column: 1 / span 3;
}
div.username{
font-size: 1.5em;
font-weight: bold;
padding-bottom: 5px;
}
div.rank {
/* color: black; */
font-size: 1.2em;
font-weight: bold;
}
/* Glittery Star Stuff */
:root {
--purple: rgb(123, 31, 162);
--violet: rgb(103, 58, 183);
--pink: rgb(244, 143, 177);
/* make shit gold? */
}
@keyframes background-pan {
from {
background-position: 0% center;
}
to {
background-position: -200% center;
}
}
@keyframes scale {
from, to {
transform: scale(0);
}
50% {
transform: scale(1);
}
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(180deg);
}
}
div > .glitter {
display: inline-block;
position: relative;
}
div > .glitter > .glitter-star {
--size: clamp(20px, 1.5vw, 30px);
animation: scale 700ms ease forwards;
display: block;
height: var(--size);
left: var(--star-left);
position: absolute;
top: var(--star-top);
width: var(--size);
}
div > .glitter > .glitter-star > svg {
animation: rotate 1000ms linear infinite;
display: block;
opacity: 0.7;
}
div > .glitter > .glitter-star > svg > path {
fill: var(--violet);
}
div > .glitter > .glitter-text {
animation: background-pan 3s linear infinite;
/* background-image: linear-gradient( */
background: linear-gradient(
to right,
var(--purple),
var(--violet),
var(--pink),
var(--purple)
);
background-size: 200%;
/* Keep these for Safari and chrome */
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
/* These are for Firefox */
background-clip: text;
color: transparent;
white-space: nowrap;
}
</style> </style>

View File

@@ -177,7 +177,7 @@
console.log('Block a non friend user, their username') console.log('Block a non friend user, their username')
console.log(aUsername) console.log(aUsername)
sentFriendRequest = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/relations`, { let sentFriendRequest = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/relations`, {
method : "POST", method : "POST",
headers: { 'Content-Type': 'application/json'}, headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({ body: JSON.stringify({

View File

@@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import Header from "../../pieces/Header.svelte"; import Header from "../../pieces/Header.svelte";
import Router from "svelte-spa-router"; import Router from "svelte-spa-router";
import { profileRoutes, prefix } from "../../routes/profileRoutes.js"; import { profileRoutes, prefix } from "../../routes/profileRoutes.js";

View File

@@ -3,9 +3,11 @@
import { location } from 'svelte-spa-router'; import { location } from 'svelte-spa-router';
// no need, it's just for links
import active from 'svelte-spa-router/active' import active from 'svelte-spa-router/active'
// or i could leave them all and not display if they're active? // or i could leave them all and not display if they're active?
$: current = $location;
let handleClickLogout = async () => { let handleClickLogout = async () => {
await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/logout`, { await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/logout`, {
@@ -23,16 +25,13 @@
<img src="/img/potato_logo.png" alt="Potato Pong Logo" on:click={() => (push('/'))}> <img src="/img/potato_logo.png" alt="Potato Pong Logo" on:click={() => (push('/'))}>
<h1>Potato Pong</h1> <h1>Potato Pong</h1>
<nav> <nav>
<button on:click={() => (push('/game'))}>Play</button> <button class:selected="{current === '/game'}" on:click={() => (push('/game'))}>Play</button>
<button on:click={() => (push('/spectator'))}>Spectate</button> <button class:selected="{current === '/spectator'}" on:click={() => (push('/spectator'))}>Spectate</button>
<button on:click={() => (push('/ranking'))}>Ranking</button> <button class:selected="{current === '/ranking'}" on:click={() => (push('/ranking'))}>Ranking</button>
{#if $location !== '/profile'} <button class:selected="{current === '/profile'}" on:click={() => (push('/profile'))}>My Profile</button>
<button on:click={() => (push('/profile'))}>My Profile</button> <!-- <button class:selected="{current === '/profile/settings'}" on:click={() => (push('/profile/settings'))}>Settings</button> -->
{:else if $location === '/profile'} <button class:selected="{current === '/profile/friends'}" on:click={() => (push('/profile/friends'))}>Friends</button>
<button on:click={() => (push('/profile/settings'))}>Settings</button> <button on:click={handleClickLogout}>Log Out</button>
{/if}
<button on:click={() => (push('/profile/friends'))}>Friends</button>
<button on:click={handleClickLogout}>Log Out</button>
</nav> </nav>
</header> </header>
@@ -54,6 +53,13 @@
} }
.selected {
background-color: chocolate;
text-decoration: underline;
/* TMP so it's obvious but we need to pick good colors */
}
/* There is a bunch of unncessary shit in here... why so many flex grids, why is everything the same class? just seemed easier but... */ /* There is a bunch of unncessary shit in here... why so many flex grids, why is everything the same class? just seemed easier but... */

View File

@@ -1,54 +1,11 @@
<script lang="ts"> <script lang="ts">
import Layouts from './Chat_layouts.svelte'; import Layouts from './Chat_layouts.svelte';
import { init_socket } from './Socket_init';
export let color = "transparent"; export let color = "transparent";
/* web sockets with socket.io init_socket();
*/
import { onMount } from 'svelte';
import io from 'socket.io-client';
const socket = io(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}`, {
path: '/chat'
});
onMount(async => {
socket.on('connect', function(){
console.log("socket.io connected");
});
socket.on('disconnect', function(){
console.log("socket.io disconnected");
});
socket.on('connect_error', function(){
console.log("socket.io connect_error");
});
socket.on('connect_timeout', function(){
console.log("socket.io connect_timeout");
});
socket.on('error', function(){
console.log("socket.io error");
});
socket.on('reconnect', function(){
console.log("socket.io reconnect");
});
socket.on('reconnect_attempt', function(){
console.log("socket.io reconnect_attempt");
});
socket.on('reconnecting', function(){
console.log("socket.io reconnecting");
});
socket.on('reconnect_error', function(){
console.log("socket.io reconnect_error");
});
socket.on('reconnect_failed', function(){
console.log("socket.io reconnect_failed");
});
socket.on('ping', function(){
console.log("socket.io ping");
});
socket.on('pong', function(){
console.log("socket.io pong");
});
});
</script> </script>

View File

@@ -1,12 +1,12 @@
<script lang="ts"> <script lang="ts">
import { layout } from './Store_chat';
export let color; export let color;
export let layout;
</script> </script>
<div class="{layout} chat_box" style="background-color: {color};"> <div class="{$layout} chat_box" style="background-color: {color};">
<slot></slot> <slot></slot>
</div> </div>

View File

@@ -1,6 +1,8 @@
<script lang="ts"> <script lang="ts">
import Debug from './tmp_debug.svelte';
import { layout } from './Store_chat';
import ChatBox from './Chat_box_css.svelte'; import ChatBox from './Chat_box_css.svelte';
import CloseLayout from './Layout_close.svelte'; import CloseLayout from './Layout_close.svelte';
@@ -14,68 +16,75 @@
import MuteLayout from './Layout_mute.svelte'; import MuteLayout from './Layout_mute.svelte';
import UserLayout from './Layout_user.svelte'; import UserLayout from './Layout_user.svelte';
import Button from './Chat_button.svelte'; import Button from './Element_button.svelte';
/* global variables /* global variables
*/ */
export let color; export let color;
let room = ""; let room = "";
let admin = false; let admin = false;
let layout = "close";
let layouts = ["home", "home"]; let layouts = ["home", "home"];
/* hold previous version of layout, to go back /* hold previous version of layout, to go back
*/ */
function set_layouts(layout) function set_layouts($layout)
{ {
if (layout === "close") console.log("layouts:", layouts);
console.log("layout:", $layout);
if ($layout.length === 0)
layout.set(layouts[0]);
else if ($layout === "close")
return; return;
if (layout === layouts[0]) else if ($layout === layouts[0])
return; return;
if (layout === layouts[1]) else if ($layout === layouts[1])
layouts = [layout, "home"]; layouts = [$layout, "home"];
else else
layouts = [layout, layouts[0]]; layouts = [$layout, layouts[0]];
console.log("- layouts:", layouts);
} }
$: set_layouts(layout); $: set_layouts($layout);
</script> </script>
<ChatBox layout={layout} color={color}> <ChatBox color={color}>
{#if layout === "home"} {#if $layout === "home"}
<HomeLayout bind:layout /> <HomeLayout />
{:else if layout === "close"} {:else if $layout === "close"}
<CloseLayout bind:layout /> <CloseLayout back={layouts[0]} />
{:else if layout === "room"} {:else if $layout === "room"}
<RoomLayout bind:layout back={layouts[1]} /> <RoomLayout back={layouts[1]} />
{:else if layout === "new"} {:else if $layout === "new"}
<NewLayout bind:layout back={layouts[1]} /> <NewLayout back={layouts[1]} />
{:else if layout === "settings"} {:else if $layout === "settings"}
<SettingsLayout bind:layout back={layouts[1]} /> <SettingsLayout back={layouts[1]} />
{:else if layout === "room_set"} {:else if $layout === "room_set"}
<RoomsetLayout bind:layout back={layouts[1]} /> <RoomsetLayout back={layouts[1]} />
{:else if layout === "protected"} {:else if $layout === "protected"}
<ProtectedLayout bind:layout back={layouts[1]} /> <ProtectedLayout back={layouts[1]} />
{:else if layout === "create"} {:else if $layout === "create"}
<CreateLayout bind:layout back={layouts[1]} /> <CreateLayout back={layouts[1]} />
{:else if layout === "mute"} {:else if $layout === "mute"}
<MuteLayout bind:layout back={layouts[1]} /> <MuteLayout back={layouts[1]} />
{:else if layout === "user"} {:else if $layout === "user"}
<UserLayout bind:layout back={layouts[1]} /> <UserLayout back={layouts[1]} />
{/if} {/if}
</ChatBox> </ChatBox>
<!-- TMP DEBUG -->
<Debug bind:layouts />
<style></style> <style></style>

View File

@@ -1,4 +1,3 @@
<!-- <!--
<Button <Button
bind:layout bind:layout
@@ -13,14 +12,15 @@
<script lang="ts"> <script lang="ts">
import { layout } from './Store_chat';
export let my_class = ""; export let my_class = "";
export let my_title = ""; export let my_title = "";
export let layout = "";
export let new_layout = ""; export let new_layout = "";
export let on_click = ""; export let on_click = "";
function update_layout() { function update_layout() {
layout = new_layout; layout.set(new_layout);
} }
</script> </script>
@@ -67,7 +67,7 @@
} }
/* for btn list /* .list
*/ */
.list:not(:hover) { .list:not(:hover) {
background-color: rgb(240, 240, 240); background-color: rgb(240, 240, 240);
@@ -77,14 +77,14 @@
} }
/* for transparent btn /* .transparent
*/ */
.transparent:not(:hover) { .transparent:not(:hover) {
background-color: transparent; background-color: transparent;
} }
/* for deactivated btn /* .deactivated
*/ */
.deactivate { .deactivate {
background-color: transparent; background-color: transparent;
@@ -92,7 +92,40 @@
} }
/* for icon /* .border
*/
.border {
border: 1px solid rgb(150, 150, 150);
}
/* .light
*/
.light {
background-color: rgb(233, 233, 233);
}
.light.border {
border: 1px solid rgb(204, 204, 204);
}
.light:hover {
background-color: rgb(220, 220, 220);
}
.light.border:hover {
border-color: rgb(200, 200, 200);
}
.light:active {
background-color: rgb(210, 210, 210);
}
/* .thin
*/
.thin p {
padding: 5px;
}
/* .icon
*/ */
.icon p { .icon p {
display: none; display: none;
@@ -107,7 +140,7 @@
} }
/* for 3 dots btn /* .dots
*/ */
.dots::after { .dots::after {
content: '\2807'; content: '\2807';
@@ -123,7 +156,7 @@
} }
/* for close btn /* .close
*/ */
.close::before { .close::before {
content: ""; content: "";
@@ -136,7 +169,7 @@
} }
/* for back btn /* .back
*/ */
.back::before { .back::before {
content: ""; content: "";
@@ -151,7 +184,7 @@
} }
/* for blocked user /* .blocked
https://www.fileformat.info/info/unicode/category/So/list.htm https://www.fileformat.info/info/unicode/category/So/list.htm
U+1F512 LOCK 🔒 U+1F512 LOCK 🔒
U+1F513 OPEN LOCK 🔓 U+1F513 OPEN LOCK 🔓

View File

@@ -0,0 +1,11 @@
<script>
export let content = "warning";
export let bg_color = "rgb(201, 87, 34)";
export let color = "rgb(240, 240, 240)";
</script>
<p style="background-color: {bg_color}; color: {color};">
{content}
</p>

View File

@@ -1,13 +1,14 @@
<script lang="ts">
<script> import { layout } from './Store_chat';
import Button from './Element_button.svelte';
import Button from './Chat_button.svelte'; export let back = "";
export let layout;
</script> </script>
<div class="grid_box"> <div class="grid_box">
<Button bind:layout new_layout="home" my_class="chat"> <Button new_layout={back} my_class="chat">
chat chat
</Button> </Button>
</div> </div>

View File

@@ -1,16 +1,41 @@
<script lang="ts">
<script> import { msgs, layout } from './Store_chat';
import { change_room, create_room } from './Request_rooms';
import Button from './Element_button.svelte';
import Warning from './Element_warning.svelte';
import Button from './Chat_button.svelte';
export let layout = "";
export let back = ""; export let back = "";
let room_name: string;
let room_type: string;
let room_password: string;
let response = {
status: 0,
message: "",
}
async function handleSubmit(evt)
{
let formIsValid = evt.target.checkValidity();
if (!formIsValid)
return;
// send the new room
response = await create_room(room_name, room_type);
// go to room
if (response.status === 200)
await change_room(room_name);
}
</script> </script>
<div class="grid_box"> <div class="grid_box">
<!-- back --> <!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}"> <Button new_layout={back} my_class="back icon" my_title="go back {back}">
back back
</Button> </Button>
@@ -20,37 +45,45 @@
</Button> </Button>
<!-- close --> <!-- close -->
<Button bind:layout new_layout="close" my_class="close icon"> <Button new_layout="close" my_class="close icon">
close close
</Button> </Button>
<!-- panel_create --> <!-- panel_create -->
<div class="panel panel_create"> <div class="panel panel_create __border_top">
<form> <form on:submit|preventDefault={handleSubmit}>
{#if response.status >= 300}
<Warning content={response.message}/>
{/if}
<!-- name: --> <!-- name: -->
<label for="chat_name"><p>new room name :</p></label> <label for="chat_name"><p>new room name :</p></label>
<input id="chat_name" required> <input id="chat_name" bind:value={room_name} name="room_name" required>
<!-- [ ] pubic --> <!-- [ ] pubic -->
<input id="chat_public" type="radio" name="chat_create_type" checked> <label for="chat_public" class="_radio">
<label for="chat_public" class="_radio"><p>public</p></label> <p>public</p>
<input id="chat_public" bind:group={room_type} type="radio" name="room_type" value="public" required>
</label>
<!-- [ ] private --> <!-- [ ] private -->
<input id="chat_private" type="radio" name="chat_create_type"> <label for="chat_private" class="_radio hide">
<label for="chat_private" class="_radio"><p>private</p></label> <p>private</p>
<input id="chat_private" bind:group={room_type} type="radio" name="room_type" value="private" required>
</label>
<!-- [ ] protected --> <!-- [ ] protected -->
<input id="chat_protected" class="__check_change_next" type="radio" name="chat_create_type"> <label for="chat_protected" class="_radio hide">
<label for="chat_protected" class="_radio"><p>protected</p></label> <p>protected</p>
<input id="chat_protected" bind:group={room_type} type="radio" name="room_type" value="protected" required>
</label>
<!-- [x] protected --> <!-- [x] protected -->
<div class="__to_show"> {#if room_type === 'protected'}
<label for="chat_pswd"><p>choose a password :</p></label> <div>
<input id="chat_pswd" type="password" placeholder="minimum 8 characters" minlength="8"> <label for="chat_pswd"><p>choose a password :</p></label>
<p>confirm password :</p> <input id="chat_pswd" bind:value={room_password} type="password" placeholder="minimum 8 characters" minlength="8" name="password" required>
<input type="password"> </div>
</div> {/if}
<input type="submit" value="&#x2BA1"> <input type="submit" value="&#x2BA1">
</form> </form>
</div> </div>
</div> </div>
<style> <style>
@@ -68,42 +101,32 @@
/ auto 1fr auto ; / auto 1fr auto ;
} }
/* temp
*/
.hide {
display: none !important;
}
/* radio elements style check /* radio elements style check
*/ */
form input[type=radio] { .panel label._radio {
display: none; display: inline;
} margin: 10px 0px 0px auto;
form label._radio {
margin: 0px 20px 0px auto;
padding-right: 10px; padding-right: 10px;
cursor: pointer; cursor: pointer;
} }
form label._radio p { .panel label._radio * {
display: inline;
}
.panel label._radio p {
margin-top: 0px; margin-top: 0px;
margin-bottom: 0px; margin-bottom: 0px;
} }
form label._radio::after {
content: "";
position: absolute;
top: calc(50% - 6px);
right: 0px;
width: 12px;
height: 12px;
border-radius: 6px;
border: 2px solid rgb(150, 150, 150);
box-sizing: border-box;
cursor: pointer;
}
form input[type=radio]:checked
+ label._radio::after {
background-color: rgb(200, 200, 200);
}
/* submit /* submit
*/ */
form input[type=submit] { .panel input[type=submit] {
margin-top: 20px; margin-top: 20px;
} }

View File

@@ -1,25 +1,36 @@
<script> <script>
import Button from './Chat_button.svelte'; import { layout, msgs, user } from './Store_chat';
export let layout; import { change_room, get_room_messages, get_all_rooms } from './Request_rooms';
import { onMount } from 'svelte';
import Button from './Element_button.svelte';
let rooms = get_all_rooms();
// go to clicked room
async function go_to_room(evt)
{
console.log("inside go_to_room");
await change_room(evt.target.innerText);
await get_room_messages();
}
</script> </script>
<div class="grid_box"> <div class="grid_box">
<!-- settings --> <!-- settings -->
<Button bind:layout new_layout="settings" my_class="settings dots icon"> <Button new_layout="settings" my_class="settings dots icon">
settings settings
</Button> </Button>
<!-- new --> <!-- new -->
<Button bind:layout new_layout="new" my_class="new transparent"> <Button new_layout="new" my_class="new transparent">
new new
</Button> </Button>
<!-- close --> <!-- close -->
<Button bind:layout new_layout="close" my_class="close icon"> <Button new_layout="close" my_class="close icon">
close close
</Button> </Button>
@@ -30,18 +41,16 @@
<div class="__show_if_only_child"> <div class="__show_if_only_child">
<p class="__center">/ you have no chat room yet /</p> <p class="__center">/ you have no chat room yet /</p>
</div> </div>
<!-- placeholders {#await rooms}
<Button bind:layout new_layout="room" my_class="list"> <!-- promise is pending -->
a room <p>rooms are loaded...</p>
</Button> {:then rooms}
<Button bind:layout new_layout="room" my_class="list"> {#each rooms as room}
another room <Button my_class="list" on_click={go_to_room}>
</Button> {room.name}
<Button bind:layout new_layout="room" my_class="list"> </Button>
placeholder {/each}
</Button> {/await}
------------- -->
<!-- END placeholders -->
</div> </div>
</div> </div>

View File

@@ -1,8 +1,8 @@
<script> <script>
import Button from './Chat_button.svelte'; import { layout } from './Store_chat';
export let layout = ""; import Button from './Element_button.svelte';
export let back = ""; export let back = "";
</script> </script>
@@ -10,7 +10,7 @@
<div class="grid_box"> <div class="grid_box">
<!-- back --> <!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}"> <Button new_layout={back} my_class="back icon" my_title="go back {back}">
back back
</Button> </Button>
@@ -20,7 +20,7 @@
</Button> </Button>
<!-- close --> <!-- close -->
<Button bind:layout new_layout="close" my_class="close icon"> <Button new_layout="close" my_class="close icon">
close close
</Button> </Button>

View File

@@ -1,16 +1,40 @@
<script> <script>
import Button from './Chat_button.svelte'; import { layout, msgs, user, socket } from './Store_chat';
export let layout = ""; import { join_room, change_room, get_room_messages } from './Request_rooms';
import Button from './Element_button.svelte';
export let back = ""; export let back = "";
let rooms = [];
// ask api for the rooms
const get_rooms = fetch('/api/v2/chat/allrooms')
.then(resp => resp.json())
.then(data =>
{
console.log("data.rooms:", data.rooms);
for (let room of data.rooms)
console.log(room.name);
rooms = data.rooms;
});
// join the room
async function join_rooms(evt)
{
console.log("inside join_room");
let room_name = evt.target.innerText;
await join_room(room_name);
await change_room(room_name);
}
</script> </script>
<div class="grid_box"> <div class="grid_box">
<!-- back --> <!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}"> <Button new_layout={back} my_class="back icon" my_title="go back {back}">
back back
</Button> </Button>
@@ -20,13 +44,13 @@
</Button> </Button>
<!-- close --> <!-- close -->
<Button bind:layout new_layout="close" my_class="close icon"> <Button new_layout="close" my_class="close icon">
close close
</Button> </Button>
<!-- panel_new --> <!-- panel_new -->
<div class="panel panel_new __border_top"> <div class="panel panel_new __border_top">
<Button bind:layout new_layout="create" my_class="create"> <Button new_layout="create" my_class="create">
create create
</Button> </Button>
<p>join room :</p> <p>join room :</p>
@@ -34,36 +58,16 @@
<div class="__show_if_only_child"> <div class="__show_if_only_child">
<p class="__center">/ there are no public rooms yet /</p> <p class="__center">/ there are no public rooms yet /</p>
</div> </div>
<!-- placeholders {#await get_rooms}
<Button bind:layout new_layout="room" my_class="list"> <!-- promise is pending -->
placeholder <p>rooms are loaded...</p>
</Button> {:then}
<Button bind:layout new_layout="room" my_class="list"> {#each rooms as room}
join room <Button my_class="list" on_click={join_rooms}>
</Button> {room.name}
<Button bind:layout new_layout="room" my_class="list"> </Button>
one room {/each}
</Button> {/await}
<Button bind:layout new_layout="room" my_class="list">
another room
</Button>
<Button bind:layout new_layout="room" my_class="list">
one room
</Button>
<Button bind:layout new_layout="room" my_class="list">
another room
</Button>
<Button bind:layout new_layout="room" my_class="list">
one room
</Button>
<Button bind:layout new_layout="room" my_class="list">
another room
</Button>
<Button bind:layout new_layout="room" my_class="list">
one more room
</Button>
------------- -->
<!-- END placeholders -->
</div> </div>
</div> </div>

View File

@@ -1,8 +1,8 @@
<script> <script>
import Button from './Chat_button.svelte'; import { layout } from './Store_chat';
export let layout = ""; import Button from './Element_button.svelte';
export let back = ""; export let back = "";
</script> </script>
@@ -10,7 +10,7 @@
<div class="grid_box"> <div class="grid_box">
<!-- back --> <!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}"> <Button new_layout={back} my_class="back icon" my_title="go back {back}">
back back
</Button> </Button>
@@ -20,7 +20,7 @@
</Button> </Button>
<!-- close --> <!-- close -->
<Button bind:layout new_layout="close" my_class="close icon"> <Button new_layout="close" my_class="close icon">
close close
</Button> </Button>

View File

@@ -1,36 +1,28 @@
<script> <script>
import Button from './Chat_button.svelte'; import { layout, socket, msgs, add_msg, room_name } from './Store_chat';
import Msg from './Chat_msg.svelte'; import Button from './Element_button.svelte';
import io from 'socket.io-client'; import Msg from './Element_msg.svelte';
export let layout = "";
export let back = ""; export let back = "";
let msg = ""; let msg = "";
let text_area; let text_area;
let msgs = [];
function add_msg(from, the_msg)
{
msgs = [...msgs, { content: the_msg, name: from }];
}
function send_msg() function send_msg()
{ {
msg = msg.trim(); msg = msg.trim();
if (msg.length > 0) { if (msg.length > 0) {
//socket.emit('sendmsg', msg); socket.emit('message', msg);
add_msg("me", msg); add_msg("me", msg);
console.log(msgs);
} }
msg = ""; msg = "";
text_area.focus(); text_area.focus();
} }
function send_msg_if(evt) function enter_send_msg(evt)
{ {
if (evt.shiftKey && evt.key === "Enter") if (evt.shiftKey && evt.key === "Enter")
{ {
@@ -44,25 +36,25 @@
<div class="grid_box"> <div class="grid_box">
<!-- back --> <!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}"> <Button new_layout={back} my_class="back icon" my_title="go back {back}">
back back
</Button> </Button>
<!-- room_name --> <!-- room_name -->
<Button bind:layout new_layout="room_set" my_class="room_name transparent"> <Button new_layout="room_set" my_class="room_name transparent">
&lt;room_name&gt; {$room_name}
</Button> </Button>
<!-- close --> <!-- close -->
<Button bind:layout new_layout="close" my_class="close icon"> <Button new_layout="close" my_class="close icon">
close close
</Button> </Button>
<!-- msg --> <!-- msg -->
<div class="panel panel_msg"> <div class="panel panel_msg">
<div class="msg_thread"> <div class="msg_thread">
{#each msgs as msg} {#each $msgs as msg}
<Msg name={msg.name}>{@html msg.content}</Msg> <Msg name={msg.name}>{@html msg.message}</Msg>
{/each} {/each}
</div> </div>
</div> </div>
@@ -73,7 +65,7 @@
class="text_area" class="text_area"
bind:innerHTML={msg} bind:innerHTML={msg}
bind:this={text_area} bind:this={text_area}
on:keypress={send_msg_if} on:keypress={enter_send_msg}
contenteditable="true" contenteditable="true"
></div> ></div>
</div> </div>

View File

@@ -1,8 +1,8 @@
<script> <script>
import Button from './Chat_button.svelte'; import { layout } from './Store_chat';
export let layout = ""; import Button from './Element_button.svelte';
export let back = ""; export let back = "";
</script> </script>
@@ -10,7 +10,7 @@
<div class="grid_box"> <div class="grid_box">
<!-- back --> <!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}"> <Button new_layout={back} my_class="back icon" my_title="go back {back}">
back back
</Button> </Button>
@@ -20,13 +20,13 @@
</Button> </Button>
<!-- close --> <!-- close -->
<Button bind:layout new_layout="close" my_class="close icon"> <Button new_layout="close" my_class="close icon">
close close
</Button> </Button>
<!-- panel_room_set --> <!-- panel_room_set -->
<div class="panel panel_room_set __border_top"> <div class="panel panel_room_set __border_top">
<Button bind:layout new_layout="create" my_class="create"> <Button new_layout="create" my_class="create">
leave leave
</Button> </Button>
<p>room users :</p> <p>room users :</p>
@@ -36,16 +36,16 @@
</div> </div>
<!-- placeholders <!-- placeholders
------------- --> ------------- -->
<Button bind:layout new_layout="user" my_class="list"> <Button new_layout="user" my_class="list">
user 1 user 1
</Button> </Button>
<Button bind:layout new_layout="user" my_class="list blocked"> <Button new_layout="user" my_class="list blocked">
user 2 user 2
</Button> </Button>
<Button bind:layout new_layout="user" my_class="list"> <Button new_layout="user" my_class="list">
user 3 user 3
</Button> </Button>
<Button bind:layout new_layout="user" my_class="list"> <Button new_layout="user" my_class="list">
user 4 user 4
</Button> </Button>
<!-- END placeholders --> <!-- END placeholders -->

View File

@@ -1,8 +1,8 @@
<script> <script>
import Button from './Chat_button.svelte'; import { layout } from './Store_chat';
export let layout = ""; import Button from './Element_button.svelte';
export let back = ""; export let back = "";
</script> </script>
@@ -10,7 +10,7 @@
<div class="grid_box"> <div class="grid_box">
<!-- back --> <!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}"> <Button new_layout={back} my_class="back icon" my_title="go back {back}">
back back
</Button> </Button>
@@ -20,7 +20,7 @@
</Button> </Button>
<!-- close --> <!-- close -->
<Button bind:layout new_layout="close" my_class="close icon"> <Button new_layout="close" my_class="close icon">
close close
</Button> </Button>

View File

@@ -1,8 +1,8 @@
<script> <script>
import Button from './Chat_button.svelte'; import { layout } from './Store_chat';
export let layout = ""; import Button from './Element_button.svelte';
export let back = ""; export let back = "";
let mute = "mute"; let mute = "mute";
@@ -14,7 +14,7 @@
<div class="grid_box"> <div class="grid_box">
<!-- back --> <!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}"> <Button new_layout={back} my_class="back icon" my_title="go back {back}">
back back
</Button> </Button>
@@ -24,7 +24,7 @@
</Button> </Button>
<!-- close --> <!-- close -->
<Button bind:layout new_layout="close" my_class="close icon"> <Button new_layout="close" my_class="close icon">
close close
</Button> </Button>

View File

@@ -0,0 +1,103 @@
import { msgs, user, layout, socket, room_name } from './Store_chat';
export async function get_room_messages()
{
console.log("in get_room_messages");
const response = await fetch('/api/v2/chat/messages');
const data = await response.json();
const messages = data.messages;
messages.forEach(function(item) {
if (item.name === user.username) {
item.name = "me";
}
});
msgs.set(messages);
}
export async function create_room(room_name, room_type)
{
console.log("in create_room");
let form_data = {
room_name: room_name,
room_type: room_type,
};
// send the new room
const response = await fetch('/api/v2/chat/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(form_data),
});
// get response status and message
let response_status = response.status;
let data = await response.json();
let response_message = "";
if (data.message)
response_message = data.message;
return {
status: response_status,
message: response_message
};
}
export async function join_room(room_name)
{
console.log("in join_room");
let name = {
room_name: room_name,
}
const response = await fetch('/api/v2/chat/join', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(name),
});
let data = await response.json();
console.log(data.message);
socket.emit('join', room_name);
}
export async function change_room(name)
{
console.log("in change_room");
let r_name = {
room_name: name,
}
const response = await fetch('/api/v2/chat/change', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(r_name),
});
let data = await response.json();
console.log(data.message);
await get_room_messages();
socket.emit('join', name);
room_name.set(name);
layout.set("room");
}
export async function get_all_rooms()
{
console.log("in get_all_rooms");
// ask api for the rooms
const response = await fetch('/api/v2/chat/myrooms');
const data = await response.json();
console.log("data.rooms:", data.rooms);
for (let room of data.rooms)
console.log(room.name);
let rooms = data.rooms;
return rooms;
}

View File

@@ -0,0 +1,12 @@
import { user, msgs } from './Store_chat';
export function socket_events(socket)
{
socket.on('message', function(from, message)
{
console.log("received msg:", message, from);
if (from === user.username)
from = "me";
msgs.update(msgs => [...msgs, { name: from, message: message }]);
});
}

View File

@@ -0,0 +1,39 @@
import io from 'socket.io-client';
import { set_socket, set_user } from './Store_chat';
import { socket_events } from './Socket_events';
const address = `http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}`;
export async function init_socket()
{
const response = await fetch(`${address}/api/v2/user`);
const response_data = await response.json();
set_user(response_data);
let socket = await io(address,
{
path: '/chat',
query:
{
username: response_data.username,
},
});
set_socket(socket);
socket.on('connect', function(){ console.log("socket.io connected"); });
socket.on('disconnect', function(){ console.log("socket.io disconnected"); });
socket.on('connect_error', function(){ console.log("socket.io connect_error"); });
socket.on('connect_timeout', function(){ console.log("socket.io connect_timeout"); });
socket.on('error', function(){ console.log("socket.io error"); });
socket.on('reconnect', function(){ console.log("socket.io reconnect"); });
socket.on('reconnect_attempt', function(){ console.log("socket.io reconnect_attempt"); });
socket.on('reconnecting', function(){ console.log("socket.io reconnecting"); });
socket.on('reconnect_error', function(){ console.log("socket.io reconnect_error"); });
socket.on('reconnect_failed', function(){ console.log("socket.io reconnect_failed"); });
socket.on('ping', function(){ console.log("socket.io ping"); });
socket.on('pong', function(){ console.log("socket.io pong"); });
socket_events(socket);
}

View File

@@ -0,0 +1,16 @@
import { writable } from 'svelte/store';
export let msgs = writable([]);
export let layout = writable("close");
export let room_name = writable("");
export let user;
export let socket;
export function set_user(new_user) { user = new_user; }
export function set_socket(new_socket) { socket = new_socket; }
export function add_msg(name: string, message: string)
{
msgs.update(msgs => [...msgs, { name: "me", message: message }]);
}

View File

@@ -0,0 +1,27 @@
<script>
export let layout = "";
export let layouts = [];
</script>
<div style="display: flex; flex-direction: column; font-size: 12px; position: fixed; top: 20px; left: 20px; background-color: white;">
<p>temp, for testing :</p>
<button on:click={function(){layout = "close" }}>close</button>
<button on:click={function(){layout = "home" }}>home</button>
<button on:click={function(){layout = "room" }}>room</button>
<button on:click={function(){layout = "new" }}>new</button>
<button on:click={function(){layout = "settings" }}>settings</button>
<button on:click={function(){layout = "room_set" }}>room_set</button>
<button on:click={function(){layout = "protected"}}>protected</button>
<button on:click={function(){layout = "create" }}>create</button>
<button on:click={function(){layout = "mute" }}>mute</button>
<button on:click={function(){
layouts = ["settings", "settings"];
layout = "user";
}}>user from settings</button>
<button on:click={function(){
layouts = ["room_set", "room_set"];
layout = "user";
}}>user from room_set</button>
</div>

View File

@@ -9,7 +9,6 @@ import Ranking from '../pages/game/Ranking.svelte';
import GameSpectator from '../pages/game/GameSpectator.svelte'; import GameSpectator from '../pages/game/GameSpectator.svelte';
export const primaryRoutes = { export const primaryRoutes = {
'/': SplashPage, '/': SplashPage,
'/2fa': TwoFactorAuthentication, '/2fa': TwoFactorAuthentication,