@harkenapp/sdk-react-native 0.0.1-alpha.1
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 +67 -0
- package/app.plugin.cjs +135 -0
- package/app.plugin.js +1 -0
- package/dist/api/client.d.ts +67 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +163 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/errors.d.ts +46 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +72 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/index.d.ts +7 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +20 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/retry.d.ts +29 -0
- package/dist/api/retry.d.ts.map +1 -0
- package/dist/api/retry.js +74 -0
- package/dist/api/retry.js.map +1 -0
- package/dist/attachments/FeedbackSheet.d.ts +88 -0
- package/dist/attachments/FeedbackSheet.d.ts.map +1 -0
- package/dist/attachments/FeedbackSheet.js +250 -0
- package/dist/attachments/FeedbackSheet.js.map +1 -0
- package/dist/attachments/index.d.ts +20 -0
- package/dist/attachments/index.d.ts.map +1 -0
- package/dist/attachments/index.js +40 -0
- package/dist/attachments/index.js.map +1 -0
- package/dist/components/AttachmentGrid.d.ts +94 -0
- package/dist/components/AttachmentGrid.d.ts.map +1 -0
- package/dist/components/AttachmentGrid.js +132 -0
- package/dist/components/AttachmentGrid.js.map +1 -0
- package/dist/components/AttachmentPicker.d.ts +98 -0
- package/dist/components/AttachmentPicker.d.ts.map +1 -0
- package/dist/components/AttachmentPicker.js +297 -0
- package/dist/components/AttachmentPicker.js.map +1 -0
- package/dist/components/AttachmentPreview.d.ts +78 -0
- package/dist/components/AttachmentPreview.d.ts.map +1 -0
- package/dist/components/AttachmentPreview.js +133 -0
- package/dist/components/AttachmentPreview.js.map +1 -0
- package/dist/components/CategorySelector.d.ts +77 -0
- package/dist/components/CategorySelector.d.ts.map +1 -0
- package/dist/components/CategorySelector.js +117 -0
- package/dist/components/CategorySelector.js.map +1 -0
- package/dist/components/FeedbackForm.d.ts +50 -0
- package/dist/components/FeedbackForm.d.ts.map +1 -0
- package/dist/components/FeedbackForm.js +141 -0
- package/dist/components/FeedbackForm.js.map +1 -0
- package/dist/components/FeedbackSheet.d.ts +75 -0
- package/dist/components/FeedbackSheet.d.ts.map +1 -0
- package/dist/components/FeedbackSheet.js +215 -0
- package/dist/components/FeedbackSheet.js.map +1 -0
- package/dist/components/ThemedButton.d.ts +23 -0
- package/dist/components/ThemedButton.d.ts.map +1 -0
- package/dist/components/ThemedButton.js +77 -0
- package/dist/components/ThemedButton.js.map +1 -0
- package/dist/components/ThemedText.d.ts +16 -0
- package/dist/components/ThemedText.d.ts.map +1 -0
- package/dist/components/ThemedText.js +44 -0
- package/dist/components/ThemedText.js.map +1 -0
- package/dist/components/ThemedTextInput.d.ts +13 -0
- package/dist/components/ThemedTextInput.d.ts.map +1 -0
- package/dist/components/ThemedTextInput.js +76 -0
- package/dist/components/ThemedTextInput.js.map +1 -0
- package/dist/components/UploadStatusOverlay.d.ts +82 -0
- package/dist/components/UploadStatusOverlay.d.ts.map +1 -0
- package/dist/components/UploadStatusOverlay.js +319 -0
- package/dist/components/UploadStatusOverlay.js.map +1 -0
- package/dist/components/index.d.ts +19 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +28 -0
- package/dist/components/index.js.map +1 -0
- package/dist/context/HarkenContext.d.ts +62 -0
- package/dist/context/HarkenContext.d.ts.map +1 -0
- package/dist/context/HarkenContext.js +128 -0
- package/dist/context/HarkenContext.js.map +1 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +7 -0
- package/dist/context/index.js.map +1 -0
- package/dist/domain/index.d.ts +3 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +7 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/upload-queue.d.ts +116 -0
- package/dist/domain/upload-queue.d.ts.map +1 -0
- package/dist/domain/upload-queue.js +34 -0
- package/dist/domain/upload-queue.js.map +1 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +16 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useAnonymousId.d.ts +28 -0
- package/dist/hooks/useAnonymousId.d.ts.map +1 -0
- package/dist/hooks/useAnonymousId.js +59 -0
- package/dist/hooks/useAnonymousId.js.map +1 -0
- package/dist/hooks/useAttachmentPicker.d.ts +84 -0
- package/dist/hooks/useAttachmentPicker.d.ts.map +1 -0
- package/dist/hooks/useAttachmentPicker.js +181 -0
- package/dist/hooks/useAttachmentPicker.js.map +1 -0
- package/dist/hooks/useAttachmentStatus.d.ts +51 -0
- package/dist/hooks/useAttachmentStatus.d.ts.map +1 -0
- package/dist/hooks/useAttachmentStatus.js +69 -0
- package/dist/hooks/useAttachmentStatus.js.map +1 -0
- package/dist/hooks/useAttachmentUpload.d.ts +101 -0
- package/dist/hooks/useAttachmentUpload.d.ts.map +1 -0
- package/dist/hooks/useAttachmentUpload.js +293 -0
- package/dist/hooks/useAttachmentUpload.js.map +1 -0
- package/dist/hooks/useFeedback.d.ts +55 -0
- package/dist/hooks/useFeedback.d.ts.map +1 -0
- package/dist/hooks/useFeedback.js +96 -0
- package/dist/hooks/useFeedback.js.map +1 -0
- package/dist/hooks/useHarkenContext.d.ts +25 -0
- package/dist/hooks/useHarkenContext.d.ts.map +1 -0
- package/dist/hooks/useHarkenContext.js +35 -0
- package/dist/hooks/useHarkenContext.js.map +1 -0
- package/dist/hooks/useHarkenTheme.d.ts +26 -0
- package/dist/hooks/useHarkenTheme.d.ts.map +1 -0
- package/dist/hooks/useHarkenTheme.js +36 -0
- package/dist/hooks/useHarkenTheme.js.map +1 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/services/index.d.ts +4 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +9 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/uploadQueueService.d.ts +193 -0
- package/dist/services/uploadQueueService.d.ts.map +1 -0
- package/dist/services/uploadQueueService.js +623 -0
- package/dist/services/uploadQueueService.js.map +1 -0
- package/dist/services/uploadQueueStorage.d.ts +30 -0
- package/dist/services/uploadQueueStorage.d.ts.map +1 -0
- package/dist/services/uploadQueueStorage.js +77 -0
- package/dist/services/uploadQueueStorage.js.map +1 -0
- package/dist/storage/IdentityStore.d.ts +38 -0
- package/dist/storage/IdentityStore.d.ts.map +1 -0
- package/dist/storage/IdentityStore.js +83 -0
- package/dist/storage/IdentityStore.js.map +1 -0
- package/dist/storage/SecureStoreAdapter.d.ts +28 -0
- package/dist/storage/SecureStoreAdapter.d.ts.map +1 -0
- package/dist/storage/SecureStoreAdapter.js +52 -0
- package/dist/storage/SecureStoreAdapter.js.map +1 -0
- package/dist/storage/defaultStorage.d.ts +20 -0
- package/dist/storage/defaultStorage.d.ts.map +1 -0
- package/dist/storage/defaultStorage.js +131 -0
- package/dist/storage/defaultStorage.js.map +1 -0
- package/dist/storage/index.d.ts +6 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +13 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/types.d.ts +32 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +11 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/theme/defaults.d.ts +43 -0
- package/dist/theme/defaults.d.ts.map +1 -0
- package/dist/theme/defaults.js +128 -0
- package/dist/theme/defaults.js.map +1 -0
- package/dist/theme/index.d.ts +3 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +14 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/types.d.ts +136 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +3 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/types/config.d.ts +100 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +3 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/openapi.d.ts +601 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +7 -0
- package/dist/types/openapi.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/uuid.d.ts +10 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +60 -0
- package/dist/utils/uuid.js.map +1 -0
- package/package.json +124 -0
- package/src/@types/expo-file-system-legacy.d.ts +13 -0
- package/src/api/client.ts +250 -0
- package/src/api/errors.ts +84 -0
- package/src/api/index.ts +15 -0
- package/src/api/retry.ts +99 -0
- package/src/attachments/FeedbackSheet.tsx +400 -0
- package/src/attachments/index.ts +70 -0
- package/src/components/AttachmentGrid.tsx +247 -0
- package/src/components/AttachmentPicker.tsx +391 -0
- package/src/components/AttachmentPreview.tsx +210 -0
- package/src/components/CategorySelector.tsx +174 -0
- package/src/components/FeedbackForm.tsx +216 -0
- package/src/components/FeedbackSheet.tsx +321 -0
- package/src/components/ThemedButton.tsx +127 -0
- package/src/components/ThemedText.tsx +65 -0
- package/src/components/ThemedTextInput.tsx +65 -0
- package/src/components/UploadStatusOverlay.tsx +440 -0
- package/src/components/index.ts +39 -0
- package/src/context/HarkenContext.tsx +129 -0
- package/src/context/index.ts +2 -0
- package/src/domain/index.ts +12 -0
- package/src/domain/upload-queue.ts +131 -0
- package/src/hooks/index.ts +10 -0
- package/src/hooks/useAnonymousId.ts +68 -0
- package/src/hooks/useAttachmentPicker.ts +243 -0
- package/src/hooks/useAttachmentStatus.ts +86 -0
- package/src/hooks/useAttachmentUpload.ts +370 -0
- package/src/hooks/useFeedback.ts +139 -0
- package/src/hooks/useHarkenContext.ts +35 -0
- package/src/hooks/useHarkenTheme.ts +36 -0
- package/src/index.ts +168 -0
- package/src/services/index.ts +11 -0
- package/src/services/uploadQueueService.ts +727 -0
- package/src/services/uploadQueueStorage.ts +78 -0
- package/src/storage/IdentityStore.ts +89 -0
- package/src/storage/SecureStoreAdapter.ts +59 -0
- package/src/storage/defaultStorage.ts +109 -0
- package/src/storage/index.ts +5 -0
- package/src/storage/types.ts +34 -0
- package/src/theme/defaults.ts +151 -0
- package/src/theme/index.ts +23 -0
- package/src/theme/types.ts +157 -0
- package/src/types/config.ts +112 -0
- package/src/types/index.ts +10 -0
- package/src/types/openapi.ts +601 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/uuid.ts +77 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upload queue domain types.
|
|
3
|
+
*
|
|
4
|
+
* These types define the state machine for background attachment uploads.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Phases of the upload lifecycle.
|
|
8
|
+
*/
|
|
9
|
+
export declare enum UploadPhase {
|
|
10
|
+
/** Waiting in queue to be processed */
|
|
11
|
+
QUEUED = "queued",
|
|
12
|
+
/** Currently uploading to storage */
|
|
13
|
+
UPLOADING = "uploading",
|
|
14
|
+
/** Upload complete, confirming with server */
|
|
15
|
+
CONFIRMING = "confirming",
|
|
16
|
+
/** Successfully uploaded and confirmed */
|
|
17
|
+
COMPLETED = "completed",
|
|
18
|
+
/** Failed after max retries */
|
|
19
|
+
FAILED = "failed"
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A single item in the upload queue.
|
|
23
|
+
*/
|
|
24
|
+
export interface QueueItem {
|
|
25
|
+
/** Internal queue item ID */
|
|
26
|
+
id: string;
|
|
27
|
+
/** Server-assigned attachment ID */
|
|
28
|
+
attachmentId: string;
|
|
29
|
+
/** Local file URI (file://) */
|
|
30
|
+
localUri: string;
|
|
31
|
+
/** Presigned upload URL */
|
|
32
|
+
uploadUrl: string;
|
|
33
|
+
/** ISO timestamp when upload URL expires */
|
|
34
|
+
uploadExpiresAt: string;
|
|
35
|
+
/** MIME type (e.g., 'image/png') */
|
|
36
|
+
mimeType: string;
|
|
37
|
+
/** Original filename */
|
|
38
|
+
fileName: string;
|
|
39
|
+
/** File size in bytes */
|
|
40
|
+
fileSize: number;
|
|
41
|
+
/** Current phase in upload lifecycle */
|
|
42
|
+
phase: UploadPhase;
|
|
43
|
+
/** Upload progress (0.0 - 1.0) */
|
|
44
|
+
progress: number;
|
|
45
|
+
/** Current attempt number (1-based) */
|
|
46
|
+
attemptNumber: number;
|
|
47
|
+
/** Maximum retry attempts */
|
|
48
|
+
maxAttempts: number;
|
|
49
|
+
/** Last error message if failed */
|
|
50
|
+
lastError?: string;
|
|
51
|
+
/** ISO timestamp when item was queued */
|
|
52
|
+
createdAt: string;
|
|
53
|
+
/** ISO timestamp when upload started */
|
|
54
|
+
startedAt?: string;
|
|
55
|
+
/** ISO timestamp when completed or failed */
|
|
56
|
+
completedAt?: string;
|
|
57
|
+
/** ISO timestamp for scheduled retry (backoff) */
|
|
58
|
+
scheduledRetryAt?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Summary of queue state.
|
|
62
|
+
*/
|
|
63
|
+
export interface QueueStatus {
|
|
64
|
+
/** Total items in queue */
|
|
65
|
+
total: number;
|
|
66
|
+
/** Items waiting to be processed */
|
|
67
|
+
queued: number;
|
|
68
|
+
/** Items currently uploading or confirming */
|
|
69
|
+
uploading: number;
|
|
70
|
+
/** Successfully completed items */
|
|
71
|
+
completed: number;
|
|
72
|
+
/** Failed items (max retries exceeded) */
|
|
73
|
+
failed: number;
|
|
74
|
+
/** Whether queue is paused (e.g., offline) */
|
|
75
|
+
isPaused: boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Progress update for a single attachment.
|
|
79
|
+
*/
|
|
80
|
+
export interface UploadProgress {
|
|
81
|
+
/** Server-assigned attachment ID */
|
|
82
|
+
attachmentId: string;
|
|
83
|
+
/** Current phase */
|
|
84
|
+
phase: UploadPhase;
|
|
85
|
+
/** Upload progress (0.0 - 1.0) */
|
|
86
|
+
progress: number;
|
|
87
|
+
/** Error message if failed */
|
|
88
|
+
error?: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Persisted queue schema for AsyncStorage.
|
|
92
|
+
*/
|
|
93
|
+
export interface PersistedQueue {
|
|
94
|
+
/** Schema version for migrations */
|
|
95
|
+
version: number;
|
|
96
|
+
/** Queue items */
|
|
97
|
+
items: QueueItem[];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Configuration for upload retry behavior.
|
|
101
|
+
*/
|
|
102
|
+
export interface UploadRetryConfig {
|
|
103
|
+
/** Base delay in milliseconds (default: 2000) */
|
|
104
|
+
baseDelayMs: number;
|
|
105
|
+
/** Maximum delay in milliseconds (default: 60000) */
|
|
106
|
+
maxDelayMs: number;
|
|
107
|
+
/** Maximum number of attempts (default: 3) */
|
|
108
|
+
maxAttempts: number;
|
|
109
|
+
/** Random jitter in milliseconds (default: 1000) */
|
|
110
|
+
jitterMs: number;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Default retry configuration per feature spec D4.
|
|
114
|
+
*/
|
|
115
|
+
export declare const DEFAULT_UPLOAD_RETRY_CONFIG: UploadRetryConfig;
|
|
116
|
+
//# sourceMappingURL=upload-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-queue.d.ts","sourceRoot":"","sources":["../../src/domain/upload-queue.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,oBAAY,WAAW;IACrB,uCAAuC;IACvC,MAAM,WAAW;IACjB,qCAAqC;IACrC,SAAS,cAAc;IACvB,8CAA8C;IAC9C,UAAU,eAAe;IACzB,0CAA0C;IAC1C,SAAS,cAAc;IACvB,+BAA+B;IAC/B,MAAM,WAAW;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,6BAA6B;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,eAAe,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC;IAGjB,wCAAwC;IACxC,KAAK,EAAE,WAAW,CAAC;IACnB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,2BAA2B,EAAE,iBAKzC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Upload queue domain types.
|
|
4
|
+
*
|
|
5
|
+
* These types define the state machine for background attachment uploads.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.DEFAULT_UPLOAD_RETRY_CONFIG = exports.UploadPhase = void 0;
|
|
9
|
+
/**
|
|
10
|
+
* Phases of the upload lifecycle.
|
|
11
|
+
*/
|
|
12
|
+
var UploadPhase;
|
|
13
|
+
(function (UploadPhase) {
|
|
14
|
+
/** Waiting in queue to be processed */
|
|
15
|
+
UploadPhase["QUEUED"] = "queued";
|
|
16
|
+
/** Currently uploading to storage */
|
|
17
|
+
UploadPhase["UPLOADING"] = "uploading";
|
|
18
|
+
/** Upload complete, confirming with server */
|
|
19
|
+
UploadPhase["CONFIRMING"] = "confirming";
|
|
20
|
+
/** Successfully uploaded and confirmed */
|
|
21
|
+
UploadPhase["COMPLETED"] = "completed";
|
|
22
|
+
/** Failed after max retries */
|
|
23
|
+
UploadPhase["FAILED"] = "failed";
|
|
24
|
+
})(UploadPhase || (exports.UploadPhase = UploadPhase = {}));
|
|
25
|
+
/**
|
|
26
|
+
* Default retry configuration per feature spec D4.
|
|
27
|
+
*/
|
|
28
|
+
exports.DEFAULT_UPLOAD_RETRY_CONFIG = {
|
|
29
|
+
baseDelayMs: 2000,
|
|
30
|
+
maxDelayMs: 60000,
|
|
31
|
+
maxAttempts: 3,
|
|
32
|
+
jitterMs: 1000,
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=upload-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-queue.js","sourceRoot":"","sources":["../../src/domain/upload-queue.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH;;GAEG;AACH,IAAY,WAWX;AAXD,WAAY,WAAW;IACrB,uCAAuC;IACvC,gCAAiB,CAAA;IACjB,qCAAqC;IACrC,sCAAuB,CAAA;IACvB,8CAA8C;IAC9C,wCAAyB,CAAA;IACzB,0CAA0C;IAC1C,sCAAuB,CAAA;IACvB,+BAA+B;IAC/B,gCAAiB,CAAA;AACnB,CAAC,EAXW,WAAW,2BAAX,WAAW,QAWtB;AAsGD;;GAEG;AACU,QAAA,2BAA2B,GAAsB;IAC5D,WAAW,EAAE,IAAI;IACjB,UAAU,EAAE,KAAK;IACjB,WAAW,EAAE,CAAC;IACd,QAAQ,EAAE,IAAI;CACf,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { useHarkenTheme } from './useHarkenTheme';
|
|
2
|
+
export { useHarkenContext } from './useHarkenContext';
|
|
3
|
+
export { useAnonymousId } from './useAnonymousId';
|
|
4
|
+
export { useFeedback } from './useFeedback';
|
|
5
|
+
export type { SubmitFeedbackParams, UseFeedbackResult } from './useFeedback';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useFeedback = exports.useAnonymousId = exports.useHarkenContext = exports.useHarkenTheme = void 0;
|
|
4
|
+
// Core hooks (no native module dependencies)
|
|
5
|
+
var useHarkenTheme_1 = require("./useHarkenTheme");
|
|
6
|
+
Object.defineProperty(exports, "useHarkenTheme", { enumerable: true, get: function () { return useHarkenTheme_1.useHarkenTheme; } });
|
|
7
|
+
var useHarkenContext_1 = require("./useHarkenContext");
|
|
8
|
+
Object.defineProperty(exports, "useHarkenContext", { enumerable: true, get: function () { return useHarkenContext_1.useHarkenContext; } });
|
|
9
|
+
var useAnonymousId_1 = require("./useAnonymousId");
|
|
10
|
+
Object.defineProperty(exports, "useAnonymousId", { enumerable: true, get: function () { return useAnonymousId_1.useAnonymousId; } });
|
|
11
|
+
var useFeedback_1 = require("./useFeedback");
|
|
12
|
+
Object.defineProperty(exports, "useFeedback", { enumerable: true, get: function () { return useFeedback_1.useFeedback; } });
|
|
13
|
+
// Note: Attachment hooks (useAttachmentUpload, useAttachmentStatus) are
|
|
14
|
+
// exported from '@harkenapp/sdk-react-native/attachments' to avoid eager
|
|
15
|
+
// loading of native modules (expo-file-system, expo-image-picker, etc.)
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";;;AAAA,6CAA6C;AAC7C,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AACzB,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AAGpB,wEAAwE;AACxE,yEAAyE;AACzE,wEAAwE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook to access the anonymous ID for the current installation.
|
|
3
|
+
*
|
|
4
|
+
* The anonymous ID is a stable UUID that persists across app sessions.
|
|
5
|
+
* It's generated once and stored securely on the device.
|
|
6
|
+
*
|
|
7
|
+
* @returns Object with the anonymous ID and loading state
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* function MyComponent() {
|
|
12
|
+
* const { anonymousId, isLoading } = useAnonymousId();
|
|
13
|
+
*
|
|
14
|
+
* if (isLoading) {
|
|
15
|
+
* return <Text>Loading...</Text>;
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* return <Text>ID: {anonymousId}</Text>;
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function useAnonymousId(): {
|
|
23
|
+
/** The anonymous ID, or null while loading */
|
|
24
|
+
anonymousId: string | null;
|
|
25
|
+
/** True while the ID is being loaded from storage */
|
|
26
|
+
isLoading: boolean;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=useAnonymousId.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAnonymousId.d.ts","sourceRoot":"","sources":["../../src/hooks/useAnonymousId.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,IAAI;IAChC,8CAA8C;IAC9C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,qDAAqD;IACrD,SAAS,EAAE,OAAO,CAAC;CACpB,CAsCA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useAnonymousId = useAnonymousId;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const context_1 = require("../context");
|
|
6
|
+
/**
|
|
7
|
+
* Hook to access the anonymous ID for the current installation.
|
|
8
|
+
*
|
|
9
|
+
* The anonymous ID is a stable UUID that persists across app sessions.
|
|
10
|
+
* It's generated once and stored securely on the device.
|
|
11
|
+
*
|
|
12
|
+
* @returns Object with the anonymous ID and loading state
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* function MyComponent() {
|
|
17
|
+
* const { anonymousId, isLoading } = useAnonymousId();
|
|
18
|
+
*
|
|
19
|
+
* if (isLoading) {
|
|
20
|
+
* return <Text>Loading...</Text>;
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* return <Text>ID: {anonymousId}</Text>;
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
function useAnonymousId() {
|
|
28
|
+
const context = (0, react_1.useContext)(context_1.HarkenContext);
|
|
29
|
+
if (!context) {
|
|
30
|
+
throw new Error('useAnonymousId must be used within a HarkenProvider');
|
|
31
|
+
}
|
|
32
|
+
// Capture identityStore to satisfy TypeScript narrowing in useEffect
|
|
33
|
+
const { identityStore } = context;
|
|
34
|
+
const [anonymousId, setAnonymousId] = (0, react_1.useState)(null);
|
|
35
|
+
const [isLoading, setIsLoading] = (0, react_1.useState)(true);
|
|
36
|
+
(0, react_1.useEffect)(() => {
|
|
37
|
+
let mounted = true;
|
|
38
|
+
async function loadAnonymousId() {
|
|
39
|
+
try {
|
|
40
|
+
const id = await identityStore.getAnonymousId();
|
|
41
|
+
if (mounted) {
|
|
42
|
+
setAnonymousId(id);
|
|
43
|
+
setIsLoading(false);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
if (mounted) {
|
|
48
|
+
setIsLoading(false);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
void loadAnonymousId();
|
|
53
|
+
return () => {
|
|
54
|
+
mounted = false;
|
|
55
|
+
};
|
|
56
|
+
}, [identityStore]);
|
|
57
|
+
return { anonymousId, isLoading };
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=useAnonymousId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAnonymousId.js","sourceRoot":"","sources":["../../src/hooks/useAnonymousId.ts"],"names":[],"mappings":";;AAwBA,wCA2CC;AAnED,iCAAwD;AACxD,wCAA2C;AAE3C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,cAAc;IAM5B,MAAM,OAAO,GAAG,IAAA,kBAAU,EAAC,uBAAa,CAAC,CAAC;IAE1C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,qEAAqE;IACrE,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IAElC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,IAAA,gBAAQ,EAAgB,IAAI,CAAC,CAAC;IACpE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAC;IAEjD,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,OAAO,GAAG,IAAI,CAAC;QAEnB,KAAK,UAAU,eAAe;YAC5B,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,cAAc,EAAE,CAAC;gBAChD,IAAI,OAAO,EAAE,CAAC;oBACZ,cAAc,CAAC,EAAE,CAAC,CAAC;oBACnB,YAAY,CAAC,KAAK,CAAC,CAAC;gBACtB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,OAAO,EAAE,CAAC;oBACZ,YAAY,CAAC,KAAK,CAAC,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC;QAED,KAAK,eAAe,EAAE,CAAC;QAEvB,OAAO,GAAG,EAAE;YACV,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for managing the attachment picker with smart source selection.
|
|
3
|
+
*
|
|
4
|
+
* Provides configurable attachment sources and automatically handles:
|
|
5
|
+
* - Skipping the picker modal when only one source is enabled
|
|
6
|
+
* - Warning when no sources are enabled
|
|
7
|
+
*/
|
|
8
|
+
import type { UseAttachmentUploadResult } from './useAttachmentUpload';
|
|
9
|
+
import type { AttachmentPickerProps } from '../components/AttachmentPicker';
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for which attachment sources are enabled.
|
|
12
|
+
*/
|
|
13
|
+
export interface AttachmentSourceConfig {
|
|
14
|
+
/** Enable camera source. @default true */
|
|
15
|
+
camera?: boolean;
|
|
16
|
+
/** Enable photo library source. @default true */
|
|
17
|
+
library?: boolean;
|
|
18
|
+
/** Enable file/document picker source. @default true */
|
|
19
|
+
files?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Return type for useAttachmentPicker hook.
|
|
23
|
+
*/
|
|
24
|
+
export interface UseAttachmentPickerResult extends UseAttachmentUploadResult {
|
|
25
|
+
/** Open the attachment picker (or directly invoke source if only one enabled) */
|
|
26
|
+
openPicker: () => void;
|
|
27
|
+
/** Whether the picker modal is visible */
|
|
28
|
+
isPickerVisible: boolean;
|
|
29
|
+
/** Close the picker modal */
|
|
30
|
+
closePicker: () => void;
|
|
31
|
+
/** Props to spread onto AttachmentPicker component */
|
|
32
|
+
pickerProps: Pick<AttachmentPickerProps, 'visible' | 'onClose' | 'onTakePhoto' | 'onPickFromLibrary' | 'onPickDocument' | 'options'>;
|
|
33
|
+
/** Which sources are enabled */
|
|
34
|
+
enabledSources: {
|
|
35
|
+
camera: boolean;
|
|
36
|
+
library: boolean;
|
|
37
|
+
files: boolean;
|
|
38
|
+
};
|
|
39
|
+
/** Count of enabled sources */
|
|
40
|
+
enabledSourceCount: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Hook for managing the attachment picker with smart source selection.
|
|
44
|
+
*
|
|
45
|
+
* When only one source is enabled, calling `openPicker()` will skip the modal
|
|
46
|
+
* and directly open that source. When no sources are enabled, a warning is logged.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```tsx
|
|
50
|
+
* // Allow only photo library
|
|
51
|
+
* const { openPicker, pickerProps, attachments } = useAttachmentPicker({
|
|
52
|
+
* camera: false,
|
|
53
|
+
* library: true,
|
|
54
|
+
* files: false,
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* // openPicker() will directly open photo library without showing modal
|
|
58
|
+
*
|
|
59
|
+
* return (
|
|
60
|
+
* <>
|
|
61
|
+
* <Button onPress={openPicker} title="Add Photo" />
|
|
62
|
+
* <AttachmentPicker {...pickerProps} />
|
|
63
|
+
* </>
|
|
64
|
+
* );
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* // With FeedbackSheet integration
|
|
70
|
+
* const {
|
|
71
|
+
* openPicker,
|
|
72
|
+
* pickerProps,
|
|
73
|
+
* attachments,
|
|
74
|
+
* removeAttachment,
|
|
75
|
+
* retryAttachment,
|
|
76
|
+
* } = useAttachmentPicker({
|
|
77
|
+
* camera: true,
|
|
78
|
+
* library: true,
|
|
79
|
+
* files: false, // Disable document picker
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function useAttachmentPicker(sourceConfig?: AttachmentSourceConfig): UseAttachmentPickerResult;
|
|
84
|
+
//# sourceMappingURL=useAttachmentPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAttachmentPicker.d.ts","sourceRoot":"","sources":["../../src/hooks/useAttachmentPicker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAE5E;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,0CAA0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,yBAAyB;IAC1E,iFAAiF;IACjF,UAAU,EAAE,MAAM,IAAI,CAAC;IAEvB,0CAA0C;IAC1C,eAAe,EAAE,OAAO,CAAC;IAEzB,6BAA6B;IAC7B,WAAW,EAAE,MAAM,IAAI,CAAC;IAExB,sDAAsD;IACtD,WAAW,EAAE,IAAI,CACf,qBAAqB,EACrB,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,mBAAmB,GAAG,gBAAgB,GAAG,SAAS,CAC3F,CAAC;IAEF,gCAAgC;IAChC,cAAc,EAAE;QACd,MAAM,EAAE,OAAO,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;IAEF,+BAA+B;IAC/B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,GAAE,sBAA2B,GACxC,yBAAyB,CAgJ3B"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hook for managing the attachment picker with smart source selection.
|
|
4
|
+
*
|
|
5
|
+
* Provides configurable attachment sources and automatically handles:
|
|
6
|
+
* - Skipping the picker modal when only one source is enabled
|
|
7
|
+
* - Warning when no sources are enabled
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.useAttachmentPicker = useAttachmentPicker;
|
|
11
|
+
const react_1 = require("react");
|
|
12
|
+
const useAttachmentUpload_1 = require("./useAttachmentUpload");
|
|
13
|
+
/**
|
|
14
|
+
* Hook for managing the attachment picker with smart source selection.
|
|
15
|
+
*
|
|
16
|
+
* When only one source is enabled, calling `openPicker()` will skip the modal
|
|
17
|
+
* and directly open that source. When no sources are enabled, a warning is logged.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* // Allow only photo library
|
|
22
|
+
* const { openPicker, pickerProps, attachments } = useAttachmentPicker({
|
|
23
|
+
* camera: false,
|
|
24
|
+
* library: true,
|
|
25
|
+
* files: false,
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* // openPicker() will directly open photo library without showing modal
|
|
29
|
+
*
|
|
30
|
+
* return (
|
|
31
|
+
* <>
|
|
32
|
+
* <Button onPress={openPicker} title="Add Photo" />
|
|
33
|
+
* <AttachmentPicker {...pickerProps} />
|
|
34
|
+
* </>
|
|
35
|
+
* );
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```tsx
|
|
40
|
+
* // With FeedbackSheet integration
|
|
41
|
+
* const {
|
|
42
|
+
* openPicker,
|
|
43
|
+
* pickerProps,
|
|
44
|
+
* attachments,
|
|
45
|
+
* removeAttachment,
|
|
46
|
+
* retryAttachment,
|
|
47
|
+
* } = useAttachmentPicker({
|
|
48
|
+
* camera: true,
|
|
49
|
+
* library: true,
|
|
50
|
+
* files: false, // Disable document picker
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
function useAttachmentPicker(sourceConfig = {}) {
|
|
55
|
+
const { camera: cameraEnabled = true, library: libraryEnabled = true, files: filesEnabled = true, } = sourceConfig;
|
|
56
|
+
const [isPickerVisible, setIsPickerVisible] = (0, react_1.useState)(false);
|
|
57
|
+
const uploadResult = (0, useAttachmentUpload_1.useAttachmentUpload)();
|
|
58
|
+
const { pickImage, pickDocument } = uploadResult;
|
|
59
|
+
// Calculate enabled sources
|
|
60
|
+
const enabledSources = (0, react_1.useMemo)(() => ({
|
|
61
|
+
camera: cameraEnabled,
|
|
62
|
+
library: libraryEnabled,
|
|
63
|
+
files: filesEnabled,
|
|
64
|
+
}), [cameraEnabled, libraryEnabled, filesEnabled]);
|
|
65
|
+
const enabledSourceCount = (0, react_1.useMemo)(() => {
|
|
66
|
+
let count = 0;
|
|
67
|
+
if (cameraEnabled)
|
|
68
|
+
count++;
|
|
69
|
+
if (libraryEnabled)
|
|
70
|
+
count++;
|
|
71
|
+
if (filesEnabled)
|
|
72
|
+
count++;
|
|
73
|
+
return count;
|
|
74
|
+
}, [cameraEnabled, libraryEnabled, filesEnabled]);
|
|
75
|
+
// Auto-close picker if sources change to 0 or 1 while visible
|
|
76
|
+
// This prevents the iOS ActionSheet from showing with no/single options
|
|
77
|
+
(0, react_1.useEffect)(() => {
|
|
78
|
+
if (isPickerVisible && enabledSourceCount < 2) {
|
|
79
|
+
setIsPickerVisible(false);
|
|
80
|
+
}
|
|
81
|
+
}, [isPickerVisible, enabledSourceCount]);
|
|
82
|
+
// Handlers for each source
|
|
83
|
+
const handleTakePhoto = (0, react_1.useCallback)(async () => {
|
|
84
|
+
setIsPickerVisible(false);
|
|
85
|
+
try {
|
|
86
|
+
await pickImage('camera');
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
console.error('[Harken] Failed to take photo:', e);
|
|
90
|
+
}
|
|
91
|
+
}, [pickImage]);
|
|
92
|
+
const handlePickFromLibrary = (0, react_1.useCallback)(async () => {
|
|
93
|
+
setIsPickerVisible(false);
|
|
94
|
+
try {
|
|
95
|
+
await pickImage('library');
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
console.error('[Harken] Failed to pick from library:', e);
|
|
99
|
+
}
|
|
100
|
+
}, [pickImage]);
|
|
101
|
+
const handlePickDocument = (0, react_1.useCallback)(async () => {
|
|
102
|
+
setIsPickerVisible(false);
|
|
103
|
+
try {
|
|
104
|
+
await pickDocument();
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
console.error('[Harken] Failed to pick document:', e);
|
|
108
|
+
}
|
|
109
|
+
}, [pickDocument]);
|
|
110
|
+
const closePicker = (0, react_1.useCallback)(() => {
|
|
111
|
+
setIsPickerVisible(false);
|
|
112
|
+
}, []);
|
|
113
|
+
/**
|
|
114
|
+
* Smart picker opener:
|
|
115
|
+
* - 0 sources enabled: log warning, do nothing
|
|
116
|
+
* - 1 source enabled: directly invoke that source
|
|
117
|
+
* - 2+ sources enabled: show picker modal
|
|
118
|
+
*/
|
|
119
|
+
const openPicker = (0, react_1.useCallback)(() => {
|
|
120
|
+
if (enabledSourceCount === 0) {
|
|
121
|
+
console.warn('[Harken] useAttachmentPicker: No attachment sources are enabled. ' +
|
|
122
|
+
'Enable at least one of: camera, library, or files.');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (enabledSourceCount === 1) {
|
|
126
|
+
// Directly invoke the single enabled source
|
|
127
|
+
if (cameraEnabled) {
|
|
128
|
+
void handleTakePhoto();
|
|
129
|
+
}
|
|
130
|
+
else if (libraryEnabled) {
|
|
131
|
+
void handlePickFromLibrary();
|
|
132
|
+
}
|
|
133
|
+
else if (filesEnabled) {
|
|
134
|
+
void handlePickDocument();
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// Multiple sources enabled - show the picker
|
|
139
|
+
setIsPickerVisible(true);
|
|
140
|
+
}, [
|
|
141
|
+
enabledSourceCount,
|
|
142
|
+
cameraEnabled,
|
|
143
|
+
libraryEnabled,
|
|
144
|
+
filesEnabled,
|
|
145
|
+
handleTakePhoto,
|
|
146
|
+
handlePickFromLibrary,
|
|
147
|
+
handlePickDocument,
|
|
148
|
+
]);
|
|
149
|
+
// Build picker props with hidden options for disabled sources
|
|
150
|
+
const pickerProps = (0, react_1.useMemo)(() => ({
|
|
151
|
+
visible: isPickerVisible,
|
|
152
|
+
onClose: closePicker,
|
|
153
|
+
onTakePhoto: handleTakePhoto,
|
|
154
|
+
onPickFromLibrary: handlePickFromLibrary,
|
|
155
|
+
onPickDocument: handlePickDocument,
|
|
156
|
+
options: {
|
|
157
|
+
camera: { hidden: !cameraEnabled },
|
|
158
|
+
library: { hidden: !libraryEnabled },
|
|
159
|
+
document: { hidden: !filesEnabled },
|
|
160
|
+
},
|
|
161
|
+
}), [
|
|
162
|
+
isPickerVisible,
|
|
163
|
+
closePicker,
|
|
164
|
+
handleTakePhoto,
|
|
165
|
+
handlePickFromLibrary,
|
|
166
|
+
handlePickDocument,
|
|
167
|
+
cameraEnabled,
|
|
168
|
+
libraryEnabled,
|
|
169
|
+
filesEnabled,
|
|
170
|
+
]);
|
|
171
|
+
return {
|
|
172
|
+
...uploadResult,
|
|
173
|
+
openPicker,
|
|
174
|
+
isPickerVisible,
|
|
175
|
+
closePicker,
|
|
176
|
+
pickerProps,
|
|
177
|
+
enabledSources,
|
|
178
|
+
enabledSourceCount,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=useAttachmentPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAttachmentPicker.js","sourceRoot":"","sources":["../../src/hooks/useAttachmentPicker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for subscribing to a single attachment's upload status.
|
|
3
|
+
*
|
|
4
|
+
* Useful for components that display a single attachment with progress indicator.
|
|
5
|
+
*/
|
|
6
|
+
import { UploadPhase } from '../domain';
|
|
7
|
+
/**
|
|
8
|
+
* Status information for a single attachment.
|
|
9
|
+
*/
|
|
10
|
+
export interface AttachmentStatus {
|
|
11
|
+
/** Current upload phase */
|
|
12
|
+
phase: UploadPhase;
|
|
13
|
+
/** Upload progress (0.0 - 1.0) */
|
|
14
|
+
progress: number;
|
|
15
|
+
/** Error message if failed */
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Hook to subscribe to a single attachment's upload status.
|
|
20
|
+
*
|
|
21
|
+
* Returns null if the attachment is not found in the queue.
|
|
22
|
+
*
|
|
23
|
+
* @param attachmentId - Server-assigned attachment ID
|
|
24
|
+
* @returns Current status or null if not found
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* function AttachmentThumbnail({ attachmentId, uri }: Props) {
|
|
29
|
+
* const status = useAttachmentStatus(attachmentId);
|
|
30
|
+
*
|
|
31
|
+
* if (!status) return null;
|
|
32
|
+
*
|
|
33
|
+
* return (
|
|
34
|
+
* <View>
|
|
35
|
+
* <Image source={{ uri }} />
|
|
36
|
+
* {status.phase === 'uploading' && (
|
|
37
|
+
* <ProgressBar progress={status.progress} />
|
|
38
|
+
* )}
|
|
39
|
+
* {status.phase === 'failed' && (
|
|
40
|
+
* <Text>Error: {status.error}</Text>
|
|
41
|
+
* )}
|
|
42
|
+
* {status.phase === 'completed' && (
|
|
43
|
+
* <Icon name="checkmark" />
|
|
44
|
+
* )}
|
|
45
|
+
* </View>
|
|
46
|
+
* );
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function useAttachmentStatus(attachmentId: string): AttachmentStatus | null;
|
|
51
|
+
//# sourceMappingURL=useAttachmentStatus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAttachmentStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/useAttachmentStatus.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,WAAW,EAAkB,MAAM,WAAW,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B;IAC3B,KAAK,EAAE,WAAW,CAAC;IACnB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,GACnB,gBAAgB,GAAG,IAAI,CA6BzB"}
|