@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,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hook for subscribing to a single attachment's upload status.
|
|
4
|
+
*
|
|
5
|
+
* Useful for components that display a single attachment with progress indicator.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.useAttachmentStatus = useAttachmentStatus;
|
|
9
|
+
const react_1 = require("react");
|
|
10
|
+
const services_1 = require("../services");
|
|
11
|
+
/**
|
|
12
|
+
* Hook to subscribe to a single attachment's upload status.
|
|
13
|
+
*
|
|
14
|
+
* Returns null if the attachment is not found in the queue.
|
|
15
|
+
*
|
|
16
|
+
* @param attachmentId - Server-assigned attachment ID
|
|
17
|
+
* @returns Current status or null if not found
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* function AttachmentThumbnail({ attachmentId, uri }: Props) {
|
|
22
|
+
* const status = useAttachmentStatus(attachmentId);
|
|
23
|
+
*
|
|
24
|
+
* if (!status) return null;
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <View>
|
|
28
|
+
* <Image source={{ uri }} />
|
|
29
|
+
* {status.phase === 'uploading' && (
|
|
30
|
+
* <ProgressBar progress={status.progress} />
|
|
31
|
+
* )}
|
|
32
|
+
* {status.phase === 'failed' && (
|
|
33
|
+
* <Text>Error: {status.error}</Text>
|
|
34
|
+
* )}
|
|
35
|
+
* {status.phase === 'completed' && (
|
|
36
|
+
* <Icon name="checkmark" />
|
|
37
|
+
* )}
|
|
38
|
+
* </View>
|
|
39
|
+
* );
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
function useAttachmentStatus(attachmentId) {
|
|
44
|
+
const [status, setStatus] = (0, react_1.useState)(() => {
|
|
45
|
+
// Initialize with current state from queue
|
|
46
|
+
const item = services_1.uploadQueueService.getItemByAttachmentId(attachmentId);
|
|
47
|
+
if (!item)
|
|
48
|
+
return null;
|
|
49
|
+
return {
|
|
50
|
+
phase: item.phase,
|
|
51
|
+
progress: item.progress,
|
|
52
|
+
error: item.lastError,
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
(0, react_1.useEffect)(() => {
|
|
56
|
+
const unsubscribe = services_1.uploadQueueService.onProgress((progress) => {
|
|
57
|
+
if (progress.attachmentId !== attachmentId)
|
|
58
|
+
return;
|
|
59
|
+
setStatus({
|
|
60
|
+
phase: progress.phase,
|
|
61
|
+
progress: progress.progress,
|
|
62
|
+
error: progress.error,
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
return unsubscribe;
|
|
66
|
+
}, [attachmentId]);
|
|
67
|
+
return status;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=useAttachmentStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAttachmentStatus.js","sourceRoot":"","sources":["../../src/hooks/useAttachmentStatus.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAkDH,kDA+BC;AA/ED,iCAA4C;AAC5C,0CAAiD;AAejD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,SAAgB,mBAAmB,CACjC,YAAoB;IAEpB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAA0B,GAAG,EAAE;QACjE,2CAA2C;QAC3C,MAAM,IAAI,GAAG,6BAAkB,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,IAAI,CAAC,SAAS;SACtB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,WAAW,GAAG,6BAAkB,CAAC,UAAU,CAC/C,CAAC,QAAwB,EAAE,EAAE;YAC3B,IAAI,QAAQ,CAAC,YAAY,KAAK,YAAY;gBAAE,OAAO;YAEnD,SAAS,CAAC;gBACR,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;aACtB,CAAC,CAAC;QACL,CAAC,CACF,CAAC;QAEF,OAAO,WAAW,CAAC;IACrB,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for managing attachment uploads.
|
|
3
|
+
*
|
|
4
|
+
* Provides methods for picking images/documents and tracking upload progress.
|
|
5
|
+
* Uploads happen in background via the singleton uploadQueueService.
|
|
6
|
+
*/
|
|
7
|
+
import { UploadPhase } from '../domain';
|
|
8
|
+
/**
|
|
9
|
+
* State for a single attachment.
|
|
10
|
+
*/
|
|
11
|
+
export interface AttachmentState {
|
|
12
|
+
/** Server-assigned attachment ID */
|
|
13
|
+
attachmentId: string;
|
|
14
|
+
/** Local file URI for preview */
|
|
15
|
+
localUri: string;
|
|
16
|
+
/** Original filename */
|
|
17
|
+
fileName: string;
|
|
18
|
+
/** MIME type */
|
|
19
|
+
mimeType: string;
|
|
20
|
+
/** Current upload phase */
|
|
21
|
+
phase: UploadPhase;
|
|
22
|
+
/** Upload progress (0.0 - 1.0) */
|
|
23
|
+
progress: number;
|
|
24
|
+
/** Error message if failed */
|
|
25
|
+
error?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Return type for useAttachmentUpload hook.
|
|
29
|
+
*/
|
|
30
|
+
export interface UseAttachmentUploadResult {
|
|
31
|
+
/** All current attachments */
|
|
32
|
+
attachments: AttachmentState[];
|
|
33
|
+
/** Pick image from camera or library */
|
|
34
|
+
pickImage: (source: 'camera' | 'library') => Promise<AttachmentState | null>;
|
|
35
|
+
/** Pick document (images or PDFs) */
|
|
36
|
+
pickDocument: () => Promise<AttachmentState | null>;
|
|
37
|
+
/** Add attachment from existing local URI */
|
|
38
|
+
addAttachment: (params: {
|
|
39
|
+
uri: string;
|
|
40
|
+
mimeType: string;
|
|
41
|
+
fileName: string;
|
|
42
|
+
fileSize: number;
|
|
43
|
+
}) => Promise<AttachmentState>;
|
|
44
|
+
/** Retry a failed upload */
|
|
45
|
+
retryAttachment: (attachmentId: string) => Promise<void>;
|
|
46
|
+
/** Remove attachment (cancels if uploading) */
|
|
47
|
+
removeAttachment: (attachmentId: string) => Promise<void>;
|
|
48
|
+
/** Get all attachment IDs for feedback submission */
|
|
49
|
+
getAttachmentIds: () => string[];
|
|
50
|
+
/** True if any uploads are in progress */
|
|
51
|
+
hasActiveUploads: boolean;
|
|
52
|
+
/** Clear all completed attachments */
|
|
53
|
+
clearCompleted: () => void;
|
|
54
|
+
/** Clear all failed attachments */
|
|
55
|
+
clearFailed: () => void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Hook for managing attachment uploads with background support.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* function FeedbackForm() {
|
|
63
|
+
* const {
|
|
64
|
+
* attachments,
|
|
65
|
+
* pickImage,
|
|
66
|
+
* removeAttachment,
|
|
67
|
+
* getAttachmentIds,
|
|
68
|
+
* hasActiveUploads,
|
|
69
|
+
* } = useAttachmentUpload();
|
|
70
|
+
*
|
|
71
|
+
* const handleAddPhoto = async () => {
|
|
72
|
+
* await pickImage('library');
|
|
73
|
+
* };
|
|
74
|
+
*
|
|
75
|
+
* const handleSubmit = async () => {
|
|
76
|
+
* // Can submit even if uploads are still in progress!
|
|
77
|
+
* await submitFeedback({
|
|
78
|
+
* message: 'Bug report',
|
|
79
|
+
* attachmentIds: getAttachmentIds(),
|
|
80
|
+
* });
|
|
81
|
+
* };
|
|
82
|
+
*
|
|
83
|
+
* return (
|
|
84
|
+
* <View>
|
|
85
|
+
* {attachments.map(att => (
|
|
86
|
+
* <AttachmentPreview
|
|
87
|
+
* key={att.attachmentId}
|
|
88
|
+
* uri={att.localUri}
|
|
89
|
+
* progress={att.progress}
|
|
90
|
+
* phase={att.phase}
|
|
91
|
+
* />
|
|
92
|
+
* ))}
|
|
93
|
+
* <Button onPress={handleAddPhoto} title="Add Photo" />
|
|
94
|
+
* <Button onPress={handleSubmit} title="Submit" />
|
|
95
|
+
* </View>
|
|
96
|
+
* );
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare function useAttachmentUpload(): UseAttachmentUploadResult;
|
|
101
|
+
//# sourceMappingURL=useAttachmentUpload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAttachmentUpload.d.ts","sourceRoot":"","sources":["../../src/hooks/useAttachmentUpload.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,EAAE,WAAW,EAAkB,MAAM,WAAW,CAAC;AAGxD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,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,yBAAyB;IACxC,8BAA8B;IAC9B,WAAW,EAAE,eAAe,EAAE,CAAC;IAE/B,wCAAwC;IACxC,SAAS,EAAE,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,KAAK,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAE7E,qCAAqC;IACrC,YAAY,EAAE,MAAM,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAEpD,6CAA6C;IAC7C,aAAa,EAAE,CAAC,MAAM,EAAE;QACtB,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAE/B,4BAA4B;IAC5B,eAAe,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD,+CAA+C;IAC/C,gBAAgB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D,qDAAqD;IACrD,gBAAgB,EAAE,MAAM,MAAM,EAAE,CAAC;IAEjC,0CAA0C;IAC1C,gBAAgB,EAAE,OAAO,CAAC;IAE1B,sCAAsC;IACtC,cAAc,EAAE,MAAM,IAAI,CAAC;IAE3B,mCAAmC;IACnC,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,mBAAmB,IAAI,yBAAyB,CA2P/D"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hook for managing attachment uploads.
|
|
4
|
+
*
|
|
5
|
+
* Provides methods for picking images/documents and tracking upload progress.
|
|
6
|
+
* Uploads happen in background via the singleton uploadQueueService.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.useAttachmentUpload = useAttachmentUpload;
|
|
43
|
+
const react_1 = require("react");
|
|
44
|
+
const ImagePicker = __importStar(require("expo-image-picker"));
|
|
45
|
+
const DocumentPicker = __importStar(require("expo-document-picker"));
|
|
46
|
+
const FileSystem = __importStar(require("expo-file-system/legacy"));
|
|
47
|
+
const services_1 = require("../services");
|
|
48
|
+
const domain_1 = require("../domain");
|
|
49
|
+
const useHarkenContext_1 = require("./useHarkenContext");
|
|
50
|
+
/**
|
|
51
|
+
* Hook for managing attachment uploads with background support.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* function FeedbackForm() {
|
|
56
|
+
* const {
|
|
57
|
+
* attachments,
|
|
58
|
+
* pickImage,
|
|
59
|
+
* removeAttachment,
|
|
60
|
+
* getAttachmentIds,
|
|
61
|
+
* hasActiveUploads,
|
|
62
|
+
* } = useAttachmentUpload();
|
|
63
|
+
*
|
|
64
|
+
* const handleAddPhoto = async () => {
|
|
65
|
+
* await pickImage('library');
|
|
66
|
+
* };
|
|
67
|
+
*
|
|
68
|
+
* const handleSubmit = async () => {
|
|
69
|
+
* // Can submit even if uploads are still in progress!
|
|
70
|
+
* await submitFeedback({
|
|
71
|
+
* message: 'Bug report',
|
|
72
|
+
* attachmentIds: getAttachmentIds(),
|
|
73
|
+
* });
|
|
74
|
+
* };
|
|
75
|
+
*
|
|
76
|
+
* return (
|
|
77
|
+
* <View>
|
|
78
|
+
* {attachments.map(att => (
|
|
79
|
+
* <AttachmentPreview
|
|
80
|
+
* key={att.attachmentId}
|
|
81
|
+
* uri={att.localUri}
|
|
82
|
+
* progress={att.progress}
|
|
83
|
+
* phase={att.phase}
|
|
84
|
+
* />
|
|
85
|
+
* ))}
|
|
86
|
+
* <Button onPress={handleAddPhoto} title="Add Photo" />
|
|
87
|
+
* <Button onPress={handleSubmit} title="Submit" />
|
|
88
|
+
* </View>
|
|
89
|
+
* );
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
function useAttachmentUpload() {
|
|
94
|
+
const { client, config } = (0, useHarkenContext_1.useHarkenContext)();
|
|
95
|
+
const [attachments, setAttachments] = (0, react_1.useState)(new Map());
|
|
96
|
+
// Track which attachment IDs this hook instance is managing
|
|
97
|
+
const attachmentIdsRef = (0, react_1.useRef)(new Set());
|
|
98
|
+
// Initialize upload queue service on first use
|
|
99
|
+
(0, react_1.useEffect)(() => {
|
|
100
|
+
if (!services_1.uploadQueueService.initialized) {
|
|
101
|
+
void services_1.uploadQueueService.initialize({
|
|
102
|
+
client,
|
|
103
|
+
debug: config.debug,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}, [client, config.debug]);
|
|
107
|
+
// Subscribe to progress updates from the queue service
|
|
108
|
+
(0, react_1.useEffect)(() => {
|
|
109
|
+
// Guard against service not being initialized
|
|
110
|
+
if (!services_1.uploadQueueService) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const unsubProgress = services_1.uploadQueueService.onProgress((progress) => {
|
|
114
|
+
// Only track attachments we added
|
|
115
|
+
if (!attachmentIdsRef.current.has(progress.attachmentId))
|
|
116
|
+
return;
|
|
117
|
+
setAttachments((prev) => {
|
|
118
|
+
const existing = prev.get(progress.attachmentId);
|
|
119
|
+
if (!existing)
|
|
120
|
+
return prev;
|
|
121
|
+
const next = new Map(prev);
|
|
122
|
+
next.set(progress.attachmentId, {
|
|
123
|
+
...existing,
|
|
124
|
+
phase: progress.phase,
|
|
125
|
+
progress: progress.progress,
|
|
126
|
+
error: progress.error,
|
|
127
|
+
});
|
|
128
|
+
return next;
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
return () => {
|
|
132
|
+
unsubProgress();
|
|
133
|
+
};
|
|
134
|
+
}, []);
|
|
135
|
+
/**
|
|
136
|
+
* Add an attachment from a local URI.
|
|
137
|
+
*/
|
|
138
|
+
const addAttachment = (0, react_1.useCallback)(async (params) => {
|
|
139
|
+
const { attachmentId } = await services_1.uploadQueueService.enqueue({
|
|
140
|
+
localUri: params.uri,
|
|
141
|
+
mimeType: params.mimeType,
|
|
142
|
+
fileName: params.fileName,
|
|
143
|
+
fileSize: params.fileSize,
|
|
144
|
+
});
|
|
145
|
+
const state = {
|
|
146
|
+
attachmentId,
|
|
147
|
+
localUri: params.uri,
|
|
148
|
+
fileName: params.fileName,
|
|
149
|
+
mimeType: params.mimeType,
|
|
150
|
+
phase: domain_1.UploadPhase.QUEUED,
|
|
151
|
+
progress: 0,
|
|
152
|
+
};
|
|
153
|
+
attachmentIdsRef.current.add(attachmentId);
|
|
154
|
+
setAttachments((prev) => new Map(prev).set(attachmentId, state));
|
|
155
|
+
return state;
|
|
156
|
+
}, []);
|
|
157
|
+
/**
|
|
158
|
+
* Pick an image from camera or photo library.
|
|
159
|
+
*/
|
|
160
|
+
const pickImage = (0, react_1.useCallback)(async (source) => {
|
|
161
|
+
const options = {
|
|
162
|
+
mediaTypes: ['images'],
|
|
163
|
+
quality: 0.8,
|
|
164
|
+
};
|
|
165
|
+
const result = source === 'camera'
|
|
166
|
+
? await ImagePicker.launchCameraAsync(options)
|
|
167
|
+
: await ImagePicker.launchImageLibraryAsync(options);
|
|
168
|
+
if (result.canceled || !result.assets[0]) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
const asset = result.assets[0];
|
|
172
|
+
const fileName = asset.fileName ?? `image_${Date.now()}.jpg`;
|
|
173
|
+
const mimeType = asset.mimeType ?? 'image/jpeg';
|
|
174
|
+
// Get file size - use asset.fileSize if available, otherwise query filesystem
|
|
175
|
+
let fileSize = asset.fileSize;
|
|
176
|
+
if (fileSize === undefined || fileSize === null) {
|
|
177
|
+
const fileInfo = await FileSystem.getInfoAsync(asset.uri);
|
|
178
|
+
fileSize = fileInfo.exists && fileInfo.size ? fileInfo.size : 0;
|
|
179
|
+
}
|
|
180
|
+
return addAttachment({
|
|
181
|
+
uri: asset.uri,
|
|
182
|
+
mimeType,
|
|
183
|
+
fileName,
|
|
184
|
+
fileSize,
|
|
185
|
+
});
|
|
186
|
+
}, [addAttachment]);
|
|
187
|
+
/**
|
|
188
|
+
* Pick a document (images or PDFs).
|
|
189
|
+
*/
|
|
190
|
+
const pickDocument = (0, react_1.useCallback)(async () => {
|
|
191
|
+
const result = await DocumentPicker.getDocumentAsync({
|
|
192
|
+
type: ['image/*', 'application/pdf'],
|
|
193
|
+
copyToCacheDirectory: true,
|
|
194
|
+
});
|
|
195
|
+
if (result.canceled || !result.assets[0]) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
const asset = result.assets[0];
|
|
199
|
+
// Get file size - use asset.size if available, otherwise query filesystem
|
|
200
|
+
let fileSize = asset.size;
|
|
201
|
+
if (fileSize === undefined || fileSize === null) {
|
|
202
|
+
const fileInfo = await FileSystem.getInfoAsync(asset.uri);
|
|
203
|
+
fileSize = fileInfo.exists && fileInfo.size ? fileInfo.size : 0;
|
|
204
|
+
}
|
|
205
|
+
return addAttachment({
|
|
206
|
+
uri: asset.uri,
|
|
207
|
+
mimeType: asset.mimeType ?? 'application/octet-stream',
|
|
208
|
+
fileName: asset.name,
|
|
209
|
+
fileSize,
|
|
210
|
+
});
|
|
211
|
+
}, [addAttachment]);
|
|
212
|
+
/**
|
|
213
|
+
* Retry a failed attachment upload.
|
|
214
|
+
*/
|
|
215
|
+
const retryAttachment = (0, react_1.useCallback)(async (attachmentId) => {
|
|
216
|
+
await services_1.uploadQueueService.retryItem(attachmentId);
|
|
217
|
+
}, []);
|
|
218
|
+
/**
|
|
219
|
+
* Remove an attachment (cancels upload if in progress).
|
|
220
|
+
*/
|
|
221
|
+
const removeAttachment = (0, react_1.useCallback)(async (attachmentId) => {
|
|
222
|
+
await services_1.uploadQueueService.cancelItem(attachmentId);
|
|
223
|
+
attachmentIdsRef.current.delete(attachmentId);
|
|
224
|
+
setAttachments((prev) => {
|
|
225
|
+
const next = new Map(prev);
|
|
226
|
+
next.delete(attachmentId);
|
|
227
|
+
return next;
|
|
228
|
+
});
|
|
229
|
+
}, []);
|
|
230
|
+
/**
|
|
231
|
+
* Get all attachment IDs for feedback submission.
|
|
232
|
+
*/
|
|
233
|
+
const getAttachmentIds = (0, react_1.useCallback)(() => {
|
|
234
|
+
return Array.from(attachments.values()).map((a) => a.attachmentId);
|
|
235
|
+
}, [attachments]);
|
|
236
|
+
/**
|
|
237
|
+
* Clear all completed attachments from both local state and queue service.
|
|
238
|
+
*/
|
|
239
|
+
const clearCompleted = (0, react_1.useCallback)(() => {
|
|
240
|
+
// Clear from queue service (persisted storage)
|
|
241
|
+
void services_1.uploadQueueService.clearCompleted();
|
|
242
|
+
// Clear from local state
|
|
243
|
+
setAttachments((prev) => {
|
|
244
|
+
const next = new Map();
|
|
245
|
+
for (const [id, att] of prev) {
|
|
246
|
+
if (att.phase !== domain_1.UploadPhase.COMPLETED) {
|
|
247
|
+
next.set(id, att);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
attachmentIdsRef.current.delete(id);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return next;
|
|
254
|
+
});
|
|
255
|
+
}, []);
|
|
256
|
+
/**
|
|
257
|
+
* Clear all failed attachments from both local state and queue service.
|
|
258
|
+
*/
|
|
259
|
+
const clearFailed = (0, react_1.useCallback)(() => {
|
|
260
|
+
// Clear from queue service (persisted storage)
|
|
261
|
+
void services_1.uploadQueueService.clearFailed();
|
|
262
|
+
// Clear from local state
|
|
263
|
+
setAttachments((prev) => {
|
|
264
|
+
const next = new Map();
|
|
265
|
+
for (const [id, att] of prev) {
|
|
266
|
+
if (att.phase !== domain_1.UploadPhase.FAILED) {
|
|
267
|
+
next.set(id, att);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
attachmentIdsRef.current.delete(id);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return next;
|
|
274
|
+
});
|
|
275
|
+
}, []);
|
|
276
|
+
// Compute whether any uploads are in progress
|
|
277
|
+
const hasActiveUploads = Array.from(attachments.values()).some((a) => a.phase === domain_1.UploadPhase.QUEUED ||
|
|
278
|
+
a.phase === domain_1.UploadPhase.UPLOADING ||
|
|
279
|
+
a.phase === domain_1.UploadPhase.CONFIRMING);
|
|
280
|
+
return {
|
|
281
|
+
attachments: Array.from(attachments.values()),
|
|
282
|
+
pickImage,
|
|
283
|
+
pickDocument,
|
|
284
|
+
addAttachment,
|
|
285
|
+
retryAttachment,
|
|
286
|
+
removeAttachment,
|
|
287
|
+
getAttachmentIds,
|
|
288
|
+
hasActiveUploads,
|
|
289
|
+
clearCompleted,
|
|
290
|
+
clearFailed,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=useAttachmentUpload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAttachmentUpload.js","sourceRoot":"","sources":["../../src/hooks/useAttachmentUpload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { components } from '../types/index.js';
|
|
2
|
+
import { HarkenApiError, HarkenNetworkError } from '../api/errors';
|
|
3
|
+
import type { FeedbackCategory, DeviceMetadata } from '../types';
|
|
4
|
+
type FeedbackSubmissionResponse = components['schemas']['FeedbackSubmissionResponse'];
|
|
5
|
+
export interface SubmitFeedbackParams {
|
|
6
|
+
/** Feedback message content */
|
|
7
|
+
message: string;
|
|
8
|
+
/** Feedback category */
|
|
9
|
+
category: FeedbackCategory;
|
|
10
|
+
/** Optional title/subject */
|
|
11
|
+
title?: string;
|
|
12
|
+
/** Additional device metadata (merged with auto-collected metadata) */
|
|
13
|
+
metadata?: Partial<DeviceMetadata>;
|
|
14
|
+
/** Attachment IDs from presigned uploads */
|
|
15
|
+
attachments?: string[];
|
|
16
|
+
}
|
|
17
|
+
export interface UseFeedbackResult {
|
|
18
|
+
/** Submit feedback to Harken */
|
|
19
|
+
submitFeedback: (params: SubmitFeedbackParams) => Promise<FeedbackSubmissionResponse>;
|
|
20
|
+
/** True while a submission is in progress */
|
|
21
|
+
isSubmitting: boolean;
|
|
22
|
+
/** Last error from submission attempt */
|
|
23
|
+
error: HarkenApiError | HarkenNetworkError | null;
|
|
24
|
+
/** Clear the error state */
|
|
25
|
+
clearError: () => void;
|
|
26
|
+
/** True if anonymous ID is still loading */
|
|
27
|
+
isInitializing: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Hook for submitting feedback through the Harken API.
|
|
31
|
+
*
|
|
32
|
+
* Automatically includes the anonymous ID and device metadata.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* function FeedbackScreen() {
|
|
37
|
+
* const { submitFeedback, isSubmitting, error } = useFeedback();
|
|
38
|
+
*
|
|
39
|
+
* const handleSubmit = async () => {
|
|
40
|
+
* try {
|
|
41
|
+
* await submitFeedback({
|
|
42
|
+
* message: 'Great app!',
|
|
43
|
+
* category: 'idea',
|
|
44
|
+
* });
|
|
45
|
+
* // Success!
|
|
46
|
+
* } catch (e) {
|
|
47
|
+
* // Error is also available in `error` state
|
|
48
|
+
* }
|
|
49
|
+
* };
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function useFeedback(): UseFeedbackResult;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=useFeedback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFeedback.d.ts","sourceRoot":"","sources":["../../src/hooks/useFeedback.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEjE,KAAK,0BAA0B,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,4BAA4B,CAAC,CAAC;AAEtF,MAAM,WAAW,oBAAoB;IACnC,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACnC,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,gCAAgC;IAChC,cAAc,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACtF,6CAA6C;IAC7C,YAAY,EAAE,OAAO,CAAC;IACtB,yCAAyC;IACzC,KAAK,EAAE,cAAc,GAAG,kBAAkB,GAAG,IAAI,CAAC;IAClD,4BAA4B;IAC5B,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,4CAA4C;IAC5C,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,WAAW,IAAI,iBAAiB,CA6E/C"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useFeedback = useFeedback;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const react_native_1 = require("react-native");
|
|
6
|
+
const useHarkenContext_1 = require("./useHarkenContext");
|
|
7
|
+
const useAnonymousId_1 = require("./useAnonymousId");
|
|
8
|
+
const client_1 = require("../api/client");
|
|
9
|
+
const errors_1 = require("../api/errors");
|
|
10
|
+
/**
|
|
11
|
+
* Hook for submitting feedback through the Harken API.
|
|
12
|
+
*
|
|
13
|
+
* Automatically includes the anonymous ID and device metadata.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* function FeedbackScreen() {
|
|
18
|
+
* const { submitFeedback, isSubmitting, error } = useFeedback();
|
|
19
|
+
*
|
|
20
|
+
* const handleSubmit = async () => {
|
|
21
|
+
* try {
|
|
22
|
+
* await submitFeedback({
|
|
23
|
+
* message: 'Great app!',
|
|
24
|
+
* category: 'idea',
|
|
25
|
+
* });
|
|
26
|
+
* // Success!
|
|
27
|
+
* } catch (e) {
|
|
28
|
+
* // Error is also available in `error` state
|
|
29
|
+
* }
|
|
30
|
+
* };
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
function useFeedback() {
|
|
35
|
+
const { config } = (0, useHarkenContext_1.useHarkenContext)();
|
|
36
|
+
const { anonymousId, isLoading: isInitializing } = (0, useAnonymousId_1.useAnonymousId)();
|
|
37
|
+
const [isSubmitting, setIsSubmitting] = (0, react_1.useState)(false);
|
|
38
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
39
|
+
// Create client instance (memoized)
|
|
40
|
+
const client = (0, react_1.useMemo)(() => {
|
|
41
|
+
return new client_1.HarkenClient({
|
|
42
|
+
publishableKey: config.publishableKey,
|
|
43
|
+
userToken: config.userToken,
|
|
44
|
+
baseUrl: config.apiBaseUrl,
|
|
45
|
+
});
|
|
46
|
+
}, [config.publishableKey, config.userToken, config.apiBaseUrl]);
|
|
47
|
+
const clearError = (0, react_1.useCallback)(() => {
|
|
48
|
+
setError(null);
|
|
49
|
+
}, []);
|
|
50
|
+
const submitFeedback = (0, react_1.useCallback)(async (params) => {
|
|
51
|
+
if (!anonymousId) {
|
|
52
|
+
throw new Error('Anonymous ID not yet initialized. Wait for isInitializing to be false.');
|
|
53
|
+
}
|
|
54
|
+
setIsSubmitting(true);
|
|
55
|
+
setError(null);
|
|
56
|
+
try {
|
|
57
|
+
// Collect device metadata
|
|
58
|
+
// Only set platform if it's a known value (ios, android)
|
|
59
|
+
// Other platforms (web, windows, macos) should be passed via metadata
|
|
60
|
+
const detectedPlatform = react_native_1.Platform.OS === 'ios' ? 'ios' :
|
|
61
|
+
react_native_1.Platform.OS === 'android' ? 'android' :
|
|
62
|
+
undefined;
|
|
63
|
+
const deviceMetadata = {
|
|
64
|
+
...(detectedPlatform && { platform: detectedPlatform }),
|
|
65
|
+
...params.metadata,
|
|
66
|
+
};
|
|
67
|
+
const response = await client.submitFeedback({
|
|
68
|
+
message: params.message,
|
|
69
|
+
category: params.category,
|
|
70
|
+
title: params.title,
|
|
71
|
+
anon_id: anonymousId,
|
|
72
|
+
metadata: deviceMetadata,
|
|
73
|
+
attachments: params.attachments,
|
|
74
|
+
});
|
|
75
|
+
return response;
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
const harkenError = e instanceof errors_1.HarkenApiError || e instanceof errors_1.HarkenNetworkError
|
|
79
|
+
? e
|
|
80
|
+
: new errors_1.HarkenNetworkError(e instanceof Error ? e.message : 'Unknown error', e instanceof Error ? e : undefined);
|
|
81
|
+
setError(harkenError);
|
|
82
|
+
throw harkenError;
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
setIsSubmitting(false);
|
|
86
|
+
}
|
|
87
|
+
}, [anonymousId, client]);
|
|
88
|
+
return {
|
|
89
|
+
submitFeedback,
|
|
90
|
+
isSubmitting,
|
|
91
|
+
error,
|
|
92
|
+
clearError,
|
|
93
|
+
isInitializing,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=useFeedback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFeedback.js","sourceRoot":"","sources":["../../src/hooks/useFeedback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { HarkenContextValue } from '../context';
|
|
2
|
+
/**
|
|
3
|
+
* Hook to access the full Harken context.
|
|
4
|
+
*
|
|
5
|
+
* Provides access to theme, config, and SDK state.
|
|
6
|
+
* Must be used within a HarkenProvider.
|
|
7
|
+
*
|
|
8
|
+
* @returns The full HarkenContextValue
|
|
9
|
+
* @throws Error if used outside of HarkenProvider
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* function MyComponent() {
|
|
14
|
+
* const { theme, isDarkMode, config } = useHarkenContext();
|
|
15
|
+
*
|
|
16
|
+
* return (
|
|
17
|
+
* <View>
|
|
18
|
+
* <Text>Dark mode: {isDarkMode ? 'on' : 'off'}</Text>
|
|
19
|
+
* </View>
|
|
20
|
+
* );
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function useHarkenContext(): HarkenContextValue;
|
|
25
|
+
//# sourceMappingURL=useHarkenContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHarkenContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useHarkenContext.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,IAAI,kBAAkB,CAQrD"}
|