@oxyhq/services 5.16.26 → 5.16.27
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/lib/commonjs/ui/context/OxyContext.js +88 -196
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/useTransferQueries.js +137 -0
- package/lib/commonjs/ui/hooks/useTransferQueries.js.map +1 -0
- package/lib/commonjs/ui/stores/transferStore.js +161 -0
- package/lib/commonjs/ui/stores/transferStore.js.map +1 -0
- package/lib/module/ui/context/OxyContext.js +88 -196
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/useTransferQueries.js +132 -0
- package/lib/module/ui/hooks/useTransferQueries.js.map +1 -0
- package/lib/module/ui/stores/transferStore.js +155 -0
- package/lib/module/ui/stores/transferStore.js.map +1 -0
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useTransferQueries.d.ts +36 -0
- package/lib/typescript/ui/hooks/useTransferQueries.d.ts.map +1 -0
- package/lib/typescript/ui/stores/transferStore.d.ts +39 -0
- package/lib/typescript/ui/stores/transferStore.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/ui/context/OxyContext.tsx +86 -205
- package/src/ui/hooks/useTransferQueries.ts +154 -0
- package/src/ui/stores/transferStore.ts +201 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
import { useShallow } from 'zustand/react/shallow';
|
|
3
|
+
|
|
4
|
+
export interface TransferCodeData {
|
|
5
|
+
code: string;
|
|
6
|
+
sourceDeviceId: string | null;
|
|
7
|
+
publicKey: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
state: 'pending' | 'completed' | 'failed';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface TransferState {
|
|
13
|
+
// Transfer codes map: transferId -> TransferCodeData
|
|
14
|
+
transferCodes: Record<string, TransferCodeData>;
|
|
15
|
+
|
|
16
|
+
// Active transfer ID (only one active transfer at a time)
|
|
17
|
+
activeTransferId: string | null;
|
|
18
|
+
|
|
19
|
+
// Restoration flag to prevent duplicate restorations
|
|
20
|
+
isRestored: boolean;
|
|
21
|
+
|
|
22
|
+
// Actions
|
|
23
|
+
storeTransferCode: (transferId: string, code: string, sourceDeviceId: string | null, publicKey: string) => void;
|
|
24
|
+
getTransferCode: (transferId: string) => TransferCodeData | null;
|
|
25
|
+
clearTransferCode: (transferId: string) => void;
|
|
26
|
+
updateTransferState: (transferId: string, state: 'pending' | 'completed' | 'failed') => void;
|
|
27
|
+
getAllPendingTransfers: () => Array<{ transferId: string; data: TransferCodeData }>;
|
|
28
|
+
getActiveTransferId: () => string | null;
|
|
29
|
+
setActiveTransferId: (transferId: string | null) => void;
|
|
30
|
+
restoreFromStorage: (codes: Record<string, TransferCodeData>, activeTransferId: string | null) => void;
|
|
31
|
+
markRestored: () => void;
|
|
32
|
+
cleanupExpired: () => void;
|
|
33
|
+
reset: () => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const FIFTEEN_MINUTES = 15 * 60 * 1000;
|
|
37
|
+
|
|
38
|
+
const initialState = {
|
|
39
|
+
transferCodes: {} as Record<string, TransferCodeData>,
|
|
40
|
+
activeTransferId: null as string | null,
|
|
41
|
+
isRestored: false,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const useTransferStore = create<TransferState>((set, get) => ({
|
|
45
|
+
...initialState,
|
|
46
|
+
|
|
47
|
+
storeTransferCode: (transferId: string, code: string, sourceDeviceId: string | null, publicKey: string) => {
|
|
48
|
+
set((state) => ({
|
|
49
|
+
transferCodes: {
|
|
50
|
+
...state.transferCodes,
|
|
51
|
+
[transferId]: {
|
|
52
|
+
code,
|
|
53
|
+
sourceDeviceId,
|
|
54
|
+
publicKey,
|
|
55
|
+
timestamp: Date.now(),
|
|
56
|
+
state: 'pending',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
activeTransferId: transferId,
|
|
60
|
+
}));
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
getTransferCode: (transferId: string) => {
|
|
64
|
+
const state = get();
|
|
65
|
+
return state.transferCodes[transferId] || null;
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
clearTransferCode: (transferId: string) => {
|
|
69
|
+
set((state) => {
|
|
70
|
+
const { [transferId]: removed, ...rest } = state.transferCodes;
|
|
71
|
+
const newActiveTransferId = state.activeTransferId === transferId ? null : state.activeTransferId;
|
|
72
|
+
return {
|
|
73
|
+
transferCodes: rest,
|
|
74
|
+
activeTransferId: newActiveTransferId,
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
updateTransferState: (transferId: string, newState: 'pending' | 'completed' | 'failed') => {
|
|
80
|
+
set((state) => {
|
|
81
|
+
const existing = state.transferCodes[transferId];
|
|
82
|
+
if (!existing) {
|
|
83
|
+
return state;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const updated = {
|
|
87
|
+
...existing,
|
|
88
|
+
state: newState,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Clear active transfer if completed or failed
|
|
92
|
+
const newActiveTransferId =
|
|
93
|
+
(newState === 'completed' || newState === 'failed') && state.activeTransferId === transferId
|
|
94
|
+
? null
|
|
95
|
+
: state.activeTransferId;
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
transferCodes: {
|
|
99
|
+
...state.transferCodes,
|
|
100
|
+
[transferId]: updated,
|
|
101
|
+
},
|
|
102
|
+
activeTransferId: newActiveTransferId,
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
getAllPendingTransfers: () => {
|
|
108
|
+
const state = get();
|
|
109
|
+
const pending: Array<{ transferId: string; data: TransferCodeData }> = [];
|
|
110
|
+
|
|
111
|
+
Object.entries(state.transferCodes).forEach(([transferId, data]) => {
|
|
112
|
+
if (data.state === 'pending') {
|
|
113
|
+
pending.push({ transferId, data });
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
return pending;
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
getActiveTransferId: () => {
|
|
121
|
+
return get().activeTransferId;
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
setActiveTransferId: (transferId: string | null) => {
|
|
125
|
+
set({ activeTransferId: transferId });
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
restoreFromStorage: (codes: Record<string, TransferCodeData>, activeTransferId: string | null) => {
|
|
129
|
+
const now = Date.now();
|
|
130
|
+
const validCodes: Record<string, TransferCodeData> = {};
|
|
131
|
+
|
|
132
|
+
// Only restore non-expired pending transfers
|
|
133
|
+
Object.entries(codes).forEach(([transferId, data]) => {
|
|
134
|
+
if (data.state === 'pending' && (now - data.timestamp) < FIFTEEN_MINUTES) {
|
|
135
|
+
validCodes[transferId] = data;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Verify active transfer is still valid
|
|
140
|
+
let validActiveTransferId = activeTransferId;
|
|
141
|
+
if (activeTransferId && (!validCodes[activeTransferId] || validCodes[activeTransferId].state !== 'pending')) {
|
|
142
|
+
validActiveTransferId = null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
set({
|
|
146
|
+
transferCodes: validCodes,
|
|
147
|
+
activeTransferId: validActiveTransferId,
|
|
148
|
+
isRestored: true,
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
markRestored: () => {
|
|
153
|
+
set({ isRestored: true });
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
cleanupExpired: () => {
|
|
157
|
+
const now = Date.now();
|
|
158
|
+
set((state) => {
|
|
159
|
+
const validCodes: Record<string, TransferCodeData> = {};
|
|
160
|
+
let newActiveTransferId = state.activeTransferId;
|
|
161
|
+
|
|
162
|
+
Object.entries(state.transferCodes).forEach(([transferId, data]) => {
|
|
163
|
+
const age = now - data.timestamp;
|
|
164
|
+
if (age < FIFTEEN_MINUTES) {
|
|
165
|
+
validCodes[transferId] = data;
|
|
166
|
+
} else if (transferId === state.activeTransferId) {
|
|
167
|
+
newActiveTransferId = null;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
transferCodes: validCodes,
|
|
173
|
+
activeTransferId: newActiveTransferId,
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
reset: () => {
|
|
179
|
+
set(initialState);
|
|
180
|
+
},
|
|
181
|
+
}));
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Hook to get transfer codes for persistence
|
|
185
|
+
*/
|
|
186
|
+
export const useTransferCodesForPersistence = () => {
|
|
187
|
+
return useTransferStore(
|
|
188
|
+
useShallow((state) => ({
|
|
189
|
+
transferCodes: state.transferCodes,
|
|
190
|
+
activeTransferId: state.activeTransferId,
|
|
191
|
+
}))
|
|
192
|
+
);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Hook to check if store has been restored
|
|
197
|
+
*/
|
|
198
|
+
export const useTransferStoreRestored = () => {
|
|
199
|
+
return useTransferStore((state) => state.isRestored);
|
|
200
|
+
};
|
|
201
|
+
|