Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cloud_firestore): Move Snapshot handling into a EventChannel #4209

Merged
merged 62 commits into from
Jan 8, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
6de525c
Bump Podfile
Nov 24, 2020
e45992d
Ensure example uses platform interface from the repo instead of pub
Nov 24, 2020
26aa040
Move QuerySnapshot handling into EventChannel
Nov 24, 2020
13fd053
Formatting
Nov 24, 2020
e1fb4a9
Remove unused methods
Nov 24, 2020
d081def
Forward errors
Nov 24, 2020
067fae2
Move document snapshot listener to event channel as well
Nov 24, 2020
14b77b7
Move snapshotInSync listener to EventChannel
Nov 24, 2020
f44b877
iOS || macOS
Nov 24, 2020
a0de5b5
Perform transaction handling via EventChannel as well
Nov 24, 2020
1d215f7
initialize dictionaries
Nov 24, 2020
b73d2d2
remove now-unused method
Nov 24, 2020
79fcbe8
+/- comments
Nov 24, 2020
c5edfec
finally remove the channel reference
Nov 24, 2020
eda9935
Merge branch 'master' into fix/4108-cloud-firestore
Nov 25, 2020
f72f59a
Typo
Nov 26, 2020
08c77fd
begin android implementation
Nov 26, 2020
c308e3f
migrate query snapshots
Nov 26, 2020
6a83d4d
Remove now-unused code
Nov 26, 2020
ad7769d
Document Snapshots
Nov 26, 2020
3aa91f3
Transactions
Nov 26, 2020
22aeea1
Formatting
Nov 26, 2020
80fd511
Remove now unused classes
ened Nov 28, 2020
882cb0d
Refactor & cleanup
ened Nov 28, 2020
5e8e6b5
remove removeListener
ened Nov 28, 2020
eb302ba
Merge branch 'master' of https://github.com/FirebaseExtended/flutterf…
ened Nov 28, 2020
a86224d
Correct merge
ened Nov 28, 2020
8825473
Create a event channel per transaction
ened Nov 28, 2020
c5cfabc
Move iOS side to the new mechanism as well
ened Nov 28, 2020
9af41ee
Formatting
ened Nov 28, 2020
05e2c3d
unused import
ened Nov 28, 2020
bb41893
reactivate all tests
ened Nov 28, 2020
83753f7
ios fixes
ened Nov 28, 2020
fc0d8b0
cleanup dart side
ened Nov 28, 2020
bf907d9
formatting
ened Nov 28, 2020
0c1d7ae
cleanups
ened Nov 29, 2020
db10057
Merge branch 'master' into fix/4108-cloud-firestore
Dec 2, 2020
e40ddec
Add new failing tests
Dec 2, 2020
d6e39e1
Replace static with dedicated event channel instances
Dec 2, 2020
f33de5f
Dart tests V1
Dec 2, 2020
1ba6f0c
Extend Dart tests
Dec 2, 2020
ce15e2b
analyzer
Dec 2, 2020
46e8688
Restore link
ened Dec 3, 2020
04b099a
Formatting, android cleanup
Dec 7, 2020
f44288a
revert podfile change
Dec 7, 2020
e4a25a2
Remove print
Dec 7, 2020
616f08b
typo
Dec 7, 2020
11a729e
remove unnecessary test
Dec 7, 2020
4b781e8
Merge branch 'master' into fix/4108-cloud-firestore
Dec 17, 2020
46a3088
Merge branch 'master' into fix/4108-cloud-firestore
ened Dec 27, 2020
384a44a
formatting
ened Dec 27, 2020
1f74a61
fix tests
ened Dec 27, 2020
84b678d
java format
ened Dec 27, 2020
f8d6312
Clear transactionHandlers when plugin is destroyed
ened Dec 27, 2020
1be114c
Address PR feedback
ened Dec 27, 2020
20cf2ee
Introduce additional interface to cleanup transaction result listener…
ened Dec 27, 2020
bde86ea
Stop document/query stream listeners once error occured
ened Dec 27, 2020
dbbb837
Add multi-transaction case
ened Dec 27, 2020
cd4f9fb
Remove unused import
ened Dec 28, 2020
49505e2
Address PR feedback
ened Jan 7, 2021
c752e3a
include remaining test in refactor
ened Jan 7, 2021
49e23be
Merge branch 'master' into fix/4108-cloud-firestore
Salakar Jan 8, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 15 additions & 60 deletions packages/cloud_firestore/cloud_firestore/example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
ened marked this conversation as resolved.
Show resolved Hide resolved
platform :ios, '9.0'
# platform :ios, '9.0'
ened marked this conversation as resolved.
Show resolved Hide resolved

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand All @@ -10,76 +10,31 @@ project 'Runner', {
'Release' => :release,
}

