Skip to content

Commit 39ce6d2

Browse files
committed
Merge branch 'remoteMaster' of github.com:SwineTech-Inc/flutterfire into not_found_exception_update
2 parents b36512a + aeafc35 commit 39ce6d2

File tree

38 files changed

+911
-36
lines changed

38 files changed

+911
-36
lines changed

.github/workflows/pr_title.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ jobs:
1111
validate:
1212
runs-on: ubuntu-latest
1313
steps:
14-
- uses: amannn/action-semantic-pull-request@cfb60706e18bc85e8aec535e3c577abe8f70378e
14+
- uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017
1515
env:
1616
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}

docs/auth/email-link-auth.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ To initiate the authentication flow, present an interface that prompts the user
5050

5151
1. Construct the ActionCodeSettings object, which provides Firebase with instructions on how to construct the email link. Set the following fields:
5252

53-
* `url`: The deep link to embed and any additional state to be passed along. The link's domain has to be whitelisted in the Firebase Console list of authorized domains, which can be found by going to the Sign-in method tab (Authentication -> Sign-in method). The link will redirect the user to this URL if the app is not installed on their device and the app was not able to be installed.
53+
* `url`: The deep link to embed and any additional state to be passed along. The link's domain has to be whitelisted in the Firebase Console list of authorized domains, which can be found by going to the Settings tab (Authentication -> Settings -> Authorized Domains). The link will redirect the user to this URL if the app is not installed on their device and the app was not able to be installed.
5454

5555
* `androidPackageName` and `IOSBundleId`: The apps to use when the sign-in link is opened on an Android or iOS device. Learn more on how to configure Firebase Dynamic Links to open email action links via mobile apps.
5656

