Skip to content

Commit d602436

Browse files
committed
fix(storage, android)!: android now updates customMetadata as a group
BREAKING CHANGE: android works like web+iOS now: customMetadata if passed in will be updated as a single atomic unit, all keys at once. Any key you want to keep in customMetadata must be passed in during update; any missing keys will be removed. Set customMetadata to null in order to remove customMetadata entirely, omit it during update to leave it unchanged.
1 parent a8c1cf4 commit d602436

File tree

6 files changed

+198
-78
lines changed

6 files changed

+198
-78
lines changed

packages/messaging/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingModule.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ public void setAutoInitEnabled(Boolean enabled, Promise promise) {
122122

123123
@ReactMethod
124124
public void getToken(String appName, String senderId, Promise promise) {
125-
FirebaseMessaging messagingInstance = FirebaseApp.getInstance(appName).get(FirebaseMessaging.class);
125+
FirebaseMessaging messagingInstance =
126+
FirebaseApp.getInstance(appName).get(FirebaseMessaging.class);
126127
Tasks.call(getExecutor(), () -> Tasks.await(messagingInstance.getToken()))
127128
.addOnCompleteListener(
128129
task -> {
@@ -136,7 +137,8 @@ public void getToken(String appName, String senderId, Promise promise) {
136137

137138
@ReactMethod
138139
public void deleteToken(String appName, String senderId, Promise promise) {
139-
FirebaseMessaging messagingInstance = FirebaseApp.getInstance(appName).get(FirebaseMessaging.class);
140+
FirebaseMessaging messagingInstance =
141+
FirebaseApp.getInstance(appName).get(FirebaseMessaging.class);
140142
Tasks.call(
141143
getExecutor(),
142144
() -> {

packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageCommon.java

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@
3636
import com.google.firebase.storage.StorageTask;
3737
import io.invertase.firebase.app.ReactNativeFirebaseApp;
3838
import io.invertase.firebase.common.SharedUtils;
39+
import java.util.HashMap;
3940
import java.util.Locale;
4041
import java.util.Map;
41-
import java.util.Objects;
4242
import javax.annotation.Nullable;
4343

4444
class ReactNativeFirebaseStorageCommon {
@@ -93,15 +93,40 @@ static String getTaskStatus(@Nullable StorageTask<?> task) {
9393
}
9494

9595
/** Converts a RN ReadableMap into a StorageMetadata instance */
96-
static StorageMetadata buildMetadataFromMap(ReadableMap metadataMap, @Nullable Uri file) {
96+
static StorageMetadata buildMetadataFromMap(
97+
ReadableMap metadataMap, @Nullable Uri file, @Nullable StorageMetadata existingMetadata) {
9798
StorageMetadata.Builder metadataBuilder = new StorageMetadata.Builder();
9899

99100
if (metadataMap != null) {
100-
if (metadataMap.hasKey(KEY_CUSTOM_META)) {
101-
ReadableMap customerMetaMap = Objects.requireNonNull(metadataMap.getMap(KEY_CUSTOM_META));
102-
Map<String, Object> customMeta = customerMetaMap.toHashMap();
103-
for (Map.Entry<String, Object> entry : customMeta.entrySet()) {
101+
if (metadataMap.hasKey(KEY_CUSTOM_META) || (existingMetadata != null)) {
102+
103+
Map<String, Object> customMetadata = new HashMap<>();
104+
ReadableMap freshCustomMetadata = metadataMap.getMap(KEY_CUSTOM_META);
105+
Map<String, Object> existingCustomMetadata = new HashMap<>();
106+
107+
// Our baseline will be any existing custom metadata if it exists
108+
if (existingMetadata != null) {
109+
for (String existingKey : existingMetadata.getCustomMetadataKeys()) {
110+
customMetadata.put(existingKey, existingMetadata.getCustomMetadata(existingKey));
111+
existingCustomMetadata.put(
112+
existingKey, existingMetadata.getCustomMetadata(existingKey));
113+
}
114+
}
115+
116+
// Clobber with any fresh custom metadata if it exists
117+
if (freshCustomMetadata != null) {
118+
customMetadata.putAll(freshCustomMetadata.toHashMap());
119+
}
120+
121+
for (Map.Entry<String, Object> entry : customMetadata.entrySet()) {
104122
metadataBuilder.setCustomMetadata(entry.getKey(), (String) entry.getValue());
123+
124+
// API contract updates custom metadata as a group but android SDK has key granularity
125+
// So if freshCustomMetadata exists, for any key that in our merged map but not in
126+
// freshCustomMetadata, set to null to clear
127+
if (freshCustomMetadata == null || !freshCustomMetadata.hasKey(entry.getKey())) {
128+
metadataBuilder.setCustomMetadata(entry.getKey(), null);
129+
}
105130
}
106131
}
107132

@@ -167,29 +192,31 @@ static WritableMap getMetadataAsMap(@Nullable StorageMetadata storageMetadata) {
167192
if (storageMetadata.getCacheControl() != null
168193
&& storageMetadata.getCacheControl().length() > 0) {
169194
metadata.putString(KEY_CACHE_CONTROL, storageMetadata.getCacheControl());
170-
} else {
171-
metadata.putNull(KEY_CACHE_CONTROL);
172195
}
173196

174197
if (storageMetadata.getContentLanguage() != null
175198
&& storageMetadata.getContentLanguage().length() > 0) {
176199
metadata.putString(KEY_CONTENT_LANG, storageMetadata.getContentLanguage());
177-
} else {
178-
metadata.putNull(KEY_CONTENT_LANG);
179200
}
180201

181-
metadata.putString(KEY_CONTENT_DISPOSITION, storageMetadata.getContentDisposition());
182-
metadata.putString(KEY_CONTENT_ENCODING, storageMetadata.getContentEncoding());
183-
metadata.putString(KEY_CONTENT_TYPE, storageMetadata.getContentType());
202+
if (storageMetadata.getContentDisposition() != null
203+
&& storageMetadata.getContentDisposition().length() > 0) {
204+
metadata.putString(KEY_CONTENT_DISPOSITION, storageMetadata.getContentDisposition());
205+
}
206+
if (storageMetadata.getContentEncoding() != null
207+
&& storageMetadata.getContentEncoding().length() > 0) {
208+
metadata.putString(KEY_CONTENT_ENCODING, storageMetadata.getContentEncoding());
209+
}
210+
if (storageMetadata.getContentType() != null && storageMetadata.getContentType().length() > 0) {
211+
metadata.putString(KEY_CONTENT_TYPE, storageMetadata.getContentType());
212+
}
184213

185214
if (storageMetadata.getCustomMetadataKeys().size() > 0) {
186215
WritableMap customMetadata = Arguments.createMap();
187216
for (String key : storageMetadata.getCustomMetadataKeys()) {
188217
customMetadata.putString(key, storageMetadata.getCustomMetadata(key));
189218
}
190219
metadata.putMap(KEY_CUSTOM_META, customMetadata);
191-
} else {
192-
metadata.putNull(KEY_CUSTOM_META);
193220
}
194221

195222
return metadata;

packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageModule.java

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,24 @@ public void listAll(String appName, String url, Promise promise) {
169169
}
170170
}
171171

172+
// Useful for development / debugging
173+
private void dumpMetadata(StorageMetadata metadata) {
174+
System.err.println("STORAGE dumping metadata contents");
175+
System.err.println("STORAGE - cacheControl " + metadata.getCacheControl());
176+
System.err.println("STORAGE - contentDisposition " + metadata.getContentDisposition());
177+
System.err.println("STORAGE - contentEncoding " + metadata.getContentEncoding());
178+
System.err.println("STORAGE - contentLanguage " + metadata.getContentLanguage());
179+
System.err.println("STORAGE - contentType " + metadata.getContentType());
180+
for (String customKey : metadata.getCustomMetadataKeys()) {
181+
System.err.println(
182+
"STORAGE - customMetadata: '"
183+
+ customKey
184+
+ "' / '"
185+
+ metadata.getCustomMetadata(customKey)
186+
+ "'");
187+
}
188+
}
189+
172190
/**
173191
* @link https://firebase.google.com/docs/reference/js/firebase.storage.Reference#updateMetadata
174192
*/
@@ -177,17 +195,35 @@ public void updateMetadata(
177195
String appName, String url, ReadableMap metadataMap, final Promise promise) {
178196
try {
179197
StorageReference reference = getReferenceFromUrl(url, appName);
180-
StorageMetadata metadata = buildMetadataFromMap(metadataMap, null);
181198

182199
reference
183-
.updateMetadata(metadata)
200+
.getMetadata()
184201
.addOnCompleteListener(
185202
getExecutor(),
186-
task -> {
187-
if (task.isSuccessful()) {
188-
promise.resolve(getMetadataAsMap(task.getResult()));
203+
getTask -> {
204+
if (getTask.isSuccessful()) {
205+
206+
// dumpMetadata(getTask.getResult());
207+
StorageMetadata metadata =
208+
buildMetadataFromMap(metadataMap, null, getTask.getResult());
209+
// dumpMetadata(metadata);
210+
211+
reference
212+
.updateMetadata(metadata)
213+
.addOnCompleteListener(
214+
getExecutor(),
215+
updateTask -> {
216+
if (updateTask.isSuccessful()) {
217+
// dumpMetadata(updateTask.getResult());
218+
promise.resolve(getMetadataAsMap(updateTask.getResult()));
219+
} else {
220+
updateTask.getException().printStackTrace();
221+
promiseRejectStorageException(promise, updateTask.getException());
222+
}
223+
});
224+
189225
} else {
190-
promiseRejectStorageException(promise, task.getException());
226+
promiseRejectStorageException(promise, getTask.getException());
191227
}
192228
});
193229
} catch (Exception e) {

packages/storage/android/src/main/java/io/invertase/firebase/storage/ReactNativeFirebaseStorageUploadTask.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ void addOnCompleteListener(ExecutorService executor, Promise promise) {
186186

187187
/** Put String or Data from JavaScript */
188188
void begin(ExecutorService executor, String string, String format, ReadableMap metadataMap) {
189-
StorageMetadata metadata = buildMetadataFromMap(metadataMap, null);
189+
StorageMetadata metadata = buildMetadataFromMap(metadataMap, null, null);
190190
uploadTask = storageReference.putBytes(uploadStringToByteArray(string, format), metadata);
191191
setStorageTask(uploadTask);
192192
addEventListeners(executor);
@@ -195,7 +195,7 @@ void begin(ExecutorService executor, String string, String format, ReadableMap m
195195
/** Put File from JavaScript */
196196
void begin(ExecutorService executor, String localFilePath, ReadableMap metadataMap) {
197197
Uri fileUri = SharedUtils.getUri(localFilePath);
198-
StorageMetadata metadata = buildMetadataFromMap(metadataMap, fileUri);
198+
StorageMetadata metadata = buildMetadataFromMap(metadataMap, fileUri, null);
199199
uploadTask = storageReference.putFile(fileUri, metadata);
200200
setStorageTask(uploadTask);
201201
addEventListeners(executor);

0 commit comments

Comments
 (0)