@oxyhq/services 22.6.4 → 22.8.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.
Files changed (48) hide show
  1. package/android/src/main/java/so/oxy/identity/OxyIdentityStore.kt +109 -14
  2. package/lib/commonjs/ui/boot/runProviderColdBoot.js +66 -1
  3. package/lib/commonjs/ui/boot/runProviderColdBoot.js.map +1 -1
  4. package/lib/commonjs/ui/components/fileManagement/AnimatedButton.js +7 -1
  5. package/lib/commonjs/ui/components/fileManagement/AnimatedButton.js.map +1 -1
  6. package/lib/commonjs/ui/context/OxyContext.js +43 -0
  7. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  8. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +17 -1
  9. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
  10. package/lib/commonjs/ui/screens/FileManagementScreen.js +6 -51
  11. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  12. package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js +130 -57
  13. package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
  14. package/lib/module/ui/boot/runProviderColdBoot.js +64 -0
  15. package/lib/module/ui/boot/runProviderColdBoot.js.map +1 -1
  16. package/lib/module/ui/components/fileManagement/AnimatedButton.js +7 -1
  17. package/lib/module/ui/components/fileManagement/AnimatedButton.js.map +1 -1
  18. package/lib/module/ui/context/OxyContext.js +44 -1
  19. package/lib/module/ui/context/OxyContext.js.map +1 -1
  20. package/lib/module/ui/hooks/queries/useAccountQueries.js +17 -1
  21. package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
  22. package/lib/module/ui/screens/FileManagementScreen.js +1 -46
  23. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  24. package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js +130 -57
  25. package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
  26. package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts +12 -0
  27. package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts.map +1 -1
  28. package/lib/typescript/commonjs/ui/components/fileManagement/AnimatedButton.d.ts +1 -0
  29. package/lib/typescript/commonjs/ui/components/fileManagement/AnimatedButton.d.ts.map +1 -1
  30. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  31. package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  32. package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts.map +1 -1
  33. package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
  34. package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts +12 -0
  35. package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts.map +1 -1
  36. package/lib/typescript/module/ui/components/fileManagement/AnimatedButton.d.ts +1 -0
  37. package/lib/typescript/module/ui/components/fileManagement/AnimatedButton.d.ts.map +1 -1
  38. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  39. package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  40. package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
  41. package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
  42. package/package.json +4 -4
  43. package/src/ui/boot/runProviderColdBoot.ts +67 -0
  44. package/src/ui/components/fileManagement/AnimatedButton.tsx +9 -1
  45. package/src/ui/context/OxyContext.tsx +43 -1
  46. package/src/ui/hooks/queries/useAccountQueries.ts +16 -0
  47. package/src/ui/screens/FileManagementScreen.tsx +1 -54
  48. package/src/ui/screens/fileManagement/PhotoPickerSection.tsx +131 -54