docs/auth/federated-auth.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,33 @@ Future<UserCredential> signInWithApple() async {
224224
}
225225
```
226226

227+
#### Apple platform sign-in only
228+
229+
Apple sign-in on iOS+ platforms can also be achieved with the following method:
230+
231+
```dart
232+
// Implement a function that generates a nonce. See iOS documentation for how to create a nonce:
233+
// https://firebase.google.com/docs/auth/ios/apple#sign_in_with_apple_and_authenticate_with_firebase
234+
String rawNonce = createNonce();
235+
// Create a SHA-256 hash of the nonce. Consider using the `crypto` package from the pub.dev registry.
236+
String hashSHA256String = createHashSHA256String(rawNonce);
237+
// Use the hash of the nonce to get the idToken. Consider using the `sign_in_with_apple` plugin from the pub.dev registry.
238+
String idToken = await getIdToken();
239+
240+
final fullName = AppleFullPersonName(
241+
familyName: 'Name',
242+
givenName: 'Your',
243+
);
244+
// Use the `rawNonce` and `idToken` to get the credential
245+
final credential = AppleAuthProvider.credentialWithIDToken(
246+
idToken,
247+
rawNonce,
248+
fullName,
249+
);
250+
251+
await FirebaseAuth.instance.signInWithCredential(credential);
252+
```
253+
227254
### Revoke Apple auth tokens {:#revoke-apple}
228255

229256
Apple sign-in on Apple platforms returns an authorization code that can be used

docs/cloud-messaging/receive.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,11 @@ Here's how to use the second method:
376376
377377
```json
378378
{
379-
"data": {
380-
"title_loc_key": "notification_title",
381-
"body_loc_key": "notification_message"
379+
"android": {
380+
"notification": {
381+
"title_loc_key": "notification_title",
382+
"body_loc_key": "notification_message"
383+
}
382384
}
383385
}
384386
```
@@ -403,9 +405,13 @@ Here's how to use the second method:
403405
404406
```json
405407
{
406-
"data": {
407-
"title_loc_key": "NOTIFICATION_TITLE",
408-
"body_loc_key": "NOTIFICATION_MESSAGE"
408+
"apns": {
409+
"payload": {
410+
"alert": {
411+
"title-loc-key": "NOTIFICATION_TITLE",
412+
"loc-key": "NOTIFICATION_MESSAGE"
413+
}
414+
}
409415
}
410416
}
411417
```

docs/setup/_setup_prereq_ios.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@
2626
If you don't already have a Flutter app, you can complete the [Get
2727
Started: Test Drive](//flutter.io/get-started/test-drive/#androidstudio) to
2828
create a new Flutter app using your preferred editor or IDE.
29+
30+
Note: If you're targeting macOS or macOS Catalyst, you must add the [Keychain Sharing capability](https://firebase.google.com/docs/ios/troubleshooting-faq#macos-keychain-sharing) to your target. In Xcode, navigate to your target's *Signing & Capabilities* tab, and then click **+ Capabilities** to add a new capability.

melos.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ scripts:
229229
melos exec -- "flutter pub run pigeon --input ./pigeons/messages.dart" && \
230230
melos run generate:pigeon:macos --no-select && \
231231
melos run generate:pigeon:android --no-select && \
232-
melos run format --no-select
232+
melos run format-ci --no-select
233233
packageFilters:
234234
fileExists: 'pigeons/messages.dart'
235235
description: Generate the pigeon messages for all the supported packages.

packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static com.google.firebase.firestore.AggregateField.sum;
1010

1111
import android.app.Activity;
12+
import android.util.Log;
1213
import androidx.annotation.NonNull;
1314
import androidx.annotation.Nullable;
1415
import com.google.android.gms.tasks.Task;
@@ -24,6 +25,7 @@
2425
import com.google.firebase.firestore.FirebaseFirestore;
2526
import com.google.firebase.firestore.FirebaseFirestoreSettings;
2627
import com.google.firebase.firestore.MemoryCacheSettings;
28+
import com.google.firebase.firestore.PersistentCacheIndexManager;
2729
import com.google.firebase.firestore.PersistentCacheSettings;
2830
import com.google.firebase.firestore.Query;
2931
import com.google.firebase.firestore.QuerySnapshot;
@@ -64,7 +66,7 @@ public class FlutterFirebaseFirestorePlugin
6466
GeneratedAndroidFirebaseFirestore.FirebaseFirestoreHostApi {
6567
protected static final HashMap<FirebaseFirestore, FlutterFirebaseFirestoreExtension>
6668
firestoreInstanceCache = new HashMap<>();
67-
69+
public static final String TAG = "FlutterFirestorePlugin";
6870
public static final String DEFAULT_ERROR_CODE = "firebase_firestore";
6971

7072
private static final String METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_firestore";
@@ -473,6 +475,35 @@ public void setIndexConfiguration(
473475
});
474476
}
475477

478+
@Override
479+
public void persistenceCacheIndexManagerRequest(
480+
@NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app,
481+
@NonNull GeneratedAndroidFirebaseFirestore.PersistenceCacheIndexManagerRequest request,
482+
@NonNull GeneratedAndroidFirebaseFirestore.Result<Void> result) {
483+
cachedThreadPool.execute(
484+
() -> {
485+
PersistentCacheIndexManager indexManager =
486+
getFirestoreFromPigeon(app).getPersistentCacheIndexManager();
487+
if (indexManager != null) {
488+
switch (request) {
489+
case ENABLE_INDEX_AUTO_CREATION:
490+
indexManager.enableIndexAutoCreation();
491+
break;
492+
case DISABLE_INDEX_AUTO_CREATION:
493+
indexManager.disableIndexAutoCreation();
494+
break;
495+
case DELETE_ALL_INDEXES:
496+
indexManager.deleteAllIndexes();
497+
break;
498+
}
499+
} else {
500+
Log.d(TAG, "`PersistentCacheIndexManager` is not available.");
501+
}
502+
503+
result.success(null);
504+
});
505+
}
506+
476507
@Override
477508
public void setLoggingEnabled(
478509
@NonNull Boolean loggingEnabled,

packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,22 @@ private AggregateSource(final int index) {
166166
}
167167
}
168168

169+
/**
170+
* [PersistenceCacheIndexManagerRequest] represents the request types for the persistence cache
171+
* index manager.
172+
*/
173+
public enum PersistenceCacheIndexManagerRequest {
174+
ENABLE_INDEX_AUTO_CREATION(0),
175+
DISABLE_INDEX_AUTO_CREATION(1),
176+
DELETE_ALL_INDEXES(2);
177+
178+
final int index;
179+
180+
private PersistenceCacheIndexManagerRequest(final int index) {
181+
this.index = index;
182+
}
183+
}
184+
169185
public enum PigeonTransactionResult {
170186
SUCCESS(0),
171187
FAILURE(1);
@@ -1815,6 +1831,11 @@ void documentReferenceSnapshot(
18151831
@NonNull ListenSource source,
18161832
@NonNull Result<String> result);
18171833

1834+
void persistenceCacheIndexManagerRequest(
1835+
@NonNull FirestorePigeonFirebaseApp app,
1836+
@NonNull PersistenceCacheIndexManagerRequest request,
1837+
@NonNull Result<Void> result);
1838+
18181839
/** The codec used by FirebaseFirestoreHostApi. */
18191840
static @NonNull MessageCodec<Object> getCodec() {
18201841
return FirebaseFirestoreHostApiCodec.INSTANCE;
@@ -2570,6 +2591,39 @@ public void error(Throwable error) {
25702591
channel.setMessageHandler(null);
25712592
}
25722593
}
2594+
{
2595+
BasicMessageChannel<Object> channel =
2596+
new BasicMessageChannel<>(
2597+
binaryMessenger,
2598+
"dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest",
2599+
getCodec());
2600+
if (api != null) {
2601+
channel.setMessageHandler(
2602+
(message, reply) -> {
2603+
ArrayList<Object> wrapped = new ArrayList<Object>();
2604+
ArrayList<Object> args = (ArrayList<Object>) message;
2605+
FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0);
2606+
PersistenceCacheIndexManagerRequest requestArg =
2607+
PersistenceCacheIndexManagerRequest.values()[(int) args.get(1)];
2608+
Result<Void> resultCallback =
2609+
new Result<Void>() {
2610+
public void success(Void result) {
2611+
wrapped.add(0, null);
2612+
reply.reply(wrapped);
2613+
}
2614+
2615+
public void error(Throwable error) {
2616+
ArrayList<Object> wrappedError = wrapError(error);
2617+
reply.reply(wrappedError);
2618+
}
2619+
};
2620+
2621+
api.persistenceCacheIndexManagerRequest(appArg, requestArg, resultCallback);
2622+
});
2623+
} else {
2624+
channel.setMessageHandler(null);
2625+
}
2626+
}
25732627
}
25742628
}
25752629
}

packages/cloud_firestore/cloud_firestore/example/integration_test/instance_e2e.dart

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'dart:async';
66
import 'dart:convert';
77

88
import 'package:cloud_firestore/cloud_firestore.dart';
9+
import 'package:firebase_core/firebase_core.dart';
910
import 'package:flutter/foundation.dart';
1011
import 'package:flutter_test/flutter_test.dart';
1112

@@ -312,6 +313,121 @@ void runInstanceTests() {
312313
{'some': 'data'},
313314
);
314315
});
316+
testWidgets(
317+
'`PersistenceCacheIndexManager` with default persistence settings for each platform',
318+
(widgetTester) async {
319+
if (defaultTargetPlatform == TargetPlatform.windows) {
320+
try {
321+
// Windows does not have `PersistenceCacheIndexManager` support
322+
FirebaseFirestore.instance.persistentCacheIndexManager();
323+
} catch (e) {
324+
expect(e, isInstanceOf<UnimplementedError>());
325+
}
326+
} else {
327+
if (kIsWeb) {
328+
// persistence is disabled by default on web
329+
final firestore = FirebaseFirestore.instanceFor(
330+
app: Firebase.app(),
331+
// Use different firestore instance to test behavior
332+
databaseId: 'default-web',
333+
);
334+
PersistentCacheIndexManager? indexManager =
335+
firestore.persistentCacheIndexManager();
336+
expect(indexManager, isNull);
337+
} else {
338+
final firestore = FirebaseFirestore.instanceFor(
339+
app: Firebase.app(),
340+
// Use different firestore instance to test behavior
341+
databaseId: 'default-other-platform-test',
342+
);
343+
// macOS, android, iOS have persistence enabled by default
344+
PersistentCacheIndexManager? indexManager =
345+
firestore.persistentCacheIndexManager();
346+
await indexManager!.enableIndexAutoCreation();
347+
await indexManager.disableIndexAutoCreation();
348+
await indexManager.deleteAllIndexes();
349+
}
350+
}
351+
},
352+
);
353+
354+
testWidgets(
355+
'`PersistenceCacheIndexManager` with persistence enabled for each platform',
356+
(widgetTester) async {
357+
if (kIsWeb) {
358+
final firestore = FirebaseFirestore.instanceFor(
359+
app: Firebase.app(),
360+
databaseId: 'web-enabled',
361+
);
362+
// persistence is disabled by default so we enable it
363+
firestore.settings = const Settings(persistenceEnabled: true);
364+
365+
PersistentCacheIndexManager? indexManager =
366+
firestore.persistentCacheIndexManager();
367+
368+
await indexManager!.enableIndexAutoCreation();
369+
await indexManager.disableIndexAutoCreation();
370+
await indexManager.deleteAllIndexes();
371+
372+
final firestore2 = FirebaseFirestore.instanceFor(
373+
app: Firebase.app(),
374+
databaseId: 'web-disabled-2',
375+
);
376+
377+
// Now try using `enablePersistence()`, web only API
378+
await firestore2.enablePersistence();
379+
380+
PersistentCacheIndexManager? indexManager2 =
381+
firestore2.persistentCacheIndexManager();
382+
383+
await indexManager2!.enableIndexAutoCreation();
384+
await indexManager2.disableIndexAutoCreation();
385+
await indexManager2.deleteAllIndexes();
386+
} else {
387+
final firestore = FirebaseFirestore.instanceFor(
388+
app: Firebase.app(),
389+
databaseId: 'other-platform-enabled',
390+
);
391+
firestore.settings = const Settings(persistenceEnabled: true);
392+
PersistentCacheIndexManager? indexManager =
393+
firestore.persistentCacheIndexManager();
394+
await indexManager!.enableIndexAutoCreation();
395+
await indexManager.disableIndexAutoCreation();
396+
await indexManager.deleteAllIndexes();
397+
}
398+
},
399+
skip: defaultTargetPlatform == TargetPlatform.windows,
400+
);
401+
402+
testWidgets(
403+
'`PersistenceCacheIndexManager` with persistence disabled for each platform',
404+
(widgetTester) async {
405+
if (kIsWeb) {
406+
final firestore = FirebaseFirestore.instanceFor(
407+
app: Firebase.app(),
408+
databaseId: 'web-disabled-1',
409+
);
410+
// persistence is disabled by default so we enable it
411+
firestore.settings = const Settings(persistenceEnabled: false);
412+
413+
PersistentCacheIndexManager? indexManager =
414+
firestore.persistentCacheIndexManager();
415+
416+
expect(indexManager, isNull);
417+
} else {
418+
final firestore = FirebaseFirestore.instanceFor(
419+
app: Firebase.app(),
420+
databaseId: 'other-platform-disabled',
421+
);
422+
// macOS, android, iOS have persistence enabled by default so we disable it
423+
firestore.settings = const Settings(persistenceEnabled: false);
424+
PersistentCacheIndexManager? indexManager =
425+
firestore.persistentCacheIndexManager();
426+
expect(indexManager, isNull);
427+
}
428+
},
429+
skip: defaultTargetPlatform == TargetPlatform.windows,
430+
);
315431
},
316432
);
317433
}

0 commit comments

Comments
 (0)