@xipkg/calls-store 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ компонент модержащий store приложения
@@ -0,0 +1,220 @@
1
+ import * as zustand_middleware from 'zustand/middleware';
2
+ import * as zustand from 'zustand';
3
+ import { LiveKitRoomProps } from '@livekit/components-react';
4
+ import { LocalUserChoices as LocalUserChoices$1 } from '@livekit/components-core';
5
+ import { VideoQuality } from 'livekit-client';
6
+ import { NoiseCancellationMode } from '@xipkg/calls-types';
7
+
8
+ type RaisedHandT = {
9
+ participantId: string;
10
+ participantName: string;
11
+ timestamp: number;
12
+ };
13
+ type CornerT = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
14
+ type useCallStoreT = {
15
+ isCameraPermission: boolean | null;
16
+ isMicroPermission: boolean | null;
17
+ audioEnabled: boolean;
18
+ videoEnabled: boolean;
19
+ audioDeviceId: ConstrainDOMString | undefined;
20
+ audioOutputDeviceId: ConstrainDOMString | undefined;
21
+ videoDeviceId: ConstrainDOMString | undefined;
22
+ connect: LiveKitRoomProps['connect'];
23
+ isStarted: boolean | undefined;
24
+ isConnecting: boolean;
25
+ mode: 'compact' | 'full';
26
+ carouselType: 'grid' | 'horizontal' | 'vertical';
27
+ preferredFocusLayout: 'horizontal' | 'vertical';
28
+ activeCorner: CornerT;
29
+ /** Режим вида компакт-ВКС на десктопе: одна плитка или развёрнутый список (учёт при DnD) */
30
+ compactViewMode: 'basic' | 'expanded';
31
+ activeBoardId: string | undefined;
32
+ activeClassroom: string | undefined;
33
+ /** Локальный переключатель: пользователь сам ушёл в полную ВКС («Только меня»), комната на сервере остаётся на доске */
34
+ localFullView: boolean;
35
+ token: string | undefined;
36
+ raisedHands: RaisedHandT[];
37
+ isHandRaised: boolean;
38
+ updateStore: (type: keyof useCallStoreT, value: any) => void;
39
+ addRaisedHand: (hand: RaisedHandT) => void;
40
+ removeRaisedHand: (participantId: string) => void;
41
+ toggleHandRaised: () => void;
42
+ clearAllRaisedHands: () => void;
43
+ isHandRaisedByParticipant: (participantId: string) => boolean;
44
+ };
45
+ declare const useCallStore: zustand.UseBoundStore<Omit<zustand.StoreApi<useCallStoreT>, "persist"> & {
46
+ persist: {
47
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<useCallStoreT, {
48
+ isCameraPermission: boolean | null;
49
+ isMicroPermission: boolean | null;
50
+ audioEnabled: boolean;
51
+ videoEnabled: boolean;
52
+ audioDeviceId: ConstrainDOMString | undefined;
53
+ videoDeviceId: ConstrainDOMString | undefined;
54
+ carouselType: "grid" | "horizontal" | "vertical";
55
+ preferredFocusLayout: "horizontal" | "vertical";
56
+ activeCorner: CornerT;
57
+ }>>) => void;
58
+ clearStorage: () => void;
59
+ rehydrate: () => Promise<void> | void;
60
+ hasHydrated: () => boolean;
61
+ onHydrate: (fn: (state: useCallStoreT) => void) => () => void;
62
+ onFinishHydration: (fn: (state: useCallStoreT) => void) => () => void;
63
+ getOptions: () => Partial<zustand_middleware.PersistOptions<useCallStoreT, {
64
+ isCameraPermission: boolean | null;
65
+ isMicroPermission: boolean | null;
66
+ audioEnabled: boolean;
67
+ videoEnabled: boolean;
68
+ audioDeviceId: ConstrainDOMString | undefined;
69
+ videoDeviceId: ConstrainDOMString | undefined;
70
+ carouselType: "grid" | "horizontal" | "vertical";
71
+ preferredFocusLayout: "horizontal" | "vertical";
72
+ activeCorner: CornerT;
73
+ }>>;
74
+ };
75
+ }>;
76
+
77
+ type PermissionStateT = undefined | 'granted' | 'prompt' | 'denied' | 'unavailable';
78
+ type BaseStateT = {
79
+ cameraPermission: PermissionStateT;
80
+ microphonePermission: PermissionStateT;
81
+ isLoading: boolean;
82
+ isPermissionDialogOpen: boolean;
83
+ };
84
+ type DerivedStateT = {
85
+ isCameraGranted: boolean;
86
+ isMicrophoneGranted: boolean;
87
+ isCameraDenied: boolean;
88
+ isMicrophoneDenied: boolean;
89
+ isCameraPrompted: boolean;
90
+ isMicrophonePrompted: boolean;
91
+ };
92
+ type State = BaseStateT & DerivedStateT;
93
+ declare const usePermissionsStore: zustand.UseBoundStore<Omit<zustand.StoreApi<State>, "persist"> & {
94
+ persist: {
95
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<State, {
96
+ cameraPermission: PermissionStateT;
97
+ microphonePermission: PermissionStateT;
98
+ }>>) => void;
99
+ clearStorage: () => void;
100
+ rehydrate: () => Promise<void> | void;
101
+ hasHydrated: () => boolean;
102
+ onHydrate: (fn: (state: State) => void) => () => void;
103
+ onFinishHydration: (fn: (state: State) => void) => () => void;
104
+ getOptions: () => Partial<zustand_middleware.PersistOptions<State, {
105
+ cameraPermission: PermissionStateT;
106
+ microphonePermission: PermissionStateT;
107
+ }>>;
108
+ };
109
+ }>;
110
+ declare const openPermissionsDialog: () => void;
111
+ declare const closePermissionsDialog: () => void;
112
+
113
+ type VideoResolution = 'h720' | 'h360' | 'h180';
114
+ type LocalUserChoices = LocalUserChoices$1 & {
115
+ noiseReductionEnabled?: boolean;
116
+ blurEnabled?: boolean;
117
+ audioOutputDeviceId?: string;
118
+ videoPublishResolution?: VideoResolution;
119
+ videoSubscribeQuality?: VideoQuality;
120
+ /** Включено ли шумоподавление (любой режим кроме off). */
121
+ noiseCancellationEnabled?: boolean;
122
+ /** Режим шумоподавления: off | webrtc | krisp. */
123
+ noiseCancellationMode?: NoiseCancellationMode;
124
+ };
125
+ declare const useUserChoicesStore: zustand.UseBoundStore<Omit<zustand.StoreApi<LocalUserChoices>, "persist"> & {
126
+ persist: {
127
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<LocalUserChoices, {
128
+ videoEnabled: boolean;
129
+ audioEnabled: boolean;
130
+ videoDeviceId: string;
131
+ audioDeviceId: string;
132
+ username: string;
133
+ noiseReductionEnabled?: boolean;
134
+ blurEnabled?: boolean;
135
+ audioOutputDeviceId?: string;
136
+ videoPublishResolution?: VideoResolution;
137
+ videoSubscribeQuality?: VideoQuality;
138
+ /** Включено ли шумоподавление (любой режим кроме off). */
139
+ noiseCancellationEnabled?: boolean;
140
+ /** Режим шумоподавления: off | webrtc | krisp. */
141
+ noiseCancellationMode?: NoiseCancellationMode;
142
+ }>>) => void;
143
+ clearStorage: () => void;
144
+ rehydrate: () => Promise<void> | void;
145
+ hasHydrated: () => boolean;
146
+ onHydrate: (fn: (state: LocalUserChoices) => void) => () => void;
147
+ onFinishHydration: (fn: (state: LocalUserChoices) => void) => () => void;
148
+ getOptions: () => Partial<zustand_middleware.PersistOptions<LocalUserChoices, {
149
+ videoEnabled: boolean;
150
+ audioEnabled: boolean;
151
+ videoDeviceId: string;
152
+ audioDeviceId: string;
153
+ username: string;
154
+ noiseReductionEnabled?: boolean;
155
+ blurEnabled?: boolean;
156
+ audioOutputDeviceId?: string;
157
+ videoPublishResolution?: VideoResolution;
158
+ videoSubscribeQuality?: VideoQuality;
159
+ /** Включено ли шумоподавление (любой режим кроме off). */
160
+ noiseCancellationEnabled?: boolean;
161
+ /** Режим шумоподавления: off | webrtc | krisp. */
162
+ noiseCancellationMode?: NoiseCancellationMode;
163
+ }>>;
164
+ };
165
+ }>;
166
+
167
+ type SoundKey = 'chatMessage' | 'handRaise' | 'userJoin' | 'userLeft' | 'boardTimerEnd' | 'boardTimerWarn';
168
+ interface SoundEffectsState {
169
+ chatMessageVolume: number;
170
+ handRaiseVolume: number;
171
+ userJoinVolume: number;
172
+ userLeftVolume: number;
173
+ boardTimerEndVolume: number;
174
+ boardTimerWarnVolume: number;
175
+ setSoundVolume: (key: SoundKey, volume: number) => void;
176
+ getEffectiveVolume: (key: SoundKey) => number;
177
+ }
178
+ declare const useSoundEffectsStore: zustand.UseBoundStore<Omit<zustand.StoreApi<SoundEffectsState>, "persist"> & {
179
+ persist: {
180
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<SoundEffectsState, {
181
+ chatMessageVolume: number;
182
+ handRaiseVolume: number;
183
+ userJoinVolume: number;
184
+ userLeftVolume: number;
185
+ boardTimerEndVolume: number;
186
+ boardTimerWarnVolume: number;
187
+ }>>) => void;
188
+ clearStorage: () => void;
189
+ rehydrate: () => Promise<void> | void;
190
+ hasHydrated: () => boolean;
191
+ onHydrate: (fn: (state: SoundEffectsState) => void) => () => void;
192
+ onFinishHydration: (fn: (state: SoundEffectsState) => void) => () => void;
193
+ getOptions: () => Partial<zustand_middleware.PersistOptions<SoundEffectsState, {
194
+ chatMessageVolume: number;
195
+ handRaiseVolume: number;
196
+ userJoinVolume: number;
197
+ userLeftVolume: number;
198
+ boardTimerEndVolume: number;
199
+ boardTimerWarnVolume: number;
200
+ }>>;
201
+ };
202
+ }>;
203
+
204
+ type FeatureKey = 'compactView' | 'whiteboard' | 'raiseHand' | 'chat';
205
+ type FeatureMapT = Record<FeatureKey, boolean>;
206
+ type FeaturesState = {
207
+ features: FeatureMapT;
208
+ setFeature: (key: FeatureKey, value: boolean) => void;
209
+ setFeatures: (features: Partial<FeatureMapT>) => void;
210
+ };
211
+ declare const useFeaturesStore: zustand.UseBoundStore<zustand.StoreApi<FeaturesState>>;
212
+
213
+ interface FocusModeState {
214
+ focusMode: boolean;
215
+ setFocusMode: (value: boolean) => void;
216
+ toggleFocusMode: () => void;
217
+ }
218
+ declare const useFocusModeStore: zustand.UseBoundStore<zustand.StoreApi<FocusModeState>>;
219
+
220
+ export { type CornerT, type VideoResolution, closePermissionsDialog, openPermissionsDialog, useCallStore, useFeaturesStore, useFocusModeStore, usePermissionsStore, useSoundEffectsStore, useUserChoicesStore };
package/dist/index.mjs ADDED
@@ -0,0 +1,231 @@
1
+ import { create } from 'zustand';
2
+ import { persist } from 'zustand/middleware';
3
+ import { saveUserChoices, loadUserChoices } from '@livekit/components-core';
4
+ import { VideoQuality } from 'livekit-client';
5
+
6
+ // src/store/callStore.ts
7
+ var useCallStore = create()(
8
+ persist(
9
+ (set, get) => ({
10
+ isCameraPermission: null,
11
+ isMicroPermission: null,
12
+ audioEnabled: false,
13
+ videoEnabled: false,
14
+ audioDeviceId: void 0,
15
+ audioOutputDeviceId: void 0,
16
+ videoDeviceId: void 0,
17
+ connect: void 0,
18
+ isStarted: void 0,
19
+ isConnecting: false,
20
+ mode: "full",
21
+ carouselType: "grid",
22
+ preferredFocusLayout: "horizontal",
23
+ activeCorner: "top-left",
24
+ compactViewMode: "basic",
25
+ // Текущая активная доска
26
+ activeBoardId: void 0,
27
+ activeClassroom: void 0,
28
+ localFullView: false,
29
+ // токен для конференции
30
+ token: void 0,
31
+ // Поднятые руки
32
+ raisedHands: [],
33
+ isHandRaised: false,
34
+ updateStore: (type, value) => set({ [type]: value }),
35
+ // Поднятые руки
36
+ addRaisedHand: (hand) => set((state) => {
37
+ const existingHand = state.raisedHands.find(
38
+ (h) => h.participantId === hand.participantId
39
+ );
40
+ if (existingHand) {
41
+ return {
42
+ raisedHands: state.raisedHands.map(
43
+ (h) => h.participantId === hand.participantId ? hand : h
44
+ )
45
+ };
46
+ }
47
+ return { raisedHands: [...state.raisedHands, hand] };
48
+ }),
49
+ removeRaisedHand: (participantId) => set((state) => ({
50
+ raisedHands: state.raisedHands.filter((hand) => hand.participantId !== participantId)
51
+ })),
52
+ toggleHandRaised: () => set((state) => ({ isHandRaised: !state.isHandRaised })),
53
+ clearAllRaisedHands: () => set({ raisedHands: [], isHandRaised: false }),
54
+ isHandRaisedByParticipant: (participantId) => {
55
+ const state = get();
56
+ return state.raisedHands.some((hand) => hand.participantId === participantId);
57
+ }
58
+ }),
59
+ {
60
+ name: "call-store",
61
+ version: 3,
62
+ migrate: (persisted, version) => {
63
+ const state = persisted;
64
+ if (version < 2) {
65
+ const ct = state.carouselType;
66
+ if (ct === "focus") {
67
+ state.carouselType = "horizontal";
68
+ }
69
+ }
70
+ if (version < 3) {
71
+ const ct = state.carouselType;
72
+ state.preferredFocusLayout = ct === "horizontal" || ct === "vertical" ? ct : "horizontal";
73
+ }
74
+ return state;
75
+ },
76
+ partialize: (state) => ({
77
+ isCameraPermission: state.isCameraPermission,
78
+ isMicroPermission: state.isMicroPermission,
79
+ audioEnabled: state.audioEnabled,
80
+ videoEnabled: state.videoEnabled,
81
+ audioDeviceId: state.audioDeviceId,
82
+ videoDeviceId: state.videoDeviceId,
83
+ carouselType: state.carouselType,
84
+ preferredFocusLayout: state.preferredFocusLayout,
85
+ activeCorner: state.activeCorner
86
+ })
87
+ }
88
+ )
89
+ );
90
+ var usePermissionsStore = create()(
91
+ persist(
92
+ (_, get) => ({
93
+ cameraPermission: void 0,
94
+ microphonePermission: void 0,
95
+ isLoading: true,
96
+ isPermissionDialogOpen: false,
97
+ get isCameraGranted() {
98
+ return get().cameraPermission === "granted";
99
+ },
100
+ get isMicrophoneGranted() {
101
+ return get().microphonePermission === "granted";
102
+ },
103
+ get isCameraDenied() {
104
+ return get().cameraPermission === "denied";
105
+ },
106
+ get isMicrophoneDenied() {
107
+ return get().microphonePermission === "denied";
108
+ },
109
+ get isCameraPrompted() {
110
+ return get().cameraPermission === "prompt";
111
+ },
112
+ get isMicrophonePrompted() {
113
+ return get().microphonePermission === "prompt";
114
+ }
115
+ }),
116
+ {
117
+ name: "permissions-storage",
118
+ partialize: (state) => ({
119
+ cameraPermission: state.cameraPermission,
120
+ microphonePermission: state.microphonePermission
121
+ })
122
+ }
123
+ )
124
+ );
125
+ var openPermissionsDialog = () => {
126
+ usePermissionsStore.setState({ isPermissionDialogOpen: true });
127
+ };
128
+ var closePermissionsDialog = () => {
129
+ usePermissionsStore.setState({ isPermissionDialogOpen: false });
130
+ };
131
+ function getUserChoicesState() {
132
+ return {
133
+ noiseReductionEnabled: false,
134
+ blurEnabled: false,
135
+ audioOutputDeviceId: "default",
136
+ videoPublishResolution: "h720",
137
+ videoSubscribeQuality: VideoQuality.HIGH,
138
+ noiseCancellationEnabled: false,
139
+ noiseCancellationMode: "webrtc",
140
+ ...loadUserChoices()
141
+ };
142
+ }
143
+ var useUserChoicesStore = create()(
144
+ persist(
145
+ () => ({
146
+ ...getUserChoicesState()
147
+ }),
148
+ {
149
+ name: "user-choices-storage",
150
+ onRehydrateStorage: () => (state) => {
151
+ if (state) {
152
+ saveUserChoices(state, false);
153
+ }
154
+ }
155
+ }
156
+ )
157
+ );
158
+ var DEFAULTS = {
159
+ chatMessage: 0.25,
160
+ handRaise: 0.25,
161
+ userJoin: 0.25,
162
+ userLeft: 0.25,
163
+ boardTimerEnd: 1,
164
+ boardTimerWarn: 1
165
+ };
166
+ var VOLUME_KEY_MAP = {
167
+ chatMessage: "chatMessageVolume",
168
+ handRaise: "handRaiseVolume",
169
+ userJoin: "userJoinVolume",
170
+ userLeft: "userLeftVolume",
171
+ boardTimerEnd: "boardTimerEndVolume",
172
+ boardTimerWarn: "boardTimerWarnVolume"
173
+ };
174
+ var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
175
+ var useSoundEffectsStore = create()(
176
+ persist(
177
+ (set, get) => ({
178
+ chatMessageVolume: DEFAULTS.chatMessage,
179
+ handRaiseVolume: DEFAULTS.handRaise,
180
+ userJoinVolume: DEFAULTS.userJoin,
181
+ userLeftVolume: DEFAULTS.userLeft,
182
+ boardTimerEndVolume: DEFAULTS.boardTimerEnd,
183
+ boardTimerWarnVolume: DEFAULTS.boardTimerWarn,
184
+ setSoundVolume: (key, volume) => {
185
+ const min = key === "boardTimerEnd" ? 0.2 : 0;
186
+ const clamped = clamp(volume, min, 1);
187
+ set({ [VOLUME_KEY_MAP[key]]: clamped });
188
+ },
189
+ getEffectiveVolume: (key) => {
190
+ const storeKey = VOLUME_KEY_MAP[key];
191
+ return get()[storeKey];
192
+ }
193
+ }),
194
+ {
195
+ name: "sound-effects-store",
196
+ version: 1,
197
+ partialize: (state) => ({
198
+ chatMessageVolume: state.chatMessageVolume,
199
+ handRaiseVolume: state.handRaiseVolume,
200
+ userJoinVolume: state.userJoinVolume,
201
+ userLeftVolume: state.userLeftVolume,
202
+ boardTimerEndVolume: state.boardTimerEndVolume,
203
+ boardTimerWarnVolume: state.boardTimerWarnVolume
204
+ })
205
+ }
206
+ )
207
+ );
208
+ var defaultFeatures = {
209
+ compactView: true,
210
+ whiteboard: true,
211
+ raiseHand: true,
212
+ chat: true
213
+ };
214
+ var useFeaturesStore = create((set) => ({
215
+ features: defaultFeatures,
216
+ setFeature: (key, value) => set((state) => ({
217
+ features: { ...state.features, [key]: value }
218
+ })),
219
+ setFeatures: (features) => set((state) => ({
220
+ features: { ...state.features, ...features }
221
+ }))
222
+ }));
223
+ var useFocusModeStore = create((set) => ({
224
+ focusMode: false,
225
+ setFocusMode: (value) => set({ focusMode: value }),
226
+ toggleFocusMode: () => set((state) => ({ focusMode: !state.focusMode }))
227
+ }));
228
+
229
+ export { closePermissionsDialog, openPermissionsDialog, useCallStore, useFeaturesStore, useFocusModeStore, usePermissionsStore, useSoundEffectsStore, useUserChoicesStore };
230
+ //# sourceMappingURL=index.mjs.map
231
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store/callStore.ts","../src/store/permissions.ts","../src/store/userChoices.ts","../src/store/useSoundEffectsStore.ts","../src/store/featuresStore.ts","../src/store/useFocusModeStore.ts"],"names":["create","persist"],"mappings":"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","file":"index.mjs","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { LiveKitRoomProps } from '@livekit/components-react';\nimport { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\n\ntype RaisedHandT = {\n participantId: string;\n participantName: string;\n timestamp: number;\n};\n\nexport type CornerT = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n\ntype useCallStoreT = {\n // разрешение от браузера на использование камеры\n isCameraPermission: boolean | null;\n isMicroPermission: boolean | null;\n // включён ли у пользователя микро\n audioEnabled: boolean;\n videoEnabled: boolean;\n // id-выбранного устройства\n audioDeviceId: ConstrainDOMString | undefined;\n audioOutputDeviceId: ConstrainDOMString | undefined;\n videoDeviceId: ConstrainDOMString | undefined;\n // подключена ли конференция\n connect: LiveKitRoomProps['connect'];\n // началась ли ВКС для пользователя\n isStarted: boolean | undefined;\n // состояние подключения\n isConnecting: boolean;\n\n mode: 'compact' | 'full';\n carouselType: 'grid' | 'horizontal' | 'vertical';\n preferredFocusLayout: 'horizontal' | 'vertical';\n activeCorner: CornerT;\n\n /** Режим вида компакт-ВКС на десктопе: одна плитка или развёрнутый список (учёт при DnD) */\n compactViewMode: 'basic' | 'expanded';\n\n // Текущая активная доска (для синхронизации с новыми участниками)\n activeBoardId: string | undefined;\n activeClassroom: string | undefined;\n\n /** Локальный переключатель: пользователь сам ушёл в полную ВКС («Только меня»), комната на сервере остаётся на доске */\n localFullView: boolean;\n\n // токен для конференции\n token: string | undefined;\n\n // Поднятые руки\n raisedHands: RaisedHandT[];\n isHandRaised: boolean;\n\n updateStore: (type: keyof useCallStoreT, value: any) => void;\n addRaisedHand: (hand: RaisedHandT) => void;\n removeRaisedHand: (participantId: string) => void;\n toggleHandRaised: () => void;\n clearAllRaisedHands: () => void;\n isHandRaisedByParticipant: (participantId: string) => boolean;\n};\n\nexport const useCallStore = create<useCallStoreT>()(\n persist(\n (set, get) => ({\n isCameraPermission: null,\n isMicroPermission: null,\n audioEnabled: false,\n videoEnabled: false,\n audioDeviceId: undefined,\n audioOutputDeviceId: undefined,\n videoDeviceId: undefined,\n connect: undefined,\n isStarted: undefined,\n isConnecting: false,\n mode: 'full',\n carouselType: 'grid',\n preferredFocusLayout: 'horizontal',\n activeCorner: 'top-left',\n compactViewMode: 'basic',\n\n // Текущая активная доска\n activeBoardId: undefined,\n activeClassroom: undefined,\n\n localFullView: false,\n\n // токен для конференции\n token: undefined,\n\n // Поднятые руки\n raisedHands: [],\n isHandRaised: false,\n\n updateStore: (type: keyof useCallStoreT, value: any) => set({ [type]: value }),\n\n // Поднятые руки\n addRaisedHand: (hand: RaisedHandT) =>\n set((state) => {\n // Проверяем, есть ли уже рука от этого участника\n const existingHand = state.raisedHands.find(\n (h) => h.participantId === hand.participantId,\n );\n if (existingHand) {\n // Обновляем существующую руку\n return {\n raisedHands: state.raisedHands.map((h) =>\n h.participantId === hand.participantId ? hand : h,\n ),\n };\n }\n // Добавляем новую руку\n return { raisedHands: [...state.raisedHands, hand] };\n }),\n removeRaisedHand: (participantId: string) =>\n set((state) => ({\n raisedHands: state.raisedHands.filter((hand) => hand.participantId !== participantId),\n })),\n toggleHandRaised: () => set((state) => ({ isHandRaised: !state.isHandRaised })),\n clearAllRaisedHands: () => set({ raisedHands: [], isHandRaised: false }),\n isHandRaisedByParticipant: (participantId: string) => {\n const state = get();\n return state.raisedHands.some((hand) => hand.participantId === participantId);\n },\n }),\n {\n name: 'call-store',\n version: 3,\n migrate: (persisted, version) => {\n const state = persisted as Record<string, unknown>;\n if (version < 2) {\n const ct = state.carouselType;\n if (ct === 'focus') {\n state.carouselType = 'horizontal';\n }\n }\n if (version < 3) {\n const ct = state.carouselType;\n state.preferredFocusLayout = ct === 'horizontal' || ct === 'vertical' ? ct : 'horizontal';\n }\n return state as useCallStoreT;\n },\n partialize: (state) => ({\n isCameraPermission: state.isCameraPermission,\n isMicroPermission: state.isMicroPermission,\n audioEnabled: state.audioEnabled,\n videoEnabled: state.videoEnabled,\n audioDeviceId: state.audioDeviceId,\n videoDeviceId: state.videoDeviceId,\n carouselType: state.carouselType,\n preferredFocusLayout: state.preferredFocusLayout,\n activeCorner: state.activeCorner,\n }),\n },\n ),\n);\n","import { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\n\ntype PermissionStateT = undefined | 'granted' | 'prompt' | 'denied' | 'unavailable';\n\ntype BaseStateT = {\n cameraPermission: PermissionStateT;\n microphonePermission: PermissionStateT;\n isLoading: boolean;\n isPermissionDialogOpen: boolean;\n};\n\ntype DerivedStateT = {\n isCameraGranted: boolean;\n isMicrophoneGranted: boolean;\n isCameraDenied: boolean;\n isMicrophoneDenied: boolean;\n isCameraPrompted: boolean;\n isMicrophonePrompted: boolean;\n};\n\ntype State = BaseStateT & DerivedStateT;\n\nexport const usePermissionsStore = create<State>()(\n persist(\n (_, get) => ({\n cameraPermission: undefined,\n microphonePermission: undefined,\n isLoading: true,\n isPermissionDialogOpen: false,\n\n get isCameraGranted() {\n return get().cameraPermission === 'granted';\n },\n get isMicrophoneGranted() {\n return get().microphonePermission === 'granted';\n },\n get isCameraDenied() {\n return get().cameraPermission === 'denied';\n },\n get isMicrophoneDenied() {\n return get().microphonePermission === 'denied';\n },\n get isCameraPrompted() {\n return get().cameraPermission === 'prompt';\n },\n get isMicrophonePrompted() {\n return get().microphonePermission === 'prompt';\n },\n }),\n {\n name: 'permissions-storage',\n partialize: (state) => ({\n cameraPermission: state.cameraPermission,\n microphonePermission: state.microphonePermission,\n }),\n },\n ),\n);\n\nexport const openPermissionsDialog = () => {\n usePermissionsStore.setState({ isPermissionDialogOpen: true });\n};\n\nexport const closePermissionsDialog = () => {\n usePermissionsStore.setState({ isPermissionDialogOpen: false });\n};\n","import { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport {\n loadUserChoices,\n saveUserChoices,\n LocalUserChoices as LocalUserChoicesLK,\n} from '@livekit/components-core';\nimport { VideoQuality } from 'livekit-client';\nimport type { NoiseCancellationMode } from '@xipkg/calls-types';\n\nexport type VideoResolution = 'h720' | 'h360' | 'h180';\n\nexport type LocalUserChoices = LocalUserChoicesLK & {\n noiseReductionEnabled?: boolean;\n blurEnabled?: boolean;\n audioOutputDeviceId?: string;\n videoPublishResolution?: VideoResolution;\n videoSubscribeQuality?: VideoQuality;\n /** Включено ли шумоподавление (любой режим кроме off). */\n noiseCancellationEnabled?: boolean;\n /** Режим шумоподавления: off | webrtc | krisp. */\n noiseCancellationMode?: NoiseCancellationMode;\n};\n\nfunction getUserChoicesState(): LocalUserChoices {\n return {\n noiseReductionEnabled: false,\n blurEnabled: false,\n audioOutputDeviceId: 'default',\n videoPublishResolution: 'h720',\n videoSubscribeQuality: VideoQuality.HIGH,\n noiseCancellationEnabled: false,\n noiseCancellationMode: 'webrtc',\n ...loadUserChoices(),\n };\n}\n\nexport const useUserChoicesStore = create<LocalUserChoices>()(\n persist(\n () => ({\n ...getUserChoicesState(),\n }),\n {\n name: 'user-choices-storage',\n onRehydrateStorage: () => (state) => {\n if (state) {\n saveUserChoices(state, false);\n }\n },\n },\n ),\n);\n","import { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\n\ntype SoundKey =\n | 'chatMessage'\n | 'handRaise'\n | 'userJoin'\n | 'userLeft'\n | 'boardTimerEnd'\n | 'boardTimerWarn';\n\ninterface SoundEffectsState {\n chatMessageVolume: number;\n handRaiseVolume: number;\n userJoinVolume: number;\n userLeftVolume: number;\n boardTimerEndVolume: number;\n boardTimerWarnVolume: number;\n\n setSoundVolume: (key: SoundKey, volume: number) => void;\n getEffectiveVolume: (key: SoundKey) => number;\n}\n\nconst DEFAULTS: Record<SoundKey, number> = {\n chatMessage: 0.25,\n handRaise: 0.25,\n userJoin: 0.25,\n userLeft: 0.25,\n boardTimerEnd: 1,\n boardTimerWarn: 1,\n};\n\nconst VOLUME_KEY_MAP: Record<SoundKey, keyof SoundEffectsState> = {\n chatMessage: 'chatMessageVolume',\n handRaise: 'handRaiseVolume',\n userJoin: 'userJoinVolume',\n userLeft: 'userLeftVolume',\n boardTimerEnd: 'boardTimerEndVolume',\n boardTimerWarn: 'boardTimerWarnVolume',\n};\n\nconst clamp = (value: number, min: number, max: number) => Math.max(min, Math.min(max, value));\n\nexport const useSoundEffectsStore = create<SoundEffectsState>()(\n persist(\n (set, get) => ({\n chatMessageVolume: DEFAULTS.chatMessage,\n handRaiseVolume: DEFAULTS.handRaise,\n userJoinVolume: DEFAULTS.userJoin,\n userLeftVolume: DEFAULTS.userLeft,\n boardTimerEndVolume: DEFAULTS.boardTimerEnd,\n boardTimerWarnVolume: DEFAULTS.boardTimerWarn,\n\n setSoundVolume: (key, volume) => {\n const min = key === 'boardTimerEnd' ? 0.2 : 0;\n const clamped = clamp(volume, min, 1);\n set({ [VOLUME_KEY_MAP[key]]: clamped });\n },\n\n getEffectiveVolume: (key) => {\n const storeKey = VOLUME_KEY_MAP[key];\n return get()[storeKey] as number;\n },\n }),\n {\n name: 'sound-effects-store',\n version: 1,\n partialize: (state) => ({\n chatMessageVolume: state.chatMessageVolume,\n handRaiseVolume: state.handRaiseVolume,\n userJoinVolume: state.userJoinVolume,\n userLeftVolume: state.userLeftVolume,\n boardTimerEndVolume: state.boardTimerEndVolume,\n boardTimerWarnVolume: state.boardTimerWarnVolume,\n }),\n },\n ),\n);\n\nexport { DEFAULTS as SOUND_DEFAULTS };\nexport type { SoundKey };\n","import { create } from 'zustand';\n\nexport type FeatureKey = 'compactView' | 'whiteboard' | 'raiseHand' | 'chat';\n\ntype FeatureMapT = Record<FeatureKey, boolean>;\n\ntype FeaturesState = {\n features: FeatureMapT;\n\n setFeature: (key: FeatureKey, value: boolean) => void;\n setFeatures: (features: Partial<FeatureMapT>) => void;\n};\n\nconst defaultFeatures: FeatureMapT = {\n compactView: true,\n whiteboard: true,\n raiseHand: true,\n chat: true,\n};\n\nexport const useFeaturesStore = create<FeaturesState>((set) => ({\n features: defaultFeatures,\n\n setFeature: (key, value) =>\n set((state) => ({\n features: { ...state.features, [key]: value },\n })),\n\n setFeatures: (features) =>\n set((state) => ({\n features: { ...state.features, ...features },\n })),\n}));\n","import { create } from 'zustand';\n\ninterface FocusModeState {\n focusMode: boolean;\n setFocusMode: (value: boolean) => void;\n toggleFocusMode: () => void;\n}\n\nexport const useFocusModeStore = create<FocusModeState>((set) => ({\n focusMode: false,\n setFocusMode: (value) => set({ focusMode: value }),\n toggleFocusMode: () => set((state) => ({ focusMode: !state.focusMode })),\n}));\n"]}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@xipkg/calls-store",
3
+ "version": "0.0.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "development": "./index.ts",
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.mjs",
10
+ "default": "./dist/index.mjs"
11
+ }
12
+ },
13
+ "license": "MIT",
14
+ "scripts": {
15
+ "lint": "eslint \"**/*.{ts,tsx}\"",
16
+ "dev": "tsup --watch",
17
+ "build": "tsup"
18
+ },
19
+ "dependencies": {
20
+ "zustand": "5.0.3",
21
+ "@xipkg/calls-types": "*"
22
+ },
23
+ "devDependencies": {
24
+ "@tanstack/react-query-devtools": "5.73.3",
25
+ "@eslint/js": "^9.19.0",
26
+ "common.typescript": "*",
27
+ "@types/node": "^20.3.1",
28
+ "@types/react": "^19.0.2",
29
+ "@types/react-dom": "^19.0.2",
30
+ "@xipkg/eslint": "3.2.0",
31
+ "@xipkg/typescript": "latest",
32
+ "common.eslint": "*",
33
+ "eslint": "^9.19.0",
34
+ "eslint-plugin-react-hooks": "^5.0.0",
35
+ "eslint-plugin-react-refresh": "^0.4.18",
36
+ "globals": "^15.14.0",
37
+ "typescript": "~5.7.2",
38
+ "typescript-eslint": "^8.22.0"
39
+ },
40
+ "peerDependencies": {
41
+ "react": "19"
42
+ },
43
+ "description": "@xipkg/calls-store",
44
+ "author": "xi.effect",
45
+ "main": "./dist/index.mjs",
46
+ "types": "./dist/index.d.ts",
47
+ "files": [
48
+ "dist"
49
+ ],
50
+ "publishConfig": {
51
+ "access": "public"
52
+ }
53
+ }