def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
generated_key_values = {}
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) do |line|
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{path}", file_abs_path)
generated_key_values[podname] = podpath
else
puts "Invalid plugin specification: #{line}"
end

File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
generated_key_values
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

target 'Runner' do
# Flutter Pod
copied_flutter_dir = File.join(__dir__, 'Flutter')
copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
# Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
# That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
# CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.

generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
unless File.exist?(generated_xcode_build_settings_path)
raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];

unless File.exist?(copied_framework_path)
FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
end
unless File.exist?(copied_podspec_path)
FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
end
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

# Keep pod path relative so it can be checked into Podfile.lock.
pod 'Flutter', :path => 'Flutter'
flutter_ios_podfile_setup

# Plugin Pods
target 'Runner' do
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.
system('rm -rf .symlinks')
system('mkdir -p .symlinks/plugins')
plugin_pods = parse_KV_file('../.flutter-plugins')
plugin_pods.each do |name, path|
symlink = File.join('.symlinks', 'plugins', name)
File.symlink(path, symlink)
pod name, :path => File.join(symlink, 'ios')
end
pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '6.33.0'
end


post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
flutter_additional_ios_build_settings(target)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@
buildPhases = (
AB1344B0443C71CD721E1BB7 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
6EA2AFC772200E017D392E90 /* [CP] Prepare Artifacts */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
Expand Down Expand Up @@ -248,37 +247,13 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
6EA2AFC772200E017D392E90 /* [CP] Prepare Artifacts */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-artifacts.sh",
"${PODS_ROOT}/FirebaseFirestore/FirebaseFirestore/abseil.xcframework",
"${PODS_ROOT}/FirebaseFirestore/FirebaseFirestore/BoringSSL-GRPC.xcframework",
"${PODS_ROOT}/FirebaseFirestore/FirebaseFirestore/FirebaseFirestore.xcframework",
"${PODS_ROOT}/FirebaseFirestore/FirebaseFirestore/gRPC-C++.xcframework",
"${PODS_ROOT}/FirebaseFirestore/FirebaseFirestore/gRPC-Core.xcframework",
"${PODS_ROOT}/FirebaseFirestore/FirebaseFirestore/leveldb-library.xcframework",
);
name = "[CP] Prepare Artifacts";
outputPaths = (
"${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-artifacts.sh\"\n";
showEnvVarsInLog = 0;
};
95BB15E9E1769C0D146AA592 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt",
"${PODS_ROOT}/../Flutter/Flutter.framework",
);
name = "[CP] Embed Pods Frameworks";
Expand Down Expand Up @@ -449,7 +424,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ARCHS = arm64;
ARCHS = "$(ARCHS_STANDARD)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
Expand All @@ -471,7 +446,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ARCHS = arm64;
ARCHS = "$(ARCHS_STANDARD)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
Expand Down
2 changes: 2 additions & 0 deletions packages/cloud_firestore/cloud_firestore/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ dependencies:
dependency_overrides:
firebase_core:
path: ../../../firebase_core/firebase_core
cloud_firestore_platform_interface:
ened marked this conversation as resolved.
Show resolved Hide resolved
path: ../../cloud_firestore_platform_interface

