@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,623 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Upload Queue Service
|
|
4
|
+
*
|
|
5
|
+
* Singleton service that manages background attachment uploads.
|
|
6
|
+
* Uses expo-file-system/legacy for background upload support.
|
|
7
|
+
*
|
|
8
|
+
* Key design decisions (from feature spec):
|
|
9
|
+
* - D1: Uses expo-file-system/legacy with BACKGROUND session type
|
|
10
|
+
* - D2: Initialized once at app startup in HarkenProvider
|
|
11
|
+
* - D3: Persists queue to AsyncStorage
|
|
12
|
+
* - D4: Exponential backoff (2s base, 60s max, 3 attempts, 1s jitter)
|
|
13
|
+
* - D5: Auto-pause when offline via NetInfo
|
|
14
|
+
* - D6: Real progress tracking from expo-file-system
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
50
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
51
|
+
};
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
exports.uploadQueueService = exports.UploadQueueService = void 0;
|
|
54
|
+
const FileSystem = __importStar(require("expo-file-system/legacy"));
|
|
55
|
+
const netinfo_1 = __importDefault(require("@react-native-community/netinfo"));
|
|
56
|
+
const uploadQueueStorage_1 = require("./uploadQueueStorage");
|
|
57
|
+
const domain_1 = require("../domain");
|
|
58
|
+
const utils_1 = require("../utils");
|
|
59
|
+
/**
|
|
60
|
+
* Singleton service for managing background attachment uploads.
|
|
61
|
+
*/
|
|
62
|
+
class UploadQueueService {
|
|
63
|
+
static instance = null;
|
|
64
|
+
client = null;
|
|
65
|
+
retryConfig = domain_1.DEFAULT_UPLOAD_RETRY_CONFIG;
|
|
66
|
+
storage = new uploadQueueStorage_1.UploadQueueStorage();
|
|
67
|
+
debug = false;
|
|
68
|
+
// Queue state
|
|
69
|
+
items = new Map();
|
|
70
|
+
isProcessing = false;
|
|
71
|
+
isPaused = false;
|
|
72
|
+
isInitialized = false;
|
|
73
|
+
// Active upload tasks (for cancellation)
|
|
74
|
+
activeTasks = new Map();
|
|
75
|
+
// Event subscribers
|
|
76
|
+
progressListeners = new Set();
|
|
77
|
+
completeListeners = new Set();
|
|
78
|
+
errorListeners = new Set();
|
|
79
|
+
// Network monitoring
|
|
80
|
+
networkUnsubscribe = null;
|
|
81
|
+
// Retry timer - schedules wake-up when next retry is due
|
|
82
|
+
retryTimerId = null;
|
|
83
|
+
constructor() { }
|
|
84
|
+
/**
|
|
85
|
+
* Get the singleton instance.
|
|
86
|
+
*/
|
|
87
|
+
static getInstance() {
|
|
88
|
+
if (!UploadQueueService.instance) {
|
|
89
|
+
UploadQueueService.instance = new UploadQueueService();
|
|
90
|
+
}
|
|
91
|
+
return UploadQueueService.instance;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Initialize the queue service.
|
|
95
|
+
*
|
|
96
|
+
* Must be called once at app startup (in HarkenProvider).
|
|
97
|
+
* This prevents the race condition where uploads complete
|
|
98
|
+
* before callbacks are registered.
|
|
99
|
+
*
|
|
100
|
+
* Supports hot reload by updating the client reference on subsequent calls.
|
|
101
|
+
*/
|
|
102
|
+
async initialize(config) {
|
|
103
|
+
// Always update client reference to support hot reload
|
|
104
|
+
// (React creates new client instance on re-render)
|
|
105
|
+
this.client = config.client;
|
|
106
|
+
this.debug = config.debug ?? false;
|
|
107
|
+
if (this.isInitialized) {
|
|
108
|
+
this.log('Already initialized, updated client reference');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
this.retryConfig = { ...domain_1.DEFAULT_UPLOAD_RETRY_CONFIG, ...config.retryConfig };
|
|
112
|
+
// Load persisted queue
|
|
113
|
+
const persistedItems = await this.storage.loadQueue();
|
|
114
|
+
for (const item of persistedItems) {
|
|
115
|
+
// Reset any "uploading" or "confirming" items to "queued"
|
|
116
|
+
// (app was killed mid-upload)
|
|
117
|
+
if (item.phase === domain_1.UploadPhase.UPLOADING ||
|
|
118
|
+
item.phase === domain_1.UploadPhase.CONFIRMING) {
|
|
119
|
+
item.phase = domain_1.UploadPhase.QUEUED;
|
|
120
|
+
item.progress = 0;
|
|
121
|
+
}
|
|
122
|
+
this.items.set(item.id, item);
|
|
123
|
+
}
|
|
124
|
+
// Setup network monitoring
|
|
125
|
+
this.setupNetworkMonitoring();
|
|
126
|
+
this.isInitialized = true;
|
|
127
|
+
this.log(`Initialized with ${this.items.size} queued items`);
|
|
128
|
+
// Start processing if we have items
|
|
129
|
+
if (this.items.size > 0) {
|
|
130
|
+
void this.processQueue();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if the service is initialized.
|
|
135
|
+
*/
|
|
136
|
+
get initialized() {
|
|
137
|
+
return this.isInitialized;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Enqueue a new attachment for upload.
|
|
141
|
+
*
|
|
142
|
+
* This method:
|
|
143
|
+
* 1. Requests a presigned URL from the server
|
|
144
|
+
* 2. Creates a queue item
|
|
145
|
+
* 3. Persists the queue
|
|
146
|
+
* 4. Triggers queue processing
|
|
147
|
+
*
|
|
148
|
+
* Returns immediately with the attachment ID (upload happens in background).
|
|
149
|
+
*/
|
|
150
|
+
async enqueue(params) {
|
|
151
|
+
if (!this.client) {
|
|
152
|
+
throw new Error('UploadQueueService not initialized');
|
|
153
|
+
}
|
|
154
|
+
// 1. Get presigned URL from server
|
|
155
|
+
const presignResponse = await this.client.createAttachmentUpload({
|
|
156
|
+
filename: params.fileName,
|
|
157
|
+
content_type: params.mimeType,
|
|
158
|
+
size: params.fileSize,
|
|
159
|
+
});
|
|
160
|
+
// 2. Create queue item
|
|
161
|
+
const queueItem = {
|
|
162
|
+
id: (0, utils_1.generateUUID)(),
|
|
163
|
+
attachmentId: presignResponse.attachment_id,
|
|
164
|
+
localUri: params.localUri,
|
|
165
|
+
uploadUrl: presignResponse.upload_url,
|
|
166
|
+
uploadExpiresAt: presignResponse.upload_expires_at,
|
|
167
|
+
mimeType: params.mimeType,
|
|
168
|
+
fileName: params.fileName,
|
|
169
|
+
fileSize: params.fileSize,
|
|
170
|
+
phase: domain_1.UploadPhase.QUEUED,
|
|
171
|
+
progress: 0,
|
|
172
|
+
attemptNumber: 0,
|
|
173
|
+
maxAttempts: this.retryConfig.maxAttempts,
|
|
174
|
+
createdAt: new Date().toISOString(),
|
|
175
|
+
};
|
|
176
|
+
// 3. Add to queue and persist
|
|
177
|
+
this.items.set(queueItem.id, queueItem);
|
|
178
|
+
await this.persistQueue();
|
|
179
|
+
// 4. Emit initial progress
|
|
180
|
+
this.emitProgress(queueItem);
|
|
181
|
+
// 5. Trigger queue processing
|
|
182
|
+
void this.processQueue();
|
|
183
|
+
this.log(`Enqueued ${presignResponse.attachment_id}`);
|
|
184
|
+
return {
|
|
185
|
+
attachmentId: presignResponse.attachment_id,
|
|
186
|
+
queueItemId: queueItem.id,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Process the upload queue.
|
|
191
|
+
*
|
|
192
|
+
* Processes items sequentially (one at a time) to avoid memory pressure
|
|
193
|
+
* on low-end devices.
|
|
194
|
+
*/
|
|
195
|
+
async processQueue() {
|
|
196
|
+
if (this.isProcessing || this.isPaused) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
// Clear any pending retry timer since we're processing now
|
|
200
|
+
this.clearRetryTimer();
|
|
201
|
+
this.isProcessing = true;
|
|
202
|
+
this.log('Processing queue...');
|
|
203
|
+
try {
|
|
204
|
+
while (true) {
|
|
205
|
+
// Find next item to process
|
|
206
|
+
const item = this.getNextQueuedItem();
|
|
207
|
+
if (!item) {
|
|
208
|
+
this.log('No more items to process');
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
if (this.isPaused) {
|
|
212
|
+
this.log('Queue paused, stopping processing');
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
await this.processItem(item);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
finally {
|
|
219
|
+
this.isProcessing = false;
|
|
220
|
+
// Schedule wake-up for any pending retries
|
|
221
|
+
this.scheduleNextRetry();
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Process a single queue item.
|
|
226
|
+
*/
|
|
227
|
+
async processItem(item) {
|
|
228
|
+
this.log(`Processing item ${item.id} (attachment: ${item.attachmentId})`);
|
|
229
|
+
// Check if URL has expired
|
|
230
|
+
if (new Date(item.uploadExpiresAt) < new Date()) {
|
|
231
|
+
this.log(`URL expired for ${item.attachmentId}`);
|
|
232
|
+
await this.handleItemFailure(item, 'Upload URL expired');
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
// Check if we need to wait for retry delay
|
|
236
|
+
if (item.scheduledRetryAt) {
|
|
237
|
+
const waitUntil = new Date(item.scheduledRetryAt);
|
|
238
|
+
if (waitUntil > new Date()) {
|
|
239
|
+
const waitMs = waitUntil.getTime() - Date.now();
|
|
240
|
+
this.log(`Waiting ${waitMs}ms before retry for ${item.attachmentId}`);
|
|
241
|
+
await this.sleep(waitMs);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// Update state to uploading
|
|
245
|
+
item.phase = domain_1.UploadPhase.UPLOADING;
|
|
246
|
+
item.startedAt = new Date().toISOString();
|
|
247
|
+
item.attemptNumber += 1;
|
|
248
|
+
await this.persistQueue();
|
|
249
|
+
this.emitProgress(item);
|
|
250
|
+
try {
|
|
251
|
+
// Perform the upload
|
|
252
|
+
await this.uploadFile(item);
|
|
253
|
+
// Confirm with server
|
|
254
|
+
item.phase = domain_1.UploadPhase.CONFIRMING;
|
|
255
|
+
await this.persistQueue();
|
|
256
|
+
this.emitProgress(item);
|
|
257
|
+
await this.client.confirmAttachment(item.attachmentId, {
|
|
258
|
+
bytes_uploaded: item.fileSize,
|
|
259
|
+
});
|
|
260
|
+
// Success!
|
|
261
|
+
item.phase = domain_1.UploadPhase.COMPLETED;
|
|
262
|
+
item.completedAt = new Date().toISOString();
|
|
263
|
+
item.progress = 1;
|
|
264
|
+
await this.persistQueue();
|
|
265
|
+
this.emitProgress(item);
|
|
266
|
+
this.emitComplete(item.attachmentId);
|
|
267
|
+
this.log(`Completed upload for ${item.attachmentId}`);
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
271
|
+
this.log(`Upload failed for ${item.attachmentId}: ${errorMessage}`);
|
|
272
|
+
if (item.attemptNumber < item.maxAttempts) {
|
|
273
|
+
// Schedule retry with exponential backoff
|
|
274
|
+
const delay = this.calculateRetryDelay(item.attemptNumber);
|
|
275
|
+
item.phase = domain_1.UploadPhase.QUEUED;
|
|
276
|
+
item.progress = 0;
|
|
277
|
+
item.lastError = errorMessage;
|
|
278
|
+
item.scheduledRetryAt = new Date(Date.now() + delay).toISOString();
|
|
279
|
+
await this.persistQueue();
|
|
280
|
+
this.emitProgress(item);
|
|
281
|
+
this.log(`Scheduled retry in ${delay}ms for ${item.attachmentId}`);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
await this.handleItemFailure(item, errorMessage);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Upload file using expo-file-system background upload.
|
|
290
|
+
*
|
|
291
|
+
* Uses FileSystemSessionType.BACKGROUND for true background uploads
|
|
292
|
+
* that continue even when the app is backgrounded.
|
|
293
|
+
*/
|
|
294
|
+
async uploadFile(item) {
|
|
295
|
+
return new Promise((resolve, reject) => {
|
|
296
|
+
const uploadTask = FileSystem.createUploadTask(item.uploadUrl, item.localUri, {
|
|
297
|
+
httpMethod: 'PUT',
|
|
298
|
+
uploadType: FileSystem.FileSystemUploadType.BINARY_CONTENT,
|
|
299
|
+
sessionType: FileSystem.FileSystemSessionType.BACKGROUND,
|
|
300
|
+
headers: {
|
|
301
|
+
'Content-Type': item.mimeType,
|
|
302
|
+
},
|
|
303
|
+
}, (progress) => {
|
|
304
|
+
// Real progress from expo-file-system (D6)
|
|
305
|
+
// Guard against NaN if totalBytesExpectedToSend is 0
|
|
306
|
+
const percent = progress.totalBytesExpectedToSend > 0
|
|
307
|
+
? progress.totalBytesSent / progress.totalBytesExpectedToSend
|
|
308
|
+
: 0;
|
|
309
|
+
item.progress = Math.min(1, Math.max(0, percent)); // Clamp to 0-1
|
|
310
|
+
this.emitProgress(item);
|
|
311
|
+
});
|
|
312
|
+
this.activeTasks.set(item.id, uploadTask);
|
|
313
|
+
uploadTask
|
|
314
|
+
.uploadAsync()
|
|
315
|
+
.then((result) => {
|
|
316
|
+
this.activeTasks.delete(item.id);
|
|
317
|
+
if (result && result.status >= 200 && result.status < 300) {
|
|
318
|
+
resolve();
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
reject(new Error(`Upload failed with status ${result?.status ?? 'unknown'}`));
|
|
322
|
+
}
|
|
323
|
+
})
|
|
324
|
+
.catch((error) => {
|
|
325
|
+
this.activeTasks.delete(item.id);
|
|
326
|
+
reject(error);
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Handle permanent item failure (max retries exceeded).
|
|
332
|
+
*/
|
|
333
|
+
async handleItemFailure(item, error) {
|
|
334
|
+
item.phase = domain_1.UploadPhase.FAILED;
|
|
335
|
+
item.lastError = error;
|
|
336
|
+
item.completedAt = new Date().toISOString();
|
|
337
|
+
await this.persistQueue();
|
|
338
|
+
this.emitProgress(item);
|
|
339
|
+
this.emitError(item.attachmentId, error);
|
|
340
|
+
// Report to server (fire and forget)
|
|
341
|
+
try {
|
|
342
|
+
await this.client.reportAttachmentFailure(item.attachmentId, error);
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
this.log(`Failed to report failure for ${item.attachmentId}`);
|
|
346
|
+
}
|
|
347
|
+
this.log(`Item ${item.attachmentId} failed: ${error}`);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Calculate retry delay with exponential backoff and jitter (D4).
|
|
351
|
+
*/
|
|
352
|
+
calculateRetryDelay(attemptNumber) {
|
|
353
|
+
const { baseDelayMs, maxDelayMs, jitterMs } = this.retryConfig;
|
|
354
|
+
// Exponential: 2s, 4s, 8s, 16s, ...
|
|
355
|
+
const exponential = baseDelayMs * Math.pow(2, attemptNumber - 1);
|
|
356
|
+
const capped = Math.min(exponential, maxDelayMs);
|
|
357
|
+
// Add random jitter (-jitterMs to +jitterMs)
|
|
358
|
+
const jitter = (Math.random() - 0.5) * 2 * jitterMs;
|
|
359
|
+
return Math.max(0, capped + jitter);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Get next item that's ready to process.
|
|
363
|
+
*/
|
|
364
|
+
getNextQueuedItem() {
|
|
365
|
+
const now = new Date();
|
|
366
|
+
for (const item of this.items.values()) {
|
|
367
|
+
if (item.phase !== domain_1.UploadPhase.QUEUED)
|
|
368
|
+
continue;
|
|
369
|
+
// Check if past scheduled retry time
|
|
370
|
+
if (item.scheduledRetryAt && new Date(item.scheduledRetryAt) > now) {
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
return item;
|
|
374
|
+
}
|
|
375
|
+
return undefined;
|
|
376
|
+
}
|
|
377
|
+
// --- Retry Timer ---
|
|
378
|
+
/**
|
|
379
|
+
* Schedule a timer to wake up processQueue when the next retry is due.
|
|
380
|
+
* This prevents retries from stalling indefinitely.
|
|
381
|
+
*/
|
|
382
|
+
scheduleNextRetry() {
|
|
383
|
+
// Don't schedule if paused
|
|
384
|
+
if (this.isPaused)
|
|
385
|
+
return;
|
|
386
|
+
// Find the earliest scheduledRetryAt among queued items
|
|
387
|
+
let earliestRetry = null;
|
|
388
|
+
for (const item of this.items.values()) {
|
|
389
|
+
if (item.phase !== domain_1.UploadPhase.QUEUED)
|
|
390
|
+
continue;
|
|
391
|
+
if (!item.scheduledRetryAt)
|
|
392
|
+
continue;
|
|
393
|
+
const retryTime = new Date(item.scheduledRetryAt);
|
|
394
|
+
if (!earliestRetry || retryTime < earliestRetry) {
|
|
395
|
+
earliestRetry = retryTime;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (!earliestRetry)
|
|
399
|
+
return;
|
|
400
|
+
const now = Date.now();
|
|
401
|
+
const delay = Math.max(0, earliestRetry.getTime() - now);
|
|
402
|
+
this.log(`Scheduling retry timer for ${delay}ms`);
|
|
403
|
+
this.retryTimerId = setTimeout(() => {
|
|
404
|
+
this.retryTimerId = null;
|
|
405
|
+
void this.processQueue();
|
|
406
|
+
}, delay);
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Clear any pending retry timer.
|
|
410
|
+
*/
|
|
411
|
+
clearRetryTimer() {
|
|
412
|
+
if (this.retryTimerId) {
|
|
413
|
+
clearTimeout(this.retryTimerId);
|
|
414
|
+
this.retryTimerId = null;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// --- Network Monitoring (D5) ---
|
|
418
|
+
setupNetworkMonitoring() {
|
|
419
|
+
this.networkUnsubscribe = netinfo_1.default.addEventListener((state) => {
|
|
420
|
+
if (state.isConnected && this.isPaused) {
|
|
421
|
+
this.log('Network restored, resuming queue');
|
|
422
|
+
this.isPaused = false;
|
|
423
|
+
void this.processQueue();
|
|
424
|
+
}
|
|
425
|
+
else if (!state.isConnected && !this.isPaused) {
|
|
426
|
+
this.log('Network lost, pausing queue');
|
|
427
|
+
this.isPaused = true;
|
|
428
|
+
// Cancel active uploads - they'll resume when back online
|
|
429
|
+
for (const [id, task] of this.activeTasks) {
|
|
430
|
+
void task.cancelAsync();
|
|
431
|
+
const item = this.items.get(id);
|
|
432
|
+
if (item) {
|
|
433
|
+
item.phase = domain_1.UploadPhase.QUEUED;
|
|
434
|
+
item.progress = 0;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
this.activeTasks.clear();
|
|
438
|
+
void this.persistQueue();
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
// --- Event Emitters ---
|
|
443
|
+
emitProgress(item) {
|
|
444
|
+
const progress = {
|
|
445
|
+
attachmentId: item.attachmentId,
|
|
446
|
+
phase: item.phase,
|
|
447
|
+
progress: item.progress,
|
|
448
|
+
error: item.lastError,
|
|
449
|
+
};
|
|
450
|
+
this.progressListeners.forEach((cb) => cb(progress));
|
|
451
|
+
}
|
|
452
|
+
emitComplete(attachmentId) {
|
|
453
|
+
this.completeListeners.forEach((cb) => cb(attachmentId));
|
|
454
|
+
}
|
|
455
|
+
emitError(attachmentId, error) {
|
|
456
|
+
this.errorListeners.forEach((cb) => cb(attachmentId, error));
|
|
457
|
+
}
|
|
458
|
+
// --- Public Event Subscriptions ---
|
|
459
|
+
/**
|
|
460
|
+
* Subscribe to progress updates.
|
|
461
|
+
* @returns Unsubscribe function
|
|
462
|
+
*/
|
|
463
|
+
onProgress(callback) {
|
|
464
|
+
this.progressListeners.add(callback);
|
|
465
|
+
return () => this.progressListeners.delete(callback);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Subscribe to upload completions.
|
|
469
|
+
* @returns Unsubscribe function
|
|
470
|
+
*/
|
|
471
|
+
onComplete(callback) {
|
|
472
|
+
this.completeListeners.add(callback);
|
|
473
|
+
return () => this.completeListeners.delete(callback);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Subscribe to upload errors.
|
|
477
|
+
* @returns Unsubscribe function
|
|
478
|
+
*/
|
|
479
|
+
onError(callback) {
|
|
480
|
+
this.errorListeners.add(callback);
|
|
481
|
+
return () => this.errorListeners.delete(callback);
|
|
482
|
+
}
|
|
483
|
+
// --- Public API ---
|
|
484
|
+
/**
|
|
485
|
+
* Get current queue status.
|
|
486
|
+
*/
|
|
487
|
+
getQueueStatus() {
|
|
488
|
+
let queued = 0;
|
|
489
|
+
let uploading = 0;
|
|
490
|
+
let completed = 0;
|
|
491
|
+
let failed = 0;
|
|
492
|
+
for (const item of this.items.values()) {
|
|
493
|
+
switch (item.phase) {
|
|
494
|
+
case domain_1.UploadPhase.QUEUED:
|
|
495
|
+
queued++;
|
|
496
|
+
break;
|
|
497
|
+
case domain_1.UploadPhase.UPLOADING:
|
|
498
|
+
case domain_1.UploadPhase.CONFIRMING:
|
|
499
|
+
uploading++;
|
|
500
|
+
break;
|
|
501
|
+
case domain_1.UploadPhase.COMPLETED:
|
|
502
|
+
completed++;
|
|
503
|
+
break;
|
|
504
|
+
case domain_1.UploadPhase.FAILED:
|
|
505
|
+
failed++;
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return {
|
|
510
|
+
total: this.items.size,
|
|
511
|
+
queued,
|
|
512
|
+
uploading,
|
|
513
|
+
completed,
|
|
514
|
+
failed,
|
|
515
|
+
isPaused: this.isPaused,
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Get a queue item by attachment ID.
|
|
520
|
+
*/
|
|
521
|
+
getItemByAttachmentId(attachmentId) {
|
|
522
|
+
for (const item of this.items.values()) {
|
|
523
|
+
if (item.attachmentId === attachmentId)
|
|
524
|
+
return item;
|
|
525
|
+
}
|
|
526
|
+
return undefined;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Retry a failed upload.
|
|
530
|
+
*/
|
|
531
|
+
async retryItem(attachmentId) {
|
|
532
|
+
const item = this.getItemByAttachmentId(attachmentId);
|
|
533
|
+
if (!item || item.phase !== domain_1.UploadPhase.FAILED) {
|
|
534
|
+
throw new Error('Item not found or not in failed state');
|
|
535
|
+
}
|
|
536
|
+
item.phase = domain_1.UploadPhase.QUEUED;
|
|
537
|
+
item.progress = 0;
|
|
538
|
+
item.attemptNumber = 0;
|
|
539
|
+
item.lastError = undefined;
|
|
540
|
+
item.scheduledRetryAt = undefined;
|
|
541
|
+
await this.persistQueue();
|
|
542
|
+
void this.processQueue();
|
|
543
|
+
this.log(`Retrying ${attachmentId}`);
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Cancel and remove an item from the queue.
|
|
547
|
+
*/
|
|
548
|
+
async cancelItem(attachmentId) {
|
|
549
|
+
for (const [id, item] of this.items) {
|
|
550
|
+
if (item.attachmentId === attachmentId) {
|
|
551
|
+
// Cancel active upload if any
|
|
552
|
+
const task = this.activeTasks.get(id);
|
|
553
|
+
if (task) {
|
|
554
|
+
await task.cancelAsync();
|
|
555
|
+
this.activeTasks.delete(id);
|
|
556
|
+
}
|
|
557
|
+
this.items.delete(id);
|
|
558
|
+
await this.persistQueue();
|
|
559
|
+
this.log(`Cancelled ${attachmentId}`);
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Clear all completed items from the queue.
|
|
566
|
+
*/
|
|
567
|
+
async clearCompleted() {
|
|
568
|
+
for (const [id, item] of this.items) {
|
|
569
|
+
if (item.phase === domain_1.UploadPhase.COMPLETED) {
|
|
570
|
+
this.items.delete(id);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
await this.persistQueue();
|
|
574
|
+
this.log('Cleared completed items');
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Clear all failed items from the queue.
|
|
578
|
+
*/
|
|
579
|
+
async clearFailed() {
|
|
580
|
+
for (const [id, item] of this.items) {
|
|
581
|
+
if (item.phase === domain_1.UploadPhase.FAILED) {
|
|
582
|
+
this.items.delete(id);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
await this.persistQueue();
|
|
586
|
+
this.log('Cleared failed items');
|
|
587
|
+
}
|
|
588
|
+
// --- Internal Utilities ---
|
|
589
|
+
async persistQueue() {
|
|
590
|
+
await this.storage.saveQueue(Array.from(this.items.values()));
|
|
591
|
+
}
|
|
592
|
+
sleep(ms) {
|
|
593
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
594
|
+
}
|
|
595
|
+
log(message) {
|
|
596
|
+
if (this.debug) {
|
|
597
|
+
console.log(`[UploadQueue] ${message}`);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
// --- Cleanup ---
|
|
601
|
+
/**
|
|
602
|
+
* Destroy the service instance.
|
|
603
|
+
* Used primarily for testing.
|
|
604
|
+
*/
|
|
605
|
+
destroy() {
|
|
606
|
+
this.clearRetryTimer();
|
|
607
|
+
this.networkUnsubscribe?.();
|
|
608
|
+
this.activeTasks.forEach((task) => void task.cancelAsync());
|
|
609
|
+
this.activeTasks.clear();
|
|
610
|
+
this.progressListeners.clear();
|
|
611
|
+
this.completeListeners.clear();
|
|
612
|
+
this.errorListeners.clear();
|
|
613
|
+
this.items.clear();
|
|
614
|
+
this.isInitialized = false;
|
|
615
|
+
UploadQueueService.instance = null;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
exports.UploadQueueService = UploadQueueService;
|
|
619
|
+
/**
|
|
620
|
+
* Singleton instance getter.
|
|
621
|
+
*/
|
|
622
|
+
exports.uploadQueueService = UploadQueueService.getInstance();
|
|
623
|
+
//# sourceMappingURL=uploadQueueService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploadQueueService.js","sourceRoot":"","sources":["../../src/services/uploadQueueService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent storage for the upload queue.
|
|
3
|
+
*
|
|
4
|
+
* Uses AsyncStorage to persist queue state across app restarts.
|
|
5
|
+
*/
|
|
6
|
+
import type { QueueItem } from '../domain';
|
|
7
|
+
/**
|
|
8
|
+
* Manages persistent storage of the upload queue.
|
|
9
|
+
*/
|
|
10
|
+
export declare class UploadQueueStorage {
|
|
11
|
+
/**
|
|
12
|
+
* Load queue items from persistent storage.
|
|
13
|
+
* Returns empty array if no queue exists or on error.
|
|
14
|
+
*/
|
|
15
|
+
loadQueue(): Promise<QueueItem[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Save queue items to persistent storage.
|
|
18
|
+
*/
|
|
19
|
+
saveQueue(items: QueueItem[]): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Clear all persisted queue data.
|
|
22
|
+
*/
|
|
23
|
+
clearQueue(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Migrate queue data from older versions.
|
|
26
|
+
* For now, unknown versions are reset to empty.
|
|
27
|
+
*/
|
|
28
|
+
private migrateQueue;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=uploadQueueStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploadQueueStorage.d.ts","sourceRoot":"","sources":["../../src/services/uploadQueueStorage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAkB,SAAS,EAAE,MAAM,WAAW,CAAC;AAK3D;;GAEG;AACH,qBAAa,kBAAkB;IAC7B;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAqBvC;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAYlD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjC;;;OAGG;IACH,OAAO,CAAC,YAAY;CAMrB"}
|