@scalemule/nextjs 0.1.8 → 0.1.9
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 +61 -1
- package/dist/index.d.mts +65 -27
- package/dist/index.d.ts +65 -27
- package/dist/index.js +43 -3
- package/dist/index.mjs +43 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -132,7 +132,67 @@ function LoginPage() {
|
|
|
132
132
|
}
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
### `
|
|
135
|
+
### `useMedia()` — recommended for image / video / audio uploads
|
|
136
|
+
|
|
137
|
+
One hook covers every MIME type, defaults to private, and auto-routes images
|
|
138
|
+
through the photo pipeline (optimization, transform breakpoints) and videos
|
|
139
|
+
through the video pipeline (HLS transcoding). Drop the result `file_id` into
|
|
140
|
+
a chat message or render it with `<ScaleMuleMedia />` and progressive
|
|
141
|
+
enhancement just works.
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
import { useMedia, ScaleMuleMedia } from '@scalemule/nextjs'
|
|
145
|
+
|
|
146
|
+
function Composer({ conversationId }: { conversationId: string }) {
|
|
147
|
+
const { upload, uploading } = useMedia()
|
|
148
|
+
|
|
149
|
+
async function handleFile(file: File) {
|
|
150
|
+
const result = await upload(file)
|
|
151
|
+
// result.file_id is private by default; post the message with it.
|
|
152
|
+
await postMessage({ conversationId, attachments: [{ file_id: result.file_id }] })
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return <input type="file" disabled={uploading} onChange={(e) => handleFile(e.target.files![0])} />
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function Attachment({ fileId, conversationId, mimeType }: {
|
|
159
|
+
fileId: string; conversationId: string; mimeType: string
|
|
160
|
+
}) {
|
|
161
|
+
// <ScaleMuleMedia /> uses useFileStatus internally; with conversationId
|
|
162
|
+
// it subscribes to the conversation channel for live optimize/transcode
|
|
163
|
+
// updates instead of polling.
|
|
164
|
+
return (
|
|
165
|
+
<ScaleMuleMedia
|
|
166
|
+
fileId={fileId}
|
|
167
|
+
mimeType={mimeType}
|
|
168
|
+
conversationId={conversationId}
|
|
169
|
+
/>
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
See [`docs/MEDIA-UPLOADS.md`](https://github.com/scalemule/scalemule-repos/blob/main/docs/MEDIA-UPLOADS.md)
|
|
175
|
+
for the full decision tree (which hook for which app, fast/safe policy modes,
|
|
176
|
+
private vs public visibility, anti-patterns).
|
|
177
|
+
|
|
178
|
+
### `useFileStatus()` — read-side progressive enhancement
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
import { useFileStatus } from '@scalemule/nextjs'
|
|
182
|
+
|
|
183
|
+
// Chat surface — subscribe to the conversation channel for push updates.
|
|
184
|
+
const { status, isReady } = useFileStatus({ fileId, conversationId })
|
|
185
|
+
|
|
186
|
+
// Non-chat — pull-only with optional polling.
|
|
187
|
+
const { status, isReady } = useFileStatus({ fileId, pollIntervalMs: 2000 })
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### `useContent()` — generic file uploads (legacy)
|
|
191
|
+
|
|
192
|
+
> **Deprecated for chat / progressive media.** Use `useMedia()` instead.
|
|
193
|
+
> `useContent()` remains available for plain non-image/video file lists
|
|
194
|
+
> (documents, downloads). It does not auto-route through the photo/video
|
|
195
|
+
> pipelines and does not enforce private-by-default for chat surfaces.
|
|
136
196
|
|
|
137
197
|
```tsx
|
|
138
198
|
import { useContent } from '@scalemule/nextjs'
|
package/dist/index.d.mts
CHANGED
|
@@ -324,25 +324,39 @@ interface UseContentOptions {
|
|
|
324
324
|
*/
|
|
325
325
|
declare function useContent(options?: UseContentOptions): UseContentReturn;
|
|
326
326
|
|
|
327
|
+
/**
|
|
328
|
+
* Conversation kinds recognized by the chat realtime channel naming scheme.
|
|
329
|
+
* Matches `broadcast_to_conversation` in `ms/scalemule-chat/src/realtime.rs`.
|
|
330
|
+
*/
|
|
331
|
+
type ConversationKind = 'standard' | 'large_room' | 'broadcast' | 'support';
|
|
327
332
|
interface UseFileStatusOptions {
|
|
328
333
|
/** Storage file_id to read status for. */
|
|
329
334
|
fileId: string | null | undefined;
|
|
330
335
|
/**
|
|
331
336
|
* Optional poll interval in milliseconds. If set, the hook re-fetches
|
|
332
|
-
* status every `pollIntervalMs
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
* Polling stops automatically once `scan.status === 'clean'` AND the
|
|
336
|
-
* caller's expected pipeline is done (`urls.optimized` returns 200 for
|
|
337
|
-
* images, `urls.hls` returns 200 for videos). Today the hook can only
|
|
338
|
-
* detect scan clean — broader pipeline-done detection lands when Phase 3
|
|
339
|
-
* enriches the optimize/transcode response fields.
|
|
337
|
+
* status every `pollIntervalMs` until scan goes clean. Useful for
|
|
338
|
+
* non-chat surfaces or as a fallback alongside `conversationId` push.
|
|
340
339
|
*/
|
|
341
340
|
pollIntervalMs?: number | null;
|
|
341
|
+
/** Disable the hook (don't fetch). Useful when `fileId` is conditional. */
|
|
342
|
+
disabled?: boolean;
|
|
342
343
|
/**
|
|
343
|
-
*
|
|
344
|
+
* Chat-surface push variant: subscribe to the conversation's realtime
|
|
345
|
+
* channel and refresh when a `file_status_changed` event arrives for
|
|
346
|
+
* `fileId`. Auth rides the existing per-conversation channel ACL.
|
|
344
347
|
*/
|
|
345
|
-
|
|
348
|
+
conversationId?: string | null;
|
|
349
|
+
/**
|
|
350
|
+
* Conversation kind, controls the channel name prefix:
|
|
351
|
+
* - `standard` (default) → `conversation:{id}`
|
|
352
|
+
* - `large_room` → `conversation:lr:{id}`
|
|
353
|
+
* - `broadcast` → `conversation:bc:{id}`
|
|
354
|
+
* - `support` → `conversation:support:{id}`
|
|
355
|
+
*
|
|
356
|
+
* If you only have a `messageId`, look up the conversation first via
|
|
357
|
+
* `client.chat.getMessage(messageId)` and pass the result here.
|
|
358
|
+
*/
|
|
359
|
+
conversationKind?: ConversationKind;
|
|
346
360
|
}
|
|
347
361
|
interface UseFileStatusReturn {
|
|
348
362
|
/** The latest status response, or null on first render / disabled. */
|
|
@@ -362,29 +376,39 @@ interface UseFileStatusReturn {
|
|
|
362
376
|
refresh: () => Promise<void>;
|
|
363
377
|
}
|
|
364
378
|
/**
|
|
365
|
-
* Subscribes to {@link FileStatus} for a single file.
|
|
366
|
-
* pull-only hook — single fetch by default, optional polling.
|
|
379
|
+
* Subscribes to {@link FileStatus} for a single file.
|
|
367
380
|
*
|
|
368
|
-
*
|
|
369
|
-
* for chat surfaces — `useFileStatus({ messageId })` will subscribe to
|
|
370
|
-
* `file.status` events on the existing per-conversation realtime channel
|
|
371
|
-
* via the `scalemule-chat` translation bridge (P5'). Until that lands,
|
|
372
|
-
* customers using this hook from chat surfaces should pass `pollIntervalMs`
|
|
373
|
-
* in the 1–3 second range while a media pipeline is expected to be running,
|
|
374
|
-
* then drop the polling once `isReady` is true.
|
|
381
|
+
* Three call shapes:
|
|
375
382
|
*
|
|
376
|
-
*
|
|
383
|
+
* 1. **Pull-only** — `useFileStatus({ fileId })` plus optional `pollIntervalMs`.
|
|
384
|
+
* One-shot fetch; useful for non-chat surfaces or static reads.
|
|
385
|
+
*
|
|
386
|
+
* 2. **Chat-surface push** — `useFileStatus({ fileId, conversationId, conversationKind? })`.
|
|
387
|
+
* Subscribes to the conversation channel and refreshes when
|
|
388
|
+
* `file_status_changed` arrives for this `fileId`. The chat service's
|
|
389
|
+
* media-status bridge fans photo/video lifecycle events into the per-conversation
|
|
390
|
+
* channel; the hook drops events for other files and dedupes against polling.
|
|
391
|
+
*
|
|
392
|
+
* 3. **Push + slow poll fallback** — combine `conversationId` with `pollIntervalMs`
|
|
393
|
+
* if you want belt-and-suspenders for environments where the websocket may drop.
|
|
394
|
+
*
|
|
395
|
+
* The `surface: 'profile'` push variant (private-user channel) is deferred until
|
|
396
|
+
* the realtime SDK exposes private-channel subscription by user.
|
|
397
|
+
*
|
|
398
|
+
* @example Chat surface (push)
|
|
377
399
|
* ```tsx
|
|
378
|
-
* function ChatImage({ fileId }: { fileId: string }) {
|
|
379
|
-
* const { status, isReady } = useFileStatus({
|
|
380
|
-
* fileId,
|
|
381
|
-
* pollIntervalMs: 2000,
|
|
382
|
-
* });
|
|
400
|
+
* function ChatImage({ fileId, conversationId }: { fileId: string; conversationId: string }) {
|
|
401
|
+
* const { status, isReady } = useFileStatus({ fileId, conversationId });
|
|
383
402
|
* if (!isReady) return <div>Scanning…</div>;
|
|
384
403
|
* const src = status?.urls.optimized ?? status?.urls.original;
|
|
385
404
|
* return <img src={src} />;
|
|
386
405
|
* }
|
|
387
406
|
* ```
|
|
407
|
+
*
|
|
408
|
+
* @example Non-chat surface (pull + poll)
|
|
409
|
+
* ```tsx
|
|
410
|
+
* const { status, isReady } = useFileStatus({ fileId, pollIntervalMs: 2000 });
|
|
411
|
+
* ```
|
|
388
412
|
*/
|
|
389
413
|
declare function useFileStatus(options: UseFileStatusOptions): UseFileStatusReturn;
|
|
390
414
|
|
|
@@ -413,9 +437,23 @@ interface ScaleMuleMediaProps {
|
|
|
413
437
|
/**
|
|
414
438
|
* Polling interval while waiting for the media pipeline to complete.
|
|
415
439
|
* Defaults to 2000ms; set to `null` to disable polling. Polling stops
|
|
416
|
-
* automatically once scan is clean.
|
|
440
|
+
* automatically once scan is clean. When `conversationId` is set the
|
|
441
|
+
* component receives push updates and you can usually pass `null`.
|
|
417
442
|
*/
|
|
418
443
|
pollIntervalMs?: number | null;
|
|
444
|
+
/**
|
|
445
|
+
* Chat-surface push: when set, the underlying `useFileStatus` hook
|
|
446
|
+
* subscribes to the conversation's realtime channel and refreshes on
|
|
447
|
+
* `file_status_changed` events for this `fileId`. See `useFileStatus`
|
|
448
|
+
* docs for channel naming and bridge behaviour.
|
|
449
|
+
*/
|
|
450
|
+
conversationId?: string | null;
|
|
451
|
+
/**
|
|
452
|
+
* Conversation kind, controls the channel name prefix
|
|
453
|
+
* (`conversation:{id}` vs `conversation:lr|bc|support:{id}`).
|
|
454
|
+
* Default is `'standard'`.
|
|
455
|
+
*/
|
|
456
|
+
conversationKind?: ConversationKind;
|
|
419
457
|
/**
|
|
420
458
|
* Render a custom placeholder while waiting for scan / upload. Defaults
|
|
421
459
|
* to a tiny "Loading…" div. Receives the current FileStatus (or null).
|
|
@@ -950,4 +988,4 @@ declare function createSafeLogger(prefix: string): {
|
|
|
950
988
|
error: (message: string, data?: unknown) => void;
|
|
951
989
|
};
|
|
952
990
|
|
|
953
|
-
export { ApiError$1 as ApiError, type FeatureFlagEvaluation, type FeatureFlagEvaluation as FeatureFlagResult, type FeedbackItem, type FeedbackItemInput, type FeedbackPriority, type FeedbackStatus, type FeedbackType, FeedbackWidget, type FeedbackWidgetConfig, type FeedbackWidgetProps, ListFilesParams, LoginResponse, type MediaPolicy, type MediaUploadResult, type PasswordValidationResult, type PhoneCountry, type PhoneValidationResult, type RealtimeEvent, type RealtimeMessage, type RealtimeStatus, ScaleMuleClient, ScaleMuleConfig, ScaleMuleMedia, type ScaleMuleMediaProps, ScaleMuleProvider, type ScaleMuleProviderProps, UseAnalyticsOptions, UseAnalyticsReturn, UseAuthReturn, UseBillingReturn, UseContentReturn, type UseFeatureFlagsOptions, type UseFeatureFlagsReturn, type UseFeedbackOptions, type UseFeedbackResult, type UseFileStatusOptions, type UseFileStatusReturn, type UseFeatureFlagsOptions as UseFlagsOptions, type UseFeatureFlagsReturn as UseFlagsReturn, type UseMediaReturn, type UseMediaUploadOptions, type UsePushNotificationsOptions, type UsePushNotificationsReturn, type UseRealtimeOptions, type UseRealtimeReturn, type UseShareOptions, type UseShareReturn, UseUserReturn, User, type UsernameValidationResult, composePhone, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
|
|
991
|
+
export { ApiError$1 as ApiError, type ConversationKind, type FeatureFlagEvaluation, type FeatureFlagEvaluation as FeatureFlagResult, type FeedbackItem, type FeedbackItemInput, type FeedbackPriority, type FeedbackStatus, type FeedbackType, FeedbackWidget, type FeedbackWidgetConfig, type FeedbackWidgetProps, ListFilesParams, LoginResponse, type MediaPolicy, type MediaUploadResult, type PasswordValidationResult, type PhoneCountry, type PhoneValidationResult, type RealtimeEvent, type RealtimeMessage, type RealtimeStatus, ScaleMuleClient, ScaleMuleConfig, ScaleMuleMedia, type ScaleMuleMediaProps, ScaleMuleProvider, type ScaleMuleProviderProps, UseAnalyticsOptions, UseAnalyticsReturn, UseAuthReturn, UseBillingReturn, UseContentReturn, type UseFeatureFlagsOptions, type UseFeatureFlagsReturn, type UseFeedbackOptions, type UseFeedbackResult, type UseFileStatusOptions, type UseFileStatusReturn, type UseFeatureFlagsOptions as UseFlagsOptions, type UseFeatureFlagsReturn as UseFlagsReturn, type UseMediaReturn, type UseMediaUploadOptions, type UsePushNotificationsOptions, type UsePushNotificationsReturn, type UseRealtimeOptions, type UseRealtimeReturn, type UseShareOptions, type UseShareReturn, UseUserReturn, User, type UsernameValidationResult, composePhone, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
|
package/dist/index.d.ts
CHANGED
|
@@ -324,25 +324,39 @@ interface UseContentOptions {
|
|
|
324
324
|
*/
|
|
325
325
|
declare function useContent(options?: UseContentOptions): UseContentReturn;
|
|
326
326
|
|
|
327
|
+
/**
|
|
328
|
+
* Conversation kinds recognized by the chat realtime channel naming scheme.
|
|
329
|
+
* Matches `broadcast_to_conversation` in `ms/scalemule-chat/src/realtime.rs`.
|
|
330
|
+
*/
|
|
331
|
+
type ConversationKind = 'standard' | 'large_room' | 'broadcast' | 'support';
|
|
327
332
|
interface UseFileStatusOptions {
|
|
328
333
|
/** Storage file_id to read status for. */
|
|
329
334
|
fileId: string | null | undefined;
|
|
330
335
|
/**
|
|
331
336
|
* Optional poll interval in milliseconds. If set, the hook re-fetches
|
|
332
|
-
* status every `pollIntervalMs
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
* Polling stops automatically once `scan.status === 'clean'` AND the
|
|
336
|
-
* caller's expected pipeline is done (`urls.optimized` returns 200 for
|
|
337
|
-
* images, `urls.hls` returns 200 for videos). Today the hook can only
|
|
338
|
-
* detect scan clean — broader pipeline-done detection lands when Phase 3
|
|
339
|
-
* enriches the optimize/transcode response fields.
|
|
337
|
+
* status every `pollIntervalMs` until scan goes clean. Useful for
|
|
338
|
+
* non-chat surfaces or as a fallback alongside `conversationId` push.
|
|
340
339
|
*/
|
|
341
340
|
pollIntervalMs?: number | null;
|
|
341
|
+
/** Disable the hook (don't fetch). Useful when `fileId` is conditional. */
|
|
342
|
+
disabled?: boolean;
|
|
342
343
|
/**
|
|
343
|
-
*
|
|
344
|
+
* Chat-surface push variant: subscribe to the conversation's realtime
|
|
345
|
+
* channel and refresh when a `file_status_changed` event arrives for
|
|
346
|
+
* `fileId`. Auth rides the existing per-conversation channel ACL.
|
|
344
347
|
*/
|
|
345
|
-
|
|
348
|
+
conversationId?: string | null;
|
|
349
|
+
/**
|
|
350
|
+
* Conversation kind, controls the channel name prefix:
|
|
351
|
+
* - `standard` (default) → `conversation:{id}`
|
|
352
|
+
* - `large_room` → `conversation:lr:{id}`
|
|
353
|
+
* - `broadcast` → `conversation:bc:{id}`
|
|
354
|
+
* - `support` → `conversation:support:{id}`
|
|
355
|
+
*
|
|
356
|
+
* If you only have a `messageId`, look up the conversation first via
|
|
357
|
+
* `client.chat.getMessage(messageId)` and pass the result here.
|
|
358
|
+
*/
|
|
359
|
+
conversationKind?: ConversationKind;
|
|
346
360
|
}
|
|
347
361
|
interface UseFileStatusReturn {
|
|
348
362
|
/** The latest status response, or null on first render / disabled. */
|
|
@@ -362,29 +376,39 @@ interface UseFileStatusReturn {
|
|
|
362
376
|
refresh: () => Promise<void>;
|
|
363
377
|
}
|
|
364
378
|
/**
|
|
365
|
-
* Subscribes to {@link FileStatus} for a single file.
|
|
366
|
-
* pull-only hook — single fetch by default, optional polling.
|
|
379
|
+
* Subscribes to {@link FileStatus} for a single file.
|
|
367
380
|
*
|
|
368
|
-
*
|
|
369
|
-
* for chat surfaces — `useFileStatus({ messageId })` will subscribe to
|
|
370
|
-
* `file.status` events on the existing per-conversation realtime channel
|
|
371
|
-
* via the `scalemule-chat` translation bridge (P5'). Until that lands,
|
|
372
|
-
* customers using this hook from chat surfaces should pass `pollIntervalMs`
|
|
373
|
-
* in the 1–3 second range while a media pipeline is expected to be running,
|
|
374
|
-
* then drop the polling once `isReady` is true.
|
|
381
|
+
* Three call shapes:
|
|
375
382
|
*
|
|
376
|
-
*
|
|
383
|
+
* 1. **Pull-only** — `useFileStatus({ fileId })` plus optional `pollIntervalMs`.
|
|
384
|
+
* One-shot fetch; useful for non-chat surfaces or static reads.
|
|
385
|
+
*
|
|
386
|
+
* 2. **Chat-surface push** — `useFileStatus({ fileId, conversationId, conversationKind? })`.
|
|
387
|
+
* Subscribes to the conversation channel and refreshes when
|
|
388
|
+
* `file_status_changed` arrives for this `fileId`. The chat service's
|
|
389
|
+
* media-status bridge fans photo/video lifecycle events into the per-conversation
|
|
390
|
+
* channel; the hook drops events for other files and dedupes against polling.
|
|
391
|
+
*
|
|
392
|
+
* 3. **Push + slow poll fallback** — combine `conversationId` with `pollIntervalMs`
|
|
393
|
+
* if you want belt-and-suspenders for environments where the websocket may drop.
|
|
394
|
+
*
|
|
395
|
+
* The `surface: 'profile'` push variant (private-user channel) is deferred until
|
|
396
|
+
* the realtime SDK exposes private-channel subscription by user.
|
|
397
|
+
*
|
|
398
|
+
* @example Chat surface (push)
|
|
377
399
|
* ```tsx
|
|
378
|
-
* function ChatImage({ fileId }: { fileId: string }) {
|
|
379
|
-
* const { status, isReady } = useFileStatus({
|
|
380
|
-
* fileId,
|
|
381
|
-
* pollIntervalMs: 2000,
|
|
382
|
-
* });
|
|
400
|
+
* function ChatImage({ fileId, conversationId }: { fileId: string; conversationId: string }) {
|
|
401
|
+
* const { status, isReady } = useFileStatus({ fileId, conversationId });
|
|
383
402
|
* if (!isReady) return <div>Scanning…</div>;
|
|
384
403
|
* const src = status?.urls.optimized ?? status?.urls.original;
|
|
385
404
|
* return <img src={src} />;
|
|
386
405
|
* }
|
|
387
406
|
* ```
|
|
407
|
+
*
|
|
408
|
+
* @example Non-chat surface (pull + poll)
|
|
409
|
+
* ```tsx
|
|
410
|
+
* const { status, isReady } = useFileStatus({ fileId, pollIntervalMs: 2000 });
|
|
411
|
+
* ```
|
|
388
412
|
*/
|
|
389
413
|
declare function useFileStatus(options: UseFileStatusOptions): UseFileStatusReturn;
|
|
390
414
|
|
|
@@ -413,9 +437,23 @@ interface ScaleMuleMediaProps {
|
|
|
413
437
|
/**
|
|
414
438
|
* Polling interval while waiting for the media pipeline to complete.
|
|
415
439
|
* Defaults to 2000ms; set to `null` to disable polling. Polling stops
|
|
416
|
-
* automatically once scan is clean.
|
|
440
|
+
* automatically once scan is clean. When `conversationId` is set the
|
|
441
|
+
* component receives push updates and you can usually pass `null`.
|
|
417
442
|
*/
|
|
418
443
|
pollIntervalMs?: number | null;
|
|
444
|
+
/**
|
|
445
|
+
* Chat-surface push: when set, the underlying `useFileStatus` hook
|
|
446
|
+
* subscribes to the conversation's realtime channel and refreshes on
|
|
447
|
+
* `file_status_changed` events for this `fileId`. See `useFileStatus`
|
|
448
|
+
* docs for channel naming and bridge behaviour.
|
|
449
|
+
*/
|
|
450
|
+
conversationId?: string | null;
|
|
451
|
+
/**
|
|
452
|
+
* Conversation kind, controls the channel name prefix
|
|
453
|
+
* (`conversation:{id}` vs `conversation:lr|bc|support:{id}`).
|
|
454
|
+
* Default is `'standard'`.
|
|
455
|
+
*/
|
|
456
|
+
conversationKind?: ConversationKind;
|
|
419
457
|
/**
|
|
420
458
|
* Render a custom placeholder while waiting for scan / upload. Defaults
|
|
421
459
|
* to a tiny "Loading…" div. Receives the current FileStatus (or null).
|
|
@@ -950,4 +988,4 @@ declare function createSafeLogger(prefix: string): {
|
|
|
950
988
|
error: (message: string, data?: unknown) => void;
|
|
951
989
|
};
|
|
952
990
|
|
|
953
|
-
export { ApiError$1 as ApiError, type FeatureFlagEvaluation, type FeatureFlagEvaluation as FeatureFlagResult, type FeedbackItem, type FeedbackItemInput, type FeedbackPriority, type FeedbackStatus, type FeedbackType, FeedbackWidget, type FeedbackWidgetConfig, type FeedbackWidgetProps, ListFilesParams, LoginResponse, type MediaPolicy, type MediaUploadResult, type PasswordValidationResult, type PhoneCountry, type PhoneValidationResult, type RealtimeEvent, type RealtimeMessage, type RealtimeStatus, ScaleMuleClient, ScaleMuleConfig, ScaleMuleMedia, type ScaleMuleMediaProps, ScaleMuleProvider, type ScaleMuleProviderProps, UseAnalyticsOptions, UseAnalyticsReturn, UseAuthReturn, UseBillingReturn, UseContentReturn, type UseFeatureFlagsOptions, type UseFeatureFlagsReturn, type UseFeedbackOptions, type UseFeedbackResult, type UseFileStatusOptions, type UseFileStatusReturn, type UseFeatureFlagsOptions as UseFlagsOptions, type UseFeatureFlagsReturn as UseFlagsReturn, type UseMediaReturn, type UseMediaUploadOptions, type UsePushNotificationsOptions, type UsePushNotificationsReturn, type UseRealtimeOptions, type UseRealtimeReturn, type UseShareOptions, type UseShareReturn, UseUserReturn, User, type UsernameValidationResult, composePhone, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
|
|
991
|
+
export { ApiError$1 as ApiError, type ConversationKind, type FeatureFlagEvaluation, type FeatureFlagEvaluation as FeatureFlagResult, type FeedbackItem, type FeedbackItemInput, type FeedbackPriority, type FeedbackStatus, type FeedbackType, FeedbackWidget, type FeedbackWidgetConfig, type FeedbackWidgetProps, ListFilesParams, LoginResponse, type MediaPolicy, type MediaUploadResult, type PasswordValidationResult, type PhoneCountry, type PhoneValidationResult, type RealtimeEvent, type RealtimeMessage, type RealtimeStatus, ScaleMuleClient, ScaleMuleConfig, ScaleMuleMedia, type ScaleMuleMediaProps, ScaleMuleProvider, type ScaleMuleProviderProps, UseAnalyticsOptions, UseAnalyticsReturn, UseAuthReturn, UseBillingReturn, UseContentReturn, type UseFeatureFlagsOptions, type UseFeatureFlagsReturn, type UseFeedbackOptions, type UseFeedbackResult, type UseFileStatusOptions, type UseFileStatusReturn, type UseFeatureFlagsOptions as UseFlagsOptions, type UseFeatureFlagsReturn as UseFlagsReturn, type UseMediaReturn, type UseMediaUploadOptions, type UsePushNotificationsOptions, type UsePushNotificationsReturn, type UseRealtimeOptions, type UseRealtimeReturn, type UseShareOptions, type UseShareReturn, UseUserReturn, User, type UsernameValidationResult, composePhone, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
|
package/dist/index.js
CHANGED
|
@@ -9118,9 +9118,28 @@ function useMedia() {
|
|
|
9118
9118
|
);
|
|
9119
9119
|
return { upload, cancelUpload, error, uploading };
|
|
9120
9120
|
}
|
|
9121
|
+
function conversationChannel(kind, id) {
|
|
9122
|
+
switch (kind) {
|
|
9123
|
+
case "large_room":
|
|
9124
|
+
return `conversation:lr:${id}`;
|
|
9125
|
+
case "broadcast":
|
|
9126
|
+
return `conversation:bc:${id}`;
|
|
9127
|
+
case "support":
|
|
9128
|
+
return `conversation:support:${id}`;
|
|
9129
|
+
case "standard":
|
|
9130
|
+
default:
|
|
9131
|
+
return `conversation:${id}`;
|
|
9132
|
+
}
|
|
9133
|
+
}
|
|
9121
9134
|
function useFileStatus(options) {
|
|
9122
|
-
const { storage } = useScaleMule();
|
|
9123
|
-
const {
|
|
9135
|
+
const { storage, realtime } = useScaleMule();
|
|
9136
|
+
const {
|
|
9137
|
+
fileId,
|
|
9138
|
+
pollIntervalMs = null,
|
|
9139
|
+
disabled = false,
|
|
9140
|
+
conversationId = null,
|
|
9141
|
+
conversationKind = "standard"
|
|
9142
|
+
} = options;
|
|
9124
9143
|
const [status, setStatus] = React.useState(null);
|
|
9125
9144
|
const [loading, setLoading] = React.useState(false);
|
|
9126
9145
|
const [error, setError] = React.useState(null);
|
|
@@ -9159,6 +9178,20 @@ function useFileStatus(options) {
|
|
|
9159
9178
|
}, pollIntervalMs);
|
|
9160
9179
|
return () => clearInterval(id);
|
|
9161
9180
|
}, [pollIntervalMs, disabled, fileId, status?.scan.status, fetchStatus]);
|
|
9181
|
+
React.useEffect(() => {
|
|
9182
|
+
if (!conversationId || !fileId || disabled) return;
|
|
9183
|
+
const channel = conversationChannel(conversationKind, conversationId);
|
|
9184
|
+
const unsub = realtime.subscribe(channel, (data) => {
|
|
9185
|
+
if (typeof data !== "object" || data === null) return;
|
|
9186
|
+
const payload = data;
|
|
9187
|
+
const wrapped = "data" in payload && typeof payload.data === "object" && payload.data !== null ? payload.data : payload;
|
|
9188
|
+
const evt = typeof payload.event === "string" ? payload.event : void 0;
|
|
9189
|
+
if (evt && evt !== "file_status_changed") return;
|
|
9190
|
+
if (wrapped.file_id !== fileId) return;
|
|
9191
|
+
void fetchStatus();
|
|
9192
|
+
});
|
|
9193
|
+
return unsub;
|
|
9194
|
+
}, [realtime, conversationId, conversationKind, fileId, disabled, fetchStatus]);
|
|
9162
9195
|
const isReady = status?.scan.status === "clean";
|
|
9163
9196
|
return { status, loading, error, isReady, refresh: fetchStatus };
|
|
9164
9197
|
}
|
|
@@ -9173,11 +9206,18 @@ function ScaleMuleMedia(props) {
|
|
|
9173
9206
|
style,
|
|
9174
9207
|
alt,
|
|
9175
9208
|
pollIntervalMs = 2e3,
|
|
9209
|
+
conversationId = null,
|
|
9210
|
+
conversationKind,
|
|
9176
9211
|
renderPlaceholder,
|
|
9177
9212
|
renderBlocked,
|
|
9178
9213
|
renderOverride
|
|
9179
9214
|
} = props;
|
|
9180
|
-
const { status, isReady } = useFileStatus({
|
|
9215
|
+
const { status, isReady } = useFileStatus({
|
|
9216
|
+
fileId,
|
|
9217
|
+
pollIntervalMs,
|
|
9218
|
+
conversationId,
|
|
9219
|
+
conversationKind
|
|
9220
|
+
});
|
|
9181
9221
|
const isImage = mimeType.startsWith("image/");
|
|
9182
9222
|
const isVideo = mimeType.startsWith("video/");
|
|
9183
9223
|
const isAudio = mimeType.startsWith("audio/");
|
package/dist/index.mjs
CHANGED
|
@@ -9098,9 +9098,28 @@ function useMedia() {
|
|
|
9098
9098
|
);
|
|
9099
9099
|
return { upload, cancelUpload, error, uploading };
|
|
9100
9100
|
}
|
|
9101
|
+
function conversationChannel(kind, id) {
|
|
9102
|
+
switch (kind) {
|
|
9103
|
+
case "large_room":
|
|
9104
|
+
return `conversation:lr:${id}`;
|
|
9105
|
+
case "broadcast":
|
|
9106
|
+
return `conversation:bc:${id}`;
|
|
9107
|
+
case "support":
|
|
9108
|
+
return `conversation:support:${id}`;
|
|
9109
|
+
case "standard":
|
|
9110
|
+
default:
|
|
9111
|
+
return `conversation:${id}`;
|
|
9112
|
+
}
|
|
9113
|
+
}
|
|
9101
9114
|
function useFileStatus(options) {
|
|
9102
|
-
const { storage } = useScaleMule();
|
|
9103
|
-
const {
|
|
9115
|
+
const { storage, realtime } = useScaleMule();
|
|
9116
|
+
const {
|
|
9117
|
+
fileId,
|
|
9118
|
+
pollIntervalMs = null,
|
|
9119
|
+
disabled = false,
|
|
9120
|
+
conversationId = null,
|
|
9121
|
+
conversationKind = "standard"
|
|
9122
|
+
} = options;
|
|
9104
9123
|
const [status, setStatus] = useState(null);
|
|
9105
9124
|
const [loading, setLoading] = useState(false);
|
|
9106
9125
|
const [error, setError] = useState(null);
|
|
@@ -9139,6 +9158,20 @@ function useFileStatus(options) {
|
|
|
9139
9158
|
}, pollIntervalMs);
|
|
9140
9159
|
return () => clearInterval(id);
|
|
9141
9160
|
}, [pollIntervalMs, disabled, fileId, status?.scan.status, fetchStatus]);
|
|
9161
|
+
useEffect(() => {
|
|
9162
|
+
if (!conversationId || !fileId || disabled) return;
|
|
9163
|
+
const channel = conversationChannel(conversationKind, conversationId);
|
|
9164
|
+
const unsub = realtime.subscribe(channel, (data) => {
|
|
9165
|
+
if (typeof data !== "object" || data === null) return;
|
|
9166
|
+
const payload = data;
|
|
9167
|
+
const wrapped = "data" in payload && typeof payload.data === "object" && payload.data !== null ? payload.data : payload;
|
|
9168
|
+
const evt = typeof payload.event === "string" ? payload.event : void 0;
|
|
9169
|
+
if (evt && evt !== "file_status_changed") return;
|
|
9170
|
+
if (wrapped.file_id !== fileId) return;
|
|
9171
|
+
void fetchStatus();
|
|
9172
|
+
});
|
|
9173
|
+
return unsub;
|
|
9174
|
+
}, [realtime, conversationId, conversationKind, fileId, disabled, fetchStatus]);
|
|
9142
9175
|
const isReady = status?.scan.status === "clean";
|
|
9143
9176
|
return { status, loading, error, isReady, refresh: fetchStatus };
|
|
9144
9177
|
}
|
|
@@ -9153,11 +9186,18 @@ function ScaleMuleMedia(props) {
|
|
|
9153
9186
|
style,
|
|
9154
9187
|
alt,
|
|
9155
9188
|
pollIntervalMs = 2e3,
|
|
9189
|
+
conversationId = null,
|
|
9190
|
+
conversationKind,
|
|
9156
9191
|
renderPlaceholder,
|
|
9157
9192
|
renderBlocked,
|
|
9158
9193
|
renderOverride
|
|
9159
9194
|
} = props;
|
|
9160
|
-
const { status, isReady } = useFileStatus({
|
|
9195
|
+
const { status, isReady } = useFileStatus({
|
|
9196
|
+
fileId,
|
|
9197
|
+
pollIntervalMs,
|
|
9198
|
+
conversationId,
|
|
9199
|
+
conversationKind
|
|
9200
|
+
});
|
|
9161
9201
|
const isImage = mimeType.startsWith("image/");
|
|
9162
9202
|
const isVideo = mimeType.startsWith("video/");
|
|
9163
9203
|
const isAudio = mimeType.startsWith("audio/");
|
package/package.json
CHANGED