@roeehrl/tinode-sdk 0.25.1-sqlite.10 → 0.25.1-sqlite.11

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@roeehrl/tinode-sdk",
3
3
  "description": "Tinode SDK fork with Storage interface for SQLite persistence in React Native",
4
- "version": "0.25.1-sqlite.10",
4
+ "version": "0.25.1-sqlite.11",
5
5
  "types": "./types/index.d.ts",
6
6
  "scripts": {
7
7
  "format": "js-beautify -r src/*.js",
@@ -112,21 +112,30 @@ export default class LargeFileHelperNative {
112
112
  const url = this._buildUploadUrl(baseUrl);
113
113
  const headers = this._buildHeaders();
114
114
 
115
+ // Log upload details
116
+ this._tinode.logger("Starting upload to:", url);
117
+ this._tinode.logger("Upload file:", { uri, filename, mimetype, size });
118
+
115
119
  // Create AbortController for cancellation
116
120
  const abortController = new AbortController();
117
121
  this._abortControllers.push(abortController);
118
122
 
119
- return new Promise((resolve, reject) => {
123
+ // Use fetch instead of XHR - React Native XHR has issues with FormData uploads
124
+ // where the response body is not accessible. Fetch works correctly.
125
+ // Note: We lose upload progress tracking with fetch, but the upload works.
126
+ return (async () => {
120
127
  try {
121
128
  // Build FormData with file URI (React Native specific)
122
129
  const formData = new FormData();
123
130
 
124
131
  // React Native FormData accepts objects with uri, type, and name
125
- formData.append('file', {
132
+ const fileObj = {
126
133
  uri: uri,
127
134
  type: mimetype,
128
135
  name: filename,
129
- });
136
+ };
137
+ instance._tinode.logger("FormData file object:", fileObj);
138
+ formData.append('file', fileObj);
130
139
 
131
140
  formData.append('id', this._tinode.getNextUniqueId());
132
141
 
@@ -134,103 +143,96 @@ export default class LargeFileHelperNative {
134
143
  formData.append('topic', avatarFor);
135
144
  }
136
145
 
137
- // Use fetch with upload progress via XMLHttpRequest
138
- // Note: fetch doesn't support upload progress, so we use XMLHttpRequest
139
- const xhr = new XMLHttpRequest();
146
+ // Signal progress start (we can't track actual progress with fetch)
147
+ if (onProgress) {
148
+ onProgress(0.1); // Indicate upload started
149
+ }
150
+ if (instance.onProgress) {
151
+ instance.onProgress(0.1);
152
+ }
140
153
 
141
- xhr.open('POST', url, true);
154
+ instance._tinode.logger("Sending fetch request...");
142
155
 
143
- // Set headers
144
- Object.keys(headers).forEach(key => {
145
- xhr.setRequestHeader(key, headers[key]);
156
+ const response = await fetch(url, {
157
+ method: 'POST',
158
+ headers: headers,
159
+ body: formData,
160
+ signal: abortController.signal,
146
161
  });
147
162
 
148
- // Handle abort
149
- abortController.signal.addEventListener('abort', () => {
150
- xhr.abort();
163
+ instance._tinode.logger("Fetch response:", {
164
+ status: response.status,
165
+ statusText: response.statusText,
166
+ ok: response.ok,
151
167
  });
152
168
 
153
- // Progress tracking
154
- if (onProgress || instance.onProgress) {
155
- xhr.upload.onprogress = (e) => {
156
- if (e.lengthComputable) {
157
- const progress = e.loaded / e.total;
158
- if (onProgress) {
159
- onProgress(progress);
160
- }
161
- if (instance.onProgress) {
162
- instance.onProgress(progress);
163
- }
164
- } else if (size > 0) {
165
- // Use provided size if available
166
- const progress = Math.min(e.loaded / size, 1);
167
- if (onProgress) {
168
- onProgress(progress);
169
- }
170
- if (instance.onProgress) {
171
- instance.onProgress(progress);
172
- }
169
+ // Signal progress near completion
170
+ if (onProgress) {
171
+ onProgress(0.9);
172
+ }
173
+ if (instance.onProgress) {
174
+ instance.onProgress(0.9);
175
+ }
176
+
177
+ const responseText = await response.text();
178
+ instance._tinode.logger("Response text:", responseText.substring(0, 200));
179
+
180
+ let pkt;
181
+ try {
182
+ pkt = JSON.parse(responseText);
183
+ } catch (err) {
184
+ instance._tinode.logger("ERROR: Failed to parse server response:", responseText);
185
+ pkt = {
186
+ ctrl: {
187
+ code: response.status,
188
+ text: response.statusText || 'Unknown error'
173
189
  }
174
190
  };
175
191
  }
176
192
 
177
- xhr.onload = function() {
178
- let pkt;
179
- try {
180
- pkt = JSON.parse(this.response);
181
- } catch (err) {
182
- instance._tinode.logger("ERROR: Invalid server response in LargeFileHelperNative", this.response);
183
- pkt = {
184
- ctrl: {
185
- code: this.status,
186
- text: this.statusText
187
- }
188
- };
189
- }
193
+ // Signal completion
194
+ if (onProgress) {
195
+ onProgress(1);
196
+ }
197
+ if (instance.onProgress) {
198
+ instance.onProgress(1);
199
+ }
190
200
 
191
- if (this.status >= 200 && this.status < 300) {
192
- const uploadUrl = pkt.ctrl.params.url;
193
- resolve(uploadUrl);
194
- if (onSuccess) {
195
- onSuccess(pkt.ctrl);
196
- }
197
- } else if (this.status >= 400) {
198
- const error = new CommError(pkt.ctrl.text, pkt.ctrl.code);
199
- reject(error);
200
- if (onFailure) {
201
- onFailure(pkt.ctrl);
202
- }
203
- } else {
204
- instance._tinode.logger("ERROR: Unexpected server response status", this.status, this.response);
205
- reject(new Error(`Unexpected status: ${this.status}`));
201
+ if (response.ok && pkt.ctrl && pkt.ctrl.params && pkt.ctrl.params.url) {
202
+ const uploadUrl = pkt.ctrl.params.url;
203
+ instance._tinode.logger("Upload success, URL:", uploadUrl);
204
+ if (onSuccess) {
205
+ onSuccess(pkt.ctrl);
206
206
  }
207
- };
208
-
209
- xhr.onerror = function(e) {
210
- const error = e || new Error("Upload failed");
211
- reject(error);
207
+ return uploadUrl;
208
+ } else if (response.status >= 400) {
209
+ const errorCode = pkt.ctrl?.code || response.status;
210
+ const errorText = pkt.ctrl?.text || 'Upload failed';
211
+ instance._tinode.logger("Upload error:", errorCode, errorText);
212
+ const error = new CommError(errorText, errorCode);
212
213
  if (onFailure) {
213
- onFailure(null);
214
+ onFailure(pkt.ctrl);
214
215
  }
215
- };
216
-
217
- xhr.onabort = function() {
218
- const error = new Error("Upload cancelled by user");
219
- reject(error);
216
+ throw error;
217
+ } else {
218
+ instance._tinode.logger("ERROR: Unexpected response - status:", response.status, "response:", responseText);
219
+ throw new Error(`Unexpected status: ${response.status}, response: ${responseText ? responseText.substring(0, 100) : 'empty'}`);
220
+ }
221
+ } catch (err) {
222
+ if (err.name === 'AbortError') {
223
+ instance._tinode.logger("Upload aborted");
220
224
  if (onFailure) {
221
225
  onFailure(null);
222
226
  }
223
- };
224
-
225
- xhr.send(formData);
226
-
227
- } catch (err) {
228
- reject(err);
227
+ throw new Error("Upload cancelled by user");
228
+ }
229
+ instance._tinode.logger("Upload error:", err.message);
229
230
  if (onFailure) {
230
231
  onFailure(null);
231
232
  }
233
+ throw err;
232
234
  }
233
- });
235
+ })();
234
236
  }
235
237
 
236
238
  /**