update: friends list + button
This commit is contained in:
parent
590604b385
commit
c5eea6e29e
8 changed files with 156 additions and 76 deletions
|
|
@ -37,6 +37,7 @@
|
|||
<a href="/ttt" class="hover:bg-gray-700 rounded-md px-3 py-2">⭕ Tic-Tac-Toe</a>
|
||||
<a href="/pong" class="hover:bg-gray-700 rounded-md px-3 py-2">▮•▮ Ping Pong</a>
|
||||
<a href="/tour" class="hover:bg-gray-700 rounded-md px-3 py-2">🏆 Tournaments</a>
|
||||
<a href="/friends" class="hover:bg-gray-700 rounded-md px-3 py-2">😎 Friends</a>
|
||||
<a href="/logout" class="hover:bg-gray-700 rounded-md px-3 py-2">🚪 Logout</a>
|
||||
</nav>
|
||||
</aside>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { showError } from "@app/toast";
|
||||
import client from "@app/api";
|
||||
import cookie from "js-cookie";
|
||||
import { ensureWindowState, isNullish } from "@app/utils";
|
||||
import { ensureWindowState, isNullish, updateFriendsList } from "@app/utils";
|
||||
import { handleRoute, navigateTo } from "./routing";
|
||||
|
||||
cookie.remove("pkce");
|
||||
|
|
@ -105,10 +105,11 @@ if (!window.__state._headerProfile) {
|
|||
|
||||
window.__state._reloadOnAuthChange ??= false;
|
||||
if (!window.__state._reloadOnAuthChange) {
|
||||
document.addEventListener("ft:userChange", () => {
|
||||
document.addEventListener("ft:userChange", async () => {
|
||||
// if the last forced auth change is less than 1000 sec old -> we do nothing
|
||||
if (Date.now() - (window.__state.lastAuthChange ?? Date.now()) < 1000)
|
||||
return;
|
||||
await updateFriendsList();
|
||||
handleRoute();
|
||||
});
|
||||
window.__state._reloadOnAuthChange = true;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ let keysPressed: Record<string, boolean> = {};
|
|||
declare module "ft_state" {
|
||||
interface State {
|
||||
chatSock?: Socket;
|
||||
friendList: { id: string; name: string }[];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,18 +83,20 @@ const sendButton = document.getElementById("b-send") as HTMLButtonElement;
|
|||
const sendtextbox = document.getElementById(
|
||||
"t-chat-window",
|
||||
) as HTMLButtonElement;
|
||||
const systemWindow = document.getElementById("chat-system-box") as HTMLDivElement;
|
||||
const systemWindow = document.getElementById(
|
||||
"chat-system-box",
|
||||
) as HTMLDivElement;
|
||||
|
||||
function chatKeyToggle() {
|
||||
let anti_flicker_control = false;
|
||||
const chat_hide_key = 'escape';
|
||||
const chat_display_key = 'f2';
|
||||
const home_display_key = 'f8';
|
||||
const chat_hide_key = "escape";
|
||||
const chat_display_key = "f2";
|
||||
const home_display_key = "f8";
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.repeat && keysPressed[chat_hide_key] === true) {
|
||||
anti_flicker_control = true;
|
||||
return ;
|
||||
};
|
||||
return;
|
||||
}
|
||||
keysPressed[event.key.toLowerCase()] = true;
|
||||
});
|
||||
document.addEventListener("keyup", (event) => {
|
||||
|
|
@ -102,34 +105,33 @@ function chatKeyToggle() {
|
|||
anti_flicker_control = false;
|
||||
}
|
||||
});
|
||||
setInterval( () => {
|
||||
if(keysPressed[chat_hide_key] === true) {
|
||||
overlay.classList.remove("opacity-60");
|
||||
chatBox.classList.add("hidden");
|
||||
chatMessageIn?.classList.add("hidden");
|
||||
chatMessageIn!.textContent = '';
|
||||
profilList?.classList.add("hidden");
|
||||
windowStateHidden();
|
||||
setInterval(() => {
|
||||
if (keysPressed[chat_hide_key] === true) {
|
||||
overlay.classList.remove("opacity-60");
|
||||
chatBox.classList.add("hidden");
|
||||
chatMessageIn?.classList.add("hidden");
|
||||
chatMessageIn!.textContent = "";
|
||||
profilList?.classList.add("hidden");
|
||||
windowStateHidden();
|
||||
}
|
||||
if (keysPressed[chat_display_key] === true) {
|
||||
anti_flicker_control = false;
|
||||
chatBox.classList.remove("hidden");
|
||||
overlay.classList.add("opacity-60");
|
||||
chatMessageIn?.classList.add("hidden");
|
||||
chatMessageIn!.textContent = '';
|
||||
let socket = window.__state.chatSock;
|
||||
if (!socket) return;
|
||||
connected(socket);
|
||||
sendtextbox.focus();
|
||||
windowStateVisable();
|
||||
|
||||
anti_flicker_control = false;
|
||||
chatBox.classList.remove("hidden");
|
||||
overlay.classList.add("opacity-60");
|
||||
chatMessageIn?.classList.add("hidden");
|
||||
chatMessageIn!.textContent = "";
|
||||
let socket = window.__state.chatSock;
|
||||
if (!socket) return;
|
||||
connected(socket);
|
||||
sendtextbox.focus();
|
||||
windowStateVisable();
|
||||
}
|
||||
if (keysPressed[home_display_key] === true) {
|
||||
navigateTo('/app/');
|
||||
if (keysPressed[home_display_key] === true) {
|
||||
navigateTo("/app/");
|
||||
quitChat();
|
||||
}
|
||||
}, 1000/10);
|
||||
};
|
||||
}, 1000 / 10);
|
||||
}
|
||||
|
||||
function initChatSocket() {
|
||||
let socket = getSocket();
|
||||
|
|
@ -153,7 +155,8 @@ function initChatSocket() {
|
|||
!sendButton ||
|
||||
!sendtextbox ||
|
||||
!systemWindow
|
||||
) return showError("fatal error");
|
||||
)
|
||||
return showError("fatal error");
|
||||
|
||||
// Listen for the 'connect' event
|
||||
socket.on("connect", async () => {
|
||||
|
|
@ -205,7 +208,7 @@ function initChatSocket() {
|
|||
|
||||
if (chatWindow && data.message.destination === "") {
|
||||
chatMessageIn?.classList.remove("hidden");
|
||||
chatMessageIn!.textContent = '🔵';
|
||||
chatMessageIn!.textContent = "🔵";
|
||||
const messageElement = document.createElement("div");
|
||||
messageElement.textContent = `${data.message.user}: ${data.message.text}`;
|
||||
chatWindow.appendChild(messageElement);
|
||||
|
|
@ -214,7 +217,7 @@ function initChatSocket() {
|
|||
|
||||
if (chatWindow && data.message.destination === "privateMsg") {
|
||||
chatMessageIn?.classList.remove("hidden");
|
||||
chatMessageIn!.textContent = '🔴';
|
||||
chatMessageIn!.textContent = "🔴";
|
||||
const messageElement = document.createElement("div-private");
|
||||
messageElement.textContent = `🔒${data.message.user}: ${data.message.text}`;
|
||||
chatWindow.appendChild(messageElement);
|
||||
|
|
@ -223,7 +226,7 @@ function initChatSocket() {
|
|||
|
||||
if (chatWindow && data.message.destination === "inviteMsg") {
|
||||
chatMessageIn?.classList.remove("hidden");
|
||||
chatMessageIn!.textContent = '🟢';
|
||||
chatMessageIn!.textContent = "🟢";
|
||||
const messageElement = document.createElement("div-private");
|
||||
const chatWindow = document.getElementById(
|
||||
"t-chatbox",
|
||||
|
|
@ -243,7 +246,6 @@ function initChatSocket() {
|
|||
}
|
||||
systemWindow.appendChild(messageElement);
|
||||
systemWindow.lastElementChild?.scrollIntoView({ block: "end" });
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -278,9 +280,9 @@ function initChatSocket() {
|
|||
if (blockUserBtn) {
|
||||
let message = "";
|
||||
if (data.userState === "block") {
|
||||
(message = "un-block");
|
||||
message = "un-block";
|
||||
} else {
|
||||
(message = "block");
|
||||
message = "block";
|
||||
}
|
||||
blockUserBtn.textContent = message;
|
||||
}
|
||||
|
|
@ -294,10 +296,8 @@ function initChatSocket() {
|
|||
const htmlBaliseRegex = /<a\b[^>]*>[\s\S]*?<\/a>/;
|
||||
const htmlBaliseMatch = message.match(htmlBaliseRegex);
|
||||
|
||||
if (htmlBaliseMatch)
|
||||
addInviteMessage(message);
|
||||
else
|
||||
addMessage(message);
|
||||
if (htmlBaliseMatch) addInviteMessage(message);
|
||||
else addMessage(message);
|
||||
});
|
||||
|
||||
//receives broadcast of the next GAME
|
||||
|
|
@ -505,7 +505,6 @@ clearText?.addEventListener("click", () => {
|
|||
|
||||
bquit?.addEventListener("click", () => {
|
||||
quitChat();
|
||||
|
||||
});
|
||||
|
||||
myGames?.addEventListener("click", () => {
|
||||
|
|
@ -527,7 +526,7 @@ sendtextbox.addEventListener("keydown", (event) => {
|
|||
}
|
||||
});
|
||||
|
||||
chatButton!.addEventListener("click",() => {
|
||||
chatButton!.addEventListener("click", () => {
|
||||
if (chatBox.classList.contains("hidden")) {
|
||||
chatBox.classList.toggle("hidden");
|
||||
overlay.classList.add("opacity-60");
|
||||
|
|
@ -536,14 +535,14 @@ chatButton!.addEventListener("click",() => {
|
|||
if (!socket) return;
|
||||
connected(socket);
|
||||
chatMessageIn?.classList.add("hidden");
|
||||
chatMessageIn!.textContent = '';
|
||||
chatMessageIn!.textContent = "";
|
||||
sendtextbox.focus();
|
||||
} else {
|
||||
chatBox.classList.toggle("hidden");
|
||||
overlay.classList.remove("opacity-60");
|
||||
windowStateHidden();
|
||||
chatMessageIn?.classList.add("hidden");
|
||||
chatMessageIn!.textContent = '';
|
||||
chatMessageIn!.textContent = "";
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import client from "@app/api";
|
||||
import type { ClientProfil } from "../types_front";
|
||||
import { Socket } from "socket.io-client";
|
||||
import { showError, showSuccess } from "@app/toast";
|
||||
import { getFriendList, updateFriendsList } from "@app/utils";
|
||||
|
||||
/**
|
||||
* function listens for a click on the TTT game History button
|
||||
|
|
@ -8,20 +11,25 @@ import { Socket } from "socket.io-client";
|
|||
**/
|
||||
|
||||
export function actionBtnFriend(profile: ClientProfil, senderSocket: Socket) {
|
||||
setTimeout(() => {
|
||||
const friend = document.querySelector("#btn-friend");
|
||||
friend?.addEventListener("click", () => {
|
||||
|
||||
if (friend.textContent = "friend") {
|
||||
friend.textContent = "not-friend"
|
||||
console.log('friend');
|
||||
}
|
||||
else {
|
||||
friend.textContent = "not-friend"
|
||||
console.log('Not a friend');
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}, 0)
|
||||
setTimeout(() => {
|
||||
const friend = document.querySelector("#btn-friend");
|
||||
friend?.addEventListener("click", async () => {
|
||||
let friendList = getFriendList();
|
||||
if (!friendList.some(v => v.id === profile.userID!)) {
|
||||
let req = await client.addFriend({ user: profile.userID! });
|
||||
if (req.kind === 'success')
|
||||
showSuccess('Successfully added a new Friend')
|
||||
else
|
||||
showError('Failed to add a new Friend');
|
||||
}
|
||||
else {
|
||||
let req = await client.removeFriend({ user: profile.userID! });
|
||||
if (req.kind === 'success')
|
||||
showSuccess('Successfully removed a Friend')
|
||||
else
|
||||
showError('Failed to remove a Friend');
|
||||
}
|
||||
await updateFriendsList();
|
||||
});
|
||||
}, 0)
|
||||
};
|
||||
9
frontend/src/pages/friendList/friendList.html
Normal file
9
frontend/src/pages/friendList/friendList.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<div class="fixed inset-0 flex items-center justify-center bg-[#43536b]">
|
||||
<div
|
||||
class="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-gray-200 w-212.5 p-6 rounded-xl shadow-2xl text-center z-50">
|
||||
<h2 class="text-2xl font-bold text-center mb-4 text-gray-700">
|
||||
FriendList
|
||||
</h2>
|
||||
<div id="friendList" class="max-w-3xl mx-auto space-y-2 max-h-[50dvh] overflow-scroll"></div>
|
||||
</div>
|
||||
</div>
|
||||
41
frontend/src/pages/friendList/friendList.ts
Normal file
41
frontend/src/pages/friendList/friendList.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { addRoute, navigateTo, setTitle, type RouteHandlerParams, type RouteHandlerReturn } from "@app/routing";
|
||||
import page from './friendList.html?raw';
|
||||
import { getFriendList, isNullish, updateFriendsList } from "@app/utils";
|
||||
import client from "@app/api";
|
||||
import { updateUser } from "@app/auth";
|
||||
import { showError } from "@app/toast";
|
||||
|
||||
|
||||
async function friends(_url: string, args: RouteHandlerParams): Promise<RouteHandlerReturn> {
|
||||
setTitle("Tic Tac Toe Games");
|
||||
let user = await updateUser();
|
||||
if (isNullish(user)) {
|
||||
return { html: '<span> You aren\'t logged in </span>', postInsert: () => { showError("You must be logged in !"); navigateTo("/") } };
|
||||
}
|
||||
await updateFriendsList();
|
||||
let friendList = getFriendList();
|
||||
friendList.sort();
|
||||
|
||||
let friendsElem = friendList.map(g => {
|
||||
let e = document.createElement('div');
|
||||
e.className = 'grid grid-cols-[1fr_auto_1fr] items-center bg-zinc-800 rounded-lg px-4 py-3';
|
||||
|
||||
e.innerHTML = `
|
||||
<div class="text-center font-semibold text-white">${g.name}</div>
|
||||
<a href="/ttt/games/${g.id}" class="text-center">TTT Games</a>
|
||||
<a href="/pong/games/${g.id}" class="text-center">Pong Games</a>
|
||||
`;
|
||||
return e;
|
||||
}).filter(v => !isNullish(v));
|
||||
|
||||
return {
|
||||
html: page, postInsert: async (app) => {
|
||||
if (!app) return;
|
||||
const friendsBox = app.querySelector<HTMLDivElement>("#friendList");
|
||||
if (!friendsBox) return;
|
||||
friendsElem.forEach(c => friendsBox.appendChild(c));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
addRoute('/friends', friends);
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import { setTitle, handleRoute } from '@app/routing';
|
||||
import './root/root.ts'
|
||||
import '../chat/chat.ts'
|
||||
import './pong/pong.ts'
|
||||
import './login/login.ts'
|
||||
import './signin/signin.ts'
|
||||
|
|
@ -10,6 +9,7 @@ import './logout/logout.ts'
|
|||
import './pongHistory/pongHistory.ts'
|
||||
import './tttHistory/tttHistory.ts'
|
||||
import './tourHistory/tourHistory.ts'
|
||||
import './friendList/friendList.ts'
|
||||
|
||||
// ---- Initial load ----
|
||||
setTitle("");
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import client from "./api";
|
||||
|
||||
export function escapeHTML(str: string): string {
|
||||
const p = document.createElement("p");
|
||||
p.appendChild(document.createTextNode(str));
|
||||
return p.innerHTML;
|
||||
}
|
||||
export function isNullish<T>(v: T | undefined | null): v is (null | undefined) {
|
||||
export function isNullish<T>(v: T | undefined | null): v is null | undefined {
|
||||
return v === null || v === undefined;
|
||||
}
|
||||
|
||||
|
|
@ -11,3 +13,22 @@ export function isNullish<T>(v: T | undefined | null): v is (null | undefined) {
|
|||
export function ensureWindowState() {
|
||||
window.__state = window.__state ?? {};
|
||||
}
|
||||
|
||||
export async function updateFriendsList() {
|
||||
window.__state = window.__state ?? {};
|
||||
window.__state.friendList ??= [];
|
||||
|
||||
try {
|
||||
let req = await client.listFriend();
|
||||
if (req.kind === "success") {
|
||||
window.__state.friendList = req.payload.friends;
|
||||
}
|
||||
} catch (e: unknown) { }
|
||||
}
|
||||
|
||||
export function getFriendList() {
|
||||
ensureWindowState();
|
||||
window.__state.friendList ??= [];
|
||||
|
||||
return window.__state.friendList;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue