dev #95

Merged
Thibaut merged 5 commits from dev into master 2026-01-05 16:57:02 +00:00
7 changed files with 48 additions and 28 deletions
Showing only changes of commit a871b52006 - Show all commits

View File

@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import fr.titionfire.ffsaf.data.repository.CompetitionRepository; import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
import fr.titionfire.ffsaf.domain.service.CompetPermService; import fr.titionfire.ffsaf.domain.service.CompetPermService;
import fr.titionfire.ffsaf.net2.MessageType; import fr.titionfire.ffsaf.net2.MessageType;
import fr.titionfire.ffsaf.rest.data.SimpleCompetData;
import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.SecurityCtx;
import fr.titionfire.ffsaf.ws.data.WelcomeInfo; import fr.titionfire.ffsaf.ws.data.WelcomeInfo;
import fr.titionfire.ffsaf.ws.recv.*; import fr.titionfire.ffsaf.ws.recv.*;
@ -118,10 +119,13 @@ public class CompetitionWS {
waitingResponse.put(connection, new HashMap<>()); waitingResponse.put(connection, new HashMap<>());
}) })
.map(cm -> { .map(cm -> {
SimpleCompetData data = SimpleCompetData.fromModel(cm);
WelcomeInfo welcomeInfo = new WelcomeInfo(); WelcomeInfo welcomeInfo = new WelcomeInfo();
welcomeInfo.setName(cm.getName()); welcomeInfo.setName(cm.getName());
welcomeInfo.setPerm(connection.userData().get(UserData.TypedKey.forString("prem"))); welcomeInfo.setPerm(connection.userData().get(UserData.TypedKey.forString("prem")));
welcomeInfo.setShow_blason(data.isShow_blason());
welcomeInfo.setShow_flag(data.isShow_flag());
return new MessageOut(UUID.randomUUID(), "welcomeInfo", MessageType.NOTIFY, welcomeInfo); return new MessageOut(UUID.randomUUID(), "welcomeInfo", MessageType.NOTIFY, welcomeInfo);
}); });

View File

@ -8,4 +8,6 @@ import lombok.Data;
public class WelcomeInfo { public class WelcomeInfo {
private String name; private String name;
private String perm; private String perm;
private boolean show_blason;
private boolean show_flag;
} }

View File