@@ -151,14 +151,61 @@ export interface PhotoPickerViewProps {
151
151
  * Apple Photos pattern: when any cell is selected, *non-selected* siblings
152
152
  * fade to 0.6 opacity to focus attention on the active selection.
153
153
  */
154
- const PhotoPickerCell = React.memo(function PhotoPickerCell(props: {
154
+ /**
155
+ * Shared cell chrome (image, dim, badge). Ring border is injected by the
156
+ * static vs animated wrappers so web never touches Reanimated worklets.
157
+ */
158
+ function PhotoPickerCellContent(props: {
159
+ photo: FileMetadata;
160
+ dim: boolean;
161
+ isSelected: boolean;
162
+ selectionIndex: number;
163
+ primaryColor: string;
164
+ thumbUrl: string | undefined;
165
+ ring: React.ReactNode;
166
+ }) {
167
+ const {
168
+ photo, dim, isSelected, selectionIndex, primaryColor, thumbUrl, ring,
169
+ } = props;
170
+
171
+ return (
172
+ <>
173
+ <View
174
+ className={`flex-1 rounded-radius-8 overflow-hidden bg-[#111111]${dim ? ' opacity-60' : ''}`}
175
+ >
176
+ <ExpoImage
177
+ source={{ uri: thumbUrl }}
178
+ style={{ width: '100%', height: '100%' }}
179
+ contentFit="cover"
180
+ transition={120}
181
+ cachePolicy="memory-disk"
182
+ accessibilityLabel={photo.filename}
183
+ />
184
+ </View>
185
+ {ring}
186
+ {isSelected && (
187
+ <View
188
+ pointerEvents="none"
189
+ className="absolute top-1.5 right-1.5 min-w-[22px] h-[22px] px-1.5 rounded-full items-center justify-center"
190
+ style={{ backgroundColor: primaryColor }}
191
+ >
192
+ <Text className="text-white text-[12px] font-bold leading-[14px]">
193
+ {selectionIndex > 0 ? String(selectionIndex) : ''}
194
+ </Text>
195
+ </View>
196
+ )}
197
+ </>
198
+ );
199
+ }
200
+
201
+ type PhotoPickerCellProps = {
155
202
  photo: FileMetadata;
156
203
  size: number;
157
204
  marginRight: number;
158
205
  marginBottom: number;
159
206
  isSelected: boolean;
160
- selectionIndex: number; // 1-based for badge; 0 if not selected
161
- dim: boolean; // any selection exists and this cell is not selected
207
+ selectionIndex: number;
208
+ dim: boolean;
162
209
  primaryColor: string;
163
210
  thumbUrl: string | undefined;
164
211
  enterIndex: number;
@@ -166,21 +213,64 @@ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: {
166
213
  onPress: () => void;
167
214
  onLongPress: () => void;
168
215
  a11yLabel: string;
169
- }) {
216
+ };
217
+
218
+ const PhotoPickerCellStatic = React.memo(function PhotoPickerCellStatic(props: PhotoPickerCellProps) {
219
+ const {
220
+ photo, size, marginRight, marginBottom, isSelected, selectionIndex,
221
+ dim, primaryColor, thumbUrl, onPress, onLongPress, a11yLabel,
222
+ } = props;
223
+
224
+ const cellWrapperStyle = {
225
+ width: size,
226
+ height: size,
227
+ marginRight,
228
+ marginBottom,
229
+ };
230
+
231
+ const ring = isSelected ? (
232
+ <View
233
+ pointerEvents="none"
234
+ className="absolute inset-0 rounded-radius-8 border-[3px]"
235
+ style={{ borderColor: primaryColor }}
236
+ />
237
+ ) : null;
238
+
239
+ return (
240
+ <TouchableOpacity
241
+ activeOpacity={0.85}
242
+ onPress={onPress}
243
+ onLongPress={onLongPress}
244
+ className="relative"
245
+ style={cellWrapperStyle}
246
+ accessibilityRole="button"
247
+ accessibilityLabel={a11yLabel}
248
+ accessibilityState={{ selected: isSelected }}
249
+ >
250
+ <PhotoPickerCellContent
251
+ photo={photo}
252
+ dim={dim}
253
+ isSelected={isSelected}
254
+ selectionIndex={selectionIndex}
255
+ primaryColor={primaryColor}
256
+ thumbUrl={thumbUrl}
257
+ ring={ring}
258
+ />
259
+ </TouchableOpacity>
260
+ );
261
+ });
262
+
263
+ const PhotoPickerCellAnimated = React.memo(function PhotoPickerCellAnimated(props: PhotoPickerCellProps) {
170
264
  const {
171
265
  photo, size, marginRight, marginBottom, isSelected, selectionIndex,
172
266
  dim, primaryColor, thumbUrl, enterIndex, reduceMotion, onPress,
173
267
  onLongPress, a11yLabel,
174
268
  } = props;
175
269
 
176
- // Cap the cumulative stagger at ~800ms total so the very long grid does
177
- // not keep fading in late tiles. Beyond ~53 tiles the delay maxes out.
178
270
  const STAGGER_PER_CELL_MS = 15;
179
271
  const MAX_TOTAL_STAGGER_MS = 800;
180
272
  const delay = Math.min(enterIndex * STAGGER_PER_CELL_MS, MAX_TOTAL_STAGGER_MS);
181
273
 
182
- // Selection ring pulse animation: 1.0 → 1.05 → 1.0 on transition to
183
- // selected. Plays at most once per selection change; reduce-motion skips.
184
274
  const ringScale = useSharedValue(1);
185
275
  const prevSelected = useRef(isSelected);
186
276
  useEffect(() => {
@@ -204,8 +294,6 @@ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: {
204
294
  transform: [{ scale: ringScale.value }],
205
295
  }));
206
296
 
207
- // Per-tile pixel geometry is derived from the measured grid width, so it
208
- // stays an inline `style` — NativeWind cannot express a runtime pixel size.
209
297
  const cellWrapperStyle = {
210
298
  width: size,
211
299
  height: size,
@@ -213,49 +301,15 @@ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: {
213
301
  marginBottom,
214
302
  };
215
303
 
216
- const inner = (
217
- <>
218
- <View
219
- className={`flex-1 rounded-radius-8 overflow-hidden bg-[#111111]${dim ? ' opacity-60' : ''}`}
220
- >
221
- <ExpoImage
222
- source={{ uri: thumbUrl }}
223
- // expo-image is a third-party component (no NativeWind
224
- // className remap), so fill via inline style.
225
- style={{ width: '100%', height: '100%' }}
226
- contentFit="cover"
227
- transition={120}
228
- cachePolicy="memory-disk"
229
- accessibilityLabel={photo.filename}
230
- />
231
- </View>
232
- {isSelected && (
233
- <Reanimated.View
234
- pointerEvents="none"
235
- className="absolute inset-0 rounded-radius-8 border-[3px]"
236
- // borderColor is the theme primary (dynamic); the animated
237
- // scale transform must ride on `style` too.
238
- style={[{ borderColor: primaryColor }, ringAnimatedStyle]}
239
- />
240
- )}
241
- {isSelected && (
242
- <View
243
- pointerEvents="none"
244
- className="absolute top-1.5 right-1.5 min-w-[22px] h-[22px] px-1.5 rounded-full items-center justify-center"
245
- style={{ backgroundColor: primaryColor }}
246
- >
247
- <Text className="text-white text-[12px] font-bold leading-[14px]">
248
- {selectionIndex > 0 ? String(selectionIndex) : ''}
249
- </Text>
250
- </View>
251
- )}
252
- </>
253
- );
304
+ const ring = isSelected ? (
305
+ <Reanimated.View
306
+ pointerEvents="none"
307
+ className="absolute inset-0 rounded-radius-8 border-[3px]"
308
+ style={[{ borderColor: primaryColor }, ringAnimatedStyle]}
309
+ />
310
+ ) : null;
254
311
 
255
- // Reanimated layout `entering` animations don't load on web (no worklets
256
- // babel plugin in the RN-Web build) — they warn and no-op. So on web (and
257
- // when reduce-motion is set) render the plain cell with no entering stagger.
258
- if (reduceMotion || Platform.OS === 'web') {
312
+ if (reduceMotion) {
259
313
  return (
260
314
  <TouchableOpacity
261
315
  activeOpacity={0.85}
@@ -267,7 +321,15 @@ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: {
267
321
  accessibilityLabel={a11yLabel}
268
322
  accessibilityState={{ selected: isSelected }}
269
323
  >
270
- {inner}
324
+ <PhotoPickerCellContent
325
+ photo={photo}
326
+ dim={dim}
327
+ isSelected={isSelected}
328
+ selectionIndex={selectionIndex}
329
+ primaryColor={primaryColor}
330
+ thumbUrl={thumbUrl}
331
+ ring={ring}
332
+ />
271
333
  </TouchableOpacity>
272
334
  );
273
335
  }
@@ -287,12 +349,27 @@ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: {
287
349
  accessibilityLabel={a11yLabel}
288
350
  accessibilityState={{ selected: isSelected }}
289
351
  >
290
- {inner}
352
+ <PhotoPickerCellContent
353
+ photo={photo}
354
+ dim={dim}
355
+ isSelected={isSelected}
356
+ selectionIndex={selectionIndex}
357
+ primaryColor={primaryColor}
358
+ thumbUrl={thumbUrl}
359
+ ring={ring}
360
+ />
291
361
  </TouchableOpacity>
292
362
  </Reanimated.View>
293
363
  );
294
364
  });
295
365
 
366
+ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: PhotoPickerCellProps) {
367
+ if (Platform.OS === 'web') {
368
+ return <PhotoPickerCellStatic {...props} />;
369
+ }
370
+ return <PhotoPickerCellAnimated {...props} />;
371
+ });
372
+
296
373
  const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
297
374
  photos,
298
375
  selectedIds,