diff --git a/apps/client/package.json b/apps/client/package.json index 12759b2ba..737b178d1 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -31,7 +31,7 @@ "react-qr-code": "^2.0.12", "react-router-dom": "^6.3.0", "web-vitals": "^3.1.1", - "zustand": "^4.5.2" + "zustand": "^5.0.3" }, "scripts": { "addversion": "node -p \"'export const ONTIME_VERSION = ' + JSON.stringify(require('../../package.json').version) + ';'\" > src/ONTIME_VERSION.js", diff --git a/apps/client/src/common/hooks/useClientPath.ts b/apps/client/src/common/hooks/useClientPath.ts index 917b3de72..37acadf33 100644 --- a/apps/client/src/common/hooks/useClientPath.ts +++ b/apps/client/src/common/hooks/useClientPath.ts @@ -1,5 +1,6 @@ import { useEffect } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; +import { useShallow } from 'zustand/shallow'; import { useClientStore } from '../stores/clientStore'; import { socketSendJson } from '../utils/socket'; @@ -9,10 +10,12 @@ import { useIsOnline } from './useSocket'; export const useClientPath = () => { const navigate = useNavigate(); const { pathname, search } = useLocation(); - const { redirect, setRedirect } = useClientStore((store) => ({ - redirect: store.redirect, - setRedirect: store.setRedirect, - })); + const { redirect, setRedirect } = useClientStore( + useShallow((store) => ({ + redirect: store.redirect, + setRedirect: store.setRedirect, + })), + ); const isOnline = useIsOnline(); // notify of client path changes diff --git a/apps/client/src/common/hooks/useSocket.ts b/apps/client/src/common/hooks/useSocket.ts index 06948c53d..6b8c7e19c 100644 --- a/apps/client/src/common/hooks/useSocket.ts +++ b/apps/client/src/common/hooks/useSocket.ts @@ -3,73 +3,54 @@ import { RuntimeStore, SimpleDirection, SimplePlayback, TimerMessage } from 'ont import { useRuntimeStore } from '../stores/runtime'; import { socketSendJson } from '../utils/socket'; +const createSelector = + (selector: (state: RuntimeStore) => T) => + () => + useRuntimeStore(selector); + export const setClientRemote = { setIdentify: (payload: { target: string; identify: boolean }) => socketSendJson('client', payload), setRedirect: (payload: { target: string; redirect: string }) => socketSendJson('client', payload), setClientName: (payload: { target: string; rename: string }) => socketSendJson('client', payload), }; -export const useRundownEditor = () => { - const featureSelector = (state: RuntimeStore) => ({ - playback: state.timer.playback, - selectedEventId: state.eventNow?.id ?? null, - nextEventId: state.eventNext?.id ?? null, - }); +export const useRundownEditor = createSelector((state: RuntimeStore) => ({ + playback: state.timer.playback, + selectedEventId: state.eventNow?.id ?? null, + nextEventId: state.eventNext?.id ?? null, +})); - return useRuntimeStore(featureSelector); -}; +export const useOperator = createSelector((state: RuntimeStore) => ({ + playback: state.timer.playback, + selectedEventId: state.eventNow?.id ?? null, +})); -export const useOperator = () => { - const featureSelector = (state: RuntimeStore) => ({ - playback: state.timer.playback, - selectedEventId: state.eventNow?.id ?? null, - }); +export const useTimerViewControl = createSelector((state: RuntimeStore) => ({ + blackout: state.message.timer.blackout, + blink: state.message.timer.blink, + secondarySource: state.message.timer.secondarySource, +})); - return useRuntimeStore(featureSelector); -}; +export const useTimerMessageInput = createSelector((state: RuntimeStore) => ({ + text: state.message.timer.text, + visible: state.message.timer.visible, +})); -export const useTimerViewControl = () => { - const featureSelector = (state: RuntimeStore) => ({ - blackout: state.message.timer.blackout, - blink: state.message.timer.blink, - secondarySource: state.message.timer.secondarySource, - }); +export const useExternalMessageInput = createSelector((state: RuntimeStore) => ({ + text: state.message.external, + visible: state.message.timer.secondarySource === 'external', +})); - return useRuntimeStore(featureSelector); -}; - -export const useTimerMessageInput = () => { - const featureSelector = (state: RuntimeStore) => ({ - text: state.message.timer.text, - visible: state.message.timer.visible, - }); - - return useRuntimeStore(featureSelector); -}; - -export const useExternalMessageInput = () => { - const featureSelector = (state: RuntimeStore) => ({ - text: state.message.external, - visible: state.message.timer.secondarySource === 'external', - }); - - return useRuntimeStore(featureSelector); -}; - -export const useMessagePreview = () => { - const featureSelector = (state: RuntimeStore) => ({ - blink: state.message.timer.blink, - blackout: state.message.timer.blackout, - phase: state.timer.phase, - showAuxTimer: state.message.timer.secondarySource === 'aux', - showExternalMessage: state.message.timer.secondarySource === 'external' && Boolean(state.message.external), - showTimerMessage: state.message.timer.visible && Boolean(state.message.timer.text), - timerType: state.eventNow?.timerType ?? null, - countToEnd: state.eventNow?.countToEnd ?? false, - }); - - return useRuntimeStore(featureSelector); -}; +export const useMessagePreview = createSelector((state: RuntimeStore) => ({ + blink: state.message.timer.blink, + blackout: state.message.timer.blackout, + phase: state.timer.phase, + showAuxTimer: state.message.timer.secondarySource === 'aux', + showExternalMessage: state.message.timer.secondarySource === 'external' && Boolean(state.message.external), + showTimerMessage: state.message.timer.visible && Boolean(state.message.timer.text), + timerType: state.eventNow?.timerType ?? null, + countToEnd: state.eventNow?.countToEnd ?? false, +})); export const setMessage = { timerText: (payload: string) => socketSendJson('message', { timer: { text: payload } }), @@ -81,16 +62,12 @@ export const setMessage = { socketSendJson('message', { timer: { secondarySource: payload } }), }; -export const usePlaybackControl = () => { - const featureSelector = (state: RuntimeStore) => ({ - playback: state.timer.playback, - selectedEventIndex: state.runtime.selectedEventIndex, - numEvents: state.runtime.numEvents, - timerPhase: state.timer.phase, - }); - - return useRuntimeStore(featureSelector); -}; +export const usePlaybackControl = createSelector((state: RuntimeStore) => ({ + playback: state.timer.playback, + selectedEventIndex: state.runtime.selectedEventIndex, + numEvents: state.runtime.numEvents, + timerPhase: state.timer.phase, +})); export const setPlayback = { start: () => socketSendJson('start'), @@ -114,32 +91,20 @@ export const setPlayback = { }, }; -export const useInfoPanel = () => { - const featureSelector = (state: RuntimeStore) => ({ - eventNow: state.eventNow, - eventNext: state.eventNext, - playback: state.timer.playback, - selectedEventIndex: state.runtime.selectedEventIndex, - numEvents: state.runtime.numEvents, - }); +export const useInfoPanel = createSelector((state: RuntimeStore) => ({ + eventNow: state.eventNow, + eventNext: state.eventNext, + playback: state.timer.playback, + selectedEventIndex: state.runtime.selectedEventIndex, + numEvents: state.runtime.numEvents, +})); - return useRuntimeStore(featureSelector); -}; +export const useAuxTimerTime = createSelector((state: RuntimeStore) => state.auxtimer1.current); -export const useAuxTimerTime = () => { - const featureSelector = (state: RuntimeStore) => state.auxtimer1.current; - - return useRuntimeStore(featureSelector); -}; - -export const useAuxTimerControl = () => { - const featureSelector = (state: RuntimeStore) => ({ - playback: state.auxtimer1.playback, - direction: state.auxtimer1.direction, - }); - - return useRuntimeStore(featureSelector); -}; +export const useAuxTimerControl = createSelector((state: RuntimeStore) => ({ + playback: state.auxtimer1.playback, + direction: state.auxtimer1.direction, +})); export const setAuxTimer = { start: () => socketSendJson('auxtimer', { '1': SimplePlayback.Start }), @@ -149,20 +114,13 @@ export const setAuxTimer = { setDuration: (time: number) => socketSendJson('auxtimer', { '1': { duration: time } }), }; -export const useSelectedEventId = () => { - const featureSelector = (state: RuntimeStore) => ({ - selectedEventId: state.eventNow?.id ?? null, - }); +export const useSelectedEventId = createSelector((state: RuntimeStore) => ({ + selectedEventId: state.eventNow?.id ?? null, +})); - return useRuntimeStore(featureSelector); -}; - -export const useCurrentBlockId = () => { - const featureSelector = (state: RuntimeStore) => ({ - currentBlockId: state.currentBlock.block?.id ?? null, - }); - return useRuntimeStore(featureSelector); -}; +export const useCurrentBlockId = createSelector((state: RuntimeStore) => ({ + currentBlockId: state.currentBlock.block?.id ?? null, +})); export const setEventPlayback = { loadEvent: (id: string) => socketSendJson('load', { id }), @@ -171,82 +129,52 @@ export const setEventPlayback = { pause: () => socketSendJson('pause'), }; -export const useTimer = () => { - const featureSelector = (state: RuntimeStore) => ({ - ...state.timer, - }); +export const useTimer = createSelector((state: RuntimeStore) => ({ + ...state.timer, +})); - return useRuntimeStore(featureSelector); -}; - -export const useClock = () => { - const featureSelector = (state: RuntimeStore) => ({ - clock: state.clock, - }); - return useRuntimeStore(featureSelector); -}; +export const useClock = createSelector((state: RuntimeStore) => ({ + clock: state.clock, +})); /** Used by the progress bar components */ -export const useProgressData = () => { - const featureSelector = (state: RuntimeStore) => ({ - current: state.timer.current, - duration: state.timer.duration, - timeWarning: state.eventNow?.timeWarning ?? null, - timeDanger: state.eventNow?.timeDanger ?? null, - }); - return useRuntimeStore(featureSelector); -}; +export const useProgressData = createSelector((state: RuntimeStore) => ({ + current: state.timer.current, + duration: state.timer.duration, + timeWarning: state.eventNow?.timeWarning ?? null, + timeDanger: state.eventNow?.timeDanger ?? null, +})); export const setClientName = (newName: string) => socketSendJson('set-client-name', newName); -export const useRuntimeOverview = () => { - const featureSelector = (state: RuntimeStore) => ({ - plannedStart: state.runtime.plannedStart, - actualStart: state.runtime.actualStart, - plannedEnd: state.runtime.plannedEnd, - expectedEnd: state.runtime.expectedEnd, - }); +export const useRuntimeOverview = createSelector((state: RuntimeStore) => ({ + plannedStart: state.runtime.plannedStart, + actualStart: state.runtime.actualStart, + plannedEnd: state.runtime.plannedEnd, + expectedEnd: state.runtime.expectedEnd, +})); - return useRuntimeStore(featureSelector); -}; +export const useRuntimePlaybackOverview = createSelector((state: RuntimeStore) => ({ + playback: state.timer.playback, + clock: state.clock, -export const useRuntimePlaybackOverview = () => { - const featureSelector = (state: RuntimeStore) => ({ - playback: state.timer.playback, - clock: state.clock, + numEvents: state.runtime.numEvents, + selectedEventIndex: state.runtime.selectedEventIndex, + offset: state.runtime.offset, - numEvents: state.runtime.numEvents, - selectedEventIndex: state.runtime.selectedEventIndex, - offset: state.runtime.offset, + currentBlock: state.currentBlock, +})); - currentBlock: state.currentBlock, - }); +export const useTimelineStatus = createSelector((state: RuntimeStore) => ({ + clock: state.clock, + offset: state.runtime.offset, +})); - return useRuntimeStore(featureSelector); -}; - -export const useTimelineStatus = () => { - const featureSelector = (state: RuntimeStore) => ({ - clock: state.clock, - offset: state.runtime.offset, - }); - - return useRuntimeStore(featureSelector); -}; - -export const usePing = () => { - const featureSelector = (state: RuntimeStore) => ({ - ping: state.ping, - }); - - return useRuntimeStore(featureSelector); -}; +export const usePing = createSelector((state: RuntimeStore) => ({ + ping: state.ping, +})); /** convert ping into a derived value which changes less often */ -export const useIsOnline = () => { - const featureSelector = (state: RuntimeStore) => ({ - isOnline: state.ping > 0, - }); - - return useRuntimeStore(featureSelector); -}; +export const useIsOnline = createSelector((state: RuntimeStore) => ({ + isOnline: state.ping > 0, +})); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30f421379..633e7b53c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -168,8 +168,8 @@ importers: specifier: ^3.1.1 version: 3.1.1 zustand: - specifier: ^4.5.2 - version: 4.5.2(@types/react@18.0.26)(react@18.3.1) + specifier: ^5.0.3 + version: 5.0.3(@types/react@18.0.26)(react@18.3.1)(use-sync-external-store@1.2.0(react@18.3.1)) devDependencies: '@sentry/vite-plugin': specifier: ^2.16.1 @@ -257,7 +257,7 @@ importers: version: 31.2.0 electron-builder: specifier: ^24.13.3 - version: 24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) + version: 24.13.3(electron-builder-squirrel-windows@24.13.3) eslint: specifier: 'catalog:' version: 8.56.0 @@ -2261,8 +2261,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-walk@8.3.2: - resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} acorn@8.11.2: @@ -2270,6 +2270,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + adler-32@1.3.1: resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} engines: {node: '>=0.8'} @@ -2375,6 +2380,9 @@ packages: async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -2496,6 +2504,10 @@ packages: resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} engines: {node: '>= 0.4'} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} @@ -2736,8 +2748,8 @@ packages: supports-color: optional: true - decimal.js@10.4.3: - resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + decimal.js@10.5.0: + resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} @@ -2908,10 +2920,18 @@ packages: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} engines: {node: '>= 0.4'} + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + es-set-tostringtag@2.0.1: resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + es-shim-unscopables@1.0.0: resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} @@ -2952,8 +2972,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - escodegen@2.0.0: - resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} engines: {node: '>=6.0'} hasBin: true @@ -3180,6 +3200,10 @@ packages: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -3271,10 +3295,18 @@ packages: resolution: {integrity: sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==} engines: {node: '>= 0.4'} + get-intrinsic@1.2.7: + resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} + engines: {node: '>= 0.4'} + get-nonce@1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-stream@5.2.0: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} engines: {node: '>=8'} @@ -3396,6 +3428,10 @@ packages: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + has@1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} @@ -3687,10 +3723,6 @@ packages: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} - levn@0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -3927,8 +3959,8 @@ packages: resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} engines: {node: '>=14.16'} - nwsapi@2.2.2: - resolution: {integrity: sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==} + nwsapi@2.2.16: + resolution: {integrity: sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -3975,10 +4007,6 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - optionator@0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} - optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -4011,8 +4039,8 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - parse5@7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + parse5@7.2.1: + resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} @@ -4079,10 +4107,6 @@ packages: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} - prelude-ls@1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -4117,8 +4141,8 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - psl@1.9.0: - resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} @@ -4127,6 +4151,10 @@ packages: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + qr.js@0.0.0: resolution: {integrity: sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==} @@ -4527,6 +4555,9 @@ packages: string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -4624,8 +4655,8 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - tough-cookie@4.1.2: - resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} tr46@0.0.3: @@ -4716,10 +4747,6 @@ packages: resolution: {integrity: sha512-DUHWQAcC8BTiUZDRzAYGvpSpGLiaOQPfYXlCieQbwUvmml/LRGIe3raKdrOPOoiX0DYlzxs2nH6BoWJoZrj8hA==} hasBin: true - type-check@0.3.2: - resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} - engines: {node: '>= 0.8.0'} - type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -4991,10 +5018,6 @@ packages: resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==} engines: {node: '>=0.8'} - word-wrap@1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} - engines: {node: '>=0.10.0'} - word@0.3.0: resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==} engines: {node: '>=0.8'} @@ -5071,13 +5094,14 @@ packages: resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} engines: {node: '>= 10'} - zustand@4.5.2: - resolution: {integrity: sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==} - engines: {node: '>=12.7.0'} + zustand@5.0.3: + resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} + engines: {node: '>=12.20.0'} peerDependencies: - '@types/react': '>=16.8' + '@types/react': '>=18.0.0' immer: '>=9.0.6' - react: '>=16.8' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' peerDependenciesMeta: '@types/react': optional: true @@ -5085,6 +5109,8 @@ packages: optional: true react: optional: true + use-sync-external-store: + optional: true snapshots: @@ -7065,19 +7091,24 @@ snapshots: acorn-globals@7.0.1: dependencies: - acorn: 8.11.2 - acorn-walk: 8.3.2 + acorn: 8.14.0 + acorn-walk: 8.3.4 optional: true acorn-jsx@5.3.2(acorn@8.11.2): dependencies: acorn: 8.11.2 - acorn-walk@8.3.2: + acorn-walk@8.3.4: + dependencies: + acorn: 8.14.0 optional: true acorn@8.11.2: {} + acorn@8.14.0: + optional: true + adler-32@1.3.1: {} agent-base@6.0.2: @@ -7120,7 +7151,7 @@ snapshots: app-builder-bin@4.0.0: {} - app-builder-lib@24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)): + app-builder-lib@24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3): dependencies: '@develar/schema-utils': 2.6.5 '@electron/notarize': 2.2.1 @@ -7185,7 +7216,7 @@ snapshots: archiver@5.3.2: dependencies: archiver-utils: 2.1.0 - async: 3.2.5 + async: 3.2.6 buffer-crc32: 0.2.13 readable-stream: 3.6.2 readdir-glob: 1.1.3 @@ -7237,6 +7268,8 @@ snapshots: async@3.2.5: {} + async@3.2.6: {} + asynckit@0.4.0: {} at-least-node@1.0.0: {} @@ -7397,6 +7430,12 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + optional: true + call-bind@1.0.2: dependencies: function-bind: 1.1.2 @@ -7640,7 +7679,7 @@ snapshots: dependencies: ms: 2.1.3 - decimal.js@10.4.3: + decimal.js@10.5.0: optional: true decompress-response@6.0.0: @@ -7689,7 +7728,7 @@ snapshots: dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3): dependencies: - app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) + app-builder-lib: 24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3) builder-util: 24.13.1 builder-util-runtime: 9.2.4 fs-extra: 10.1.0 @@ -7755,7 +7794,7 @@ snapshots: electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3): dependencies: - app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) + app-builder-lib: 24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3) archiver: 5.3.2 builder-util: 24.13.1 fs-extra: 10.1.0 @@ -7763,9 +7802,9 @@ snapshots: - dmg-builder - supports-color - electron-builder@24.13.3(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)): + electron-builder@24.13.3(electron-builder-squirrel-windows@24.13.3): dependencies: - app-builder-lib: 24.13.3(dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3))(electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3)) + app-builder-lib: 24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3) builder-util: 24.13.1 builder-util-runtime: 9.2.4 chalk: 4.1.2 @@ -7868,12 +7907,25 @@ snapshots: dependencies: es-errors: 1.3.0 + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + optional: true + es-set-tostringtag@2.0.1: dependencies: get-intrinsic: 1.2.2 has: 1.0.3 has-tostringtag: 1.0.0 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + optional: true + es-shim-unscopables@1.0.0: dependencies: has: 1.0.3 @@ -7975,12 +8027,11 @@ snapshots: escape-string-regexp@4.0.0: {} - escodegen@2.0.0: + escodegen@2.1.0: dependencies: esprima: 4.0.1 estraverse: 5.3.0 esutils: 2.0.3 - optionator: 0.8.3 optionalDependencies: source-map: 0.6.1 optional: true @@ -8276,6 +8327,14 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + optional: true + forwarded@0.2.0: {} frac@1.1.2: {} @@ -8380,8 +8439,28 @@ snapshots: hasown: 2.0.2 math-intrinsics: 1.1.0 + get-intrinsic@1.2.7: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + optional: true + get-nonce@1.0.1: {} + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + optional: true + get-stream@5.2.0: dependencies: pump: 3.0.0 @@ -8550,6 +8629,11 @@ snapshots: dependencies: has-symbols: 1.0.3 + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + optional: true + has@1.0.3: dependencies: function-bind: 1.1.2 @@ -8788,24 +8872,24 @@ snapshots: jsdom@21.1.0: dependencies: abab: 2.0.6 - acorn: 8.11.2 + acorn: 8.14.0 acorn-globals: 7.0.1 cssom: 0.5.0 cssstyle: 2.3.0 data-urls: 3.0.2 - decimal.js: 10.4.3 + decimal.js: 10.5.0 domexception: 4.0.0 - escodegen: 2.0.0 - form-data: 4.0.0 + escodegen: 2.1.0 + form-data: 4.0.2 html-encoding-sniffer: 3.0.0 http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.2 - parse5: 7.1.2 + nwsapi: 2.2.16 + parse5: 7.2.1 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 4.1.2 + tough-cookie: 4.1.4 w3c-xmlserializer: 4.0.0 webidl-conversions: 7.0.0 whatwg-encoding: 2.0.0 @@ -8874,12 +8958,6 @@ snapshots: dependencies: readable-stream: 2.3.8 - levn@0.3.0: - dependencies: - prelude-ls: 1.1.2 - type-check: 0.3.2 - optional: true - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -9060,7 +9138,7 @@ snapshots: normalize-url@8.0.1: {} - nwsapi@2.2.2: + nwsapi@2.2.16: optional: true object-assign@4.1.1: {} @@ -9111,16 +9189,6 @@ snapshots: dependencies: wrappy: 1.0.2 - optionator@0.8.3: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.3.0 - prelude-ls: 1.1.2 - type-check: 0.3.2 - word-wrap: 1.2.3 - optional: true - optionator@0.9.3: dependencies: '@aashutoshrathi/word-wrap': 1.2.6 @@ -9155,7 +9223,7 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - parse5@7.1.2: + parse5@7.2.1: dependencies: entities: 4.5.0 optional: true @@ -9209,9 +9277,6 @@ snapshots: picocolors: 1.0.1 source-map-js: 1.2.0 - prelude-ls@1.1.2: - optional: true - prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: @@ -9242,7 +9307,9 @@ snapshots: proxy-from-env@1.1.0: {} - psl@1.9.0: + psl@1.15.0: + dependencies: + punycode: 2.3.1 optional: true pump@3.0.0: @@ -9252,6 +9319,9 @@ snapshots: punycode@2.1.1: {} + punycode@2.3.1: + optional: true + qr.js@0.0.0: {} qs@6.11.0: @@ -9390,7 +9460,7 @@ snapshots: readable-stream@3.6.2: dependencies: inherits: 2.0.4 - string_decoder: 1.1.1 + string_decoder: 1.3.0 util-deprecate: 1.0.2 readdir-glob@1.1.3: @@ -9712,6 +9782,10 @@ snapshots: dependencies: safe-buffer: 5.1.2 + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -9802,10 +9876,10 @@ snapshots: toidentifier@1.0.1: {} - tough-cookie@4.1.2: + tough-cookie@4.1.4: dependencies: - psl: 1.9.0 - punycode: 2.1.1 + psl: 1.15.0 + punycode: 2.3.1 universalify: 0.2.0 url-parse: 1.5.10 optional: true @@ -9814,7 +9888,7 @@ snapshots: tr46@3.0.0: dependencies: - punycode: 2.1.1 + punycode: 2.3.1 optional: true truncate-utf8-bytes@1.0.2: @@ -9878,11 +9952,6 @@ snapshots: turbo-windows-64: 2.3.3 turbo-windows-arm64: 2.3.3 - type-check@0.3.2: - dependencies: - prelude-ls: 1.1.2 - optional: true - type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -9976,6 +10045,7 @@ snapshots: use-sync-external-store@1.2.0(react@18.3.1): dependencies: react: 18.3.1 + optional: true utf8-byte-length@1.0.4: {} @@ -10223,9 +10293,6 @@ snapshots: wmf@1.0.2: {} - word-wrap@1.2.3: - optional: true - word@0.3.0: {} wrap-ansi@7.0.0: @@ -10291,9 +10358,8 @@ snapshots: compress-commons: 4.1.2 readable-stream: 3.6.2 - zustand@4.5.2(@types/react@18.0.26)(react@18.3.1): - dependencies: - use-sync-external-store: 1.2.0(react@18.3.1) + zustand@5.0.3(@types/react@18.0.26)(react@18.3.1)(use-sync-external-store@1.2.0(react@18.3.1)): optionalDependencies: '@types/react': 18.0.26 react: 18.3.1 + use-sync-external-store: 1.2.0(react@18.3.1)