From 012caef5060ee876e5dfd6d4defd1795fce30d8f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lucien=20Asti=C3=A9?= <lucien@MacBook-Air-de-Lucien.local>
Date: Fri, 9 Aug 2024 14:38:16 +0200
Subject: [PATCH] Add avatar image + generateur de pseudo

---
 app/[id]/page.tsx       | 36 +++++++++-------
 app/avatarImage.ts      |  1 +
 app/page.tsx            | 94 ++++++++++++++++++++++++++++++++++++++---
 app/usernameGenerate.ts | 25 +++++++++++
 package-lock.json       | 11 +++++
 package.json            |  1 +
 server.mjs              | 21 ++++-----
 7 files changed, 159 insertions(+), 30 deletions(-)
 create mode 100644 app/avatarImage.ts
 create mode 100644 app/usernameGenerate.ts

diff --git a/app/[id]/page.tsx b/app/[id]/page.tsx
index dca3fa4..7c88966 100644
--- a/app/[id]/page.tsx
+++ b/app/[id]/page.tsx
@@ -4,6 +4,7 @@ import { io } from "socket.io-client"
 import { getRandomQuestion } from "./questions"
 import { useForceUpdate } from "./forceUpdate"
 import { IconCrown } from "@tabler/icons-react"
+import { defaultAvatarImage } from '../avatarImage'
 
 interface roomProps {
   params: {
@@ -17,6 +18,7 @@ export default function Home({ params }: roomProps) {
 
   const [role, setRole] = useState("")
   const [name, setName] = useState("")
+  const [avatar, setAvatar] = useState(defaultAvatarImage)
 
   const [gameStarted, setGameStarted] = useState(false)
   const [gameEnded, setGameEnded] = useState(false)
@@ -37,14 +39,16 @@ export default function Home({ params }: roomProps) {
   const roomNameDisplay = id.substring(0,3) + " " + id.substring(3,6)
 
   useEffect(() => {
-        const username = localStorage.getItem('name')
-        setName(username)
+        const localName = localStorage.getItem('name')
+        setName(localName)
+        const localAvatar = localStorage.getItem('avatar')
+        setAvatar(localAvatar)
         // Listen for incoming setMessages
         socketRef.current = io("ws://localhost:3000");
 
         socketRef.current.on("connect", () => {
           setIsConnected(true)
-          socketRef.current.emit('room_connect', {"id": id, "name": username})
+          socketRef.current.emit('room_connect', {id: id, name: localName, avatar: localAvatar})
         });
 
         socketRef.current.on("new_player", (params) => {
@@ -195,19 +199,21 @@ export default function Home({ params }: roomProps) {
             }
             { (isConnected && players.length > 0) &&
               <div className="flex flex-col space-y-16">
-                <div>
+                <div className="grid grid-cols-3 gap-4">
                   { players.map((player) => {
-                    console.log(player)
-                    if(player.role == "player") {
-                      return (
-                        <p>{player.name}</p>
-                      )
-                    }
-                    if(player.role == "owner") {
-                      return (
-                        <p className="flex flex-row">{player.name}<IconCrown /></p>
-                      )
-                    }
+                    return (
+                      <>
+                        <div className="flex flex-col items-center">
+                          <div className="avatar indicator">
+                            {player.role == "owner" && <IconCrown className="indicator-item" />}
+                            <div className="w-16 rounded">
+                              <img src={player.avatar} />
+                            </div>
+                          </div>
+                          <p className="flex flex-row">{player.name}</p>
+                        </div>
+                      </>
+                    )
                   })}
                 </div>
                 { role == "owner" && 
diff --git a/app/avatarImage.ts b/app/avatarImage.ts
new file mode 100644
index 0000000..9a72002
--- /dev/null
+++ b/app/avatarImage.ts
@@ -0,0 +1 @@
+export const defaultAvatarImage = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEBLAEsAAD/4QBWRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAAITAAMAAAABAAEAAAAAAAAAAAEsAAAAAQAAASwAAAAB/+0ALFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAPHAFaAAMbJUccAQAAAgAEAP/hDW5odHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvADw/eHBhY2tldCBiZWdpbj0n77u/JyBpZD0nVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkJz8+Cjx4OnhtcG1ldGEgeG1sbnM6eD0nYWRvYmU6bnM6bWV0YS8nIHg6eG1wdGs9J0ltYWdlOjpFeGlmVG9vbCAxMS44OCc+CjxyZGY6UkRGIHhtbG5zOnJkZj0naHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyc+CgogPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9JycKICB4bWxuczp0aWZmPSdodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyc+CiAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICA8dGlmZjpYUmVzb2x1dGlvbj4zMDAvMTwvdGlmZjpYUmVzb2x1dGlvbj4KICA8dGlmZjpZUmVzb2x1dGlvbj4zMDAvMTwvdGlmZjpZUmVzb2x1dGlvbj4KIDwvcmRmOkRlc2NyaXB0aW9uPgoKIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PScnCiAgeG1sbnM6eG1wPSdodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvJz4KICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFN0b2NrIFBsYXRmb3JtPC94bXA6Q3JlYXRvclRvb2w+CiA8L3JkZjpEZXNjcmlwdGlvbj4KCiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0nJwogIHhtbG5zOnhtcE1NPSdodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vJz4KICA8eG1wTU06RG9jdW1lbnRJRD54bXAuaWlkOmFhNGI1ZWU1LTAxMDUtNDZmNS1hN2Y4LTBmYWEwMWY2NDczODwveG1wTU06RG9jdW1lbnRJRD4KICA8eG1wTU06SW5zdGFuY2VJRD5hZG9iZTpkb2NpZDpzdG9jazo4ZGM0ODU1Ni05ZmRkLTRiNGMtYThmOC1jYTlkNTVjODQ2YTE8L3htcE1NOkluc3RhbmNlSUQ+CiAgPHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD5hZG9iZTpkb2NpZDpzdG9jazo1NDk5ODM5NzA8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KIDwvcmRmOkRlc2NyaXB0aW9uPgo8L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSd3Jz8+/9sAQwAF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"
diff --git a/app/page.tsx b/app/page.tsx
index 5672327..b3634c3 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -2,10 +2,16 @@
 
 import { navigate } from './action'
 import { useState, useEffect, useRef } from 'react'
-import { IconPencilMinus } from "@tabler/icons-react"
+import { IconPencilMinus, IconCamera, IconDice6 } from "@tabler/icons-react"
+import { defaultAvatarImage } from './avatarImage'
+import { getUsername } from './usernameGenerate'
+import Webcam from 'react-webcam'
 
 export default function Home() {
   const [name, setName] = useState("") 
+  const [avatar, setAvatar] = useState(defaultAvatarImage)
+  const [showWebcam, setShowWebcam] = useState(false)
+  const webcamRef = useRef()
   const modal = useRef()
   const inputName = useRef()
 
@@ -14,35 +20,113 @@ export default function Home() {
     localStorage.setItem("name", inputName.current.value)
   }
 
+  function setAndStoreAvatar(data){
+    resizeBase64Image(data).then((data) => {
+      localStorage.setItem("avatar", data)
+      setAvatar(data)
+    })
+  }
+
+  function takePictureAvatar() {
+    const imageSrc = webcamRef.current.getScreenshot()
+    setAndStoreAvatar(imageSrc)
+    setShowWebcam(false)
+  }
+
+  function getBase64OfImage(file, cb) {
+    let reader = new FileReader();
+    reader.readAsDataURL(file);
+    reader.onload = function () {
+        cb(reader.result)
+    };
+    reader.onerror = function (error) {
+        console.log('Error: ', error);
+    };
+  }
+
+  function resizeBase64Image(base64Image) {
+    return new Promise((resolve, reject) => {
+      const maxSizeInKB = 500;
+      const maxSizeInBytes = maxSizeInKB * 1024;
+      const img = new Image();
+      img.src = base64Image;
+      img.onload = function () {
+        const canvas = document.createElement("canvas");
+        const ctx = canvas.getContext('2d');
+        const width = img.width;
+        const height = img.height;
+        const aspectRatio = width / height;
+        const newWidth = Math.sqrt(maxSizeInBytes * aspectRatio);
+        const newHeight = Math.sqrt(maxSizeInBytes / aspectRatio);
+        canvas.width = newWidth;
+        canvas.height = newHeight;
+        ctx.drawImage(img, 0, 0, newWidth, newHeight);
+        let quality = 0.8;
+        let dataURL = canvas.toDataURL('image/jpeg', quality);
+        resolve(dataURL);
+      };
+    });
+  }
+
   useEffect(() => {
     let localName = localStorage.getItem("name")
+    let localAvatar = localStorage.getItem("avatar")
     if(localName != null){
       setName(localName)
     } else {
       modal.current.showModal()
     }
+
+    if(localAvatar != null) {
+      setAvatar(localAvatar)
+    }
   }, [])
 
   return (
     <main data-theme="light" className="flex min-h-screen flex-col items-center space-y-16 p-24">
       <dialog ref={modal} className="modal">
-        <div className="modal-box">
-          <label className="form-control w-full max-w-xs">
+        <div className="modal-box flex flex-col space-y-4">
+          <div className="avatar flex flex-col items-center space-y-4">
+            <div className="w-24 rounded">
+              <img src={avatar} />
+            </div>
+            { showWebcam &&
+              <>
+                <Webcam ref={webcamRef} />
+                <button className="btn btn-primary" onClick={takePictureAvatar}><IconCamera /></button>
+              </>
+            }
+            { !showWebcam &&
+              <>
+                <button className="btn btn-primary" onClick={() => {setShowWebcam(true)}}>Use Webcam</button>
+                <input type="file" onChange={(e) => {getBase64OfImage(e.target.files[0], (data) => setAndStoreAvatar(data))}} className="file-input w-full max-w-xs"/>
+              </>
+            }
+          </div>
+          <label className="form-control w-full">
             <div className="label">
               <span className="label-text">What is your name?</span>
             </div>
-            <input type="text" ref={inputName} defaultValue={name} placeholder="Name" className="input input-bordered w-full max-w-xs" />
+            <div className="flex flex-row w-full space-x-4">
+              <input type="text" ref={inputName} defaultValue={name} placeholder="Name" className="input input-bordered w-full" />
+              <button onClick={() => {inputName.current.value = getUsername()}} ><IconDice6 /></button>
+            </div>
           </label>
           <div className="modal-action">
             <form method="dialog">
               {/* if there is a button in form, it will close the modal */}
-              <button onClick={setUsername} className="btn">Close</button>
+              <button onClick={setUsername} className="btn">Save</button>
             </form>
           </div>
         </div>
       </dialog>
       <h1 className="text-3xl">Bazaar</h1>
       <div className="flex flex-col space-y-4 items-center">
+        <div className="avatar">
+          <div className="w-24 rounded">
+            <img src={avatar} />
+          </div>
+        </div>
         <div className="flex flex-row space-x-4">
           <span className="text-xl">{name}</span>
           <button onClick={() => { modal.current.showModal()}}>
diff --git a/app/usernameGenerate.ts b/app/usernameGenerate.ts
new file mode 100644
index 0000000..80e0d96
--- /dev/null
+++ b/app/usernameGenerate.ts
@@ -0,0 +1,25 @@
+const prenom = [
+  "Stéphane",
+  "Hubert",
+  "Alphonse",
+  "Marjolaine",
+  "Cathy",
+  "Patrick",
+  "Agathe",
+  "Erneste",
+]
+
+const nom = [
+  "Falzar",
+  "Globule",
+  "Bermuda",
+  "Zigounette",
+  "Pissenlit",
+  "Détritus",
+]
+
+export function getUsername(){
+  const prenomIndex = Math.floor(Math.random() * prenom.length)
+  const nomIndex = Math.floor(Math.random() * nom.length)
+  return prenom[prenomIndex] + " " + nom[nomIndex]
+}
diff --git a/package-lock.json b/package-lock.json
index 075fc7f..ab0c254 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
         "next": "14.2.5",
         "react": "^18",
         "react-dom": "^18",
+        "react-webcam": "^7.2.0",
         "socket.io": "^4.7.5",
         "socket.io-client": "^4.7.5"
       },
@@ -4272,6 +4273,16 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/react-webcam": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/react-webcam/-/react-webcam-7.2.0.tgz",
+      "integrity": "sha512-xkrzYPqa1ag2DP+2Q/kLKBmCIfEx49bVdgCCCcZf88oF+0NPEbkwYk3/s/C7Zy0mhM8k+hpdNkBLzxg8H0aWcg==",
+      "license": "MIT",
+      "peerDependencies": {
+        "react": ">=16.2.0",
+        "react-dom": ">=16.2.0"
+      }
+    },
     "node_modules/read-cache": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
diff --git a/package.json b/package.json
index e9658ec..45e0f6a 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,7 @@
     "next": "14.2.5",
     "react": "^18",
     "react-dom": "^18",
+    "react-webcam": "^7.2.0",
     "socket.io": "^4.7.5",
     "socket.io-client": "^4.7.5"
   },
diff --git a/server.mjs b/server.mjs
index 1cfa3a5..d98f06a 100644
--- a/server.mjs
+++ b/server.mjs
@@ -18,18 +18,19 @@ app.prepare().then(() => {
 
   io.on("connection", (socket) => {
     console.log("User connected " + socket.id)
-    socket.on('room_connect', (room) => {
-      if(!Object.keys(active_rooms).includes(room.id)){
-        console.log("First person joined " + room.id + " ! " + room.name + " is owner.")
-        active_rooms[room.id] = [{id: socket.id, name: room.name, role: "owner", vote: ""}]
-        socket.emit("room_joined", {"room_users": active_rooms[room.id], "role": "owner"})
+
+    socket.on('room_connect', (params) => {
+      if(!Object.keys(active_rooms).includes(params.id)){
+        console.log("First person joined " + params.id + " ! " + params.name + " is owner.")
+        active_rooms[params.id] = [{id: socket.id, name: params.name, avatar: params.avatar, role: "owner", vote: ""}]
+        socket.emit("room_joined", {"room_users": active_rooms[params.id], "role": "owner"})
       } else {
-        socket.to(room.id).emit("new_player",{"id": socket.id, "name": room.name, role: "player"})
-        active_rooms[room.id].push({id: socket.id, name: room.name, role: "player", vote: ""})
-        socket.emit("room_joined", {"room_users": active_rooms[room.id], role: "player"})
-        console.log("New person joined " + room.id + " ! " + room.name + " is player.")
+        socket.to(params.id).emit("new_player",{"id": socket.id, "name": params.name, avatar: params.avatar, role: "player"})
+        active_rooms[params.id].push({id: socket.id, name: params.name, avatar: params.avatar, role: "player", vote: ""})
+        socket.emit("room_joined", {"room_users": active_rooms[params.id], role: "player"})
+        console.log("New person joined " + params.id + " ! " + params.name + " is player.")
       }
-      socket.join(room.id)
+      socket.join(params.id)
     })
 
     socket.on("start_game", (params) => {