Add avatar image + generateur de pseudo
This commit is contained in:
parent
ada0fa5ae8
commit
012caef506
7 changed files with 159 additions and 30 deletions
|
@ -4,6 +4,7 @@ import { io } from "socket.io-client"
|
||||||
import { getRandomQuestion } from "./questions"
|
import { getRandomQuestion } from "./questions"
|
||||||
import { useForceUpdate } from "./forceUpdate"
|
import { useForceUpdate } from "./forceUpdate"
|
||||||
import { IconCrown } from "@tabler/icons-react"
|
import { IconCrown } from "@tabler/icons-react"
|
||||||
|
import { defaultAvatarImage } from '../avatarImage'
|
||||||
|
|
||||||
interface roomProps {
|
interface roomProps {
|
||||||
params: {
|
params: {
|
||||||
|
@ -17,6 +18,7 @@ export default function Home({ params }: roomProps) {
|
||||||
|
|
||||||
const [role, setRole] = useState("")
|
const [role, setRole] = useState("")
|
||||||
const [name, setName] = useState("")
|
const [name, setName] = useState("")
|
||||||
|
const [avatar, setAvatar] = useState(defaultAvatarImage)
|
||||||
|
|
||||||
const [gameStarted, setGameStarted] = useState(false)
|
const [gameStarted, setGameStarted] = useState(false)
|
||||||
const [gameEnded, setGameEnded] = 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)
|
const roomNameDisplay = id.substring(0,3) + " " + id.substring(3,6)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const username = localStorage.getItem('name')
|
const localName = localStorage.getItem('name')
|
||||||
setName(username)
|
setName(localName)
|
||||||
|
const localAvatar = localStorage.getItem('avatar')
|
||||||
|
setAvatar(localAvatar)
|
||||||
// Listen for incoming setMessages
|
// Listen for incoming setMessages
|
||||||
socketRef.current = io("ws://localhost:3000");
|
socketRef.current = io("ws://localhost:3000");
|
||||||
|
|
||||||
socketRef.current.on("connect", () => {
|
socketRef.current.on("connect", () => {
|
||||||
setIsConnected(true)
|
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) => {
|
socketRef.current.on("new_player", (params) => {
|
||||||
|
@ -195,19 +199,21 @@ export default function Home({ params }: roomProps) {
|
||||||
}
|
}
|
||||||
{ (isConnected && players.length > 0) &&
|
{ (isConnected && players.length > 0) &&
|
||||||
<div className="flex flex-col space-y-16">
|
<div className="flex flex-col space-y-16">
|
||||||
<div>
|
<div className="grid grid-cols-3 gap-4">
|
||||||
{ players.map((player) => {
|
{ players.map((player) => {
|
||||||
console.log(player)
|
|
||||||
if(player.role == "player") {
|
|
||||||
return (
|
return (
|
||||||
<p>{player.name}</p>
|
<>
|
||||||
|
<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>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
|
||||||
if(player.role == "owner") {
|
|
||||||
return (
|
|
||||||
<p className="flex flex-row">{player.name}<IconCrown /></p>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{ role == "owner" &&
|
{ role == "owner" &&
|
||||||
|
|
1
app/avatarImage.ts
Normal file
1
app/avatarImage.ts
Normal file
File diff suppressed because one or more lines are too long
94
app/page.tsx
94
app/page.tsx
|
@ -2,10 +2,16 @@
|
||||||
|
|
||||||
import { navigate } from './action'
|
import { navigate } from './action'
|
||||||
import { useState, useEffect, useRef } from 'react'
|
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() {
|
export default function Home() {
|
||||||
const [name, setName] = useState("")
|
const [name, setName] = useState("")
|
||||||
|
const [avatar, setAvatar] = useState(defaultAvatarImage)
|
||||||
|
const [showWebcam, setShowWebcam] = useState(false)
|
||||||
|
const webcamRef = useRef()
|
||||||
const modal = useRef()
|
const modal = useRef()
|
||||||
const inputName = useRef()
|
const inputName = useRef()
|
||||||
|
|
||||||
|
@ -14,35 +20,113 @@ export default function Home() {
|
||||||
localStorage.setItem("name", inputName.current.value)
|
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(() => {
|
useEffect(() => {
|
||||||
let localName = localStorage.getItem("name")
|
let localName = localStorage.getItem("name")
|
||||||
|
let localAvatar = localStorage.getItem("avatar")
|
||||||
if(localName != null){
|
if(localName != null){
|
||||||
setName(localName)
|
setName(localName)
|
||||||
} else {
|
} else {
|
||||||
modal.current.showModal()
|
modal.current.showModal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(localAvatar != null) {
|
||||||
|
setAvatar(localAvatar)
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main data-theme="light" className="flex min-h-screen flex-col items-center space-y-16 p-24">
|
<main data-theme="light" className="flex min-h-screen flex-col items-center space-y-16 p-24">
|
||||||
<dialog ref={modal} className="modal">
|
<dialog ref={modal} className="modal">
|
||||||
<div className="modal-box">
|
<div className="modal-box flex flex-col space-y-4">
|
||||||
<label className="form-control w-full max-w-xs">
|
<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">
|
<div className="label">
|
||||||
<span className="label-text">What is your name?</span>
|
<span className="label-text">What is your name?</span>
|
||||||
</div>
|
</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>
|
</label>
|
||||||
<div className="modal-action">
|
<div className="modal-action">
|
||||||
<form method="dialog">
|
<form method="dialog">
|
||||||
{/* if there is a button in form, it will close the modal */}
|
{/* 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>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
<h1 className="text-3xl">Bazaar</h1>
|
<h1 className="text-3xl">Bazaar</h1>
|
||||||
<div className="flex flex-col space-y-4 items-center">
|
<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">
|
<div className="flex flex-row space-x-4">
|
||||||
<span className="text-xl">{name}</span>
|
<span className="text-xl">{name}</span>
|
||||||
<button onClick={() => { modal.current.showModal()}}>
|
<button onClick={() => { modal.current.showModal()}}>
|
||||||
|
|
25
app/usernameGenerate.ts
Normal file
25
app/usernameGenerate.ts
Normal file
|
@ -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]
|
||||||
|
}
|
11
package-lock.json
generated
11
package-lock.json
generated
|
@ -12,6 +12,7 @@
|
||||||
"next": "14.2.5",
|
"next": "14.2.5",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
|
"react-webcam": "^7.2.0",
|
||||||
"socket.io": "^4.7.5",
|
"socket.io": "^4.7.5",
|
||||||
"socket.io-client": "^4.7.5"
|
"socket.io-client": "^4.7.5"
|
||||||
},
|
},
|
||||||
|
@ -4272,6 +4273,16 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"next": "14.2.5",
|
"next": "14.2.5",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
|
"react-webcam": "^7.2.0",
|
||||||
"socket.io": "^4.7.5",
|
"socket.io": "^4.7.5",
|
||||||
"socket.io-client": "^4.7.5"
|
"socket.io-client": "^4.7.5"
|
||||||
},
|
},
|
||||||
|
|
21
server.mjs
21
server.mjs
|
@ -18,18 +18,19 @@ app.prepare().then(() => {
|
||||||
|
|
||||||
io.on("connection", (socket) => {
|
io.on("connection", (socket) => {
|
||||||
console.log("User connected " + socket.id)
|
console.log("User connected " + socket.id)
|
||||||
socket.on('room_connect', (room) => {
|
|
||||||
if(!Object.keys(active_rooms).includes(room.id)){
|
socket.on('room_connect', (params) => {
|
||||||
console.log("First person joined " + room.id + " ! " + room.name + " is owner.")
|
if(!Object.keys(active_rooms).includes(params.id)){
|
||||||
active_rooms[room.id] = [{id: socket.id, name: room.name, role: "owner", vote: ""}]
|
console.log("First person joined " + params.id + " ! " + params.name + " is owner.")
|
||||||
socket.emit("room_joined", {"room_users": active_rooms[room.id], "role": "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 {
|
} else {
|
||||||
socket.to(room.id).emit("new_player",{"id": socket.id, "name": room.name, role: "player"})
|
socket.to(params.id).emit("new_player",{"id": socket.id, "name": params.name, avatar: params.avatar, role: "player"})
|
||||||
active_rooms[room.id].push({id: socket.id, name: room.name, role: "player", vote: ""})
|
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[room.id], role: "player"})
|
socket.emit("room_joined", {"room_users": active_rooms[params.id], role: "player"})
|
||||||
console.log("New person joined " + room.id + " ! " + room.name + " is 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) => {
|
socket.on("start_game", (params) => {
|
||||||
|
|
Loading…
Reference in a new issue