dev_dependencies:
pedantic: ^1.8.0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// FLTDocumentSnapshotStreamHandler.m
// cloud_firestore
//
// Created by Sebastian Roth on 24/11/2020.
//

#import <Firebase/Firebase.h>
#import <firebase_core/FLTFirebasePluginRegistry.h>

#import "Private/FLTDocumentSnapshotStreamHandler.h"
#import "Private/FLTFirebaseFirestoreUtils.h"

@implementation FLTDocumentSnapshotStreamHandler {
NSMutableDictionary<NSNumber *, id<FIRListenerRegistration>> *_listeners;
}

- (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments
eventSink:(nonnull FlutterEventSink)events {

NSNumber *handle = arguments[@"handle"];
NSNumber *includeMetadataChanges = arguments[@"includeMetadataChanges"];

FIRDocumentReference *document = arguments[@"reference"];

id listener = ^(FIRDocumentSnapshot *snapshot, NSError *_Nullable error) {
if (error != nil) {
NSArray *codeAndMessage = [FLTFirebaseFirestoreUtils ErrorCodeAndMessageFromNSError:error];

events(@{
@"handle" : handle,
@"error" : @{@"code" : codeAndMessage[0], @"message" : codeAndMessage[1]},
});
} else if (snapshot != nil) {
events(@{
@"handle" : handle,
@"snapshot" : snapshot,
});
}
};

id<FIRListenerRegistration> listenerRegistration =
[document addSnapshotListenerWithIncludeMetadataChanges:includeMetadataChanges.boolValue
listener:listener];

@synchronized(_listeners) {
_listeners[handle] = listenerRegistration;
}

return nil;
}

- (FlutterError *_Nullable)onCancelWithArguments:(id _Nullable)arguments {
NSNumber *handle = arguments[@"handle"];

@synchronized(_listeners) {
[_listeners[handle] remove];
[_listeners removeObjectForKey:handle];
}

return nil;
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@
#import <firebase_core/FLTFirebasePluginRegistry.h>

#import "Private/FLTFirebaseFirestoreUtils.h"
#import "Private/FLTDocumentSnapshotStreamHandler.h"
#import "Private/FLTQuerySnapshotStreamHandler.h"
#import "Public/FLTFirebaseFirestorePlugin.h"

NSString *const kFLTFirebaseFirestoreChannelName = @"plugins.flutter.io/firebase_firestore";
NSString *const kFLTFirebaseFirestoreQuerySnapshotEventChannelName =
@"plugins.flutter.io/firebase_firestore/query";
NSString *const kFLTFirebaseFirestoreDocumentSnapshotEventChannelName =
@"plugins.flutter.io/firebase_firestore/document";

@interface FLTFirebaseFirestorePlugin ()
@property(nonatomic, retain) FlutterMethodChannel *channel;
Expand Down Expand Up @@ -55,6 +61,24 @@ + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FLTFirebaseFirestorePlugin *instance = [FLTFirebaseFirestorePlugin sharedInstance];
instance.channel = channel;
[registrar addMethodCallDelegate:instance channel:channel];

FlutterEventChannel *querySnapshotChannel =
[FlutterEventChannel eventChannelWithName:kFLTFirebaseFirestoreQuerySnapshotEventChannelName
binaryMessenger:registrar.messenger
codec:[FlutterStandardMethodCodec
codecWithReaderWriter:firestoreReaderWriter]];

[querySnapshotChannel setStreamHandler:[[FLTQuerySnapshotStreamHandler alloc] init]];

FlutterEventChannel *documentSnapshotChannel =
[FlutterEventChannel eventChannelWithName:kFLTFirebaseFirestoreDocumentSnapshotEventChannelName
binaryMessenger:registrar.messenger
codec:[FlutterStandardMethodCodec
codecWithReaderWriter:firestoreReaderWriter]];

[documentSnapshotChannel setStreamHandler:[[FLTDocumentSnapshotStreamHandler alloc] init]];


#if TARGET_OS_OSX
// TODO(Salakar): Publish does not exist on MacOS version of FlutterPluginRegistrar.
#else
Expand Down Expand Up @@ -141,10 +165,6 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)flutter
[self documentDelete:call.arguments withMethodCallResult:methodCallResult];
} else if ([@"DocumentReference#get" isEqualToString:call.method]) {
[self documentGet:call.arguments withMethodCallResult:methodCallResult];
} else if ([@"Query#addSnapshotListener" isEqualToString:call.method]) {
[self queryAddSnapshotListener:call.arguments withMethodCallResult:methodCallResult];
} else if ([@"DocumentReference#addSnapshotListener" isEqualToString:call.method]) {
[self documentAddSnapshotListener:call.arguments withMethodCallResult:methodCallResult];
} else if ([@"Query#get" isEqualToString:call.method]) {
[self queryGet:call.arguments withMethodCallResult:methodCallResult];
} else if ([@"Firestore#removeListener" isEqualToString:call.method]) {
Expand Down Expand Up @@ -438,87 +458,6 @@ - (void)documentGet:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallRes
[document getDocumentWithSource:source completion:completion];
}

