import { createStore } from 'vuex'; import dialogs from './modules/dialogs'; import loadMenu from '../utils/menuLoader.js'; import router from '../router'; import apiClient from '../utils/axios.js'; import { io } from 'socket.io-client'; const store = createStore({ state: { isLoggedIn: localStorage.getItem('isLoggedIn') === 'true', user: JSON.parse(localStorage.getItem('user')) || null, language: navigator.language.startsWith('de') ? 'de' : 'en', menu: JSON.parse(localStorage.getItem('menu')) || [], socket: null, daemonSocket: null, menuNeedsUpdate: false, }, mutations: { async dologin(state, user) { state.isLoggedIn = true; state.user = user; localStorage.setItem('isLoggedIn', 'true'); localStorage.setItem('user', JSON.stringify(user)); state.menuNeedsUpdate = true; if (user.param.filter(param => ['birthdate', 'gender'].includes(param.name)).length < 2) { router.push({ path: '/settings/personal' }); } }, async dologout(state) { state.isLoggedIn = false; state.user = null; localStorage.removeItem('isLoggedIn'); localStorage.removeItem('user'); localStorage.removeItem('menu'); state.menuNeedsUpdate = false; }, setLanguage(state, language) { state.language = language; }, setMenu(state, menu) { state.menu = menu; localStorage.setItem('menu', JSON.stringify(menu)); state.menuNeedsUpdate = false; }, setSocket(state, socket) { state.socket = socket; }, clearSocket(state) { if (state.socket) { state.socket.disconnect(); } state.socket = null; }, setDaemonSocket(state, daemonSocket) { state.daemonSocket = daemonSocket; }, clearDaemonSocket(state) { if (state.daemonSocket) { state.daemonSocket.close(); } state.daemonSocket = null; }, }, actions: { async login({ commit, dispatch }, user) { await commit('dologin', user); await dispatch('initializeSocket'); await dispatch('initializeDaemonSocket'); const socket = this.getters.socket; if (socket) { socket.emit('setUserId', user.id); } await dispatch('loadMenu'); }, logout({ commit }) { commit('clearSocket'); commit('clearDaemonSocket'); commit('dologout'); router.push('/'); }, initializeSocket({ commit, state }) { if (state.isLoggedIn && state.user) { let currentSocket = state.socket; const connectSocket = () => { if (currentSocket) { currentSocket.disconnect(); } console.log('🔌 Initializing Socket.io connection to:', import.meta.env.VITE_API_BASE_URL); const socket = io(import.meta.env.VITE_API_BASE_URL, { secure: true, transports: ['websocket', 'polling'] }); socket.on('connect', () => { console.log('✅ Socket.io connected successfully'); socket.emit('setUserId', state.user.id); // Sende user.id, wenn user vorhanden ist }); socket.on('disconnect', (reason) => { console.warn('❌ Socket.io disconnected:', reason); retryConnection(connectSocket); }); socket.on('connect_error', (error) => { console.error('❌ Socket.io connection error:', error); console.error('❌ URL attempted:', import.meta.env.VITE_API_BASE_URL); }); commit('setSocket', socket); }; const retryConnection = (reconnectFn) => { setTimeout(() => { console.log('Retrying Socket.io connection...'); reconnectFn(); }, 1000); // Retry every second }; connectSocket(); } else { console.log("User is not logged in or user data is not available."); } }, initializeDaemonSocket({ commit, state }) { if (!state.isLoggedIn || !state.user) { console.log("User is not logged in or user data is not available for Daemon WebSocket."); return; } const daemonUrl = import.meta.env.VITE_DAEMON_SOCKET || 'wss://www.your-part.de:4551'; console.log('🔌 Initializing Daemon WebSocket connection to:', daemonUrl); const connectDaemonSocket = () => { try { const daemonSocket = new WebSocket(daemonUrl, 'yourpart-protocol'); console.log('🔌 Protocol: yourpart-protocol'); daemonSocket.onopen = () => { console.log('✅ Daemon WebSocket connected successfully'); retryCount = 0; // Reset retry counter on successful connection const payload = JSON.stringify({ user_id: state.user.id, event: 'setUserId', data: { userId: state.user.id } }); daemonSocket.send(payload); }; daemonSocket.onclose = (event) => { console.warn('❌ Daemon WebSocket disconnected:', event.reason); console.warn('❌ Close details:', { code: event.code, reason: event.reason, wasClean: event.wasClean, readyState: daemonSocket.readyState }); retryConnection(connectDaemonSocket); }; daemonSocket.onerror = (error) => { console.error('❌ Daemon WebSocket error:', error); console.error('❌ Error details:', { type: error.type, target: error.target, readyState: daemonSocket.readyState, url: daemonSocket.url, protocol: daemonSocket.protocol }); retryConnection(connectDaemonSocket); }; daemonSocket.addEventListener('message', (event) => { const message = event.data; if (message === "ping") { daemonSocket.send("pong"); } else { try { const data = JSON.parse(message); // Handle daemon messages here console.log('📨 Daemon message received:', data); } catch (error) { console.error("Error parsing daemon message:", error); } } }); commit('setDaemonSocket', daemonSocket); } catch (error) { console.error('❌ Failed to create Daemon WebSocket:', error); console.error('❌ URL attempted:', import.meta.env.VITE_DAEMON_SOCKET); retryConnection(connectDaemonSocket); } }; let retryCount = 0; const maxRetries = 5; const retryConnection = (reconnectFn) => { if (retryCount >= maxRetries) { console.error('❌ Max retry attempts reached for Daemon WebSocket'); return; } retryCount++; const delay = Math.min(1000 * Math.pow(2, retryCount - 1), 10000); // Exponential backoff, max 10s console.log(`🔄 Retrying Daemon WebSocket connection in ${delay}ms (attempt ${retryCount}/${maxRetries})`); setTimeout(() => { reconnectFn(); }, delay); }; connectDaemonSocket(); }, setLanguage({ commit }, language) { commit('setLanguage', language); }, async loadMenu({ commit }) { try { const menu = await loadMenu(); commit('setMenu', menu); } catch (err) { console.error(err); commit('setMenu', []); } }, }, getters: { isLoggedIn: state => state.isLoggedIn, user: state => state.user, language: state => state.language, menu: state => state.menu, socket: state => state.socket, daemonSocket: state => state.daemonSocket, menuNeedsUpdate: state => state.menuNeedsUpdate, }, modules: { dialogs, }, }); if (store.state.isLoggedIn && store.state.user) { store.dispatch('initializeSocket'); store.dispatch('initializeDaemonSocket'); } export default store;