@ -25,7 +25,7 @@ function reducer(state, action) {
country: action.payload.data.country, country: action.payload.data.country,
}) })
if (state[comb.id] === undefined || !compareCombs(comb, state[comb.id])) { if (state[comb.id] === undefined || !compareCombs(comb, state[comb.id])) {
console.debug("Updating comb", comb); //console.debug("Updating comb", comb);
return { return {
...state, ...state,
[comb.id]: comb [comb.id]: comb
@ -49,7 +49,7 @@ function reducer(state, action) {
for (const o of combs) { for (const o of combs) {
newCombs[o.id] = o; newCombs[o.id] = o;
} }
console.debug("Updating combs", newCombs); //console.debug("Updating combs", newCombs);
return { return {
...state, ...state,

View File

@ -44,6 +44,7 @@ export function WSProvider({url, onmessage, children}) {
const {is_authenticated} = useAuth() const {is_authenticated} = useAuth()
const [isReady, setIsReady] = useState(false) const [isReady, setIsReady] = useState(false)
const [doReconnect, setDoReconnect] = useState(false) const [doReconnect, setDoReconnect] = useState(false)
const [welcomeData, setWelcomeData] = useState({name: "", perm: "", show_blason: true, show_flag: false})
const [state, dispatch] = useReducer(reducer, {listener: []}) const [state, dispatch] = useReducer(reducer, {listener: []})
const ws = useRef(null) const ws = useRef(null)
const listenersRef = useRef([]) const listenersRef = useRef([])
@ -58,6 +59,15 @@ export function WSProvider({url, onmessage, children}) {
listenersRef.current = state.listener listenersRef.current = state.listener
}, [state.listener]) }, [state.listener])
const welcomeListener = ({data}) => {
setWelcomeData({
name: data.name,
perm: data.perm,
show_blason: data.show_blason,
show_flag: data.show_flag
})
}
useEffect(() => { useEffect(() => {
if (!doReconnect && !is_authenticated && isReady) if (!doReconnect && !is_authenticated && isReady)
return; return;
@ -73,7 +83,7 @@ export function WSProvider({url, onmessage, children}) {
newSocket.onclose = ws.current.onclose newSocket.onclose = ws.current.onclose
newSocket.onmessage = ws.current.onmessage newSocket.onmessage = ws.current.onmessage
ws.current = newSocket ws.current = newSocket
}catch (e) { } catch (e) {
} }
}, 5000); }, 5000);
@ -87,7 +97,7 @@ export function WSProvider({url, onmessage, children}) {
setDoReconnect(true) setDoReconnect(true)
console.log(`WSProvider ${id} mounted ${mountCounter[id]} time(s)`); console.log(`WSProvider ${id} mounted ${mountCounter[id]} time(s)`);
if (mountCounter[id] === 1 && (ws.current === null || ws.current.readyState >= WebSocket.CLOSING)){ if (mountCounter[id] === 1 && (ws.current === null || ws.current.readyState >= WebSocket.CLOSING)) {
console.log("WSProvider: connecting to", url); console.log("WSProvider: connecting to", url);
const socket = new WebSocket(url) const socket = new WebSocket(url)
@ -122,6 +132,12 @@ export function WSProvider({url, onmessage, children}) {
console.error("Listener callback error:", err) console.error("Listener callback error:", err)
} }
}); });
if (msg.code === 'welcomeInfo') {
welcomeListener({...msg})
isHandled = true;
}
if (!isHandled && onmessage) if (!isHandled && onmessage)
onmessage(JSON.parse(event.data)) onmessage(JSON.parse(event.data))
} }
@ -170,7 +186,7 @@ export function WSProvider({url, onmessage, children}) {
} }
} }
console.log("WSProvider: sending message", {uuid, code, type, data}); //console.log("WSProvider: sending message", {uuid, code, type, data});
ws.current?.send(JSON.stringify({ ws.current?.send(JSON.stringify({
uuid: uuid, uuid: uuid,
code: code, code: code,
@ -183,7 +199,7 @@ export function WSProvider({url, onmessage, children}) {
}) => { }) => {
if (isReadyRef.current) { if (isReadyRef.current) {
send2(uuid, code, type, data, resolve, reject); send2(uuid, code, type, data, resolve, reject);
}else { } else {
let counter = 0; let counter = 0;
const waitInterval = setInterval(() => { const waitInterval = setInterval(() => {
if (isReadyRef.current) { if (isReadyRef.current) {
@ -200,18 +216,19 @@ export function WSProvider({url, onmessage, children}) {
} }
const ret = {isReady, dispatch, send, wait_length: callbackRef} const ret = {isReady, dispatch, send, wait_length: callbackRef, welcomeData}
return <WebsocketContext.Provider value={ret}> return <WebsocketContext.Provider value={ret}>
{children} {children}
</WebsocketContext.Provider> </WebsocketContext.Provider>
} }
export function useWS() { export function useWS() {
const {isReady, dispatch, send, wait_length} = useContext(WebsocketContext) const {isReady, dispatch, send, wait_length, welcomeData} = useContext(WebsocketContext)
return { return {
dispatch, dispatch,
isReady, isReady,
wait_length, wait_length,
welcomeData,
sendRequest: (code, data) => { sendRequest: (code, data) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
send(uuidv4(), code, "REQUEST", data, resolve, reject); send(uuidv4(), code, "REQUEST", data, resolve, reject);
@ -255,7 +272,7 @@ export function useRequestWS(code, payload, setLoading = null, loadingLevel = 1)
useEffect(() => { useEffect(() => {
if (isReady) if (isReady)
refresh(code, payload) refresh(code, payload)
else{ else {
if (setLoading) if (setLoading)
setLoading(loadingLevel) setLoading(loadingLevel)
setTimeout(() => refresh(code, payload), 1000) setTimeout(() => refresh(code, payload), 1000)

View File

@ -1,5 +1,5 @@
import React, {useEffect, useRef, useState} from "react"; import React, {useEffect, useRef, useState} from "react";
import {useRequestWS} from "../../../hooks/useWS.jsx"; import {useRequestWS, useWS} from "../../../hooks/useWS.jsx";
import {useCombs, useCombsDispatch} from "../../../hooks/useComb.jsx"; import {useCombs, useCombsDispatch} from "../../../hooks/useComb.jsx";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {createPortal} from "react-dom"; import {createPortal} from "react-dom";
@ -13,7 +13,6 @@ import {CategorieSelect} from "./CMTMatchPanel.jsx";
import {PointPanel} from "./CMTPoint.jsx"; import {PointPanel} from "./CMTPoint.jsx";
import {importOBSConfiguration, OBSProvider, useOBS} from "../../../hooks/useOBS.jsx"; import {importOBSConfiguration, OBSProvider, useOBS} from "../../../hooks/useOBS.jsx";
import {SimpleIconsOBS} from "../../../assets/SimpleIconsOBS.ts"; import {SimpleIconsOBS} from "../../../assets/SimpleIconsOBS.ts";
import {timePrint} from "../../../utils/Tools.js";
import {toast} from "react-toastify"; import {toast} from "react-toastify";
export function CMTable() { export function CMTable() {
@ -235,6 +234,7 @@ function ObsAutoSyncWhitPubAff() {
const {connected, setText, setTextAndColor, setDiapo} = useOBS(); const {connected, setText, setTextAndColor, setDiapo} = useOBS();
const oldState = useRef({timeColor: "#000000", timeStr: "--:--", c1: null, c2: null, showScore: true, scoreRouge: 0, scoreBleu: 0}); const oldState = useRef({timeColor: "#000000", timeStr: "--:--", c1: null, c2: null, showScore: true, scoreRouge: 0, scoreBleu: 0});
const state = usePubAffState(); const state = usePubAffState();
const {welcomeData} = useWS();
const {getComb} = useCombs(); const {getComb} = useCombs();
useEffect(() => { useEffect(() => {
@ -242,8 +242,8 @@ function ObsAutoSyncWhitPubAff() {
const comb = getComb(state.c1); const comb = getComb(state.c1);
setText("comb.rouge", comb ? (comb?.fname + " " + comb?.lname) : ""); setText("comb.rouge", comb ? (comb?.fname + " " + comb?.lname) : "");
const files = [] const files = []
if (comb?.club_uuid) files.push(`club_${comb.club_uuid}.png`) if (comb?.club_uuid && welcomeData.show_blason) files.push(`club_${comb.club_uuid}.png`)
if (comb?.country) files.push(`flag_${comb.country.toLowerCase()}.png`) if (comb?.country && welcomeData.show_flag) files.push(`flag_${comb.country.toLowerCase()}.png`)
setDiapo("img.rouge", files); setDiapo("img.rouge", files);
oldState.current.c1 = state.c1; oldState.current.c1 = state.c1;
} }
@ -252,8 +252,8 @@ function ObsAutoSyncWhitPubAff() {
const comb = getComb(state.c2); const comb = getComb(state.c2);
setText("comb.blue", comb ? (comb?.fname + " " + comb?.lname) : ""); setText("comb.blue", comb ? (comb?.fname + " " + comb?.lname) : "");
const files = [] const files = []
if (comb?.club_uuid) files.push(`club_${comb.club_uuid}.png`) if (comb?.club_uuid && welcomeData.show_blason) files.push(`club_${comb.club_uuid}.png`)
if (comb?.country) files.push(`flag_${comb.country.toLowerCase()}.png`) if (comb?.country && welcomeData.show_flag) files.push(`flag_${comb.country.toLowerCase()}.png`)
setDiapo("img.blue", files); setDiapo("img.blue", files);
oldState.current.c2 = state.c2; oldState.current.c2 = state.c2;
} }

View File

@ -75,9 +75,8 @@ function HomeComp() {
} }
function WSStatus({setPerm}) { function WSStatus({setPerm}) {
const [name, setName] = useState("")
const [inWait, setInWait] = useState(false) const [inWait, setInWait] = useState(false)
const {isReady, wait_length, dispatch} = useWS(); const {isReady, wait_length, welcomeData} = useWS();
useEffect(() => { useEffect(() => {
const timer = setInterval(() => { const timer = setInterval(() => {
@ -87,16 +86,11 @@ function WSStatus({setPerm}) {
}, []); }, []);
useEffect(() => { useEffect(() => {
const welcomeListener = ({data}) => { setPerm(welcomeData.perm)
setName(data.name) }, [welcomeData])
setPerm(data.perm)
}
dispatch({type: 'addListener', payload: {callback: welcomeListener, code: 'welcomeInfo'}})
return () => dispatch({type: 'removeListener', payload: welcomeListener})
}, [])
return <div className="row" style={{marginRight: "inherit"}}> return <div className="row" style={{marginRight: "inherit"}}>
<h2 className="col">{name}</h2> <h2 className="col">{welcomeData.name}</h2>
<div className="col-auto" style={{margin: "auto 0", padding: 0}}>Serveur: <ColoredCircle <div className="col-auto" style={{margin: "auto 0", padding: 0}}>Serveur: <ColoredCircle
color={isReady ? (inWait ? "#ffad32" : "#00c700") : "#e50000"}/> color={isReady ? (inWait ? "#ffad32" : "#00c700") : "#e50000"}/>
</div> </div>

View File

@ -2,6 +2,7 @@ import {useCombs} from "../../../hooks/useComb.jsx";
import {usePubAffState} from "../../../hooks/useExternalWindow.jsx"; import {usePubAffState} from "../../../hooks/useExternalWindow.jsx";
import {SmartLogoBackgroundMemo} from "../../../components/SmartLogoBackground.jsx"; import {SmartLogoBackgroundMemo} from "../../../components/SmartLogoBackground.jsx";
import {useMemo, useRef} from 'react'; import {useMemo, useRef} from 'react';
import {useWS} from "../../../hooks/useWS.jsx";
const vite_url = import.meta.env.VITE_URL; const vite_url = import.meta.env.VITE_URL;
@ -124,6 +125,7 @@ const logoStyle = {width: "6vw", height: "min(11vh, 6vw)", objectFit: "contain",
function CombDisplay({combId, background, children}) { function CombDisplay({combId, background, children}) {
const {getComb} = useCombs(); const {getComb} = useCombs();
const comb = getComb(combId, ""); const comb = getComb(combId, "");
const {welcomeData} = useWS();
const logoAlt = useMemo(() => { const logoAlt = useMemo(() => {
return comb?.club_str return comb?.club_str
@ -142,10 +144,11 @@ function CombDisplay({combId, background, children}) {
alignItems: "center", alignItems: "center",
}}> }}>
{comb !== "" && <> {comb !== "" && <>
<SmartLogoBackgroundMemo src={logoSrc} alt={logoAlt} style={logoStyle}/> {welcomeData.show_blason && <SmartLogoBackgroundMemo src={logoSrc} alt={logoAlt} style={logoStyle}/>}
<div style={{fontSize: "min(3.5vw, 6.5vh)"}}>{comb.fname} {comb.lname}</div> <div style={{fontSize: "min(3.5vw, 6.5vh)"}}>{comb.fname} {comb.lname}</div>
<img src={`/flags/svg/${comb.country.toLowerCase()}.svg`} alt={comb.country} {welcomeData.show_flag ? <img src={`/flags/svg/${comb.country.toLowerCase()}.svg`} alt={comb.country}
style={{width: "4vw", height: "8vh", objectFit: "contain", margin: "0 1.25vw"}}/> style={{width: "4vw", height: "8vh", objectFit: "contain", margin: "0 1.25vw"}}/>
: <div style={{width: "4vw", height: "8vh", objectFit: "contain", margin: "0 1.25vw"}}></div>}
</>} </>}
<div className="position-absolute top-0 start-0 w-100" style={{...noMP, height: "0.4vh", backgroundColor: "#646464AA"}}/> <div className="position-absolute top-0 start-0 w-100" style={{...noMP, height: "0.4vh", backgroundColor: "#646464AA"}}/>
{children} {children}