- (void)queryAddSnapshotListener:(id)arguments
withMethodCallResult:(FLTFirebaseMethodCallResult *)result {
__weak __typeof__(self) weakSelf = self;
FIRQuery *query = arguments[@"query"];

if (query == nil) {
result.error(@"sdk-error",
@"An error occurred while parsing query arguments, see native logs for more "
@"information. Please report this issue.",
nil, nil);
return;
}

NSNumber *handle = arguments[@"handle"];
NSNumber *includeMetadataChanges = arguments[@"includeMetadataChanges"];

id listener = ^(FIRQuerySnapshot *_Nullable snapshot, NSError *_Nullable error) {
if (error != nil) {
NSArray *codeAndMessage = [FLTFirebaseFirestoreUtils ErrorCodeAndMessageFromNSError:error];
[weakSelf.channel
invokeMethod:@"QuerySnapshot#error"
arguments:@{
@"handle" : handle,
@"error" : @{@"code" : codeAndMessage[0], @"message" : codeAndMessage[1]},
}];
} else if (snapshot != nil) {
[weakSelf.channel invokeMethod:@"QuerySnapshot#event"
arguments:@{
@"handle" : handle,
@"snapshot" : snapshot,
}];
}
};

id<FIRListenerRegistration> listenerRegistration =
[query addSnapshotListenerWithIncludeMetadataChanges:includeMetadataChanges.boolValue
listener:listener];

@synchronized(_listeners) {
_listeners[handle] = listenerRegistration;
}
result.success(nil);
}

- (void)documentAddSnapshotListener:(id)arguments
withMethodCallResult:(FLTFirebaseMethodCallResult *)result {
__weak __typeof__(self) weakSelf = self;

NSNumber *handle = arguments[@"handle"];
NSNumber *includeMetadataChanges = arguments[@"includeMetadataChanges"];

FIRDocumentReference *document = arguments[@"reference"];

id listener = ^(FIRDocumentSnapshot *snapshot, NSError *_Nullable error) {
if (error != nil) {
NSArray *codeAndMessage = [FLTFirebaseFirestoreUtils ErrorCodeAndMessageFromNSError:error];
[weakSelf.channel
invokeMethod:@"DocumentSnapshot#error"
arguments:@{
@"handle" : handle,
@"error" : @{@"code" : codeAndMessage[0], @"message" : codeAndMessage[1]},
}];
} else if (snapshot != nil) {
[weakSelf.channel invokeMethod:@"DocumentSnapshot#event"
arguments:@{
@"handle" : handle,
@"snapshot" : snapshot,
}];
}
};

id<FIRListenerRegistration> listenerRegistration =
[document addSnapshotListenerWithIncludeMetadataChanges:includeMetadataChanges.boolValue
listener:listener];

@synchronized(_listeners) {
_listeners[handle] = listenerRegistration;
}
result.success(nil);
}

- (void)queryGet:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result {
FIRQuery *query = arguments[@"query"];

Expand Down
Loading