merge
This commit is contained in:
@ -4,7 +4,7 @@ import { Profiles } from "./Profiles.js";
|
||||
import { Channels } from './chat/Channels.js';
|
||||
import { MyProfile } from "./MyProfile.js";
|
||||
import { Tourmanents } from "./tournament/Tournaments.js";
|
||||
import { Notice } from "./chat/Notice.js";
|
||||
import Notice from "./notice/Notice.js";
|
||||
import { Channel } from "./chat/Channel.js";
|
||||
import LanguageManager from './LanguageManager.js';
|
||||
|
||||
@ -83,7 +83,7 @@ class Client
|
||||
{
|
||||
if (this._logged == undefined)
|
||||
this._logged = await this._test_logged();
|
||||
return this._logged;
|
||||
return this._logged;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,7 +217,7 @@ class Client
|
||||
{
|
||||
this.me = new MyProfile(this);
|
||||
await this.me.init();
|
||||
this.notice.connect();
|
||||
this.notice.start();
|
||||
document.getElementById('navbarLoggedOut').classList.add('d-none');
|
||||
document.getElementById('navbarLoggedIn').classList.remove('d-none');
|
||||
document.getElementById('navbarDropdownButton').innerHTML = this.me.username;
|
||||
@ -226,7 +226,7 @@ class Client
|
||||
else
|
||||
{
|
||||
this.me = undefined;
|
||||
this.notice.disconnect();
|
||||
this.notice.stop();
|
||||
document.getElementById('navbarLoggedOut').classList.remove('d-none');
|
||||
document.getElementById('navbarLoggedIn').classList.add('d-none');
|
||||
document.getElementById('navbarDropdownButton').innerHTML = 'Me';
|
||||
|
@ -21,12 +21,12 @@ class MatchMaking
|
||||
* @param {Number} mode The number of players in a game
|
||||
* @returns {Promise<?>}
|
||||
*/
|
||||
async start(receive_func, disconnect_func, gamemode, mode)
|
||||
async start(receive_func, disconnect_func, game_type, mode)
|
||||
{
|
||||
if (!await this.client.isAuthenticated())
|
||||
return null;
|
||||
|
||||
let url = `${window.location.protocol[4] === 's' ? 'wss' : 'ws'}://${window.location.host}/ws/matchmaking/${gamemode}/${mode}`;
|
||||
let url = `${window.location.protocol[4] === 's' ? 'wss' : 'ws'}://${window.location.host}/ws/matchmaking/${game_type}/${mode}`;
|
||||
|
||||
this._socket = new WebSocket(url);
|
||||
|
||||
|
@ -18,7 +18,7 @@ class MyProfile extends Profile
|
||||
/**
|
||||
* @type {[Profile]}
|
||||
*/
|
||||
this.friends = [];
|
||||
this.friendList = [];
|
||||
/**
|
||||
* @type {[Profile]}
|
||||
*/
|
||||
@ -40,28 +40,74 @@ class MyProfile extends Profile
|
||||
async getBlockedUsers() {
|
||||
const response = await this.client._get('/api/profiles/block');
|
||||
const data = await response.json();
|
||||
data.forEach(profileData => this.blockedUsers.push(new Profile(this.client, profileData.username, profileData.user_id, profileData.avatar)));
|
||||
data.forEach(profileData => this.blockedUsers.push(new Profile(this.client, profileData.username, profileData.id, profileData.avatar)));
|
||||
}
|
||||
|
||||
async getFriends() {
|
||||
const response = await this.client._get('/api/profiles/friends');
|
||||
const data = await response.json();
|
||||
data.forEach(profileData => this.friends.push(new Profile(this.client, profileData.username, profileData.user_id, profileData.avatar)));
|
||||
data.forEach(profileData => this.friendList.push(new Profile(this.client, profileData.username, profileData.id, profileData.avatar)));
|
||||
}
|
||||
async getIncomingFriendRequests() {
|
||||
const response = await this.client._get('/api/profiles/incoming_friend_requests');
|
||||
const data = await response.json();
|
||||
data.forEach(profileData => this.incomingFriendRequests.push(
|
||||
new Profile(this.client, profileData.username, profileData.user_id, profileData.avatar)
|
||||
new Profile(this.client, profileData.username, profileData.id, profileData.avatar)
|
||||
));
|
||||
}
|
||||
async getOutgoingFriendRequests() {
|
||||
const response = await this.client._get('/api/profiles/outgoing_friend_requests');
|
||||
const data = await response.json();
|
||||
data.forEach(profileData => this.outgoingFriendRequests.push(
|
||||
new Profile(this.client, profileData.username, profileData.user_id, profileData.avatar)
|
||||
new Profile(this.client, profileData.username, profileData.id, profileData.avatar)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Profile} profile
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
_isFriend(profile) {
|
||||
for (const user of this.friendList) {
|
||||
if (user.id === profile.id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @param {Profile} profile
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
_isBlocked(profile) {
|
||||
for (const user of this.blockedUsers) {
|
||||
if (user.id === profile.id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @param {Profile} profile
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
_hasIncomingRequestFrom(profile) {
|
||||
for (const user of this.incomingFriendRequests) {
|
||||
if (user.id === profile.id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @param {Profile} profile
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
_hasOutgoingRequestTo(profile) {
|
||||
for (const user of this.outgoingFriendRequests) {
|
||||
if (user.id === profile.id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {File} selectedFile
|
||||
|
@ -33,8 +33,10 @@ export class Profile extends AExchangeable
|
||||
/**
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isBlocked = false;
|
||||
this.isFriend = false;
|
||||
this.isFriend;
|
||||
this.isBlocked;
|
||||
this.hasIncomingRequest;
|
||||
this.hasOutgoingRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,10 +55,17 @@ export class Profile extends AExchangeable
|
||||
return response.status;
|
||||
|
||||
let response_data = await response.json();
|
||||
this.id = response_data.user_id;
|
||||
this.id = response_data.id;
|
||||
this.username = response_data.username;
|
||||
this.avatar = response_data.avatar;
|
||||
|
||||
if (!this.client.me || this.client.me.id === this.id)
|
||||
return;
|
||||
|
||||
this.isBlocked = this.client.me._isBlocked(this);
|
||||
this.hasIncomingRequest = this.client.me._hasIncomingRequestFrom(this);
|
||||
this.hasOutgoingRequest = this.client.me._hasOutgoingRequestTo(this);
|
||||
this.isFriend = this.client.me._isFriend(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,7 @@ class Profiles
|
||||
|
||||
let profiles = [];
|
||||
response_data.forEach((profile) => {
|
||||
profiles.push(new Profile(this.client, profile.username, profile.user_id, profile.avatar));
|
||||
profiles.push(new Profile(this.client, profile.username, profile.id, profile.avatar));
|
||||
});
|
||||
return profiles;
|
||||
}
|
||||
@ -54,40 +54,6 @@ class Profiles
|
||||
return null;
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block a user
|
||||
* @param {Number} user_id
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async block(user_id) {
|
||||
|
||||
// blocker & blocked
|
||||
let response = await this.client._post("/api/profiles/block", {
|
||||
users_id:[this.client.me.id, user_id],
|
||||
});
|
||||
|
||||
let data = await response.json();
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblock a user
|
||||
* @param {Number} user_id
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async deblock(user_id) {
|
||||
|
||||
// blocker & blocked
|
||||
let response = await this.client._delete("/api/profiles/block", {
|
||||
users_id:[this.client.me.id, user_id],
|
||||
});
|
||||
|
||||
let data = await response.json();
|
||||
return data;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export {Profiles};
|
||||
|
@ -1,308 +0,0 @@
|
||||
import { navigateTo } from "../../index.js";
|
||||
import {createNotification} from "../../utils/noticeUtils.js";
|
||||
|
||||
class Notice {
|
||||
constructor(client) {
|
||||
this.client = client;
|
||||
this.data = {};
|
||||
|
||||
// users online, invited by ..., asked by ..., asker to ...
|
||||
let data_variable = ["online", "invited", "asked", "asker"];
|
||||
for (let i in data_variable)
|
||||
this.data[data_variable[i]] = [];
|
||||
|
||||
//this.connect();
|
||||
|
||||
}
|
||||
|
||||
async connect() {
|
||||
return
|
||||
let url = `${window.location.protocol[4] === 's' ? 'wss' : 'ws'}://${window.location.host}/ws/chat/notice`;
|
||||
|
||||
this.chatSocket = new WebSocket(url);
|
||||
this.chatSocket.onmessage = (event) =>{
|
||||
let send = JSON.parse(event.data);
|
||||
//console.log("notice: ", send);
|
||||
|
||||
try {
|
||||
this["receive_" + send.type](send);
|
||||
}
|
||||
catch (error) {
|
||||
console.log("receive_" + send.type + ": Function not found");
|
||||
}
|
||||
|
||||
};
|
||||
this.chatSocket.onopen = (event) => {
|
||||
this.getOnlineUser();
|
||||
this.ask_friend();
|
||||
};
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
if (this.chatSocket == undefined)
|
||||
return ;
|
||||
|
||||
this.chatSocket.close();
|
||||
}
|
||||
|
||||
async reconnect() {
|
||||
this.disconnect();
|
||||
this.connect();
|
||||
}
|
||||
|
||||
async accept_invite(invitedBy) {
|
||||
|
||||
this.sendRequest({
|
||||
type: "accept_invite",
|
||||
targets: [invitedBy],
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
async receive_accept_invite(send) {
|
||||
|
||||
this.data.invited = send.invites;
|
||||
let id_game = send.id_game;
|
||||
navigateTo("/game/" + id_game);
|
||||
|
||||
}
|
||||
|
||||
async refuse_invite(invitedBy) {
|
||||
|
||||
this.sendRequest({
|
||||
type: "refuse_invite",
|
||||
targets: [invitedBy],
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
async receive_refuse_invite(send) {
|
||||
|
||||
this.data.invited = send.invites;
|
||||
|
||||
if (send.author_id == this.client.me.id) {
|
||||
if (this.rewrite_invite !== undefined)
|
||||
this.rewrite_invite();
|
||||
}
|
||||
else {
|
||||
let sender = await this.client.profiles.getProfileId(send.author_id);
|
||||
createNotification(sender.username + " refuse your invitation");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
async send_invite(id_inviteds) {
|
||||
|
||||
this.sendRequest({
|
||||
type: "invite",
|
||||
targets: id_inviteds,
|
||||
time: new Date().getTime(),
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
async receive_invite(send) {
|
||||
|
||||
if (this.client.me == undefined)
|
||||
return ;
|
||||
|
||||
let content = send.invites;
|
||||
|
||||
if (send.author_id == this.client.me.id) {
|
||||
if (send.status == 200) {
|
||||
for (let target in send.targets)
|
||||
return createNotification("Invitation send");
|
||||
}
|
||||
else if (send.status == 444)
|
||||
return createNotification("User not connected");
|
||||
else if (send.status == 409)
|
||||
return createNotification("Already invited");
|
||||
}
|
||||
else {
|
||||
|
||||
// Regarder qu'il est bien invité par l'auteur
|
||||
// Et qu'il n'est pas déjà invité
|
||||
if (!content.includes(send.author_id) ||
|
||||
this.data.invited.includes(send.author_id))
|
||||
return;
|
||||
|
||||
this.data.invited = content;
|
||||
let sender = await this.client.profiles.getProfileId(send.author_id);
|
||||
|
||||
createNotification("Invitation received by " + sender.username);
|
||||
|
||||
if (this.rewrite_invite !== undefined)
|
||||
this.rewrite_invite();
|
||||
}
|
||||
}
|
||||
|
||||
async getOnlineUser() {
|
||||
|
||||
this.online_users = {};
|
||||
|
||||
this.sendRequest({
|
||||
type: "online_users",
|
||||
targets: [],
|
||||
time: new Date().getTime(),
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
async receive_online_users(send) {
|
||||
let content = send.online;
|
||||
if (content !== undefined) {
|
||||
|
||||
if (this.data.online.length > 0) {
|
||||
// get all disconnect user
|
||||
//let disconnects = this.data["online"].filter(id => !Object.keys(content).includes(id));
|
||||
|
||||
let disconnects = [];
|
||||
|
||||
for (const [key, value] of Object.entries(this.data.online)) {
|
||||
if (content[key] == "red" && value == "green")
|
||||
disconnects.push(key);
|
||||
}
|
||||
|
||||
// delete invite
|
||||
this.data.invited = this.data.invited.filter(id => !disconnects.includes(id));
|
||||
|
||||
//console.log(this.data["invited"]);
|
||||
}
|
||||
|
||||
this.data.online = content;
|
||||
|
||||
if (this.rewrite_usernames !== undefined)
|
||||
this.rewrite_usernames();
|
||||
}
|
||||
}
|
||||
|
||||
async ask_friend(user_id=undefined) {
|
||||
this.sendRequest({
|
||||
type: "ask_friend",
|
||||
targets: [user_id],
|
||||
time: new Date().getTime(),
|
||||
});
|
||||
}
|
||||
|
||||
async receive_ask_friend(send) {
|
||||
|
||||
let my_id = (this.client.me && this.client.me.id) || send.author_id;
|
||||
if (send.author_id == my_id) {
|
||||
if (send.status == 400)
|
||||
createNotification("Friend ask error");
|
||||
else if (send.status == 409)
|
||||
createNotification("Already asked friend");
|
||||
}
|
||||
|
||||
//if (!send.asked.includes(send.author_id) ||
|
||||
//this.data["asked"].includes(send.author_id))
|
||||
//return;
|
||||
|
||||
//if (!send.asker.includes(send.author_id) ||
|
||||
//this.data["asker"].includes(send.author_id))
|
||||
//return;
|
||||
|
||||
this.data.asked = send.asked;
|
||||
this.data.asker = send.asker;
|
||||
|
||||
if (send.author_id != my_id) {
|
||||
let sender = await this.client.profiles.getProfileId(send.author_id);
|
||||
if (this.data.asker.includes(send.author_id))
|
||||
createNotification(sender.username + " ask you as friend");
|
||||
if (this.rewrite_profile !== undefined)
|
||||
await this.rewrite_profile();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async remove_friend(user_id) {
|
||||
this.sendRequest({
|
||||
type: "remove_friend",
|
||||
targets: [user_id],
|
||||
time: new Date().getTime(),
|
||||
});
|
||||
}
|
||||
|
||||
async receive_remove_friend(send) {
|
||||
|
||||
if (send.author_id == this.client.me.id) {
|
||||
if (send.status == 400)
|
||||
createNotification("Error remove Friend");
|
||||
else if (send.status == 409)
|
||||
createNotification("Not friend, wtf");
|
||||
|
||||
}
|
||||
|
||||
if (this.rewrite_profile !== undefined)
|
||||
await this.rewrite_profile();
|
||||
|
||||
this.receive_online_users(send);
|
||||
}
|
||||
|
||||
async accept_friend(user_id) {
|
||||
this.sendRequest({
|
||||
type: "accept_friend",
|
||||
targets: [user_id],
|
||||
time: new Date().getTime(),
|
||||
});
|
||||
}
|
||||
|
||||
async receive_accept_friend(send) {
|
||||
this.data.asked = send.asked;
|
||||
this.data.asker = send.asker;
|
||||
let sender = await this.client.profiles.getProfileId(send.author_id);
|
||||
|
||||
if (send.author_id == this.client.me.id) {
|
||||
if (send.status == 400)
|
||||
createNotification("Error accept Friend");
|
||||
else if (send.status == 404)
|
||||
createNotification("Not found request Friend");
|
||||
else if (send.status == 409)
|
||||
createNotification("Already Friend, wtf");
|
||||
}
|
||||
else {
|
||||
createNotification(sender.username + " accept your friend request");
|
||||
}
|
||||
|
||||
if (this.rewrite_profile !== undefined)
|
||||
await this.rewrite_profile();
|
||||
|
||||
this.receive_online_users(send);
|
||||
}
|
||||
|
||||
async refuse_friend(user_id) {
|
||||
this.sendRequest({
|
||||
type: "refuse_friend",
|
||||
targets: [user_id],
|
||||
time: new Date().getTime(),
|
||||
});
|
||||
}
|
||||
|
||||
async receive_refuse_friend(send) {
|
||||
this.data.asked = send.asked;
|
||||
this.data.asker = send.asker;
|
||||
let sender = await this.client.profiles.getProfileId(send.author_id);
|
||||
|
||||
if (send.author_id == this.client.me.id) {
|
||||
if (send.status == 400)
|
||||
createNotification("Error refuse Friend");
|
||||
else if (send.status == 404)
|
||||
createNotification("Not found request Friend");
|
||||
else if (send.status == 409)
|
||||
createNotification("Already Friend, WTF");
|
||||
|
||||
}
|
||||
if (this.rewrite_profile !== undefined)
|
||||
await this.rewrite_profile();
|
||||
}
|
||||
|
||||
async sendRequest(content) {
|
||||
if (this.chatSocket == undefined)
|
||||
return;
|
||||
|
||||
this.chatSocket.send(JSON.stringify(content));
|
||||
}
|
||||
}
|
||||
|
||||
export {Notice};
|
@ -18,12 +18,12 @@ class TicTacToe
|
||||
this.canvas = canvas
|
||||
this.context = this.canvas.getContext("2d");
|
||||
this.sign;
|
||||
this.currentMorpion = 4;
|
||||
this.turn;
|
||||
}
|
||||
|
||||
async init()
|
||||
{
|
||||
console.log(this.game_id);
|
||||
await this.game.join();
|
||||
this.canvas.addEventListener("mousedown", (event, morpion = this) => this.onClick(event, morpion));
|
||||
}
|
||||
@ -37,22 +37,46 @@ class TicTacToe
|
||||
async onReceive(messageData)
|
||||
{
|
||||
console.log(messageData)
|
||||
if (messageData.detail == "x" || messageData.detail == "o")
|
||||
switch (messageData.detail)
|
||||
{
|
||||
this.sign = messageData.detail;
|
||||
this.turn = messageData.detail == "x";
|
||||
}
|
||||
else if (messageData.detail == "game_start")
|
||||
this.game.started = true;
|
||||
else if (messageData.targetMorpion && messageData.targetCase)
|
||||
{
|
||||
this.map[messageData.targetMorpion][messageData.targetCase] = (this.sign == "x") ? 1 : 0;
|
||||
this.printSign(messageData.targetMorpion, messageData.targetCase, (this.sign == "x") ? "o" : "x");
|
||||
if (this.checkWin() != -1)
|
||||
printWin();
|
||||
case 'x':
|
||||
case 'o':
|
||||
this.sign = messageData.detail;
|
||||
this.turn = messageData.detail == "x";
|
||||
if (this.turn)
|
||||
this.setOutline(4, false);
|
||||
break;
|
||||
|
||||
case 'game_start':
|
||||
this.game.started = true;
|
||||
this.game.finished = false;
|
||||
break;
|
||||
|
||||
case 'game_move':
|
||||
this.map[messageData.targetMorpion][messageData.targetCase] = (this.sign == "x") ? 1 : 0;
|
||||
this.printSign(messageData.targetMorpion, messageData.targetCase, (this.sign == "x") ? "o" : "x");
|
||||
this.setOutline(this.currentMorpion, false);
|
||||
break;
|
||||
|
||||
case 'game_end':
|
||||
this.game.finished = true;
|
||||
this.canvas.removeEventListener("mousedown", (event, morpion = this) => this.onClick(event, morpion));
|
||||
this.printWin(messageData.winning_sign);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printWin(winning_sign)
|
||||
{
|
||||
this.context.beginPath();
|
||||
this.context.fillStyle = "white";
|
||||
this.context.fillRect(this.width / 2 - 200, this.height - this.gap + 10, 400, 80);
|
||||
this.context.closePath();
|
||||
this.context.beginPath();
|
||||
this.context.fillStyle = (winning_sign == "o") ? "red" : "green";
|
||||
this.context.fillText((winning_sign == "o") ? "Winner is : O" : "Winner is : X", this.width / 2 - 30, this.height - this.gap / 2, 140);
|
||||
this.context.closePath();
|
||||
}
|
||||
checkWin()
|
||||
{
|
||||
for (let i = 0; i < 9; i++)
|
||||
@ -85,6 +109,10 @@ class TicTacToe
|
||||
let y = event.offsetY;
|
||||
let targetMorpion, targetCase;
|
||||
|
||||
if (this.game.finished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
targetMorpion = morpion.findPlace(x, this) + morpion.findPlace(y, this) * 3;
|
||||
if (morpion.findPlace(x, this) < 0 || morpion.findPlace(y, this) < 0)
|
||||
return -1;
|
||||
@ -92,8 +120,8 @@ class TicTacToe
|
||||
|
||||
if (morpion.checkCase(targetMorpion, targetCase))
|
||||
{
|
||||
morpion.setOutline(this.currentMorpion, true);
|
||||
morpion.sendCase(targetMorpion, targetCase);
|
||||
morpion.setOutline();
|
||||
}
|
||||
else
|
||||
morpion.incorrectCase();
|
||||
@ -101,19 +129,20 @@ class TicTacToe
|
||||
|
||||
checkCase(targetMorpion, targetCase)
|
||||
{
|
||||
return (this.map[targetMorpion][targetCase] == -1 && this.turn == true);
|
||||
return (this.map[targetMorpion][targetCase] == -1 && this.turn == true && targetMorpion == this.currentMorpion);
|
||||
}
|
||||
|
||||
incorrectCase()
|
||||
{
|
||||
console.log("bozo");
|
||||
|
||||
}
|
||||
|
||||
sendCase(targetMorpion, targetCase)
|
||||
{
|
||||
this.map[targetMorpion][targetCase] = (this.sign == "x") ? 0 : 1;
|
||||
this.currentMorpion = targetCase;
|
||||
this.printSign(targetMorpion, targetCase, this.sign);
|
||||
console.log(this.game.send, targetMorpion, targetCase)
|
||||
console.log(targetMorpion, targetCase)
|
||||
this.game.send(JSON.stringify({"targetMorpion" : targetMorpion, "targetCase" : targetCase, "sign" : this.sign}));
|
||||
console.log(this.turn);
|
||||
this.turn = !this.turn;
|
||||
@ -172,21 +201,25 @@ class TicTacToe
|
||||
return -1;
|
||||
}
|
||||
|
||||
setOutline()
|
||||
setOutline(targetMorpion, clear)
|
||||
{
|
||||
if (this.turn)
|
||||
let targetX = (this.gap + targetMorpion % 3 * this.rectsize * 3);
|
||||
let targetY = (this.gap + Math.floor(targetMorpion / 3) * this.rectsize * 3);
|
||||
if (this.game.finished)
|
||||
return;
|
||||
if (!clear)
|
||||
{
|
||||
this.context.beginPath();
|
||||
this.context.strokeStyle = (this.sign == "x") ? "green" : "red";
|
||||
this.context.roundRect(0, 0, this.canvas.width, this.canvas.height, 25);
|
||||
this.context.rect(targetX, targetY, this.rectsize * 3, this.rectsize * 3)
|
||||
this.context.stroke();
|
||||
this.context.closePath();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.context.beginPath();
|
||||
this.context.strokeStyle = "#1a1a1d";
|
||||
this.context.roundRect(0, 0, this.canvas.width, this.canvas.height, 25);
|
||||
this.context.strokeStyle = `rgb(230 230 230)`;
|
||||
this.context.rect(targetX, targetY, this.rectsize * 3, this.rectsize * 3)
|
||||
this.context.stroke();
|
||||
this.context.closePath();
|
||||
}
|
||||
@ -244,34 +277,6 @@ class TicTacToe
|
||||
}
|
||||
this.context.closePath();
|
||||
}
|
||||
|
||||
selectCase(x, y)
|
||||
{
|
||||
case_morpion = Math.floor(x / this.rectsize) + Math.floor((y / this.rectsize)) * 3
|
||||
case_square = Math.floor(x / Math.floor(this.rectsize / 3)) % this.rectsize + Math.floor(y / this.rectsize) % this.rectsize
|
||||
// ask server if case_morpion == playing_case && case_square == empty
|
||||
|
||||
}
|
||||
|
||||
setOutline()
|
||||
{
|
||||
if (this.turn)
|
||||
{
|
||||
this.context.beginPath();
|
||||
this.context.strokeStyle = (this.sign == "x") ? "green" : "red";
|
||||
this.context.roundRect(0, 0, this.canvas.width, this.canvas.height, 25);
|
||||
this.context.stroke();
|
||||
this.context.closePath();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.context.beginPath();
|
||||
this.context.strokeStyle = "#1a1a1d";
|
||||
this.context.roundRect(0, 0, this.canvas.width, this.canvas.height, 25);
|
||||
this.context.stroke();
|
||||
this.context.closePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { TicTacToe };
|
81
frontend/static/js/api/notice/Notice.js
Normal file
81
frontend/static/js/api/notice/Notice.js
Normal file
@ -0,0 +1,81 @@
|
||||
import {Client} from '../Client.js';
|
||||
import {createNotification} from '../../utils/noticeUtils.js'
|
||||
import { client, lastView } from '../../index.js';
|
||||
import { Profile } from '../Profile.js';
|
||||
import ProfilePageView from '../../views/ProfilePageView.js';
|
||||
|
||||
export default class Notice {
|
||||
|
||||
/**
|
||||
* @param {Client} client
|
||||
*/
|
||||
constructor(client) {
|
||||
/**
|
||||
* @type {Client}
|
||||
*/
|
||||
this.client = client;
|
||||
this.url = location.origin.replace('http', 'ws') + '/ws/notice';
|
||||
}
|
||||
|
||||
start() {
|
||||
this._socket = new WebSocket(this.url);
|
||||
|
||||
this._socket.onclose = _ => this._socket = undefined;
|
||||
this._socket.onmessage = message => {
|
||||
const data = JSON.parse(message.data);
|
||||
|
||||
if (data.type === 'friend_request') {
|
||||
this.friend_request(data.author);
|
||||
} else if (data.type === 'new_friend') {
|
||||
this.new_friend(data.friend);
|
||||
} else if (data.type === 'friend_removed') {
|
||||
this.friend_removed(data.friend);
|
||||
} else if (data.type === 'friend_request_canceled') {
|
||||
this.friend_request_canceled(data.author);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this._socket) {
|
||||
this._socket.close();
|
||||
this._socket = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
friend_request(author) {
|
||||
client.me.incomingFriendRequests.push(new Profile(author.username, author.id, author.avatar));
|
||||
createNotification('Friend Request', `<strong>${author.username}</strong> sent you a friend request.`);
|
||||
if (lastView instanceof ProfilePageView && lastView.profile.id === author.id) {
|
||||
lastView.profile.hasIncomingRequest = true;
|
||||
lastView.loadFriendshipStatus();
|
||||
}
|
||||
}
|
||||
|
||||
new_friend(friend) {
|
||||
client.me.friendList.push(new Profile(friend.username, friend.id, friend.avatar));
|
||||
createNotification('New Friend', `<strong>${friend.username}</strong> accepted your friend request.`);
|
||||
if (lastView instanceof ProfilePageView && lastView.profile.id === friend.id) {
|
||||
lastView.profile.isFriend = true;
|
||||
lastView.profile.hasIncomingRequest = false;
|
||||
lastView.profile.hasOutgoingRequest = false;
|
||||
lastView.loadFriendshipStatus();
|
||||
}
|
||||
}
|
||||
|
||||
friend_removed(exFriend) {
|
||||
client.me.friendList = client.me.friendList.filter(friend => friend.id !== exFriend.id);
|
||||
if (lastView instanceof ProfilePageView && lastView.profile.id === exFriend.id) {
|
||||
lastView.profile.isFriend = false;
|
||||
lastView.loadFriendshipStatus();
|
||||
}
|
||||
}
|
||||
|
||||
friend_request_canceled(author) {
|
||||
client.me.incomingFriendRequests = client.me.incomingFriendRequests.filter(user => user.id !== author.id);
|
||||
if (lastView instanceof ProfilePageView && lastView.profile.id === author.id) {
|
||||
lastView.profile.hasIncomingRequest = false;
|
||||
lastView.loadFriendshipStatus();
|
||||
}
|
||||
}
|
||||
}
|
@ -42,14 +42,33 @@ class Tourmanent extends AExchangeable
|
||||
* @type {Number}
|
||||
*/
|
||||
this.finished;
|
||||
|
||||
|
||||
/**
|
||||
* @type {"finished" | "started" | "waiting"} must be "finished", or "started", or "waiting". Any other return all elements
|
||||
*/
|
||||
this.state;
|
||||
|
||||
/**
|
||||
* @type {Boolean} the client is a participant of the tournament
|
||||
*/
|
||||
this.is_participating;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Boolean} newParticipation
|
||||
*/
|
||||
async setParticipation(newParticipation)
|
||||
{
|
||||
if (this.isParticipating == newParticipation)
|
||||
return;
|
||||
|
||||
this.isParticipating = newParticipation;
|
||||
|
||||
this._socket.send(JSON.stringify({"detail": "update_participating",
|
||||
"is_participating": newParticipation})
|
||||
);
|
||||
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @returns {Promise<?>}
|
||||
@ -79,28 +98,66 @@ class Tourmanent extends AExchangeable
|
||||
/**
|
||||
* @param {Object} data
|
||||
*/
|
||||
async _receiveParticipantUpdate(data)
|
||||
async _receiveAddParticipant(data)
|
||||
{
|
||||
this.par
|
||||
const participant = new Profile(this.client, undefined, data.participant.user_id);
|
||||
participant.import(data.participant)
|
||||
|
||||
this.participantList.push(participant);
|
||||
|
||||
await this._addParticipantHandler(this.participantList.length)
|
||||
}
|
||||
|
||||
async onError(data)
|
||||
/**
|
||||
* @param {Object} data
|
||||
*/
|
||||
async _receiveDelParticipant(data)
|
||||
{
|
||||
const index = this.participantList.indexOf((profile) => profile.id === data.profile.user_id)
|
||||
|
||||
this.participantList.splice(index, 1);
|
||||
|
||||
await this._delParticipantHandler(this.participantList.length);
|
||||
}
|
||||
|
||||
async _receiveError(data)
|
||||
{
|
||||
await this.errorHandler(data);
|
||||
}
|
||||
|
||||
async _receiveGoTo(data)
|
||||
{
|
||||
await this._goToHandler(data)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {MessageEvent} event
|
||||
*/
|
||||
onReceive(event)
|
||||
async onReceive(event)
|
||||
{
|
||||
const data = JSON.parse(event.data);
|
||||
|
||||
if (data.detail === "error")
|
||||
this.onError(data);
|
||||
else if (["del_participant", "add_participant"].includes(data.detail))
|
||||
this._receiveParticipantUpdate(data);
|
||||
switch (data.detail) {
|
||||
case "error":
|
||||
await this._receiveError(data)
|
||||
break;
|
||||
|
||||
case "add_participant":
|
||||
await this._receiveAddParticipant(data);
|
||||
break;
|
||||
|
||||
case "del_participant":
|
||||
await this._receiveDelParticipant(data);
|
||||
break;
|
||||
|
||||
case "go_to":
|
||||
await this._receiveGoTo(data);
|
||||
break
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,9 +167,11 @@ class Tourmanent extends AExchangeable
|
||||
* @param {CallableFunction} delParticipantHandler called when a participants leave the tournament
|
||||
* @param {CallableFunction} disconnectHandler
|
||||
* @param {CallableFunction} goToHandler called when the next game will start
|
||||
* @returns {?}
|
||||
* @param {CallableFunction} startHandler called when tournament start
|
||||
* @param {CallableFunction} finishHandler called when tournament finish
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async join(participantsUpdateHandler, errorHandler, goToHandler, disconnectHandler)
|
||||
async join(addParticipantHandler, delParticipantHandler, startHandler, finishHandler, errorHandler, goToHandler, disconnectHandler)
|
||||
{
|
||||
if (!await this.client.isAuthenticated())
|
||||
return null;
|
||||
@ -124,10 +183,13 @@ class Tourmanent extends AExchangeable
|
||||
this.connected = true;
|
||||
this.isParticipating = false;
|
||||
|
||||
this.participantsUpdateHandler = participantsUpdateHandler;
|
||||
this.errorHandler = errorHandler;
|
||||
this.disconnectHandler = disconnectHandler;
|
||||
this.goToHandler = goToHandler;
|
||||
this._startHandler = startHandler;
|
||||
this._finishHandler = finishHandler;
|
||||
this._addParticipantHandler = addParticipantHandler;
|
||||
this._delParticipantHandler = delParticipantHandler;
|
||||
this._errorHandler = errorHandler;
|
||||
this._disconnectHandler = disconnectHandler;
|
||||
this._goToHandler = goToHandler;
|
||||
|
||||
this._socket.onmessage = this.onReceive.bind(this);
|
||||
|
||||
|
@ -167,4 +167,4 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
document.querySelector('a[href=\'' + location.pathname + '\']')?.classList.add('active');
|
||||
});
|
||||
|
||||
export { client, lang, navigateTo, reloadView };
|
||||
export { client, lang, lastView, navigateTo, reloadView };
|
||||
|
BIN
frontend/static/js/sound/tictactoe/play-move.mp3
Normal file
BIN
frontend/static/js/sound/tictactoe/play-move.mp3
Normal file
Binary file not shown.
@ -1,22 +1,15 @@
|
||||
export function createNotification(text, timer = 3000) {
|
||||
export function createNotification(title = 'New notification', content, delay = 3000) {
|
||||
|
||||
if (!createNotification.templateToast) {
|
||||
createNotification.templateToast = new DOMParser().parseFromString(`
|
||||
<div class='toast' role='alert' data-bs-delay='${timer}'>
|
||||
<div class='toast-header'>
|
||||
<strong class='me-auto'>Notification</strong>
|
||||
<button type='button' class='btn-close' data-bs-dismiss='toast'></button>
|
||||
</div>
|
||||
<div class='toast-body'>
|
||||
</div>
|
||||
</div>
|
||||
`, 'text/html')
|
||||
.querySelector('body')
|
||||
.firstChild;
|
||||
}
|
||||
|
||||
const toastElement = createNotification.templateToast.cloneNode(true);
|
||||
toastElement.getElementsByClassName('toast-body')[0].innerHTML = text;
|
||||
const toastElement = document.createElement('div');
|
||||
toastElement.classList.add('toast');
|
||||
toastElement.role = 'alert';
|
||||
toastElement.setAttribute('data-bs-delay', delay);
|
||||
toastElement.innerHTML =
|
||||
`<div class='toast-header'>
|
||||
<strong class='me-auto'>${title}</strong>
|
||||
<button type='button' class='btn-close' data-bs-dismiss='toast'></button>
|
||||
</div>
|
||||
<div class='toast-body'>${content}</div>`
|
||||
toastElement.addEventListener('hidden.bs.toast', e => e.target.remove());
|
||||
new bootstrap.Toast(toastElement).show();
|
||||
|
||||
|
@ -19,7 +19,7 @@ export default class extends AbstractAuthenticatedView {
|
||||
}
|
||||
else
|
||||
{
|
||||
await client.matchmaking.start(this.onreceive.bind(this), this.ondisconnect.bind(this), this.gamemode_input.value, this.nb_players_input.value);
|
||||
await client.matchmaking.start(this.onreceive.bind(this), this.ondisconnect.bind(this), this.game_type_input.value, this.nb_players_input.value);
|
||||
|
||||
this.button.innerHTML = lang.get("matchmakingStopSearch");
|
||||
}
|
||||
@ -34,10 +34,10 @@ export default class extends AbstractAuthenticatedView {
|
||||
{
|
||||
if (data.detail === "game_found")
|
||||
{
|
||||
if (this.gamemode_input.value == "pong")
|
||||
navigateTo(`/games/${data.gamemode}/${data.game_id}`);
|
||||
if (this.game_type_input.value == "pong")
|
||||
navigateTo(`/games/${data.game_type}/${data.game_id}`);
|
||||
else
|
||||
navigateTo(`/games/${data.gamemode}/${data.game_id}`);
|
||||
navigateTo(`/games/${data.game_type}/${data.game_id}`);
|
||||
return;
|
||||
}
|
||||
this.display_data(data);
|
||||
@ -51,7 +51,7 @@ export default class extends AbstractAuthenticatedView {
|
||||
|
||||
addEnterEvent()
|
||||
{
|
||||
[this.nb_players_input, this.gamemode_input].forEach((input) => {
|
||||
[this.nb_players_input, this.game_type_input].forEach((input) => {
|
||||
|
||||
input.addEventListener('keydown', async ev => {
|
||||
|
||||
@ -74,13 +74,13 @@ export default class extends AbstractAuthenticatedView {
|
||||
});
|
||||
}
|
||||
|
||||
addChangeGameModeEvent()
|
||||
addChangegame_typeEvent()
|
||||
{
|
||||
let nb_players_div = document.getElementById("nb-players-div");
|
||||
|
||||
this.gamemode_input.addEventListener("change", () => {
|
||||
this.game_type_input.addEventListener("change", () => {
|
||||
|
||||
if (this.gamemode_input.value === "tictactoe")
|
||||
if (this.game_type_input.value === "tictactoe")
|
||||
{
|
||||
nb_players_div.style.display = 'none';
|
||||
this.nb_players_input.value = 2;
|
||||
@ -96,7 +96,7 @@ export default class extends AbstractAuthenticatedView {
|
||||
addEvents()
|
||||
{
|
||||
this.addEnterEvent();
|
||||
this.addChangeGameModeEvent();
|
||||
this.addChangegame_typeEvent();
|
||||
this.addChangeNbPlayersEvent();
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ export default class extends AbstractAuthenticatedView {
|
||||
{
|
||||
this.button = document.getElementById("toggle-search");
|
||||
this.nb_players_input = document.getElementById("nb-players-input");
|
||||
this.gamemode_input = document.getElementById("gamemode-input");
|
||||
this.game_type_input = document.getElementById("game-type-input");
|
||||
|
||||
this.button.onclick = this.toggle_search.bind(this);
|
||||
|
||||
@ -117,12 +117,12 @@ export default class extends AbstractAuthenticatedView {
|
||||
<div class='border border-2 rounded bg-light-subtle mx-auto p-2 col-md-7 col-lg-4'>
|
||||
<h4 class='text-center fw-semibold mb-4' id="title">${lang.get("matchmakingTitle")}</h4>
|
||||
<div>
|
||||
<div class='form-floating mb-2' id='gamemode-div'>
|
||||
<select class='form-control' id='gamemode-input'>
|
||||
<div class='form-floating mb-2' id='game_type-div'>
|
||||
<select class='form-control' id='game-type-input'>
|
||||
<option value='pong'>Pong</option>
|
||||
<option value='tictactoe'>ticTacToe</option>
|
||||
</select>
|
||||
<label for='gamemode-input'>${lang.get("gamemodeChoice")}</label>
|
||||
<label for='game-type-input'>${lang.get("game_typeChoice")}</label>
|
||||
</div>
|
||||
<div class='form-floating mb-2' id='nb-players-div'>
|
||||
<input type='number' min='2' value='2' max='4' class='form-control' id='nb-players-input' placeholder='${lang.get("matchmakingNbPlayers")}'>
|
||||
|
@ -8,7 +8,7 @@ export default class extends AbstractView {
|
||||
}
|
||||
|
||||
setTitle() {
|
||||
document.title = `${this.username} - Profile`;
|
||||
document.title = this.titleKey;
|
||||
}
|
||||
|
||||
async postInit()
|
||||
@ -16,99 +16,48 @@ export default class extends AbstractView {
|
||||
if (!this.profile)
|
||||
return 404;
|
||||
|
||||
this.userId = this.profile.id;
|
||||
|
||||
await this.blockButton();
|
||||
await this.friendButton();
|
||||
|
||||
client.notice.rewrite_profile = async () => {
|
||||
await this.profile.getFriend();
|
||||
await this.profile.getBlock();
|
||||
await this.friendButton();
|
||||
};
|
||||
}
|
||||
|
||||
async blockButton() {
|
||||
// Block option
|
||||
if (await client.isAuthenticated() === false)
|
||||
if (this.profile.id === client.me.id)
|
||||
return;
|
||||
|
||||
if (client.me.id != this.userId) {
|
||||
let block = document.getElementById("block");
|
||||
if (block == undefined) {
|
||||
block = document.createElement("p");
|
||||
// this.info.appendChild(block);
|
||||
}
|
||||
const addFriendButton = document.getElementById('addFriendButton'),
|
||||
removeFriendButton = document.getElementById('removeFriendButton'),
|
||||
blockButton = document.getElementById('blockButton'),
|
||||
unblockButton = document.getElementById('unblockButton');
|
||||
|
||||
block.id = "block";
|
||||
block.onclick = async () => {
|
||||
if (!this.profile.isBlocked)
|
||||
await client.profiles.block(this.userId);
|
||||
else
|
||||
await client.profiles.deblock(this.userId);
|
||||
this.profile = await client.profiles.getProfile(this.username);
|
||||
this.loadFriendshipStatus();
|
||||
if (this.profile.isBlocked)
|
||||
unblockButton.classList.remove('d-none');
|
||||
else
|
||||
blockButton.classList.remove('d-none');
|
||||
|
||||
this.blockButton();
|
||||
};
|
||||
if (this.profile.isBlocked)
|
||||
block.textContent = lang.get('profileUnblock', 'Unblock');
|
||||
else
|
||||
block.textContent = lang.get('profileBlock', 'Block');
|
||||
}
|
||||
addFriendButton.onclick = _ => this.addFriend();
|
||||
removeFriendButton.onclick = _ => this.removeFriend();
|
||||
unblockButton.onclick = _ => this.unblockUser();
|
||||
blockButton.onclick = _ => this.blockUser();
|
||||
}
|
||||
|
||||
async friendButton() {
|
||||
if (await client.isAuthenticated() === false)
|
||||
return;
|
||||
loadFriendshipStatus() {
|
||||
const addFriendButton = document.getElementById('addFriendButton'),
|
||||
removeFriendButton = document.getElementById('removeFriendButton');
|
||||
|
||||
if (client.me.id != this.userId) {
|
||||
let yes = document.getElementById("yes") || document.createElement("p");
|
||||
let no = document.getElementById("no") || document.createElement("p");
|
||||
let friend = document.getElementById("friend") || document.createElement("p");
|
||||
|
||||
if (client.notice.data.asker.includes(this.userId)) {
|
||||
|
||||
if (friend)
|
||||
friend.remove();
|
||||
|
||||
yes.id = "yes";
|
||||
yes.textContent = lang.get('profileAcceptRequest', 'Accept Friend');
|
||||
yes.onclick = async () => {
|
||||
client.notice.accept_friend(this.userId);
|
||||
};
|
||||
|
||||
no.id = "no";
|
||||
no.textContent = lang.get('profileDenyRequest', 'Decline Friend');
|
||||
no.onclick = async () => {
|
||||
client.notice.refuse_friend(this.userId);
|
||||
};
|
||||
|
||||
// this.info.appendChild(yes);
|
||||
// this.info.appendChild(document.createTextNode(" "));
|
||||
// this.info.appendChild(no);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
if (yes && no)
|
||||
yes.remove(); no.remove();
|
||||
|
||||
friend.id = "friend";
|
||||
friend.onclick = async () => {
|
||||
if (this.profile.isFriend)
|
||||
await client.notice.remove_friend(this.userId);
|
||||
else
|
||||
await client.notice.ask_friend(this.userId);
|
||||
await client.profiles.getProfile(this.username);
|
||||
this.friendButton();
|
||||
};
|
||||
if (this.profile.isFriend)
|
||||
friend.textContent = lang.get('profileRemoveFriend', 'Remove Friend');
|
||||
else {
|
||||
friend.textContent = lang.get('profileAddFriend', 'Ask Friend');
|
||||
}
|
||||
// this.info.appendChild(friend);
|
||||
}
|
||||
if (this.profile.hasIncomingRequest) {
|
||||
removeFriendButton.classList.add('d-none');
|
||||
addFriendButton.classList.remove('d-none');
|
||||
addFriendButton.innerHTML = 'Accept Request';
|
||||
} else if (this.profile.hasOutgoingRequest) {
|
||||
addFriendButton.classList.add('d-none');
|
||||
removeFriendButton.classList.remove('d-none');
|
||||
removeFriendButton.classList.replace('btn-danger', 'btn-secondary');
|
||||
removeFriendButton.innerHTML = 'Cancel Request';
|
||||
} else if (this.profile.isFriend) {
|
||||
addFriendButton.classList.add('d-none');
|
||||
removeFriendButton.classList.remove('d-none');
|
||||
removeFriendButton.classList.replace('btn-secondary', 'btn-danger');
|
||||
removeFriendButton.innerHTML = 'Remove Friend';
|
||||
} else {
|
||||
addFriendButton.innerHTML = 'Add Friend';
|
||||
removeFriendButton.classList.add('d-none');
|
||||
addFriendButton.classList.remove('d-none');
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,19 +67,94 @@ export default class extends AbstractView {
|
||||
if (!this.profile)
|
||||
return '';
|
||||
|
||||
const logged = await client.isAuthenticated();
|
||||
|
||||
return `
|
||||
<div class='mb-3' id='profileInfo'>
|
||||
<h1>${this.username}</h1>
|
||||
<a href=${this.profile.avatar} target='_blank'>
|
||||
<img class='img-thumbnail' src=${this.profile.avatar} style='width:auto; max-height:20vh; min-height:10vh'>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<button class='btn btn-sm btn-success ${logged ? '' : 'd-none'}' id='addFriendButton'>Add Friend</button>
|
||||
<button class='btn btn-sm btn-danger ${logged ? '' : 'd-none'}' id='removeFriendButton'>Remove Friend</button>
|
||||
</div>
|
||||
`;
|
||||
<div>
|
||||
<div class='mb-3' id='profileInfo'>
|
||||
<h1>${this.username}</h1>
|
||||
<a href=${this.profile.avatar} target='_blank'>
|
||||
<img class='img-thumbnail' src=${this.profile.avatar} style='width:auto; max-height:20vh; min-height:10vh'>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<button class='btn btn-sm btn-success d-none' id='addFriendButton'>Add Friend</button>
|
||||
<button class='btn btn-sm btn-danger d-none' id='removeFriendButton'>Remove Friend</button>
|
||||
<button class='btn btn-sm btn-danger d-none' id='blockButton'>Block</button>
|
||||
<button class='btn btn-sm btn-secondary d-none' id='unblockButton'>Unblock</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
async addFriend() {
|
||||
const removeFriendButton = document.getElementById('removeFriendButton');
|
||||
|
||||
const response = await client._post(`/api/profiles/friends/${this.profile.id}`);
|
||||
const body = await response.json();
|
||||
console.log(body);
|
||||
|
||||
if (response.ok) {
|
||||
removeFriendButton.classList.remove('d-none');
|
||||
document.getElementById('addFriendButton').classList.add('d-none');
|
||||
}
|
||||
if (response.status === 200) {
|
||||
removeFriendButton.innerHTML = 'Cancel Request';
|
||||
removeFriendButton.classList.replace('btn-danger', 'btn-secondary');
|
||||
client.me.outgoingFriendRequests.push(this.profile);
|
||||
this.profile.hasOutgoingRequest = true;
|
||||
} else if (response.status === 201) {
|
||||
removeFriendButton.innerHTML = 'Remove Friend';
|
||||
removeFriendButton.classList.replace('btn-secondary', 'btn-danger');
|
||||
this.profile.friend = true;
|
||||
this.profile.hasIncomingRequest = false;
|
||||
client.me.incomingFriendRequests = client.me.incomingFriendRequests.filter(profile => profile.id !== this.profile.id);
|
||||
client.me.friendList.push(this.profile);
|
||||
}
|
||||
}
|
||||
|
||||
async removeFriend() {
|
||||
const addFriendButton = document.getElementById('addFriendButton');
|
||||
|
||||
const response = await client._delete(`/api/profiles/friends/${this.profile.id}`);
|
||||
const body = await response.json();
|
||||
console.log(body);
|
||||
|
||||
if (response.ok) {
|
||||
addFriendButton.innerHTML = 'Add Friend';
|
||||
addFriendButton.classList.remove('d-none');
|
||||
document.getElementById('removeFriendButton').classList.add('d-none');
|
||||
}
|
||||
if (response.status === 200) {
|
||||
this.profile.hasOutgoingRequest = false;
|
||||
client.me.outgoingFriendRequests = client.me.outgoingFriendRequests.filter(profile => profile.id !== this.profile.id);
|
||||
} else if (response.status === 201) {
|
||||
this.profile.isFriend = false;
|
||||
client.me.friendList = client.me.friendList.filter(friend => friend.id !== this.profile.id);
|
||||
}
|
||||
}
|
||||
|
||||
async blockUser() {
|
||||
const response = await client._post(`/api/profiles/block/${this.profile.id}`);
|
||||
const body = await response.json();
|
||||
console.log(body);
|
||||
|
||||
if (response.ok) {
|
||||
document.getElementById('blockButton').classList.add('d-none');
|
||||
document.getElementById('unblockButton').classList.remove('d-none');
|
||||
client.me.blockedUsers.push(this.profile);
|
||||
this.profile.isBlocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
async unblockUser() {
|
||||
const response = await client._delete(`/api/profiles/block/${this.profile.id}`);
|
||||
const body = await response.json();
|
||||
console.log(body);
|
||||
|
||||
if (response.ok) {
|
||||
document.getElementById('unblockButton').classList.add('d-none');
|
||||
document.getElementById('blockButton').classList.remove('d-none');
|
||||
client.me.blockedUsers = client.me.blockedUsers.filter(profile => profile.id !== this.profile.id);
|
||||
this.profile.isBlocked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ export class TicTacToeOnlineView extends AbstractView
|
||||
this.Morpion = new TicTacToe(this.height, this.width, 60, 60, document.getElementById("Morpion"), this.game_id);
|
||||
this.Morpion.DrawSuperMorpion();
|
||||
await this.Morpion.init();
|
||||
this.Morpion.setOutline();
|
||||
}
|
||||
|
||||
async leavePage()
|
||||
|
@ -10,7 +10,6 @@ export default class extends AbstractAuthenticatedView
|
||||
|
||||
async postInit() {
|
||||
await client.logout();
|
||||
await client.notice.disconnect();
|
||||
navigateTo(this.lastPageUrl);
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,9 @@ export default class extends AbstractAuthenticatedView
|
||||
if (name.length == 0)
|
||||
name = lang.get("TournamentCreateTournamentName");
|
||||
|
||||
console.log(name);
|
||||
let nb_players = document.getElementById("nb-players-input").value;
|
||||
let nb_participant = document.getElementById("nb-participant-input").value;
|
||||
|
||||
let response = await client.tournaments.createTournament(nb_players, name);
|
||||
let response = await client.tournaments.createTournament(nb_participant, name);
|
||||
let response_data = await response.json();
|
||||
|
||||
let id = response_data.id;
|
||||
@ -29,7 +28,7 @@ export default class extends AbstractAuthenticatedView
|
||||
return;
|
||||
}
|
||||
|
||||
clearIds("innerHTML", ["name", "nb_players"]);
|
||||
clearIds("innerHTML", ["name", "nb_participants"]);
|
||||
fill_errors(response_data, "innerHTML");
|
||||
}
|
||||
|
||||
@ -50,9 +49,16 @@ export default class extends AbstractAuthenticatedView
|
||||
<span class='text-danger' id='name'></span>
|
||||
</div>
|
||||
<div class='form-floating mb-2'>
|
||||
<input type='number' class='form-control' min='2' value='4' id='nb-players-input' placeholder='${lang.get("TournamentCreateNbPlayer")}'>
|
||||
<label for='nb-players-input' id='nb-players-label'>${lang.get("TournamentCreateNbPlayer")}</label>
|
||||
<span class='text-danger' id='nb_players'></span>
|
||||
<select class='form-control' id="nb-participant-input">
|
||||
<option value="2">2</option>
|
||||
<option value="4">4</option>
|
||||
<option value="8">8</option>
|
||||
<option value="16">16</option>
|
||||
<option value="32">32</option>
|
||||
<option value="64">64</option>
|
||||
</select>
|
||||
<label for='nb-participant-input' id='nb-participant-label'>${lang.get("TournamentCreateNbPlayer")}</label>
|
||||
<span class='text-danger' id='nb_participants'></span>
|
||||
</div>
|
||||
<div class='d-flex'>
|
||||
<button type='button' class='btn btn-primary mt-3 mb-2 mx-2' id='create-button'>${lang.get("TournamentCreateButton")}</button>
|
||||
|
@ -3,6 +3,10 @@ import { Tourmanent } from "../../api/tournament/Tournament.js";
|
||||
import {client, navigateTo} from "../../index.js";
|
||||
import AbstractAuthenticatedView from "../abstracts/AbstractAuthenticatedView.js";
|
||||
|
||||
const TEXT_CONVENTION = {
|
||||
"error": "[ERROR]"
|
||||
}
|
||||
|
||||
export default class extends AbstractAuthenticatedView
|
||||
{
|
||||
constructor(params)
|
||||
@ -13,44 +17,49 @@ export default class extends AbstractAuthenticatedView
|
||||
|
||||
pressButton()
|
||||
{
|
||||
this.tournament.toggle_participation();
|
||||
this.tournament.setParticipation(!this.tournament.isParticipating);
|
||||
this.updateParticipating()
|
||||
}
|
||||
|
||||
async receive(data)
|
||||
updateParticipating()
|
||||
{
|
||||
if (data.detail === "update_participants")
|
||||
document.getElementById("nb_participants").innerText = `${data.participants} / ${this.tournament.nb_participants}`;
|
||||
if (data.detail === "go_to")
|
||||
navigateTo(data.url);
|
||||
if (data.detail === "is_participant")
|
||||
this.updateParticipating(data.is_participant);
|
||||
if (data.detail === "error")
|
||||
document.getElementById("display").innerText = data.error_message;
|
||||
}
|
||||
|
||||
async updateParticipating(state)
|
||||
{
|
||||
document.getElementById("button").value = state ? `Leave ${this.tournament.name}` : `Join ${this.tournament.name}`;
|
||||
document.getElementById("display").innerText = state ? "You are a particpant" : "You are not a participant";
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {[Profile]} oldParticipantsList
|
||||
* @param {[Profile]} currentParticipantsList
|
||||
*/
|
||||
async onParticipantsUpdate(oldParticipantsList, currentParticipantsList)
|
||||
{
|
||||
|
||||
document.getElementById("button").value = this.tournament.isParticipating ? `Leave ${this.tournament.name}` : `Join ${this.tournament.name}`;
|
||||
document.getElementById("display").innerText = this.tournament.isParticipating ? "You are a particpant" : "You are not a participant";
|
||||
}
|
||||
|
||||
async onDisconnect(event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
async onError(data)
|
||||
{
|
||||
this.addChatMessage(`${TEXT_CONVENTION} data.error_message`);
|
||||
}
|
||||
|
||||
async onFinish()
|
||||
{
|
||||
document.getElementById("state").innerText = "finished"
|
||||
}
|
||||
|
||||
async onStart()
|
||||
{
|
||||
document.getElementById("state").innerText = "started"
|
||||
}
|
||||
|
||||
async onGoTo(data)
|
||||
{
|
||||
await navigateTo(`/games/pong/${data.game_id}`)
|
||||
}
|
||||
|
||||
async onAddParticipant(nb_participants)
|
||||
{
|
||||
document.getElementById("nb_participants").innerText = nb_participants;
|
||||
}
|
||||
|
||||
async onDelParticipant(nb_participants)
|
||||
{
|
||||
document.getElementById("nb_participants").innerText = nb_participants;
|
||||
}
|
||||
|
||||
async postInit()
|
||||
@ -63,25 +72,32 @@ export default class extends AbstractAuthenticatedView
|
||||
if (this.tournament === null)
|
||||
return 404;
|
||||
|
||||
this.tournament.join(this.onParticipantsUpdate.bind(this), this.onError.bind(this), this.onDisconnect.bind(this));
|
||||
this.tournament.join(this.onAddParticipant, this.onDelParticipant, this.onStart, this.onFinish, this.onError, this.onGoTo, this.onDisconnect);
|
||||
|
||||
let button = document.getElementById("button");
|
||||
|
||||
button.onclick = this.pressButton.bind(this);
|
||||
|
||||
document.getElementById("name").innerText = this.tournament.name;
|
||||
document.getElementById("nb_participants").innerText = this.tournament.nb_participants;
|
||||
document.getElementById("nb_participants").innerText = this.tournament.participantList.length;
|
||||
document.getElementById("expected_nb_participants").innerText = this.tournament.nb_participants;
|
||||
document.getElementById("round").innerText = this.tournament.round;
|
||||
document.getElementById("state").innerText = this.tournament.state;
|
||||
|
||||
if (this.tournament.started === false)
|
||||
button.disabled = false;
|
||||
|
||||
console.log(this.tournament);
|
||||
this.chat = document.getElementById("chat");
|
||||
|
||||
console.log(this.tournament);
|
||||
this.display_tree_tournament(this.tournament.nb_participants, this.tournament.participantList);
|
||||
}
|
||||
|
||||
addChatMessage(message)
|
||||
{
|
||||
this.chat.innerText += message;
|
||||
}
|
||||
|
||||
async display_tree_tournament(nb_participants, participants) {
|
||||
const svg = document.getElementById('tree');
|
||||
|
||||
@ -137,15 +153,25 @@ export default class extends AbstractAuthenticatedView
|
||||
<td id="nb_participants">Loading...</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>status</td>
|
||||
<td>Expected number of participants</td>
|
||||
<td id="expected_nb_participants">Loading...</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>state</td>
|
||||
<td id="state">Loading...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<input type="button" id="button" value="Join tournament" disabled>
|
||||
<<<<<<< HEAD
|
||||
<br>
|
||||
<svg id="tree" height="3000" width="3000">
|
||||
</svg>
|
||||
=======
|
||||
<span id="display"></span>
|
||||
<textarea id="chat" rows="4" cols="50" readonly>
|
||||
</textarea>
|
||||
>>>>>>> 55d29d5763f22f136d2b4bae6464463acb514a5c
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user